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.HProgress = 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 = 'hprogress';
38 * Compatibility with older browsers
40 RGraph.OldBrowserCompat(this.context);
44 'chart.colors': ['#0c0'],
45 'chart.tickmarks': true,
46 'chart.tickmarks.color': 'black',
47 'chart.tickmarks.inner': false,
50 'chart.numticks.inner': 50,
51 'chart.background.color': '#eee',
52 'chart.shadow': false,
53 'chart.shadow.color': 'rgba(0,0,0,0.5)',
54 'chart.shadow.blur': 3,
55 'chart.shadow.offsetx': 3,
56 'chart.shadow.offsety': 3,
58 'chart.title.background': null,
59 'chart.title.hpos': null,
60 'chart.title.vpos': null,
63 'chart.text.size': 10,
64 'chart.text.color': 'black',
65 'chart.text.font': 'Verdana',
66 'chart.contextmenu': null,
67 'chart.units.pre': '',
68 'chart.units.post': '',
70 'chart.tooltips.effect': 'fade',
71 'chart.tooltips.css.class': 'RGraph_tooltip',
72 'chart.tooltips.highlight': true,
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.thumbnail.width': 100,
86 'chart.zoom.thumbnail.height': 100,
87 'chart.arrows': false,
89 'chart.resizable': false,
90 'chart.label.inner': false,
91 'chart.adjustable': false,
92 'chart.scale.decimals': 0
97 alert('[PROGRESS] No canvas support');
101 // Check the common library has been included
102 if (typeof(RGraph) == 'undefined') {
103 alert('[PROGRESS] Fatal error: The common library does not appear to have been included');
111 * @param string name The name of the property to set
112 * @param string value The value of the poperty
114 RGraph.HProgress.prototype.Set = function (name, value)
116 this.properties[name.toLowerCase()] = value;
123 * @param string name The name of the property to get
125 RGraph.HProgress.prototype.Get = function (name)
127 return this.properties[name.toLowerCase()];
132 * Draws the progress bar
134 RGraph.HProgress.prototype.Draw = function ()
137 * Fire the onbeforedraw event
139 RGraph.FireCustomEvent(this, 'onbeforedraw');
142 * Clear all of this canvases event handlers (the ones installed by RGraph)
144 RGraph.ClearEventListeners(this.id);
146 // Figure out the width and height
147 this.width = this.canvas.width - (2 * this.Get('chart.gutter'));
148 this.height = this.canvas.height - (2 * this.Get('chart.gutter'));
152 this.DrawTickMarks();
155 this.context.stroke();
159 * Setup the context menu if required
161 if (this.Get('chart.contextmenu')) {
162 RGraph.ShowContext(this);
166 * Alternatively, show the tooltip if requested
168 if (typeof(this.Get('chart.tooltips')) == 'function' || this.Get('chart.tooltips').length) {
170 // Need to register this object for redrawing
171 RGraph.Register(this);
174 * Install the window onclick handler
176 window.onclick = function ()
183 * Install the onclick event handler for the tooltips
185 var canvas_onclick_func = function (e)
187 e = RGraph.FixEventObject(e);
189 var canvas = document.getElementById(this.id);
190 var obj = canvas.__object__;
193 * Redraw the graph first, in effect resetting the graph to as it was when it was first drawn
194 * This "deselects" any already selected bar
199 * Get the mouse X/Y coordinates
201 var mouseCoords = RGraph.getMouseXY(e);
204 * Loop through the bars determining if the mouse is over a bar
206 for (var i=0; i<obj.coords.length; i++) {
208 var mouseX = mouseCoords[0];
209 var mouseY = mouseCoords[1];
210 var left = obj.coords[i][0];
211 var top = obj.coords[i][1];
212 var width = obj.coords[i][2];
213 var height = obj.coords[i][3];
216 if (mouseX >= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) {
219 * Get the tooltip text
221 if (typeof(obj.Get('chart.tooltips')) == 'function') {
222 var text = obj.Get('chart.tooltips')(idx);
224 } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') {
225 var text = obj.Get('chart.tooltips')[idx](idx);
227 } else if (typeof(obj.Get('chart.tooltips')) == 'object') {
228 var text = obj.Get('chart.tooltips')[idx];
235 * Show a tooltip if it's defined
239 obj.context.beginPath();
240 obj.context.strokeStyle = 'black';
241 obj.context.fillStyle = 'rgba(255,255,255,0.5)';
242 obj.context.strokeRect(left, top, width, height);
243 obj.context.fillRect(left, top, width, height);
245 obj.context.stroke();
248 RGraph.Tooltip(canvas, text, e.pageX, e.pageY, i);
254 * Stop the event bubbling
258 this.canvas.addEventListener('click', canvas_onclick_func, false);
259 RGraph.AddEventListener(this.id, 'click', canvas_onclick_func);
262 * If the cursor is over a hotspot, change the cursor to a hand
264 var canvas_onmousemove_func = function (e)
266 e = RGraph.FixEventObject(e);
268 var canvas = document.getElementById(this.id);
269 var obj = canvas.__object__;
272 * Get the mouse X/Y coordinates
274 var mouseCoords = RGraph.getMouseXY(e);
277 * Loop through the bars determining if the mouse is over a bar
279 for (var i=0; i<obj.coords.length; i++) {
281 var mouseX = mouseCoords[0]; // In relation to the canvas
282 var mouseY = mouseCoords[1]; // In relation to the canvas
283 var left = obj.coords[i][0];
284 var top = obj.coords[i][1];
285 var width = obj.coords[i][2];
286 var height = obj.coords[i][3];
288 if (mouseX >= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) {
289 canvas.style.cursor = 'pointer';
293 canvas.style.cursor = 'default';
296 this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false);
297 RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func);
301 * If the canvas is annotatable, do install the event handlers
303 if (this.Get('chart.annotatable')) {
304 RGraph.Annotate(this);
308 * This bit shows the mini zoom window if requested
310 if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') {
311 RGraph.ShowZoomWindow(this);
316 * This function enables resizing
318 if (this.Get('chart.resizable')) {
319 RGraph.AllowResizing(this);
323 * Instead of using RGraph.common.adjusting.js, handle them here
325 if (this.Get('chart.adjustable')) {
326 RGraph.AllowAdjusting(this);
330 * Fire the RGraph ondraw event
332 RGraph.FireCustomEvent(this, 'ondraw');
338 RGraph.HProgress.prototype.Drawbar = function ()
340 // Set a shadow if requested
341 if (this.Get('chart.shadow')) {
342 RGraph.SetShadow(this, this.Get('chart.shadow.color'), this.Get('chart.shadow.offsetx'), this.Get('chart.shadow.offsety'), this.Get('chart.shadow.blur'));
345 // Draw the shadow for MSIE
346 if (RGraph.isIE8() && this.Get('chart.shadow')) {
347 this.context.fillStyle = this.Get('chart.shadow.color');
348 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);
352 this.context.fillStyle = this.Get('chart.background.color');
353 this.context.strokeStyle = 'black';
354 this.context.strokeRect(this.Get('chart.gutter'), this.Get('chart.gutter'), this.width, this.height);
355 this.context.fillRect(this.Get('chart.gutter'), this.Get('chart.gutter'), this.width, this.height);
357 // Turn off any shadow
358 RGraph.NoShadow(this);
360 this.context.fillStyle = this.Get('chart.color');
361 this.context.strokeStyle = 'black';
363 var margin = this.Get('chart.margin');
365 // Draw the actual bar itself
366 var barWidth = Math.min(this.width, ((RGraph.array_sum(this.value) - this.Get('chart.min')) / (this.max - this.Get('chart.min')) ) * this.width);
368 if (this.Get('chart.tickmarks.inner')) {
370 var spacing = (this.canvas.width - this.Get('chart.gutter') - this.Get('chart.gutter')) / this.Get('chart.numticks.inner');
372 this.context.lineWidth = 1;
373 this.context.strokeStyle = '#999';
375 this.context.beginPath();
376 for (var x = this.Get('chart.gutter'); x<this.canvas.width - this.Get('chart.gutter'); x+=spacing) {
377 this.context.moveTo(x, this.Get('chart.gutter'));
378 this.context.lineTo(x, this.Get('chart.gutter') + 2);
380 this.context.moveTo(x, this.canvas.height - this.Get('chart.gutter'));
381 this.context.lineTo(x, this.canvas.height - this.Get('chart.gutter') - 2);
383 this.context.stroke();
387 * This bit draws the actual progress bar
389 if (typeof(this.value) == 'number') {
390 this.context.beginPath();
391 this.context.strokeStyle = 'black';
392 this.context.fillStyle = this.Get('chart.colors')[0];
393 this.context.strokeRect(this.Get('chart.gutter'), this.Get('chart.gutter') + margin, barWidth, this.height - margin - margin);
394 this.context.fillRect(this.Get('chart.gutter'), this.Get('chart.gutter') + margin, barWidth, this.height - margin - margin);
397 this.coords.push([this.Get('chart.gutter'),
398 this.Get('chart.gutter') + margin,
400 this.height - margin - margin]);
402 } else if (typeof(this.value) == 'object') {
404 this.context.beginPath();
405 this.context.strokeStyle = 'black';
407 var startPoint = this.Get('chart.gutter');
409 for (var i=0; i<this.value.length; ++i) {
411 var segmentLength = (this.value[i] / RGraph.array_sum(this.value)) * barWidth;
412 this.context.fillStyle = this.Get('chart.colors')[i];
414 this.context.strokeRect(startPoint, this.Get('chart.gutter') + margin, segmentLength, this.height - margin - margin);
415 this.context.fillRect(startPoint, this.Get('chart.gutter') + margin, segmentLength, this.height - margin - margin);
419 this.coords.push([startPoint,
420 this.Get('chart.gutter') + margin,
422 this.height - margin - margin]);
424 startPoint += segmentLength;
429 * Draw the arrows indicating the level if requested
431 if (this.Get('chart.arrows')) {
432 var x = this.Get('chart.gutter') + barWidth;
433 var y = this.Get('chart.gutter');
435 this.context.lineWidth = 1;
436 this.context.fillStyle = 'black';
437 this.context.strokeStyle = 'black';
439 this.context.beginPath();
440 this.context.moveTo(x, y - 3);
441 this.context.lineTo(x + 2, y - 7);
442 this.context.lineTo(x - 2, y - 7);
443 this.context.closePath();
445 this.context.stroke();
448 this.context.beginPath();
449 this.context.moveTo(x, y + this.height + 4);
450 this.context.lineTo(x + 2, y + this.height + 9);
451 this.context.lineTo(x - 2, y + this.height + 9);
452 this.context.closePath();
454 this.context.stroke();
459 * Draw the "in-bar" label
461 if (this.Get('chart.label.inner')) {
462 this.context.beginPath();
463 this.context.fillStyle = 'black';
464 RGraph.Text(this.context, this.Get('chart.text.font'), this.Get('chart.text.size') + 2, this.Get('chart.gutter') + barWidth + 5, this.canvas.height / 2, String(this.Get('chart.units.pre') + this.value + this.Get('chart.units.post')), 'center', 'left');
472 * The function that draws the tick marks. Apt name...
474 RGraph.HProgress.prototype.DrawTickMarks = function ()
476 var context = this.context;
477 var gutter = this.Get('chart.gutter');
479 context.strokeStyle = this.Get('chart.tickmarks.color');
481 if (this.Get('chart.tickmarks')) {
483 this.context.beginPath();
485 // This is used by the label function below
486 this.tickInterval = this.width / this.Get('chart.numticks');
488 if (this.Get('chart.labels.position') == 'top') {
489 for (var i=gutter + this.tickInterval; i<=(this.width + gutter); i+=this.tickInterval) {
490 context.moveTo(i, gutter);
491 context.lineTo(i, gutter - 4);
496 for (var i=gutter + this.tickInterval; i<=(this.width + gutter); i+=this.tickInterval) {
497 context.moveTo(i, gutter + this.height);
498 context.lineTo(i, gutter + this.height + 4);
502 this.context.stroke();
508 * The function that draws the labels
510 RGraph.HProgress.prototype.DrawLabels = function ()
512 var context = this.context;
513 this.context.fillStyle = this.Get('chart.text.color');
518 for (i=this.Get('chart.gutter') + this.tickInterval; i <= (this.Get('chart.gutter') + this.width); i+= this.tickInterval) {
520 yPoints.push(this.Get('chart.gutter') + this.height + 4);
523 var font = this.Get('chart.text.font');
524 var size = this.Get('chart.text.size');
526 this.context.beginPath();
528 if (this.Get('chart.labels.position') == 'top') {
529 for (i=0; i<xPoints.length; ++i) {
530 RGraph.Text(context,font,size,xPoints[i],yPoints[i] - this.height - 4 - 4 - 2,this.Get('chart.units.pre') + String((((this.max - this.Get('chart.min')) / xPoints.length) * (i + 1) + this.Get('chart.min')).toFixed(this.Get('chart.scale.decimals'))) + this.Get('chart.units.post'),'bottom','center');
535 for (i=0; i<xPoints.length; ++i) {
536 RGraph.Text(this.context,font,size,xPoints[i],yPoints[i],this.Get('chart.units.pre') + String((((this.max - this.Get('chart.min')) / xPoints.length) * (i + 1) + this.Get('chart.min')).toFixed(this.Get('chart.scale.decimals'))) + this.Get('chart.units.post'),'top','center');
541 // Draw the title text
542 if (this.Get('chart.title')) {
543 RGraph.DrawTitle(this.canvas, this.Get('chart.title'), this.Get('chart.gutter'), 0, this.Get('chart.text.size') + 2);