Subversion Repositories Applications.papyrus

Rev

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