source: Dev/branches/jQueryUI/client/RGraph/libraries/RGraph.hbar.js @ 249

Last change on this file since 249 was 249, checked in by hendrikvanantwerpen, 13 years ago

This one's for Subversion, because it's so close...

First widget (stripped down sequencer).
Seperated client and server code in two direcotry trees.

File size: 40.8 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 horizontal bar chart constructor. The horizontal bar is a minor variant
19    * on the bar chart. If you have big labels, this may be useful as there is usually
20    * more space available for them.
21    *
22    * @param object canvas The canvas object
23    * @param array  data   The chart data
24    */
25    RGraph.HBar = function (id, data)
26    {
27        // Get the canvas and context objects
28        this.id                = id;
29        this.canvas            = document.getElementById(id);
30        this.context           = this.canvas.getContext ? this.canvas.getContext("2d") : null;
31        this.canvas.__object__ = this;
32        this.data              = data;
33        this.type              = 'hbar';
34        this.coords            = [];
35        this.isRGraph          = true;
36
37
38        /**
39        * Compatibility with older browsers
40        */
41        RGraph.OldBrowserCompat(this.context);
42
43       
44        this.max = 0;
45        this.stackedOrGrouped  = false;
46
47        // Default properties
48        this.properties = {
49            'chart.gutter.left':            75,
50            'chart.gutter.right':           25,
51            'chart.gutter.top':             35,
52            'chart.gutter.bottom':          25,
53            'chart.background.grid':        true,
54            'chart.background.grid.color':  '#ddd',
55            'chart.background.grid.width':  1,
56            'chart.background.grid.hsize':  25,
57            'chart.background.grid.vsize':  25,
58            'chart.background.barcolor1':   'white',
59            'chart.background.barcolor2':   'white',
60            'chart.background.grid.hlines': true,
61            'chart.background.grid.vlines': true,
62            'chart.background.grid.border': true,
63            'chart.background.grid.autofit':false,
64            'chart.background.grid.autofit.numhlines': 14,
65            'chart.background.grid.autofit.numvlines': 20,
66            'chart.title':                  '',
67            'chart.title.background':       null,
68            'chart.title.xaxis':            '',
69            'chart.title.yaxis':            '',
70            'chart.title.xaxis.pos':        0.25,
71            'chart.title.yaxis.pos':        10,
72            'chart.title.hpos':             null,
73            'chart.title.vpos':             null,
74            'chart.text.size':              10,
75            'chart.text.color':             'black',
76            'chart.text.font':              'Verdana',
77            'chart.colors':                 ['red', 'blue', 'green', 'pink', 'yellow', 'cyan', 'navy', 'gray', 'black'],
78            'chart.labels':                 [],
79            'chart.labels.above':           false,
80            'chart.labels.above.decimals':  0,
81            'chart.xlabels':                true,
82            'chart.contextmenu':            null,
83            'chart.key':                    [],
84            'chart.key.background':         'white',
85            'chart.key.position':           'graph',
86            'chart.key.halign':             'right',
87            'chart.key.shadow':             false,
88            'chart.key.shadow.color':       '#666',
89            'chart.key.shadow.blur':        3,
90            'chart.key.shadow.offsetx':     2,
91            'chart.key.shadow.offsety':     2,
92            'chart.key.position.gutter.boxed': true,
93            'chart.key.position.x':         null,
94            'chart.key.position.y':         null,
95            'chart.key.color.shape':        'square',
96            'chart.key.rounded':            true,
97            'chart.key.linewidth':          1,
98            'chart.units.pre':              '',
99            'chart.units.post':             '',
100            'chart.units.ingraph':          false,
101            'chart.strokestyle':            'black',
102            'chart.xmin':                   0,
103            'chart.xmax':                   0,
104            'chart.axis.color':             'black',
105            'chart.shadow':                 false,
106            'chart.shadow.color':           '#666',
107            'chart.shadow.blur':            3,
108            'chart.shadow.offsetx':         3,
109            'chart.shadow.offsety':         3,
110            'chart.vmargin':                3,
111            'chart.grouping':               'grouped',
112            'chart.tooltips':               null,
113            'chart.tooltips.event':         'onclick',
114            'chart.tooltips.effect':        'fade',
115            'chart.tooltips.css.class':     'RGraph_tooltip',
116            'chart.tooltips.highlight':     true,
117            'chart.highlight.fill':         'rgba(255,255,255,0.5)',
118            'chart.highlight.stroke':       'black',
119            'chart.annotatable':            false,
120            'chart.annotate.color':         'black',
121            'chart.zoom.factor':            1.5,
122            'chart.zoom.fade.in':           true,
123            'chart.zoom.fade.out':          true,
124            'chart.zoom.hdir':              'right',
125            'chart.zoom.vdir':              'down',
126            'chart.zoom.frames':            10,
127            'chart.zoom.delay':             50,
128            'chart.zoom.shadow':            true,
129            'chart.zoom.mode':              'canvas',
130            'chart.zoom.thumbnail.width':   75,
131            'chart.zoom.thumbnail.height':  75,
132            'chart.zoom.background':        true,
133            'chart.zoom.action':            'zoom',
134            'chart.resizable':              false,
135            'chart.resize.handle.adjust':   [0,0],
136            'chart.resize.handle.background': null,
137            'chart.scale.point':            '.',
138            'chart.scale.thousand':         ',',
139            'chart.scale.decimals':         null,
140            'chart.noredraw':               false
141        }
142
143        // Check for support
144        if (!this.canvas) {
145            alert('[HBAR] No canvas support');
146            return;
147        }
148
149        for (i=0; i<this.data.length; ++i) {
150            if (typeof(this.data[i]) == 'object') {
151                this.stackedOrGrouped = true;
152            }
153        }
154
155
156        /**
157        * Set the .getShape commonly named method
158        */
159        this.getShape = this.getBar;
160    }
161
162
163    /**
164    * A setter
165    *
166    * @param name  string The name of the property to set
167    * @param value mixed  The value of the property
168    */
169    RGraph.HBar.prototype.Set = function (name, value)
170    {
171        if (name == 'chart.labels.abovebar') {
172            name = 'chart.labels.above';
173        }
174
175        this.properties[name.toLowerCase()] = value;
176    }
177
178
179    /**
180    * A getter
181    *
182    * @param name  string The name of the property to get
183    */
184    RGraph.HBar.prototype.Get = function (name)
185    {
186        if (name == 'chart.labels.abovebar') {
187            name = 'chart.labels.above';
188        }
189
190        return this.properties[name];
191    }
192
193
194    /**
195    * The function you call to draw the bar chart
196    */
197    RGraph.HBar.prototype.Draw = function ()
198    {
199        /**
200        * Fire the onbeforedraw event
201        */
202        RGraph.FireCustomEvent(this, 'onbeforedraw');
203
204
205        /**
206        * Clear all of this canvases event handlers (the ones installed by RGraph)
207        */
208        RGraph.ClearEventListeners(this.id);
209       
210        /**
211        * This is new in May 2011 and facilitates indiviual gutter settings,
212        * eg chart.gutter.left
213        */
214        this.gutterLeft   = this.Get('chart.gutter.left');
215        this.gutterRight  = this.Get('chart.gutter.right');
216        this.gutterTop    = this.Get('chart.gutter.top');
217        this.gutterBottom = this.Get('chart.gutter.bottom');
218
219        /**
220        * Stop the coords array from growing uncontrollably
221        */
222        this.coords = [];
223        this.max    = 0;
224
225        /**
226        * Check for chart.xmin in stacked charts
227        */
228        if (this.Get('chart.xmin') > 0 && this.Get('chart.grouping') == 'stacked') {
229            alert('[HBAR] Using chart.xmin is not supported with stacked charts, resetting chart.xmin to zero');
230            this.Set('chart.xmin', 0);
231        }
232
233        /**
234        * Work out a few things. They need to be here because they depend on things you can change before you
235        * call Draw() but after you instantiate the object
236        */
237        this.graphwidth     = this.canvas.width - this.gutterLeft - this.gutterRight;
238        this.graphheight    = this.canvas.height - this.gutterTop - this.gutterBottom;
239        this.halfgrapharea  = this.grapharea / 2;
240        this.halfTextHeight = this.Get('chart.text.size') / 2;
241
242
243        // Progressively Draw the chart
244        RGraph.background.Draw(this);
245
246        this.Drawbars();
247        this.DrawAxes();
248        this.DrawLabels();
249
250
251        // Draw the key if necessary
252        if (this.Get('chart.key').length) {
253            RGraph.DrawKey(this, this.Get('chart.key'), this.Get('chart.colors'));
254        }
255
256        /**
257        * Install the event handlers for tooltips
258        */
259        if (this.Get('chart.tooltips')) {
260
261            // Need to register this object for redrawing
262            RGraph.Register(this);
263
264            /**
265            * Install the window onclick handler
266            */
267            window.onclick = function ()
268            {
269                RGraph.Redraw();
270            }
271
272
273
274            /**
275            * If the cursor is over a hotspot, change the cursor to a hand
276            */
277            //this.canvas.onmousemove = function (e)
278            var canvas_onmousemove_func = function (e)
279            {
280                e = RGraph.FixEventObject(e);
281
282                var canvas = document.getElementById(this.id);
283                var obj = canvas.__object__;
284                var bar = obj.getBar(e);
285
286                /**
287                * Get the mouse X/Y coordinates
288                */
289                var mouseCoords = RGraph.getMouseXY(e);
290
291                if (bar && (typeof(obj.Get('chart.tooltips')) == 'function' || obj.Get('chart.tooltips')[bar[4]]) ) {
292
293                    canvas.style.cursor = 'pointer';
294                   
295                    var left   = bar[0];
296                    var top    = bar[1];
297                    var width  = bar[2];
298                    var height = bar[3];
299                    var idx    = bar[4];
300                   
301                    /**
302                    * Show the tooltip if the event is onmousemove
303                    */
304                    if (obj.Get('chart.tooltips.event') == 'onmousemove') {
305                   
306                        var tooltipObj = RGraph.Registry.Get('chart.tooltip');
307
308                        /**
309                        * Get the tooltip text
310                        */
311                        if (typeof(obj.Get('chart.tooltips')) == 'function') {
312                            var text = obj.Get('chart.tooltips')(idx);
313                       
314                        } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') {
315                            var text = obj.Get('chart.tooltips')[idx](idx);
316                       
317                        } else if (typeof(obj.Get('chart.tooltips')) == 'object') {
318                            var text = obj.Get('chart.tooltips')[idx];
319
320                        } else {
321                            var text = null;
322                        }
323
324                        if (text) {
325                            if (!tooltipObj || tooltipObj.__index__ != idx) {
326                           
327                                RGraph.HideTooltip();
328                                RGraph.Redraw();
329
330                                obj.context.beginPath();
331                                obj.context.strokeStyle = obj.Get('chart.highlight.stroke');
332                                obj.context.fillStyle   = obj.Get('chart.highlight.fill');
333                                obj.context.strokeRect(left, top, width, height);
334                                obj.context.fillRect(left, top, width, height);
335
336                                RGraph.Tooltip(canvas, text, e.pageX, e.pageY, idx);
337                            }
338                            return;
339                        }
340                    }
341                }
342               
343                if (!bar) {
344                    canvas.style.cursor = 'default';
345                }
346            }
347            this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false);
348            RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func);
349
350
351            /**
352            * Install the onclick event handler for the tooltips
353            */
354            //this.canvas.onclick = function (e)
355            var canvas_onclick_func = function (e)
356            {
357                e = RGraph.FixEventObject(e);
358
359                //var canvas = document.getElementById(this.id);
360                var canvas = e.target;
361                var obj = canvas.__object__;
362                var bar = obj.getBar(e);
363
364                /**
365                * Redraw the graph first, in effect resetting the graph to as it was when it was first drawn
366                * This "deselects" any already selected bar
367                */
368                RGraph.Redraw();
369
370                /**
371                * Get the mouse X/Y coordinates
372                */
373                var mouseCoords = RGraph.getMouseXY(e);
374               
375                /*******************************************************
376                * Only do this if a bar is being hovered over
377                *******************************************************/
378                if (bar) {
379                   
380                    var left   = bar[0];
381                    var top    = bar[1];
382                    var width  = bar[2];
383                    var height = bar[3];
384                    var idx    = bar[4];
385
386                    /**
387                    * Get the tooltip text
388                    */
389                    if (typeof(obj.Get('chart.tooltips')) == 'function') {
390                        var text = obj.Get('chart.tooltips')(idx);
391                   
392                    } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') {
393                        var text = obj.Get('chart.tooltips')[idx](idx);
394                   
395                    } else if (typeof(obj.Get('chart.tooltips')) == 'object') {
396                        var text = obj.Get('chart.tooltips')[idx];
397
398                    } else {
399                        var text = null;
400                    }
401
402                    /**
403                    * Show a tooltip if it's defined
404                    */
405                    if (String(text).length && text != null) {
406
407                        obj.context.beginPath();
408                        obj.context.strokeStyle = obj.Get('chart.highlight.stroke');
409                        obj.context.fillStyle   = obj.Get('chart.highlight.fill');
410                        obj.context.strokeRect(left, top, width, height);
411                        obj.context.fillRect(left, top, width, height);
412   
413                        obj.context.stroke();
414                        obj.context.fill();
415
416                        RGraph.Tooltip(canvas, text, e.pageX, e.pageY, idx);
417                    }
418                }
419
420                /**
421                * Stop the event bubbling
422                */
423                e.stopPropagation();
424            }
425            this.canvas.addEventListener('click', canvas_onclick_func, false);
426            RGraph.AddEventListener(this.id,'click', canvas_onclick_func);
427
428            // This resets the bar graph
429            if (RGraph.Registry.Get('chart.tooltip')) {
430                RGraph.Registry.Get('chart.tooltip').style.display = 'none';
431                RGraph.Registry.Set('chart.tooltip', null)
432            }
433        }
434
435        /**
436        * Setup the context menu if required
437        */
438        if (this.Get('chart.contextmenu')) {
439            RGraph.ShowContext(this);
440        }
441
442
443        /**
444        * Draw "in graph" labels
445        */
446        RGraph.DrawInGraphLabels(this);
447       
448        /**
449        * If the canvas is annotatable, do install the event handlers
450        */
451        if (this.Get('chart.annotatable')) {
452            RGraph.Annotate(this);
453        }
454       
455        /**
456        * This bit shows the mini zoom window if requested
457        */
458        if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') {
459            RGraph.ShowZoomWindow(this);
460        }
461
462       
463        /**
464        * This function enables resizing
465        */
466        if (this.Get('chart.resizable')) {
467            RGraph.AllowResizing(this);
468        }
469
470
471        /**
472        * Fire the RGraph ondraw event
473        */
474        RGraph.FireCustomEvent(this, 'ondraw');
475    }
476   
477    /**
478    * This draws the axes
479    */
480    RGraph.HBar.prototype.DrawAxes = function ()
481    {
482        var halfway = (this.graphwidth / 2) + this.gutterLeft;
483
484        this.context.beginPath();
485        this.context.lineWidth   = 1;
486        this.context.strokeStyle = this.Get('chart.axis.color');
487
488        // Draw the Y axis
489        if (this.Get('chart.yaxispos') == 'center') {
490            this.context.moveTo(halfway, this.gutterTop);
491            this.context.lineTo(halfway, RGraph.GetHeight(this) - this.gutterBottom);
492        } else {
493            this.context.moveTo(this.gutterLeft, this.gutterTop);
494            this.context.lineTo(this.gutterLeft, RGraph.GetHeight(this) - this.gutterBottom);
495        }
496
497        // Draw the X axis
498        this.context.moveTo(this.gutterLeft, RGraph.GetHeight(this) - this.gutterBottom);
499        this.context.lineTo(RGraph.GetWidth(this) - this.gutterRight, RGraph.GetHeight(this) - this.gutterBottom);
500
501        // Draw the Y tickmarks
502        var yTickGap = (RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) / this.data.length;
503
504        for (y=this.gutterTop; y<(RGraph.GetHeight(this) - this.gutterBottom); y+=yTickGap) {
505            if (this.Get('chart.yaxispos') == 'center') {
506                this.context.moveTo(halfway + 3, y);
507                this.context.lineTo(halfway  - 3, y);
508            } else {
509                this.context.moveTo(this.gutterLeft, y);
510                this.context.lineTo( this.gutterLeft  - 3, y);
511            }
512        }
513
514
515        // Draw the X tickmarks
516        xTickGap = (RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight ) / 10;
517        yStart   = RGraph.GetHeight(this) - this.gutterBottom;
518        yEnd     = (RGraph.GetHeight(this) - this.gutterBottom) + 3;
519
520        for (x=(RGraph.GetWidth(this) - this.gutterRight), i=0; this.Get('chart.yaxispos') == 'center' ? x>=this.gutterLeft : x>this.gutterLeft; x-=xTickGap) {
521
522            if (this.Get('chart.yaxispos') != 'center' || i != 5) {
523                this.context.moveTo(x, yStart);
524                this.context.lineTo(x, yEnd);
525            }
526            i++;
527        }
528
529        this.context.stroke();
530    }
531
532
533    /**
534    * This draws the labels for the graph
535    */
536    RGraph.HBar.prototype.DrawLabels = function ()
537    {
538        var context    = this.context;
539        var canvas     = this.canvas;
540        var units_pre  = this.Get('chart.units.pre');
541        var units_post = this.Get('chart.units.post');
542        var text_size  = this.Get('chart.text.size');
543        var font       = this.Get('chart.text.font');
544
545
546        /**
547        * Set the units to blank if they're to be used for ingraph labels only
548        */
549        if (this.Get('chart.units.ingraph')) {
550            units_pre  = '';
551            units_post = '';
552        }
553
554
555        /**
556        * Draw the X axis labels
557        */
558        if (this.Get('chart.xlabels')) {
559            this.context.beginPath();
560            this.context.fillStyle = this.Get('chart.text.color');
561
562            if (this.Get('chart.yaxispos') == 'center') {
563                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (10/10)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
564                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (9/10)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
565                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (8/10)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
566                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (7/10)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
567                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (6/10)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
568
569                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (4/10)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, '-' + RGraph.number_format(this, Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
570                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (3/10)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, '-' + RGraph.number_format(this, Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
571                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (2/10)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, '-' + RGraph.number_format(this, Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
572                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (1/10)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, '-' + RGraph.number_format(this, Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
573                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (0)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, '-' + RGraph.number_format(this, Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
574   
575            } else {
576   
577                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (5/5)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, Number(this.scale[4]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
578                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (4/5)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, Number(this.scale[3]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
579                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (3/5)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, Number(this.scale[2]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
580                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (2/5)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, Number(this.scale[1]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
581                RGraph.Text(context, font, text_size, this.gutterLeft + (this.graphwidth * (1/5)), this.gutterTop + this.halfTextHeight + this.graphheight + 2, RGraph.number_format(this, Number(this.scale[0]).toFixed(this.Get('chart.scale.decimals')), units_pre, units_post), 'center', 'center');
582               
583                if (this.Get('chart.xmin') > 0) {
584                    RGraph.Text(context,font,text_size,this.gutterLeft,this.gutterTop + this.halfTextHeight + this.graphheight + 2,RGraph.number_format(this, this.Get('chart.xmin'), units_pre, units_post),'center','center');
585                }
586            }
587           
588            this.context.fill();
589            this.context.stroke();
590        }
591
592        /**
593        * The Y axis labels
594        */
595        if (typeof(this.Get('chart.labels')) == 'object') {
596       
597            var xOffset = 5;
598            var font    = this.Get('chart.text.font');
599
600            // Draw the X axis labels
601            this.context.fillStyle = this.Get('chart.text.color');
602           
603            // How wide is each bar
604            var barHeight = (RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom ) / this.Get('chart.labels').length;
605           
606            // Reset the xTickGap
607            yTickGap = (RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) / this.Get('chart.labels').length
608
609            // Draw the X tickmarks
610            var i=0;
611            for (y=this.gutterTop + (yTickGap / 2); y<=RGraph.GetHeight(this) - this.gutterBottom; y+=yTickGap) {
612                RGraph.Text(this.context, font,this.Get('chart.text.size'),this.gutterLeft - xOffset,y,String(this.Get('chart.labels')[i++]),'center','right');
613            }
614        }
615    }
616   
617   
618    /**
619    * This function draws the actual bars
620    */
621    RGraph.HBar.prototype.Drawbars = function ()
622    {
623        this.context.lineWidth   = 1;
624        this.context.strokeStyle = this.Get('chart.strokestyle');
625        this.context.fillStyle   = this.Get('chart.colors')[0];
626        var prevX                = 0;
627        var prevY                = 0;
628
629        /**
630        * Work out the max value
631        */
632        if (this.Get('chart.xmax')) {
633            this.scale = [
634                          (((this.Get('chart.xmax') - this.Get('chart.xmin')) * 0.2) + this.Get('chart.xmin')).toFixed(this.Get('chart.scale.decimals')),
635                          (((this.Get('chart.xmax') - this.Get('chart.xmin')) * 0.4) + this.Get('chart.xmin')).toFixed(this.Get('chart.scale.decimals')),
636                          (((this.Get('chart.xmax') - this.Get('chart.xmin')) * 0.6) + this.Get('chart.xmin')).toFixed(this.Get('chart.scale.decimals')),
637                          (((this.Get('chart.xmax') - this.Get('chart.xmin')) * 0.8) + this.Get('chart.xmin')).toFixed(this.Get('chart.scale.decimals')),
638                          (((this.Get('chart.xmax') - this.Get('chart.xmin')) + this.Get('chart.xmin'))).toFixed(this.Get('chart.scale.decimals'))
639                         ];
640            this.max = this.scale[4];
641       
642        } else {
643       
644            var grouping = this.Get('chart.grouping');
645
646            for (i=0; i<this.data.length; ++i) {
647                if (typeof(this.data[i]) == 'object') {
648                    var value = grouping == 'grouped' ? Number(RGraph.array_max(this.data[i], true)) : Number(RGraph.array_sum(this.data[i])) ;
649                } else {
650                    var value = Number(Math.abs(this.data[i]));
651                }
652
653                this.max = Math.max(Math.abs(this.max), Math.abs(value));
654            }
655
656            this.scale = RGraph.getScale(this.max, this);
657
658            /**
659            * Account for chart.xmin
660            */
661            if (this.Get('chart.xmin') > 0) {
662                this.scale[0] = Number((((this.scale[4] - this.Get('chart.xmin')) * 0.2) + this.Get('chart.xmin')).toFixed(this.Get('chart.scale.decimals')));
663                this.scale[1] = Number((((this.scale[4] - this.Get('chart.xmin')) * 0.4) + this.Get('chart.xmin')).toFixed(this.Get('chart.scale.decimals')));
664                this.scale[2] = Number((((this.scale[4] - this.Get('chart.xmin')) * 0.6) + this.Get('chart.xmin')).toFixed(this.Get('chart.scale.decimals')));
665                this.scale[3] = Number((((this.scale[4] - this.Get('chart.xmin')) * 0.8) + this.Get('chart.xmin')).toFixed(this.Get('chart.scale.decimals')));
666                this.scale[4] = Number((((this.scale[4] - this.Get('chart.xmin')) * 1.0) + this.Get('chart.xmin')).toFixed(this.Get('chart.scale.decimals')));
667            }
668
669            this.max = this.scale[4];
670        }
671
672        if (this.Get('chart.scale.decimals') == null && Number(this.max) == 1) {
673            this.Set('chart.scale.decimals', 1);
674        }
675       
676        /*******************************************************
677        * This is here to facilitate sequential colors
678        *******************************************************/
679        var colorIdx = 0;
680
681        /**
682        * The bars are drawn HERE
683        */
684        var graphwidth = (this.canvas.width - this.gutterLeft - this.gutterRight);
685        var halfwidth  = graphwidth / 2;
686
687        for (i=0; i<this.data.length; ++i) {
688
689            // Work out the width and height
690            var width  = (this.data[i] / this.max) *  graphwidth;
691            var height = this.graphheight / this.data.length;
692
693            var orig_height = height;
694
695            var x       = this.gutterLeft;
696            var y       = this.gutterTop + (i * height);
697            var vmargin = this.Get('chart.vmargin');
698
699            // Account for negative lengths - Some browsers (eg Chrome) don't like a negative value
700            if (width < 0) {
701                x -= width;
702                width = Math.abs(width);
703            }
704
705            /**
706            * Turn on the shadow if need be
707            */
708            if (this.Get('chart.shadow')) {
709                this.context.shadowColor   = this.Get('chart.shadow.color');
710                this.context.shadowBlur    = this.Get('chart.shadow.blur');
711                this.context.shadowOffsetX = this.Get('chart.shadow.offsetx');
712                this.context.shadowOffsetY = this.Get('chart.shadow.offsety');
713            }
714
715            /**
716            * Draw the bar
717            */
718            this.context.beginPath();
719                if (typeof(this.data[i]) == 'number') {
720
721                    var barHeight = height - (2 * vmargin);
722                    var barWidth  = ((this.data[i] - this.Get('chart.xmin')) / (this.max - this.Get('chart.xmin'))) * this.graphwidth;
723                    var barX      = this.gutterLeft;
724
725                    // Account for Y axis pos
726                    if (this.Get('chart.yaxispos') == 'center') {
727                        barWidth /= 2;
728                        barX += halfwidth;
729                    }
730
731                    // Set the fill color
732                    this.context.strokeStyle = this.Get('chart.strokestyle');
733                    this.context.fillStyle = this.Get('chart.colors')[0];
734                   
735                    // Sequential colors
736                    if (this.Get('chart.colors.sequential')) {
737                        this.context.fillStyle = this.Get('chart.colors')[colorIdx++];
738                    }
739
740                    this.context.strokeRect(barX, this.gutterTop + (i * height) + this.Get('chart.vmargin'), barWidth, barHeight);
741                    this.context.fillRect(barX, this.gutterTop + (i * height) + this.Get('chart.vmargin'), barWidth, barHeight);
742
743                    this.coords.push([barX,
744                                      y + vmargin,
745                                      barWidth,
746                                      height - (2 * vmargin),
747                                      this.context.fillStyle,
748                                      this.data[i],
749                                      true]);
750
751                /**
752                * Stacked bar chart
753                */
754                } else if (typeof(this.data[i]) == 'object' && this.Get('chart.grouping') == 'stacked') {
755
756                    if (this.Get('chart.yaxispos') == 'center') {
757                        alert('[HBAR] You can\'t have a stacked chart with the Y axis in the center, change it to grouped');
758                    }
759
760                    var barHeight = height - (2 * vmargin);
761
762                    for (j=0; j<this.data[i].length; ++j) {
763                   
764
765                        // Set the fill/stroke colors
766                        this.context.strokeStyle = this.Get('chart.strokestyle');
767                        this.context.fillStyle = this.Get('chart.colors')[j];
768                       
769
770                        // Sequential colors
771                        if (this.Get('chart.colors.sequential')) {
772                            this.context.fillStyle = this.Get('chart.colors')[colorIdx++];
773                        }
774                       
775
776                        var width = (((this.data[i][j]) / (this.max))) * this.graphwidth;
777                        var totalWidth = (RGraph.array_sum(this.data[i]) / this.max) * this.graphwidth;
778
779                        this.context.strokeRect(x, this.gutterTop + this.Get('chart.vmargin') + (this.graphheight / this.data.length) * i, width, height - (2 * vmargin) );
780                        this.context.fillRect(x, this.gutterTop + this.Get('chart.vmargin') + (this.graphheight / this.data.length) * i, width, height - (2 * vmargin) );
781
782                        /**
783                        * Store the coords for tooltips
784                        */
785
786                        // The last property of this array is a boolean which tells you whether the value is the last or not
787                        this.coords.push([x,
788                                          y + vmargin,
789                                          width,
790                                          height - (2 * vmargin),
791                                          this.context.fillStyle,
792                                          RGraph.array_sum(this.data[i]),
793                                          j == (this.data[i].length - 1)
794                                         ]);
795
796                        x += width;
797                    }
798
799                /**
800                * A grouped bar chart
801                */
802                } else if (typeof(this.data[i]) == 'object' && this.Get('chart.grouping') == 'grouped') {
803
804                    for (j=0; j<this.data[i].length; ++j) {
805
806                        /**
807                        * Turn on the shadow if need be
808                        */
809                        if (this.Get('chart.shadow')) {
810                            RGraph.SetShadow(this, this.Get('chart.shadow.color'), this.Get('chart.shadow.offsetx'), this.Get('chart.shadow.offsety'), this.Get('chart.shadow.blur'));
811                        }
812
813                        // Set the fill/stroke colors
814                        this.context.strokeStyle = this.Get('chart.strokestyle');
815                        this.context.fillStyle = this.Get('chart.colors')[j];
816                       
817
818                        // Sequential colors
819                        if (this.Get('chart.colors.sequential')) {
820                            this.context.fillStyle = this.Get('chart.colors')[colorIdx++];
821                        }
822
823                        var width = ((this.data[i][j] - this.Get('chart.xmin')) / (this.max - this.Get('chart.xmin'))) * (RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight );
824                        var individualBarHeight = (height - (2 * vmargin)) / this.data[i].length;
825
826                        var startX = this.gutterLeft;
827                        var startY = y + vmargin + (j * individualBarHeight);
828
829                        // Account for the Y axis being in the middle
830                        if (this.Get('chart.yaxispos') == 'center') {
831                            width  /= 2;
832                            startX += halfwidth;
833                        }
834                       
835                        if (width < 0) {
836                            startX += width;
837                            width *= -1;
838                        }
839
840                        this.context.strokeRect(startX, startY, width, individualBarHeight);
841                        this.context.fillRect(startX, startY, width, individualBarHeight);
842
843                        this.coords.push([startX,
844                                          startY,
845                                          width,
846                                          individualBarHeight,
847                                          this.context.fillStyle,
848                                          this.data[i][j],
849                                          true]);
850                    }
851                }
852
853            this.context.closePath();
854        }
855
856        this.context.fill();
857        this.context.stroke();
858
859
860
861        /**
862        * Now the bars are stroke()ed, turn off the shadow
863        */
864        RGraph.NoShadow(this);
865       
866        this.RedrawBars();
867    }
868   
869   
870    /**
871    * This function goes over the bars after they been drawn, so that upwards shadows are underneath the bars
872    */
873    RGraph.HBar.prototype.RedrawBars = function ()
874    {
875        if (this.Get('chart.noredraw')) {
876            return;
877        }
878
879        var coords = this.coords;
880
881        var font   = this.Get('chart.text.font');
882        var size   = this.Get('chart.text.size');
883        var color  = this.Get('chart.text.color');
884
885        RGraph.NoShadow(this);
886        this.context.strokeStyle = this.Get('chart.strokestyle');
887
888        for (var i=0; i<coords.length; ++i) {
889
890            if (this.Get('chart.shadow')) {
891                this.context.beginPath();
892                    this.context.strokeStyle = this.Get('chart.strokestyle');
893                    this.context.fillStyle = coords[i][4];
894                    this.context.lineWidth = 1;
895                    this.context.strokeRect(coords[i][0], coords[i][1], coords[i][2], coords[i][3]);
896                    this.context.fillRect(coords[i][0], coords[i][1], coords[i][2], coords[i][3]);
897                this.context.fill();
898                this.context.stroke();
899            }
900
901            /**
902            * Draw labels "above" the bar
903            */
904            if (this.Get('chart.labels.above') && coords[i][6]) {
905
906                this.context.fillStyle   = color;
907                this.context.strokeStyle = 'black';
908                RGraph.NoShadow(this);
909
910                var border = (coords[i][0] + coords[i][2] + 7 + this.context.measureText(this.Get('chart.units.pre') + this.coords[i][5] + this.Get('chart.units.post')).width) > RGraph.GetWidth(this) ? true : false;
911
912                RGraph.Text(this.context,
913                            font,
914                            size,
915                            coords[i][0] + coords[i][2] + (border ? -5 : 5),
916                            coords[i][1] + (coords[i][3] / 2),
917                            RGraph.number_format(this, (this.coords[i][5]).toFixed(this.Get('chart.labels.above.decimals')), this.Get('chart.units.pre'), this.Get('chart.units.post')),
918                            'center',
919                            border ? 'right' : 'left',
920                            border,
921                            null,
922                            border ? 'rgba(255,255,255,0.9)' : null);
923            }
924        }
925    }
926   
927   
928    /*******************************************************
929    * This function can be used to get the appropriate bar information (if any)
930    *
931    * @param  e Event object
932    * @return   Appriate bar information (if any)
933    *******************************************************/
934    RGraph.HBar.prototype.getBar = function (e)
935    {
936        var obj         = e.target.__object__;
937        var canvas      = obj.canvas;
938        var context     = obj.context;
939        var mouseCoords = RGraph.getMouseXY(e);
940
941        /**
942        * Loop through the bars determining if the mouse is over a bar
943        */
944        for (var i=0,len=obj.coords.length; i<len; i++) {
945
946            var mouseX = mouseCoords[0];  // In relation to the canvas
947            var mouseY = mouseCoords[1];  // In relation to the canvas
948            var left   = obj.coords[i][0];
949            var top    = obj.coords[i][1];
950            var width  = obj.coords[i][2];
951            var height = obj.coords[i][3];
952            var idx    = i;
953
954            if (mouseX >= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height) ) {
955                return [left, top, width, height, idx];
956            }
957        }
958    }
Note: See TracBrowser for help on using the repository browser.