2 * o------------------------------------------------------------------------------o
3 * | This file is part of the RGraph package - you can learn more at: |
5 * | http://www.rgraph.net |
7 * | This package is licensed under the RGraph license. For all kinds of business |
8 * | purposes there is a small one-time licensing fee to pay and for non |
9 * | commercial purposes it is free to use. You can read the full license here: |
11 * | http://www.rgraph.net/LICENSE.txt |
12 * o------------------------------------------------------------------------------o
15 if (typeof(RGraph) == 'undefined') RGraph = {};
18 * The progress bar constructor
20 * @param int id The ID of the canvas tag
21 * @param int value The indicated value of the meter.
22 * @param int max The end value (the upper most) of the meter
24 RGraph.VProgress = function (id, value, max)
29 this.canvas = document.getElementById(id);
30 this.context = this.canvas.getContext('2d');
31 this.canvas.__object__ = this;
32 this.type = 'vprogress';
38 * Compatibility with older browsers
40 RGraph.OldBrowserCompat(this.context);
43 'chart.colors': ['#0c0'],
44 'chart.tickmarks': true,
45 'chart.tickmarks.color': 'black',
46 'chart.tickmarks.inner': false,
49 'chart.numticks.inner': 50,
50 'chart.background.color': '#eee',
51 'chart.shadow': false,
52 'chart.shadow.color': 'rgba(0,0,0,0.5)',
53 'chart.shadow.blur': 3,
54 'chart.shadow.offsetx': 3,
55 'chart.shadow.offsety': 3,
57 'chart.title.background': null,
58 'chart.title.hpos': null,
59 'chart.title.vpos': null,
62 'chart.text.size': 10,
63 'chart.text.color': 'black',
64 'chart.text.font': 'Verdana',
65 'chart.contextmenu': null,
66 'chart.units.pre': '',
67 'chart.units.post': '',
69 'chart.tooltips.effect': 'fade',
70 'chart.tooltips.css.class': 'RGraph_tooltip',
71 'chart.tooltips.highlight': true,
72 'chart.tooltips.coords.adjust': [0,0],
73 'chart.annotatable': false,
74 'chart.annotate.color': 'black',
75 'chart.zoom.mode': 'canvas',
76 'chart.zoom.factor': 1.5,
77 'chart.zoom.fade.in': true,
78 'chart.zoom.fade.out': true,
79 'chart.zoom.hdir': 'right',
80 'chart.zoom.vdir': 'down',
81 'chart.zoom.frames': 10,
82 'chart.zoom.delay': 50,
83 'chart.zoom.shadow': true,
84 'chart.zoom.background': true,
85 'chart.zoom.action': 'zoom',
86 'chart.arrows': false,
88 'chart.resizable': false,
89 'chart.label.inner': false,
90 'chart.labels.count': 10,
91 'chart.labels.position': 'right',
92 'chart.adjustable': false,
94 'chart.scale.decimals': 0
99 alert('[PROGRESS] No canvas support');
103 // Check the common library has been included
104 if (typeof(RGraph) == 'undefined') {
105 alert('[PROGRESS] Fatal error: The common library does not appear to have been included');
113 * @param string name The name of the property to set
114 * @param string value The value of the poperty
116 RGraph.VProgress.prototype.Set = function (name, value)
118 this.properties[name.toLowerCase()] = value;
125 * @param string name The name of the property to get
127 RGraph.VProgress.prototype.Get = function (name)
129 return this.properties[name.toLowerCase()];
134 * Draws the progress bar
136 RGraph.VProgress.prototype.Draw = function ()
139 * Fire the onbeforedraw event
141 RGraph.FireCustomEvent(this, 'onbeforedraw');
144 * Clear all of this canvases event handlers (the ones installed by RGraph)
146 RGraph.ClearEventListeners(this.id);
148 // Figure out the width and height
149 this.width = this.canvas.width - (2 * this.Get('chart.gutter'));
150 this.height = this.canvas.height - (2 * this.Get('chart.gutter'));
154 this.DrawTickMarks();
157 this.context.stroke();
161 * Setup the context menu if required
163 if (this.Get('chart.contextmenu')) {
164 RGraph.ShowContext(this);
168 * Alternatively, show the tooltip if requested
170 if (typeof(this.Get('chart.tooltips')) == 'function' || this.Get('chart.tooltips').length) {
172 // Need to register this object for redrawing
173 RGraph.Register(this);
176 * Install the window onclick handler
178 window.onclick = function ()
185 * Install the onclick event handler for the tooltips
187 //this.canvas.onclick = function (e)
188 var canvas_onclick_func = function (e)
190 e = RGraph.FixEventObject(e);
192 var canvas = document.getElementById(this.id);
193 var obj = canvas.__object__;
196 * Redraw the graph first, in effect resetting the graph to as it was when it was first drawn
197 * This "deselects" any already selected bar
202 * Get the mouse X/Y coordinates
204 var mouseCoords = RGraph.getMouseXY(e);
207 * Loop through the bars determining if the mouse is over a bar
209 for (var i=0; i<obj.coords.length; i++) {
211 var mouseX = mouseCoords[0] - obj.Get('chart.tooltips.coords.adjust')[0];
212 var mouseY = mouseCoords[1] - obj.Get('chart.tooltips.coords.adjust')[1];
213 var left = obj.coords[i][0];
214 var top = obj.coords[i][1];
215 var width = obj.coords[i][2];
216 var height = obj.coords[i][3];
219 if (mouseX >= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) {
222 * Get the tooltip text
224 if (typeof(obj.Get('chart.tooltips')) == 'function') {
225 var text = obj.Get('chart.tooltips')(idx);
227 } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') {
228 var text = obj.Get('chart.tooltips')[idx](idx);
230 } else if (typeof(obj.Get('chart.tooltips')) == 'object') {
231 var text = obj.Get('chart.tooltips')[idx];
238 * Show a tooltip if it's defined
242 obj.context.beginPath();
243 obj.context.strokeStyle = 'black';
244 obj.context.fillStyle = 'rgba(255,255,255,0.5)';
245 obj.context.strokeRect(left, top, width, height);
246 obj.context.fillRect(left, top, width, height);
248 obj.context.stroke();
251 RGraph.Tooltip(canvas, text, e.pageX, e.pageY, i);
257 * Stop the event bubbling
261 this.canvas.addEventListener('click', canvas_onclick_func, false);
262 RGraph.AddEventListener(this.id, 'click', canvas_onclick_func);
266 * If the cursor is over a hotspot, change the cursor to a hand
268 //this.canvas.onmousemove = function (e)
269 var canvas_onmousemove_func = function (e)
271 e = RGraph.FixEventObject(e);
273 var canvas = document.getElementById(this.id);
274 var obj = canvas.__object__;
277 * Get the mouse X/Y coordinates
279 var mouseCoords = RGraph.getMouseXY(e);
282 * Loop through the bars determining if the mouse is over a bar
284 for (var i=0; i<obj.coords.length; i++) {
286 var mouseX = mouseCoords[0] - obj.Get('chart.tooltips.coords.adjust')[0]; // In relation to the canvas
287 var mouseY = mouseCoords[1] - obj.Get('chart.tooltips.coords.adjust')[1]; // In relation to the canvas
288 var left = obj.coords[i][0];
289 var top = obj.coords[i][1];
290 var width = obj.coords[i][2];
291 var height = obj.coords[i][3];
293 if (mouseX >= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) {
294 canvas.style.cursor = 'pointer';
298 canvas.style.cursor = 'default';
301 this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false);
302 RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func);
306 * If the canvas is annotatable, do install the event handlers
308 if (this.Get('chart.annotatable')) {
309 RGraph.Annotate(this);
313 * This bit shows the mini zoom window if requested
315 if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') {
316 RGraph.ShowZoomWindow(this);
321 * This function enables resizing
323 if (this.Get('chart.resizable')) {
324 RGraph.AllowResizing(this);
328 * Instead of using RGraph.common.adjusting.js, handle them here
330 if (this.Get('chart.adjustable')) {
331 RGraph.AllowAdjusting(this);
335 * Fire the RGraph ondraw event
337 RGraph.FireCustomEvent(this, 'ondraw');
342 * Draw the bar itself
344 RGraph.VProgress.prototype.Drawbar = function ()
346 // Set a shadow if requested
347 if (this.Get('chart.shadow')) {
348 RGraph.SetShadow(this, this.Get('chart.shadow.color'), this.Get('chart.shadow.offsetx'), this.Get('chart.shadow.offsety'), this.Get('chart.shadow.blur'));
351 // Draw the shadow for MSIE
352 if (document.all && this.Get('chart.shadow')) {
353 this.context.fillStyle = this.Get('chart.shadow.color');
354 this.context.fillRect(this.Get('chart.gutter') + this.Get('chart.shadow.offsetx'), this.Get('chart.gutter') + this.Get('chart.shadow.offsety'), this.width, this.height);
358 this.context.fillStyle = this.Get('chart.background.color');
359 this.context.strokeStyle = 'black';
360 this.context.strokeRect(this.Get('chart.gutter'), this.Get('chart.gutter'), this.width, this.height);
361 this.context.fillRect(this.Get('chart.gutter'), this.Get('chart.gutter'), this.width, this.height);
363 // Turn off any shadow
364 RGraph.NoShadow(this);
366 this.context.strokeStyle = 'black';
367 this.context.fillStyle = this.Get('chart.colors')[0];
368 var margin = this.Get('chart.margin');
369 var barHeight = this.canvas.height - this.Get('chart.gutter') - this.Get('chart.gutter');
371 // Draw the actual bar itself
372 if (typeof(this.value) == 'number') {
374 this.context.lineWidth = 1;
375 this.context.strokeStyle = '#999';
377 } else if (typeof(this.value) == 'object') {
379 this.context.beginPath();
380 this.context.strokeStyle = '#999';
382 var startPoint = this.canvas.height - this.Get('chart.gutter');
384 for (var i=0; i<this.value.length; ++i) {
386 var segmentHeight = ( (this.value[i] - this.Get('chart.min')) / (this.max - this.Get('chart.min')) ) * barHeight;
388 this.context.fillStyle = this.Get('chart.colors')[i];
390 this.context.fillRect(this.Get('chart.gutter') + margin, startPoint - segmentHeight, this.width - margin - margin, segmentHeight);
391 this.context.strokeRect(this.Get('chart.gutter') + margin, startPoint - segmentHeight, this.width - margin - margin, segmentHeight);
395 this.coords.push([this.Get('chart.gutter') + margin, startPoint - segmentHeight, this.width - margin - margin, segmentHeight]);
397 startPoint -= segmentHeight;
405 if (this.Get('chart.tickmarks.inner')) {
407 var spacing = (this.canvas.height - this.Get('chart.gutter') - this.Get('chart.gutter')) / this.Get('chart.numticks.inner');
409 this.context.lineWidth = 1;
410 this.context.strokeStyle = '#999';
412 this.context.beginPath();
414 for (var y = this.Get('chart.gutter'); y<this.canvas.height - this.Get('chart.gutter'); y+=spacing) {
415 this.context.moveTo(this.Get('chart.gutter'), y);
416 this.context.lineTo(this.Get('chart.gutter') + 3, y);
418 this.context.moveTo(this.canvas.width - this.Get('chart.gutter'), y);
419 this.context.lineTo(this.canvas.width - this.Get('chart.gutter') - 3, y);
422 this.context.stroke();
426 * Draw the actual bar
428 var barHeight = Math.min(this.height, ( (this.value - this.Get('chart.min')) / (this.max - this.Get('chart.min')) ) * this.height);
430 this.context.beginPath();
431 this.context.strokeStyle = 'black';
433 if (typeof(this.value) == 'number') {
434 this.context.strokeRect(this.Get('chart.gutter') + margin, this.Get('chart.gutter') + this.height - barHeight, this.width - margin - margin, barHeight);
435 this.context.fillRect(this.Get('chart.gutter') + margin, this.Get('chart.gutter') + this.height - barHeight, this.width - margin - margin, barHeight);
440 * Draw the arrows indicating the level if requested
442 if (this.Get('chart.arrows')) {
443 var x = this.Get('chart.gutter') - 4;
444 var y = this.canvas.height - this.Get('chart.gutter') - barHeight;
446 this.context.lineWidth = 1;
447 this.context.fillStyle = 'black';
448 this.context.strokeStyle = 'black';
450 this.context.beginPath();
451 this.context.moveTo(x, y);
452 this.context.lineTo(x - 4, y - 2);
453 this.context.lineTo(x - 4, y + 2);
454 this.context.closePath();
456 this.context.stroke();
461 this.context.beginPath();
462 this.context.moveTo(x, y);
463 this.context.lineTo(x + 4, y - 2);
464 this.context.lineTo(x + 4, y + 2);
465 this.context.closePath();
467 this.context.stroke();
475 * Draw the "in-bar" label
477 if (this.Get('chart.label.inner')) {
478 this.context.beginPath();
479 this.context.fillStyle = 'black';
480 RGraph.Text(this.context, this.Get('chart.text.font'), this.Get('chart.text.size') + 2, this.canvas.width / 2, this.canvas.height - this.Get('chart.gutter') - barHeight - 5, String(this.Get('chart.units.pre') + this.value + this.Get('chart.units.post')), 'bottom', 'center');
486 this.coords.push([this.Get('chart.gutter') + margin, this.Get('chart.gutter') + this.height - barHeight, this.width - margin - margin, barHeight]);
490 * The function that draws the tick marks. Apt name...
492 RGraph.VProgress.prototype.DrawTickMarks = function ()
494 var gutter = this.Get('chart.gutter');
496 this.context.strokeStyle = this.Get('chart.tickmarks.color');
498 if (this.Get('chart.tickmarks')) {
500 var startX = this.Get('chart.labels.position') == 'left' ? (gutter - 4) : (this.canvas.width - gutter);
501 var endX = this.Get('chart.labels.position') == 'left' ? gutter : this.canvas.width - gutter + 4;
503 this.tickInterval = this.height / this.Get('chart.numticks');
505 this.context.beginPath();
506 for (var i=gutter; i<=(this.canvas.height - gutter - this.tickInterval); i+=this.tickInterval) {
507 this.context.moveTo(startX, i);
508 this.context.lineTo(endX, i);
513 //this.context.stroke();
518 * The function that draws the labels
520 RGraph.VProgress.prototype.DrawLabels = function ()
522 this.context.fillStyle = this.Get('chart.text.color');
524 var context = this.context;
525 var gutter = this.Get('chart.gutter');
526 var position = this.Get('chart.labels.position');
527 var xAlignment = position == 'left' ? 'right' : 'left';
528 var yAlignment = 'center';
529 var count = this.Get('chart.labels.count');
530 var units_pre = this.Get('chart.units.pre');
531 var units_post = this.Get('chart.units.post');
532 var text_size = this.Get('chart.text.size');
533 var text_font = this.Get('chart.text.font');
535 if (this.Get('chart.tickmarks')) {
536 for (var i=0; i<count ; ++i) {
539 ((( (this.max - this.Get('chart.min')) / count) * (count - i)) + this.Get('chart.min')).toFixed(this.Get('chart.scale.decimals'))
542 RGraph.Text(context, text_font, text_size, position == 'left' ? (gutter - 5) : (this.canvas.width - gutter + 5), (((this.canvas.height - (2 * gutter)) / count) * i) + gutter, units_pre + text + units_post, yAlignment, xAlignment);
545 if (this.Get('chart.min') != 0) {
546 RGraph.Text(context, text_font, text_size, position == 'left' ? (gutter - 5) : (this.canvas.width - gutter + 5), this.canvas.height - gutter, units_pre + String(this.Get('chart.min').toFixed(this.Get('chart.scale.decimals'))) + units_post, yAlignment, xAlignment);
550 // Draw the title text
551 if (this.Get('chart.title')) {
552 RGraph.DrawTitle(this.canvas, this.Get('chart.title'), this.Get('chart.gutter'), 0, this.Get('chart.text.size') + 2);