Subversion Repositories Applications.papyrus

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1318 alexandre_ 1
/*
2
	Copyright (c) 2004-2006, The Dojo Foundation
3
	All Rights Reserved.
4
 
5
	Licensed under the Academic Free License version 2.1 or above OR the
6
	modified BSD license. For more information on Dojo licensing, see:
7
 
8
		http://dojotoolkit.org/community/licensing.shtml
9
*/
10
 
11
dojo.provide("dojo.widget.vml.Chart");
12
dojo.require("dojo.widget.HtmlWidget");
13
dojo.require("dojo.widget.Chart");
14
dojo.require("dojo.math");
15
dojo.require("dojo.html.layout");
16
dojo.require("dojo.gfx.color");
17
dojo.widget.defineWidget("dojo.widget.vml.Chart", [dojo.widget.HtmlWidget, dojo.widget.Chart], function () {
18
	this.templatePath = null;
19
	this.templateCssPath = null;
20
	this._isInitialize = false;
21
	this.hasData = false;
22
	this.vectorNode = null;
23
	this.plotArea = null;
24
	this.dataGroup = null;
25
	this.axisGroup = null;
26
	this.properties = {height:0, width:0, defaultWidth:600, defaultHeight:400, plotType:null, padding:{top:10, bottom:2, left:60, right:30}, axes:{x:{plotAt:0, label:"", unitLabel:"", unitType:Number, nUnitsToShow:10, range:{min:0, max:200}}, y:{plotAt:0, label:"", unitLabel:"", unitType:Number, nUnitsToShow:10, range:{min:0, max:200}}}};
27
}, {parseProperties:function (node) {
28
	var bRangeX = false;
29
	var bRangeY = false;
30
	if (node.getAttribute("width")) {
31
		this.properties.width = node.getAttribute("width");
32
	}
33
	if (node.getAttribute("height")) {
34
		this.properties.height = node.getAttribute("height");
35
	}
36
	if (node.getAttribute("plotType")) {
37
		this.properties.plotType = node.getAttribute("plotType");
38
	}
39
	if (node.getAttribute("padding")) {
40
		if (node.getAttribute("padding").indexOf(",") > -1) {
41
			var p = node.getAttribute("padding").split(",");
42
		} else {
43
			var p = node.getAttribute("padding").split(" ");
44
		}
45
		if (p.length == 1) {
46
			var pad = parseFloat(p[0]);
47
			this.properties.padding.top = pad;
48
			this.properties.padding.right = pad;
49
			this.properties.padding.bottom = pad;
50
			this.properties.padding.left = pad;
51
		} else {
52
			if (p.length == 2) {
53
				var padV = parseFloat(p[0]);
54
				var padH = parseFloat(p[1]);
55
				this.properties.padding.top = padV;
56
				this.properties.padding.right = padH;
57
				this.properties.padding.bottom = padV;
58
				this.properties.padding.left = padH;
59
			} else {
60
				if (p.length == 4) {
61
					this.properties.padding.top = parseFloat(p[0]);
62
					this.properties.padding.right = parseFloat(p[1]);
63
					this.properties.padding.bottom = parseFloat(p[2]);
64
					this.properties.padding.left = parseFloat(p[3]);
65
				}
66
			}
67
		}
68
	}
69
	if (node.getAttribute("rangeX")) {
70
		var p = node.getAttribute("rangeX");
71
		if (p.indexOf(",") > -1) {
72
			p = p.split(",");
73
		} else {
74
			p = p.split(" ");
75
		}
76
		this.properties.axes.x.range.min = parseFloat(p[0]);
77
		this.properties.axes.x.range.max = parseFloat(p[1]);
78
		bRangeX = true;
79
	}
80
	if (node.getAttribute("rangeY")) {
81
		var p = node.getAttribute("rangeY");
82
		if (p.indexOf(",") > -1) {
83
			p = p.split(",");
84
		} else {
85
			p = p.split(" ");
86
		}
87
		this.properties.axes.y.range.min = parseFloat(p[0]);
88
		this.properties.axes.y.range.max = parseFloat(p[1]);
89
		bRangeY = true;
90
	}
91
	return {rangeX:bRangeX, rangeY:bRangeY};
92
}, setAxesPlot:function (table) {
93
	if (table.getAttribute("axisAt")) {
94
		var p = table.getAttribute("axisAt");
95
		if (p.indexOf(",") > -1) {
96
			p = p.split(",");
97
		} else {
98
			p = p.split(" ");
99
		}
100
		if (!isNaN(parseFloat(p[0]))) {
101
			this.properties.axes.x.plotAt = parseFloat(p[0]);
102
		} else {
103
			if (p[0].toLowerCase() == "ymin") {
104
				this.properties.axes.x.plotAt = this.properties.axes.y.range.min;
105
			} else {
106
				if (p[0].toLowerCase() == "ymax") {
107
					this.properties.axes.x.plotAt = this.properties.axes.y.range.max;
108
				}
109
			}
110
		}
111
		if (!isNaN(parseFloat(p[1]))) {
112
			this.properties.axes.y.plotAt = parseFloat(p[1]);
113
		} else {
114
			if (p[1].toLowerCase() == "xmin") {
115
				this.properties.axes.y.plotAt = this.properties.axes.x.range.min;
116
			} else {
117
				if (p[1].toLowerCase() == "xmax") {
118
					this.properties.axes.y.plotAt = this.properties.axes.x.range.max;
119
				}
120
			}
121
		}
122
	} else {
123
		this.properties.axes.x.plotAt = this.properties.axes.y.range.min;
124
		this.properties.axes.y.plotAt = this.properties.axes.x.range.min;
125
	}
126
}, drawVectorNode:function () {
127
	if (this.vectorNode) {
128
		this.destroy();
129
	}
130
	this.vectorNode = document.createElement("div");
131
	this.vectorNode.style.width = this.properties.width + "px";
132
	this.vectorNode.style.height = this.properties.height + "px";
133
	this.vectorNode.style.position = "relative";
134
	this.domNode.appendChild(this.vectorNode);
135
}, drawPlotArea:function () {
136
	var plotWidth = this.properties.width - this.properties.padding.left - this.properties.padding.right;
137
	var plotHeight = this.properties.height - this.properties.padding.top - this.properties.padding.bottom;
138
	if (this.plotArea) {
139
		this.plotArea.parentNode.removeChild(this.plotArea);
140
		this.plotArea = null;
141
	}
142
	this.plotArea = document.createElement("div");
143
	this.plotArea.style.position = "absolute";
144
	this.plotArea.style.backgroundColor = "#fff";
145
	this.plotArea.style.top = (this.properties.padding.top) - 2 + "px";
146
	this.plotArea.style.left = (this.properties.padding.left - 1) + "px";
147
	this.plotArea.style.width = plotWidth + "px";
148
	this.plotArea.style.height = plotHeight + "px";
149
	this.plotArea.style.clip = "rect(0 " + plotWidth + " " + plotHeight + " 0)";
150
	this.vectorNode.appendChild(this.plotArea);
151
}, drawDataGroup:function () {
152
	var plotWidth = this.properties.width - this.properties.padding.left - this.properties.padding.right;
153
	var plotHeight = this.properties.height - this.properties.padding.top - this.properties.padding.bottom;
154
	if (this.dataGroup) {
155
		this.dataGroup.parentNode.removeChild(this.dataGroup);
156
		this.dataGroup = null;
157
	}
158
	this.dataGroup = document.createElement("div");
159
	this.dataGroup.style.position = "absolute";
160
	this.dataGroup.setAttribute("title", "Data Group");
161
	this.dataGroup.style.top = "0px";
162
	this.dataGroup.style.left = "0px";
163
	this.dataGroup.style.width = plotWidth + "px";
164
	this.dataGroup.style.height = plotHeight + "px";
165
	this.plotArea.appendChild(this.dataGroup);
166
}, drawAxes:function () {
167
	var plotWidth = this.properties.width - this.properties.padding.left - this.properties.padding.right;
168
	var plotHeight = this.properties.height - this.properties.padding.top - this.properties.padding.bottom;
169
	if (this.axisGroup) {
170
		this.axisGroup.parentNode.removeChild(this.axisGroup);
171
		this.axisGroup = null;
172
	}
173
	this.axisGroup = document.createElement("div");
174
	this.axisGroup.style.position = "absolute";
175
	this.axisGroup.setAttribute("title", "Axis Group");
176
	this.axisGroup.style.top = "0px";
177
	this.axisGroup.style.left = "0px";
178
	this.axisGroup.style.width = plotWidth + "px";
179
	this.axisGroup.style.height = plotHeight + "px";
180
	this.plotArea.appendChild(this.axisGroup);
181
	var stroke = 1;
182
	var line = document.createElement("v:line");
183
	var y = dojo.widget.vml.Chart.Plotter.getY(this.properties.axes.x.plotAt, this);
184
	line.setAttribute("from", "0px," + y + "px");
185
	line.setAttribute("to", plotWidth + "px," + y + "px");
186
	line.style.position = "absolute";
187
	line.style.top = "0px";
188
	line.style.left = "0px";
189
	line.style.antialias = "false";
190
	line.setAttribute("strokecolor", "#666");
191
	line.setAttribute("strokeweight", stroke * 2 + "px");
192
	this.axisGroup.appendChild(line);
193
	var line = document.createElement("v:line");
194
	var x = dojo.widget.vml.Chart.Plotter.getX(this.properties.axes.y.plotAt, this);
195
	line.setAttribute("from", x + "px,0px");
196
	line.setAttribute("to", x + "px," + plotHeight + "px");
197
	line.style.position = "absolute";
198
	line.style.top = "0px";
199
	line.style.left = "0px";
200
	line.style.antialias = "false";
201
	line.setAttribute("strokecolor", "#666");
202
	line.setAttribute("strokeweight", stroke * 2 + "px");
203
	this.axisGroup.appendChild(line);
204
	var size = 10;
205
	var t = document.createElement("div");
206
	t.style.position = "absolute";
207
	t.style.top = (this.properties.height - this.properties.padding.bottom) + "px";
208
	t.style.left = this.properties.padding.left + "px";
209
	t.style.fontFamily = "sans-serif";
210
	t.style.fontSize = size + "px";
211
	t.innerHTML = dojo.math.round(parseFloat(this.properties.axes.x.range.min), 2);
212
	this.vectorNode.appendChild(t);
213
	t = document.createElement("div");
214
	t.style.position = "absolute";
215
	t.style.top = (this.properties.height - this.properties.padding.bottom) + "px";
216
	t.style.left = (this.properties.width - this.properties.padding.right - size) + "px";
217
	t.style.fontFamily = "sans-serif";
218
	t.style.fontSize = size + "px";
219
	t.innerHTML = dojo.math.round(parseFloat(this.properties.axes.x.range.max), 2);
220
	this.vectorNode.appendChild(t);
221
	t = document.createElement("div");
222
	t.style.position = "absolute";
223
	t.style.top = (size / 2) + "px";
224
	t.style.left = "0px";
225
	t.style.width = this.properties.padding.left + "px";
226
	t.style.textAlign = "right";
227
	t.style.paddingRight = "4px";
228
	t.style.fontFamily = "sans-serif";
229
	t.style.fontSize = size + "px";
230
	t.innerHTML = dojo.math.round(parseFloat(this.properties.axes.y.range.max), 2);
231
	this.vectorNode.appendChild(t);
232
	t = document.createElement("div");
233
	t.style.position = "absolute";
234
	t.style.top = (this.properties.height - this.properties.padding.bottom - size) + "px";
235
	t.style.left = "0px";
236
	t.style.width = this.properties.padding.left + "px";
237
	t.style.textAlign = "right";
238
	t.style.paddingRight = "4px";
239
	t.style.fontFamily = "sans-serif";
240
	t.style.fontSize = size + "px";
241
	t.innerHTML = dojo.math.round(parseFloat(this.properties.axes.y.range.min), 2);
242
	this.vectorNode.appendChild(t);
243
}, init:function () {
244
	if (!this.properties.width || !this.properties.height) {
245
		var box = dojo.html.getContentBox(this.domNode);
246
		if (!this.properties.width) {
247
			this.properties.width = (box.width < 32) ? this.properties.defaultWidth : box.width;
248
		}
249
		if (!this.properties.height) {
250
			this.properties.height = (box.height < 32) ? this.properties.defaultHeight : box.height;
251
		}
252
	}
253
	this.drawVectorNode();
254
	this.drawPlotArea();
255
	this.drawDataGroup();
256
	this.drawAxes();
257
	this.assignColors();
258
	this._isInitialized = true;
259
}, destroy:function () {
260
	while (this.domNode.childNodes.length > 0) {
261
		this.domNode.removeChild(this.domNode.childNodes[0]);
262
	}
263
	this.vectorNode = this.plotArea = this.dataGroup = this.axisGroup = null;
264
}, render:function () {
265
	if (this.dataGroup) {
266
		while (this.dataGroup.childNodes.length > 0) {
267
			this.dataGroup.removeChild(this.dataGroup.childNodes[0]);
268
		}
269
	} else {
270
		this.init();
271
	}
272
	for (var i = 0; i < this.series.length; i++) {
273
		dojo.widget.vml.Chart.Plotter.plot(this.series[i], this);
274
	}
275
}, postCreate:function () {
276
	var table = this.domNode.getElementsByTagName("table")[0];
277
	if (table) {
278
		var ranges = this.parseProperties(table);
279
		var bRangeX = false;
280
		var bRangeY = false;
281
		var axisValues = this.parseData(table);
282
		if (!bRangeX) {
283
			this.properties.axes.x.range = {min:axisValues.x.min, max:axisValues.x.max};
284
		}
285
		if (!bRangeY) {
286
			this.properties.axes.y.range = {min:axisValues.y.min, max:axisValues.y.max};
287
		}
288
		this.setAxesPlot(table);
289
		this.domNode.removeChild(table);
290
	}
291
	if (this.series.length > 0) {
292
		this.render();
293
	}
294
}});
295
dojo.widget.vml.Chart.Plotter = new function () {
296
	var self = this;
297
	var plotters = {};
298
	var types = dojo.widget.Chart.PlotTypes;
299
	this.getX = function (value, chart) {
300
		var v = parseFloat(value);
301
		var min = chart.properties.axes.x.range.min;
302
		var max = chart.properties.axes.x.range.max;
303
		var ofst = 0 - min;
304
		min += ofst;
305
		max += ofst;
306
		v += ofst;
307
		var xmin = 0;
308
		var xmax = chart.properties.width - chart.properties.padding.left - chart.properties.padding.right;
309
		var x = (v * ((xmax - xmin) / max)) + xmin;
310
		return x;
311
	};
312
	this.getY = function (value, chart) {
313
		var v = parseFloat(value);
314
		var max = chart.properties.axes.y.range.max;
315
		var min = chart.properties.axes.y.range.min;
316
		var ofst = 0;
317
		if (min < 0) {
318
			ofst += Math.abs(min);
319
		}
320
		min += ofst;
321
		max += ofst;
322
		v += ofst;
323
		var ymin = chart.properties.height - chart.properties.padding.top - chart.properties.padding.bottom;
324
		var ymax = 0;
325
		var y = (((ymin - ymax) / (max - min)) * (max - v)) + ymax;
326
		return y;
327
	};
328
	this.addPlotter = function (name, func) {
329
		plotters[name] = func;
330
	};
331
	this.plot = function (series, chart) {
332
		if (series.values.length == 0) {
333
			return;
334
		}
335
		if (series.plotType && plotters[series.plotType]) {
336
			return plotters[series.plotType](series, chart);
337
		} else {
338
			if (chart.plotType && plotters[chart.plotType]) {
339
				return plotters[chart.plotType](series, chart);
340
			}
341
		}
342
	};
343
	plotters["bar"] = function (series, chart) {
344
		var space = 1;
345
		var lastW = 0;
346
		var ys = [];
347
		var yAxis = self.getY(chart.properties.axes.x.plotAt, chart);
348
		var yA = yAxis;
349
		for (var i = 0; i < series.values.length; i++) {
350
			var x = self.getX(series.values[i].x, chart);
351
			var w;
352
			if (i == series.values.length - 1) {
353
				w = lastW;
354
			} else {
355
				w = self.getX(series.values[i + 1].x, chart) - x - space;
356
				lastW = w;
357
			}
358
			x -= (w / 2);
359
			var y = self.getY(series.values[i].value, chart);
360
			var h = Math.abs(yA - y);
361
			if (parseFloat(series.values[i].value) < chart.properties.axes.x.plotAt) {
362
				y = yA;
363
			}
364
			var bar = document.createElement("v:rect");
365
			bar.style.position = "absolute";
366
			bar.style.top = y + "px";
367
			bar.style.left = x + "px";
368
			bar.style.width = w + "px";
369
			bar.style.height = h + "px";
370
			bar.setAttribute("fillColor", series.color);
371
			bar.setAttribute("stroked", "false");
372
			bar.style.antialias = "false";
373
			bar.setAttribute("title", series.label + " (" + i + "): " + series.values[i].value);
374
			var fill = document.createElement("v:fill");
375
			fill.setAttribute("opacity", "0.9");
376
			bar.appendChild(fill);
377
			chart.dataGroup.appendChild(bar);
378
		}
379
	};
380
	plotters["line"] = function (series, chart) {
381
		var tension = 1.5;
382
		var line = document.createElement("v:shape");
383
		line.setAttribute("strokeweight", "2px");
384
		line.setAttribute("strokecolor", series.color);
385
		line.setAttribute("fillcolor", "none");
386
		line.setAttribute("filled", "false");
387
		line.setAttribute("title", series.label);
388
		line.setAttribute("coordsize", chart.properties.width + "," + chart.properties.height);
389
		line.style.position = "absolute";
390
		line.style.top = "0px";
391
		line.style.left = "0px";
392
		line.style.width = chart.properties.width + "px";
393
		line.style.height = chart.properties.height + "px";
394
		var stroke = document.createElement("v:stroke");
395
		stroke.setAttribute("opacity", "0.85");
396
		line.appendChild(stroke);
397
		var path = [];
398
		for (var i = 0; i < series.values.length; i++) {
399
			var x = Math.round(self.getX(series.values[i].x, chart));
400
			var y = Math.round(self.getY(series.values[i].value, chart));
401
			if (i == 0) {
402
				path.push("m");
403
				path.push(x + "," + y);
404
			} else {
405
				var lastx = Math.round(self.getX(series.values[i - 1].x, chart));
406
				var lasty = Math.round(self.getY(series.values[i - 1].value, chart));
407
				var dx = x - lastx;
408
				var dy = y - lasty;
409
				path.push("c");
410
				var cx = Math.round((x - (tension - 1) * (dx / tension)));
411
				path.push(cx + "," + lasty);
412
				cx = Math.round((x - (dx / tension)));
413
				path.push(cx + "," + y);
414
				path.push(x + "," + y);
415
			}
416
		}
417
		line.setAttribute("path", path.join(" ") + " e");
418
		chart.dataGroup.appendChild(line);
419
	};
420
	plotters["area"] = function (series, chart) {
421
		var tension = 1.5;
422
		var line = document.createElement("v:shape");
423
		line.setAttribute("strokeweight", "1px");
424
		line.setAttribute("strokecolor", series.color);
425
		line.setAttribute("fillcolor", series.color);
426
		line.setAttribute("title", series.label);
427
		line.setAttribute("coordsize", chart.properties.width + "," + chart.properties.height);
428
		line.style.position = "absolute";
429
		line.style.top = "0px";
430
		line.style.left = "0px";
431
		line.style.width = chart.properties.width + "px";
432
		line.style.height = chart.properties.height + "px";
433
		var stroke = document.createElement("v:stroke");
434
		stroke.setAttribute("opacity", "0.8");
435
		line.appendChild(stroke);
436
		var fill = document.createElement("v:fill");
437
		fill.setAttribute("opacity", "0.4");
438
		line.appendChild(fill);
439
		var path = [];
440
		for (var i = 0; i < series.values.length; i++) {
441
			var x = Math.round(self.getX(series.values[i].x, chart));
442
			var y = Math.round(self.getY(series.values[i].value, chart));
443
			if (i == 0) {
444
				path.push("m");
445
				path.push(x + "," + y);
446
			} else {
447
				var lastx = Math.round(self.getX(series.values[i - 1].x, chart));
448
				var lasty = Math.round(self.getY(series.values[i - 1].value, chart));
449
				var dx = x - lastx;
450
				var dy = y - lasty;
451
				path.push("c");
452
				var cx = Math.round((x - (tension - 1) * (dx / tension)));
453
				path.push(cx + "," + lasty);
454
				cx = Math.round((x - (dx / tension)));
455
				path.push(cx + "," + y);
456
				path.push(x + "," + y);
457
			}
458
		}
459
		path.push("l");
460
		path.push(x + "," + self.getY(0, chart));
461
		path.push("l");
462
		path.push(self.getX(0, chart) + "," + self.getY(0, chart));
463
		line.setAttribute("path", path.join(" ") + " x e");
464
		chart.dataGroup.appendChild(line);
465
	};
466
	plotters["scatter"] = function (series, chart) {
467
		var r = 6;
468
		for (var i = 0; i < series.values.length; i++) {
469
			var x = self.getX(series.values[i].x, chart);
470
			var y = self.getY(series.values[i].value, chart);
471
			var mod = r / 2;
472
			var point = document.createElement("v:rect");
473
			point.setAttribute("fillcolor", series.color);
474
			point.setAttribute("strokecolor", series.color);
475
			point.setAttribute("title", series.label + ": " + series.values[i].value);
476
			point.style.position = "absolute";
477
			point.style.rotation = "45";
478
			point.style.top = (y - mod) + "px";
479
			point.style.left = (x - mod) + "px";
480
			point.style.width = r + "px";
481
			point.style.height = r + "px";
482
			var fill = document.createElement("v:fill");
483
			fill.setAttribute("opacity", "0.6");
484
			point.appendChild(fill);
485
			chart.dataGroup.appendChild(point);
486
		}
487
	};
488
	plotters["bubble"] = function (series, chart) {
489
		var minR = 1;
490
		var min = chart.properties.axes.x.range.min;
491
		var max = chart.properties.axes.x.range.max;
492
		var ofst = 0 - min;
493
		min += ofst;
494
		max += ofst;
495
		var xmin = chart.properties.padding.left;
496
		var xmax = chart.properties.width - chart.properties.padding.right;
497
		var factor = (max - min) / (xmax - xmin) * 25;
498
		for (var i = 0; i < series.values.length; i++) {
499
			var size = series.values[i].size;
500
			if (isNaN(parseFloat(size))) {
501
				size = minR;
502
			}
503
			var radius = (parseFloat(size) * factor) / 2;
504
			var diameter = radius * 2;
505
			var cx = self.getX(series.values[i].x, chart);
506
			var cy = self.getY(series.values[i].value, chart);
507
			var top = cy - radius;
508
			var left = cx - radius;
509
			var point = document.createElement("v:oval");
510
			point.setAttribute("fillcolor", series.color);
511
			point.setAttribute("title", series.label + ": " + series.values[i].value + " (" + size + ")");
512
			point.setAttribute("stroked", "false");
513
			point.style.position = "absolute";
514
			point.style.top = top + "px";
515
			point.style.left = left + "px";
516
			point.style.width = diameter + "px";
517
			point.style.height = diameter + "px";
518
			var fill = document.createElement("v:fill");
519
			fill.setAttribute("opacity", "0.8");
520
			point.appendChild(fill);
521
			chart.dataGroup.appendChild(point);
522
		}
523
	};
524
}();
525