source: Dev/trunk/RGraph/libraries/RGraph.vprogress.js @ 77

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

RGraph

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