source: Dev/trunk/RGraph/libraries/RGraph.hprogress.js @ 201

Last change on this file since 201 was 77, checked in by fpvanagthoven, 14 years ago

RGraph

File size: 22.2 KB
Line 
1    /**
2    * o------------------------------------------------------------------------------o
3    * | This file is part of the RGraph package - you can learn more at:             |
4    * |                                                                              |
5    * |                          http://www.rgraph.net                               |
6    * |                                                                              |
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:  |
10    * |                                                                              |
11    * |                      http://www.rgraph.net/LICENSE.txt                       |
12    * o------------------------------------------------------------------------------o
13    */
14
15    if (typeof(RGraph) == 'undefined') RGraph = {};
16
17    /**
18    * The progress bar constructor
19    *
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
23    */
24    RGraph.HProgress = function (id, value, max)
25    {
26        this.id                = id;
27        this.max               = max;
28        this.value             = value;
29        this.canvas            = document.getElementById(id);
30        this.context           = this.canvas.getContext('2d');
31        this.canvas.__object__ = this;
32        this.type              = 'hprogress';
33        this.coords            = [];
34        this.isRGraph          = true;
35
36
37        /**
38        * Compatibility with older browsers
39        */
40        RGraph.OldBrowserCompat(this.context);
41
42        this.properties = {
43            'chart.min':                0,
44            'chart.colors':             ['#0c0'],
45            'chart.tickmarks':          true,
46            'chart.tickmarks.color':    'black',
47            'chart.tickmarks.inner':    false,
48            'chart.gutter.left':        25,
49            'chart.gutter.right':       25,
50            'chart.gutter.top':         25,
51            'chart.gutter.bottom':      25,
52            'chart.numticks':           10,
53            'chart.numticks.inner':     50,
54            'chart.background.color':   '#eee',
55            'chart.shadow':             false,
56            'chart.shadow.color':       'rgba(0,0,0,0.5)',
57            'chart.shadow.blur':        3,
58            'chart.shadow.offsetx':     3,
59            'chart.shadow.offsety':     3,
60            'chart.title':              '',
61            'chart.title.background':   null,
62            'chart.title.hpos':         null,
63            'chart.title.vpos':         null,
64            'chart.width':              0,
65            'chart.height':             0,
66            'chart.text.size':          10,
67            'chart.text.color':         'black',
68            'chart.text.font':          'Verdana',
69            'chart.contextmenu':        null,
70            'chart.units.pre':          '',
71            'chart.units.post':         '',
72            'chart.tooltips':           [],
73            'chart.tooltips.effect':    'fade',
74            'chart.tooltips.css.class': 'RGraph_tooltip',
75            'chart.tooltips.highlight': true,
76            'chart.highlight.stroke':   'black',
77            'chart.highlight.fill':     'rgba(255,255,255,0.5)',
78            'chart.annotatable':        false,
79            'chart.annotate.color':     'black',
80            'chart.zoom.mode':          'canvas',
81            'chart.zoom.factor':        1.5,
82            'chart.zoom.fade.in':       true,
83            'chart.zoom.fade.out':      true,
84            'chart.zoom.hdir':          'right',
85            'chart.zoom.vdir':          'down',
86            'chart.zoom.frames':        10,
87            'chart.zoom.delay':         50,
88            'chart.zoom.shadow':        true,
89            'chart.zoom.background':    true,
90            'chart.zoom.thumbnail.width': 100,
91            'chart.zoom.thumbnail.height': 100,
92            'chart.arrows':             false,
93            'chart.margin':             0,
94            'chart.resizable':              false,
95            'chart.resize.handle.adjust':   [0,0],
96            'chart.resize.handle.background': null,
97            'chart.label.inner':        false,
98            'chart.adjustable':         false,
99            'chart.scale.decimals':     0,
100            'chart.key':                [],
101            'chart.key.background':     'white',
102            'chart.key.position':       'gutter',
103            'chart.key.halign':             'right',
104            'chart.key.shadow':         false,
105            'chart.key.shadow.color':   '#666',
106            'chart.key.shadow.blur':    3,
107            'chart.key.shadow.offsetx': 2,
108            'chart.key.shadow.offsety': 2,
109            'chart.key.position.gutter.boxed': false,
110            'chart.key.position.x':     null,
111            'chart.key.position.y':     null,
112            'chart.key.color.shape':    'square',
113            'chart.key.rounded':        true,
114            'chart.key.linewidth':      1,
115            'chart.key.color.shape':    'square',
116            'chart.labels.position':     'bottom'
117        }
118
119        // Check for support
120        if (!this.canvas) {
121            alert('[PROGRESS] No canvas support');
122            return;
123        }
124    }
125
126
127    /**
128    * A generic setter
129    *
130    * @param string name  The name of the property to set
131    * @param string value The value of the poperty
132    */
133    RGraph.HProgress.prototype.Set = function (name, value)
134    {
135        this.properties[name.toLowerCase()] = value;
136    }
137
138
139    /**
140    * A generic getter
141    *
142    * @param string name  The name of the property to get
143    */
144    RGraph.HProgress.prototype.Get = function (name)
145    {
146        return this.properties[name.toLowerCase()];
147    }
148
149
150    /**
151    * Draws the progress bar
152    */
153    RGraph.HProgress.prototype.Draw = function ()
154    {
155        /**
156        * Fire the onbeforedraw event
157        */
158        RGraph.FireCustomEvent(this, 'onbeforedraw');
159
160        /**
161        * Clear all of this canvases event handlers (the ones installed by RGraph)
162        */
163        RGraph.ClearEventListeners(this.id);
164       
165        /**
166        * This is new in May 2011 and facilitates indiviual gutter settings,
167        * eg chart.gutter.left
168        */
169        this.gutterLeft   = this.Get('chart.gutter.left');
170        this.gutterRight  = this.Get('chart.gutter.right');
171        this.gutterTop    = this.Get('chart.gutter.top');
172        this.gutterBottom = this.Get('chart.gutter.bottom');
173
174        // Figure out the width and height
175        this.width  = RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight;
176        this.height = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom;
177        this.coords = [];
178
179        this.Drawbar();
180        this.DrawTickMarks();
181        this.DrawLabels();
182
183        this.context.stroke();
184        this.context.fill();
185
186        /**
187        * Setup the context menu if required
188        */
189        if (this.Get('chart.contextmenu')) {
190            RGraph.ShowContext(this);
191        }
192       
193        /**
194        * Alternatively, show the tooltip if requested
195        */
196        if (typeof(this.Get('chart.tooltips')) == 'function' || this.Get('chart.tooltips').length) {
197
198            // Need to register this object for redrawing
199            RGraph.Register(this);
200
201            /**
202            * Install the window onclick handler
203            */
204            var window_onclick = function ()
205            {
206                RGraph.Redraw();
207            }
208            window.addEventListener('click', window_onclick, false);
209            RGraph.AddEventListener('window_' + this.id, 'click', window_onclick);
210
211
212            /**
213            * Install the onclick event handler for the tooltips
214            */
215            var canvas_onclick_func = function (e)
216            {
217                e = RGraph.FixEventObject(e);
218
219                var canvas = document.getElementById(this.id);
220                var obj = canvas.__object__;
221
222                /**
223                * Redraw the graph first, in effect resetting the graph to as it was when it was first drawn
224                * This "deselects" any already selected bar
225                */
226                RGraph.Redraw();
227   
228                /**
229                * Get the mouse X/Y coordinates
230                */
231                var mouseCoords = RGraph.getMouseXY(e);
232
233                /**
234                * Loop through the bars determining if the mouse is over a bar
235                */
236                for (var i=0; i<obj.coords.length; i++) {
237
238                    var mouseX = mouseCoords[0];
239                    var mouseY = mouseCoords[1];
240                    var left   = obj.coords[i][0];
241                    var top    = obj.coords[i][1];
242                    var width  = obj.coords[i][2];
243                    var height = obj.coords[i][3];
244                    var idx    = i;
245
246                    if (mouseX >= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) {
247   
248                        /**
249                        * Get the tooltip text
250                        */
251                        if (typeof(obj.Get('chart.tooltips')) == 'function') {
252                            var text = obj.Get('chart.tooltips')(idx);
253                       
254                        } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') {
255                            var text = obj.Get('chart.tooltips')[idx](idx);
256                       
257                        } else if (typeof(obj.Get('chart.tooltips')) == 'object') {
258                            var text = obj.Get('chart.tooltips')[idx];
259
260                        } else {
261                            var text = null;
262                        }
263
264                        /**
265                        * Show a tooltip if it's defined
266                        */
267                        if (text) {
268
269                            obj.context.beginPath();
270                            obj.context.strokeStyle = obj.Get('chart.highlight.stroke');
271                            obj.context.fillStyle   = obj.Get('chart.highlight.fill');
272                            obj.context.strokeRect(left, top, width, height);
273                            obj.context.fillRect(left, top, width, height);
274       
275                            obj.context.stroke();
276                            obj.context.fill();
277
278                            RGraph.Tooltip(canvas, text, e.pageX, e.pageY, i);
279                        }
280                    }
281                }
282
283                /**
284                * Stop the event bubbling
285                */
286                e.stopPropagation();
287            }
288            this.canvas.addEventListener('click', canvas_onclick_func, false);
289            RGraph.AddEventListener(this.id, 'click', canvas_onclick_func);
290
291            /**
292            * If the cursor is over a hotspot, change the cursor to a hand
293            */
294            var canvas_onmousemove_func = function (e)
295            {
296                e = RGraph.FixEventObject(e);
297
298                var canvas = document.getElementById(this.id);
299                var obj = canvas.__object__;
300
301                /**
302                * Get the mouse X/Y coordinates
303                */
304                var mouseCoords = RGraph.getMouseXY(e);
305
306                /**
307                * Loop through the bars determining if the mouse is over a bar
308                */
309                for (var i=0; i<obj.coords.length; i++) {
310
311                    var mouseX = mouseCoords[0];  // In relation to the canvas
312                    var mouseY = mouseCoords[1];  // In relation to the canvas
313                    var left   = obj.coords[i][0];
314                    var top    = obj.coords[i][1];
315                    var width  = obj.coords[i][2];
316                    var height = obj.coords[i][3];
317
318                    if (mouseX >= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) {
319                        canvas.style.cursor = 'pointer';
320                        break;
321                    }
322                   
323                    canvas.style.cursor = 'default';
324                }
325            }
326            this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false);
327            RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func);
328        }
329       
330        /**
331        * If the canvas is annotatable, do install the event handlers
332        */
333        if (this.Get('chart.annotatable')) {
334            RGraph.Annotate(this);
335        }
336
337
338        // Draw the key if necessary
339        if (this.Get('chart.key').length) {
340            RGraph.DrawKey(this, this.Get('chart.key'), this.Get('chart.colors'));
341        }
342       
343        /**
344        * This bit shows the mini zoom window if requested
345        */
346        if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') {
347            RGraph.ShowZoomWindow(this);
348        }
349
350       
351        /**
352        * This function enables resizing
353        */
354        if (this.Get('chart.resizable')) {
355            RGraph.AllowResizing(this);
356        }
357       
358        /**
359        * Instead of using RGraph.common.adjusting.js, handle them here
360        */
361        if (this.Get('chart.adjustable')) {
362            RGraph.AllowAdjusting(this);
363        }
364       
365        /**
366        * Fire the RGraph ondraw event
367        */
368        RGraph.FireCustomEvent(this, 'ondraw');
369    }
370
371    /**
372    * Draws the bar
373    */
374    RGraph.HProgress.prototype.Drawbar = function ()
375    {
376        // Set a shadow if requested
377        if (this.Get('chart.shadow')) {
378            RGraph.SetShadow(this, this.Get('chart.shadow.color'), this.Get('chart.shadow.offsetx'), this.Get('chart.shadow.offsety'), this.Get('chart.shadow.blur'));
379        }
380
381        // Draw the shadow for MSIE
382        if (RGraph.isIE8() && this.Get('chart.shadow')) {
383            this.context.fillStyle = this.Get('chart.shadow.color');
384            this.context.fillRect(this.gutterLeft + this.Get('chart.shadow.offsetx'), this.gutterTop + this.Get('chart.shadow.offsety'), this.width, this.height);
385        }
386
387        // Draw the outline
388        this.context.fillStyle   = this.Get('chart.background.color');
389        this.context.strokeStyle = 'black';
390        this.context.strokeRect(this.gutterLeft, this.gutterTop, this.width, this.height);
391        this.context.fillRect(this.gutterLeft, this.gutterTop, this.width, this.height);
392
393        // Turn off any shadow
394        RGraph.NoShadow(this);
395
396        this.context.fillStyle   = this.Get('chart.color');
397        this.context.strokeStyle = 'black';
398       
399        var margin = this.Get('chart.margin');
400
401        // Draw the actual bar itself
402        var barWidth = Math.min(this.width, ((RGraph.array_sum(this.value) - this.Get('chart.min')) / (this.max - this.Get('chart.min')) ) * this.width);
403
404        if (this.Get('chart.tickmarks.inner')) {
405
406            var spacing = (RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight) / this.Get('chart.numticks.inner');
407
408            this.context.lineWidth   = 1;
409            this.context.strokeStyle = '#999';
410
411            this.context.beginPath();
412            for (var x = this.gutterLeft; x<RGraph.GetWidth(this) - this.gutterRight; x+=spacing) {
413                this.context.moveTo(x, this.gutterTop);
414                this.context.lineTo(x, this.gutterTop + 2);
415
416                this.context.moveTo(x, RGraph.GetHeight(this) - this.gutterBottom);
417                this.context.lineTo(x, RGraph.GetHeight(this) - this.gutterBottom - 2);
418            }
419            this.context.stroke();
420        }
421       
422        /**
423        * This bit draws the actual progress bar
424        */
425        if (typeof(this.value) == 'number') {
426            this.context.beginPath();
427            this.context.strokeStyle = 'black';
428            this.context.fillStyle = this.Get('chart.colors')[0];
429            this.context.strokeRect(this.gutterLeft, this.gutterTop + margin, barWidth, this.height - margin - margin);
430            this.context.fillRect(this.gutterLeft, this.gutterTop + margin, barWidth, this.height - margin - margin);
431
432            // Store the coords
433            this.coords.push([this.gutterLeft,
434                              this.gutterTop + margin,
435                              barWidth,
436                              this.height - margin - margin]);
437
438        } else if (typeof(this.value) == 'object') {
439
440            this.context.beginPath();
441            this.context.strokeStyle = 'black';
442
443            var startPoint = this.gutterLeft;
444           
445            for (var i=0; i<this.value.length; ++i) {
446
447                var segmentLength = (this.value[i] / RGraph.array_sum(this.value)) * barWidth;
448                this.context.fillStyle = this.Get('chart.colors')[i];
449
450                this.context.strokeRect(startPoint, this.gutterTop + margin, segmentLength, this.height - margin - margin);
451                this.context.fillRect(startPoint, this.gutterTop + margin, segmentLength, this.height - margin - margin);
452
453
454                // Store the coords
455                this.coords.push([startPoint,
456                                  this.gutterTop + margin,
457                                  segmentLength,
458                                  this.height - margin - margin]);
459
460                startPoint += segmentLength;
461            }
462        }
463
464        /**
465        * Draw the arrows indicating the level if requested
466        */
467        if (this.Get('chart.arrows')) {
468            var x = this.gutterLeft + barWidth;
469            var y = this.gutterTop;
470           
471            this.context.lineWidth = 1;
472            this.context.fillStyle = 'black';
473            this.context.strokeStyle = 'black';
474
475            this.context.beginPath();
476                this.context.moveTo(x, y - 3);
477                this.context.lineTo(x + 2, y - 7);
478                this.context.lineTo(x - 2, y - 7);
479            this.context.closePath();
480
481            this.context.stroke();
482            this.context.fill();
483
484            this.context.beginPath();
485                this.context.moveTo(x, y + this.height + 4);
486                this.context.lineTo(x + 2, y + this.height + 9);
487                this.context.lineTo(x - 2, y + this.height + 9);
488            this.context.closePath();
489
490            this.context.stroke();
491            this.context.fill()
492
493
494            /**
495            * Draw the "in-bar" label
496            */
497            if (this.Get('chart.label.inner')) {
498                this.context.beginPath();
499                this.context.fillStyle = 'black';
500                RGraph.Text(this.context, this.Get('chart.text.font'), this.Get('chart.text.size') + 2, this.gutterLeft + barWidth + 5, RGraph.GetHeight(this) / 2, String(this.Get('chart.units.pre') + this.value + this.Get('chart.units.post')), 'center', 'left');
501                this.context.fill();
502            }
503        }
504
505    }
506
507    /**
508    * The function that draws the tick marks. Apt name...
509    */
510    RGraph.HProgress.prototype.DrawTickMarks = function ()
511    {
512        var context = this.context;
513
514        context.strokeStyle = this.Get('chart.tickmarks.color');
515
516        if (this.Get('chart.tickmarks')) {
517           
518            this.context.beginPath();       
519
520            // This is used by the label function below
521            this.tickInterval = this.width / this.Get('chart.numticks');
522           
523            var start   = this.Get('chart.tickmarks.zerostart') ? 0 : this.tickInterval;
524
525            if (this.Get('chart.labels.position') == 'top') {
526                for (var i=this.gutterLeft + start; i<=(this.width + this.gutterLeft + 0.1); i+=this.tickInterval) {
527                    context.moveTo(i, this.gutterTop);
528                    context.lineTo(i, this.gutterTop - 4);
529                }
530
531            } else {
532
533                for (var i=this.gutterLeft + start; i<=(this.width + this.gutterLeft + 0.1); i+=this.tickInterval) {
534                    context.moveTo(i, this.gutterTop + this.height);
535                    context.lineTo(i, this.gutterTop + this.height + 4);
536                }
537            }
538
539            this.context.stroke();
540        }
541    }
542
543
544    /**
545    * The function that draws the labels
546    */
547    RGraph.HProgress.prototype.DrawLabels = function ()
548    {
549        var context = this.context;
550        this.context.fillStyle = this.Get('chart.text.color');
551
552        var xPoints = [];
553        var yPoints = [];
554
555        for (i=0; i<this.Get('chart.numticks'); i++) {
556
557            var font       = this.Get('chart.text.font');
558            var size       = this.Get('chart.text.size');
559
560            if (this.Get('chart.labels.position') == 'top') {
561                var x = this.width * (i/this.Get('chart.numticks')) + this.gutterLeft + (this.width / this.Get('chart.numticks'));
562                var y = this.gutterTop - 6;
563                var valign = 'bottom';
564            } else {
565                var x = this.width * (i/this.Get('chart.numticks')) + this.gutterLeft + (this.width / this.Get('chart.numticks'));
566                var y = this.height + this.gutterTop + 4;
567                var valign = 'top';
568            }
569               
570            RGraph.Text(this.context,font,size,x,y,this.Get('chart.units.pre') + String((((this.max - this.Get('chart.min')) / this.Get('chart.numticks') ) * (i + 1) + this.Get('chart.min')).toFixed(this.Get('chart.scale.decimals'))) + this.Get('chart.units.post'),valign,'center');
571        }
572
573        if (this.Get('chart.tickmarks.zerostart')) {
574            if (this.Get('chart.labels.position') == 'top') {
575                RGraph.Text(this.context,font,size,this.gutterLeft,this.gutterTop - 6,this.Get('chart.units.pre') + Number(this.Get('chart.min')).toFixed(this.Get('chart.scale.decimals')) + this.Get('chart.units.post'),'bottom','center');
576            } else {
577                RGraph.Text(this.context,font,size,this.gutterLeft,this.canvas.height - this.gutterBottom + 5,this.Get('chart.units.pre') + Number(this.Get('chart.min')).toFixed(this.Get('chart.scale.decimals')) + this.Get('chart.units.post'),'top','center');
578            }
579        }
580
581
582
583        // Draw the title text
584        if (this.Get('chart.title')) {
585            RGraph.DrawTitle(this.canvas,
586                             this.Get('chart.title'),
587                             this.gutterTop + this.Get('chart.text.size'),
588                             0,
589                             this.Get('chart.text.size') + 2);
590        }
591    }
Note: See TracBrowser for help on using the repository browser.