OSDN Git Service

初回コミット(v2.6.17.1)
[magic3/magic3.git] / scripts / jquery / jqplot1.0.7 / plugins / jqplot.barRenderer.js
1 /**
2  * jqPlot
3  * Pure JavaScript plotting plugin using jQuery
4  *
5  * Version: 1.0.7
6  * Revision: 1224
7  *
8  * Copyright (c) 2009-2013 Chris Leonello
9  * jqPlot is currently available for use in all personal or commercial projects 
10  * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL 
11  * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can 
12  * choose the license that best suits your project and use it accordingly. 
13  *
14  * Although not required, the author would appreciate an email letting him 
15  * know of any substantial use of jqPlot.  You can reach the author at: 
16  * chris at jqplot dot com or see http://www.jqplot.com/info.php .
17  *
18  * If you are feeling kind and generous, consider supporting the project by
19  * making a donation at: http://www.jqplot.com/donate.php .
20  *
21  * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
22  *
23  *     version 2007.04.27
24  *     author Ash Searle
25  *     http://hexmen.com/blog/2007/03/printf-sprintf/
26  *     http://hexmen.com/js/sprintf.js
27  *     The author (Ash Searle) has placed this code in the public domain:
28  *     "This code is unrestricted: you are free to use it however you like."
29  * 
30  */
31 (function($) {
32     
33     // Class: $.jqplot.BarRenderer
34     // A plugin renderer for jqPlot to draw a bar plot.
35     // Draws series as a line.
36     
37     $.jqplot.BarRenderer = function(){
38         $.jqplot.LineRenderer.call(this);
39     };
40     
41     $.jqplot.BarRenderer.prototype = new $.jqplot.LineRenderer();
42     $.jqplot.BarRenderer.prototype.constructor = $.jqplot.BarRenderer;
43     
44     // called with scope of series.
45     $.jqplot.BarRenderer.prototype.init = function(options, plot) {
46         // Group: Properties
47         //
48         // prop: barPadding
49         // Number of pixels between adjacent bars at the same axis value.
50         this.barPadding = 8;
51         // prop: barMargin
52         // Number of pixels between groups of bars at adjacent axis values.
53         this.barMargin = 10;
54         // prop: barDirection
55         // 'vertical' = up and down bars, 'horizontal' = side to side bars
56         this.barDirection = 'vertical';
57         // prop: barWidth
58         // Width of the bar in pixels (auto by devaul).  null = calculated automatically.
59         this.barWidth = null;
60         // prop: shadowOffset
61         // offset of the shadow from the slice and offset of 
62         // each succesive stroke of the shadow from the last.
63         this.shadowOffset = 2;
64         // prop: shadowDepth
65         // number of strokes to apply to the shadow, 
66         // each stroke offset shadowOffset from the last.
67         this.shadowDepth = 5;
68         // prop: shadowAlpha
69         // transparency of the shadow (0 = transparent, 1 = opaque)
70         this.shadowAlpha = 0.08;
71         // prop: waterfall
72         // true to enable waterfall plot.
73         this.waterfall = false;
74         // prop: groups
75         // group bars into this many groups
76         this.groups = 1;
77         // prop: varyBarColor
78         // true to color each bar of a series separately rather than
79         // have every bar of a given series the same color.
80         // If used for non-stacked multiple series bar plots, user should
81         // specify a separate 'seriesColors' array for each series.
82         // Otherwise, each series will set their bars to the same color array.
83         // This option has no Effect for stacked bar charts and is disabled.
84         this.varyBarColor = false;
85         // prop: highlightMouseOver
86         // True to highlight slice when moused over.
87         // This must be false to enable highlightMouseDown to highlight when clicking on a slice.
88         this.highlightMouseOver = true;
89         // prop: highlightMouseDown
90         // True to highlight when a mouse button is pressed over a slice.
91         // This will be disabled if highlightMouseOver is true.
92         this.highlightMouseDown = false;
93         // prop: highlightColors
94         // an array of colors to use when highlighting a bar.
95         this.highlightColors = [];
96         // prop: transposedData
97         // NOT IMPLEMENTED YET.  True if this is a horizontal bar plot and 
98         // x and y values are "transposed".  Tranposed, or "swapped", data is 
99         // required prior to rev. 894 builds of jqPlot with horizontal bars. 
100         // Allows backward compatability of bar renderer horizontal bars with 
101         // old style data sets.
102         this.transposedData = true;
103         this.renderer.animation = {
104             show: false,
105             direction: 'down',
106             speed: 3000,
107             _supported: true
108         };
109         this._type = 'bar';
110         
111         // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver
112         if (options.highlightMouseDown && options.highlightMouseOver == null) {
113             options.highlightMouseOver = false;
114         }
115         
116         //////
117         // This is probably wrong here.
118         // After going back and forth on whether renderer should be the thing
119         // or extend the thing, it seems that it it best if it is a property
120         // on the thing.  This should be something that is commonized 
121         // among series renderers in the future.
122         //////
123         $.extend(true, this, options);
124
125         // really should probably do this
126         $.extend(true, this.renderer, options);
127         // fill is still needed to properly draw the legend.
128         // bars have to be filled.
129         this.fill = true;
130
131         // if horizontal bar and animating, reset the default direction
132         if (this.barDirection === 'horizontal' && this.rendererOptions.animation && this.rendererOptions.animation.direction == null) {
133             this.renderer.animation.direction = 'left';
134         }
135         
136         if (this.waterfall) {
137             this.fillToZero = false;
138             this.disableStack = true;
139         }
140         
141         if (this.barDirection == 'vertical' ) {
142             this._primaryAxis = '_xaxis';
143             this._stackAxis = 'y';
144             this.fillAxis = 'y';
145         }
146         else {
147             this._primaryAxis = '_yaxis';
148             this._stackAxis = 'x';
149             this.fillAxis = 'x';
150         }
151         // index of the currenty highlighted point, if any
152         this._highlightedPoint = null;
153         // total number of values for all bar series, total number of bar series, and position of this series
154         this._plotSeriesInfo = null;
155         // Array of actual data colors used for each data point.
156         this._dataColors = [];
157         this._barPoints = [];
158         
159         // set the shape renderer options
160         var opts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, strokeStyle:this.color, fillStyle:this.color, closePath:this.fill};
161         this.renderer.shapeRenderer.init(opts);
162         // set the shadow renderer options
163         var sopts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, closePath:this.fill};
164         this.renderer.shadowRenderer.init(sopts);
165         
166         plot.postInitHooks.addOnce(postInit);
167         plot.postDrawHooks.addOnce(postPlotDraw);
168         plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);
169         plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);
170         plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);
171         plot.eventListenerHooks.addOnce('jqplotClick', handleClick);
172         plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); 
173     };
174     
175     // called with scope of series
176     function barPreInit(target, data, seriesDefaults, options) {
177         if (this.rendererOptions.barDirection == 'horizontal') {
178             this._stackAxis = 'x';
179             this._primaryAxis = '_yaxis';
180         }
181         if (this.rendererOptions.waterfall == true) {
182             this._data = $.extend(true, [], this.data);
183             var sum = 0;
184             var pos = (!this.rendererOptions.barDirection || this.rendererOptions.barDirection === 'vertical' || this.transposedData === false) ? 1 : 0;
185             for(var i=0; i<this.data.length; i++) {
186                 sum += this.data[i][pos];
187                 if (i>0) {
188                     this.data[i][pos] += this.data[i-1][pos];
189                 }
190             }
191             this.data[this.data.length] = (pos == 1) ? [this.data.length+1, sum] : [sum, this.data.length+1];
192             this._data[this._data.length] = (pos == 1) ? [this._data.length+1, sum] : [sum, this._data.length+1];
193         }
194         if (this.rendererOptions.groups > 1) {
195             this.breakOnNull = true;
196             var l = this.data.length;
197             var skip = parseInt(l/this.rendererOptions.groups, 10);
198             var count = 0;
199             for (var i=skip; i<l; i+=skip) {
200                 this.data.splice(i+count, 0, [null, null]);
201                 this._plotData.splice(i+count, 0, [null, null]);
202                 this._stackData.splice(i+count, 0, [null, null]);
203                 count++;
204             }
205             for (i=0; i<this.data.length; i++) {
206                 if (this._primaryAxis == '_xaxis') {
207                     this.data[i][0] = i+1;
208                     this._plotData[i][0] = i+1;
209                     this._stackData[i][0] = i+1;
210                 }
211                 else {
212                     this.data[i][1] = i+1;
213                     this._plotData[i][1] = i+1;
214                     this._stackData[i][1] = i+1;
215                 }
216             }
217         }
218     }
219     
220     $.jqplot.preSeriesInitHooks.push(barPreInit);
221     
222     // needs to be called with scope of series, not renderer.
223     $.jqplot.BarRenderer.prototype.calcSeriesNumbers = function() {
224         var nvals = 0;
225         var nseries = 0;
226         var paxis = this[this._primaryAxis];
227         var s, series, pos;
228         // loop through all series on this axis
229         for (var i=0; i < paxis._series.length; i++) {
230             series = paxis._series[i];
231             if (series === this) {
232                 pos = i;
233             }
234             // is the series rendered as a bar?
235             if (series.renderer.constructor == $.jqplot.BarRenderer) {
236                 // gridData may not be computed yet, use data length insted
237                 nvals += series.data.length;
238                 nseries += 1;
239             }
240         }
241         // return total number of values for all bar series, total number of bar series, and position of this series
242         return [nvals, nseries, pos];
243     };
244
245     $.jqplot.BarRenderer.prototype.setBarWidth = function() {
246         // need to know how many data values we have on the approprate axis and figure it out.
247         var i;
248         var nvals = 0;
249         var nseries = 0;
250         var paxis = this[this._primaryAxis];
251         var s, series, pos;
252         var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this);
253         nvals = temp[0];
254         nseries = temp[1];
255         var nticks = paxis.numberTicks;
256         var nbins = (nticks-1)/2;
257         // so, now we have total number of axis values.
258         if (paxis.name == 'xaxis' || paxis.name == 'x2axis') {
259             if (this._stack) {
260                 this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals * nseries - this.barMargin;
261             }
262             else {
263                 this.barWidth = ((paxis._offsets.max - paxis._offsets.min)/nbins  - this.barPadding * (nseries-1) - this.barMargin*2)/nseries;
264                 // this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals - this.barPadding - this.barMargin/nseries;
265             }
266         }
267         else {
268             if (this._stack) {
269                 this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals * nseries - this.barMargin;
270             }
271             else {
272                 this.barWidth = ((paxis._offsets.min - paxis._offsets.max)/nbins  - this.barPadding * (nseries-1) - this.barMargin*2)/nseries;
273                 // this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals - this.barPadding - this.barMargin/nseries;
274             }
275         }
276         return [nvals, nseries];
277     };
278
279     function computeHighlightColors (colors) {
280         var ret = [];
281         for (var i=0; i<colors.length; i++){
282             var rgba = $.jqplot.getColorComponents(colors[i]);
283             var newrgb = [rgba[0], rgba[1], rgba[2]];
284             var sum = newrgb[0] + newrgb[1] + newrgb[2];
285             for (var j=0; j<3; j++) {
286                 // when darkening, lowest color component can be is 60.
287                 newrgb[j] = (sum > 570) ?  newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);
288                 newrgb[j] = parseInt(newrgb[j], 10);
289             }
290             ret.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')');
291         }
292         return ret;
293     }
294
295     function getStart(sidx, didx, comp, plot, axis) {
296         // check if sign change
297         var seriesIndex = sidx,
298             prevSeriesIndex = sidx - 1,
299             start,
300             prevVal,
301             aidx = (axis === 'x') ? 0 : 1;
302
303         // is this not the first series?
304         if (seriesIndex > 0) {
305             prevVal = plot.series[prevSeriesIndex]._plotData[didx][aidx];
306
307             // is there a sign change
308             if ((comp * prevVal) < 0) {
309                 start = getStart(prevSeriesIndex, didx, comp, plot, axis);
310             }
311
312             // no sign change.
313             else {
314                 start = plot.series[prevSeriesIndex].gridData[didx][aidx];
315             }
316
317         }
318
319         // if first series, return value at 0
320         else {
321
322             start = (aidx === 0) ? plot.series[seriesIndex]._xaxis.series_u2p(0) : plot.series[seriesIndex]._yaxis.series_u2p(0);
323         }
324
325         return start;
326     }
327
328     
329     $.jqplot.BarRenderer.prototype.draw = function(ctx, gridData, options, plot) {
330         var i;
331         // Ughhh, have to make a copy of options b/c it may be modified later.
332         var opts = $.extend({}, options);
333         var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
334         var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;
335         var fill = (opts.fill != undefined) ? opts.fill : this.fill;
336         var xaxis = this.xaxis;
337         var yaxis = this.yaxis;
338         var xp = this._xaxis.series_u2p;
339         var yp = this._yaxis.series_u2p;
340         var pointx, pointy;
341         // clear out data colors.
342         this._dataColors = [];
343         this._barPoints = [];
344         
345         if (this.barWidth == null) {
346             this.renderer.setBarWidth.call(this);
347         }
348         
349         var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this);
350         var nvals = temp[0];
351         var nseries = temp[1];
352         var pos = temp[2];
353                 var points = [];
354         
355         if (this._stack) {
356             this._barNudge = 0;
357         }
358         else {
359             this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding);
360         }
361         if (showLine) {
362             var negativeColors = new $.jqplot.ColorGenerator(this.negativeSeriesColors);
363             var positiveColors = new $.jqplot.ColorGenerator(this.seriesColors);
364             var negativeColor = negativeColors.get(this.index);
365             if (! this.useNegativeColors) {
366                 negativeColor = opts.fillStyle;
367             }
368             var positiveColor = opts.fillStyle;
369                         var base;
370                         var xstart; 
371                         var ystart;
372             
373             if (this.barDirection == 'vertical') {
374                 for (var i=0; i<gridData.length; i++) {
375                     if (!this._stack && this.data[i][1] == null) {
376                         continue;
377                     }
378                     points = [];
379                     base = gridData[i][0] + this._barNudge;
380                     
381                     // stacked
382                     if (this._stack && this._prevGridData.length) {
383                         ystart = getStart(this.index, i, this._plotData[i][1], plot, 'y');
384                     }
385
386                     // not stacked
387                     else {
388                         if (this.fillToZero) {
389                             ystart = this._yaxis.series_u2p(0);
390                         }
391                         else if (this.waterfall && i > 0 && i < this.gridData.length-1) {
392                             ystart = this.gridData[i-1][1];
393                         }
394                         else if (this.waterfall && i == 0 && i < this.gridData.length-1) {
395                             if (this._yaxis.min <= 0 && this._yaxis.max >= 0) {
396                                 ystart = this._yaxis.series_u2p(0);
397                             }
398                             else if (this._yaxis.min > 0) {
399                                 ystart = ctx.canvas.height;
400                             }
401                             else {
402                                 ystart = 0;
403                             }
404                         }
405                         else if (this.waterfall && i == this.gridData.length - 1) {
406                             if (this._yaxis.min <= 0 && this._yaxis.max >= 0) {
407                                 ystart = this._yaxis.series_u2p(0);
408                             }
409                             else if (this._yaxis.min > 0) {
410                                 ystart = ctx.canvas.height;
411                             }
412                             else {
413                                 ystart = 0;
414                             }
415                         }
416                         else {
417                             ystart = ctx.canvas.height;
418                         }
419                     }
420                     if ((this.fillToZero && this._plotData[i][1] < 0) || (this.waterfall && this._data[i][1] < 0)) {
421                         if (this.varyBarColor && !this._stack) {
422                             if (this.useNegativeColors) {
423                                 opts.fillStyle = negativeColors.next();
424                             }
425                             else {
426                                 opts.fillStyle = positiveColors.next();
427                             }
428                         }
429                         else {
430                             opts.fillStyle = negativeColor;
431                         }
432                     }
433                     else {
434                         if (this.varyBarColor && !this._stack) {
435                             opts.fillStyle = positiveColors.next();
436                         }
437                         else {
438                             opts.fillStyle = positiveColor;
439                         }
440                     }
441                                         
442                                         if (!this.fillToZero || this._plotData[i][1] >= 0) { 
443                                                 points.push([base-this.barWidth/2, ystart]);
444                                                 points.push([base-this.barWidth/2, gridData[i][1]]);
445                                                 points.push([base+this.barWidth/2, gridData[i][1]]);
446                                                 points.push([base+this.barWidth/2, ystart]);
447                                         }
448                                         // for negative bars make sure points are always ordered clockwise
449                                         else {              
450                                                 points.push([base-this.barWidth/2, gridData[i][1]]);
451                                                 points.push([base-this.barWidth/2, ystart]);
452                                                 points.push([base+this.barWidth/2, ystart]);
453                                                 points.push([base+this.barWidth/2, gridData[i][1]]);
454                                         }
455                     this._barPoints.push(points);
456                     // now draw the shadows if not stacked.
457                     // for stacked plots, they are predrawn by drawShadow
458                     if (shadow && !this._stack) {
459                         var sopts = $.extend(true, {}, opts);
460                         // need to get rid of fillStyle on shadow.
461                         delete sopts.fillStyle;
462                         this.renderer.shadowRenderer.draw(ctx, points, sopts);
463                     }
464                     var clr = opts.fillStyle || this.color;
465                     this._dataColors.push(clr);
466                     this.renderer.shapeRenderer.draw(ctx, points, opts); 
467                 }
468             }
469             
470             else if (this.barDirection == 'horizontal'){
471                 for (var i=0; i<gridData.length; i++) {
472                     if (!this._stack && this.data[i][0] == null) {
473                         continue;
474                     }
475                     points = [];
476                     base = gridData[i][1] - this._barNudge;
477                     xstart;
478                     
479                     if (this._stack && this._prevGridData.length) {
480                         xstart = getStart(this.index, i, this._plotData[i][0], plot, 'x');
481                     }
482                     // not stacked
483                     else {
484                         if (this.fillToZero) {
485                             xstart = this._xaxis.series_u2p(0);
486                         }
487                         else if (this.waterfall && i > 0 && i < this.gridData.length-1) {
488                             xstart = this.gridData[i-1][0];
489                         }
490                         else if (this.waterfall && i == 0 && i < this.gridData.length-1) {
491                             if (this._xaxis.min <= 0 && this._xaxis.max >= 0) {
492                                 xstart = this._xaxis.series_u2p(0);
493                             }
494                             else if (this._xaxis.min > 0) {
495                                 xstart = 0;
496                             }
497                             else {
498                                 xstart = 0;
499                             }
500                         }
501                         else if (this.waterfall && i == this.gridData.length - 1) {
502                             if (this._xaxis.min <= 0 && this._xaxis.max >= 0) {
503                                 xstart = this._xaxis.series_u2p(0);
504                             }
505                             else if (this._xaxis.min > 0) {
506                                 xstart = 0;
507                             }
508                             else {
509                                 xstart = ctx.canvas.width;
510                             }
511                         }
512                         else {
513                             xstart = 0;
514                         }
515                     }
516                     if ((this.fillToZero && this._plotData[i][0] < 0) || (this.waterfall && this._data[i][0] < 0)) {
517                         if (this.varyBarColor && !this._stack) {
518                             if (this.useNegativeColors) {
519                                 opts.fillStyle = negativeColors.next();
520                             }
521                             else {
522                                 opts.fillStyle = positiveColors.next();
523                             }
524                         }
525                         else {
526                             opts.fillStyle = negativeColor;
527                         }
528                     }
529                     else {
530                         if (this.varyBarColor && !this._stack) {
531                             opts.fillStyle = positiveColors.next();
532                         }
533                         else {
534                             opts.fillStyle = positiveColor;
535                         }                    
536                     }
537                     
538
539                     if (!this.fillToZero || this._plotData[i][0] >= 0) {
540                         points.push([xstart, base + this.barWidth / 2]);
541                         points.push([xstart, base - this.barWidth / 2]);
542                         points.push([gridData[i][0], base - this.barWidth / 2]);
543                         points.push([gridData[i][0], base + this.barWidth / 2]);
544                     }
545                     else {
546                         points.push([gridData[i][0], base + this.barWidth / 2]);
547                         points.push([gridData[i][0], base - this.barWidth / 2]);
548                         points.push([xstart, base - this.barWidth / 2]);
549                         points.push([xstart, base + this.barWidth / 2]);
550                     }
551
552                     this._barPoints.push(points);
553                     // now draw the shadows if not stacked.
554                     // for stacked plots, they are predrawn by drawShadow
555                     if (shadow && !this._stack) {
556                         var sopts = $.extend(true, {}, opts);
557                         delete sopts.fillStyle;
558                         this.renderer.shadowRenderer.draw(ctx, points, sopts);
559                     }
560                     var clr = opts.fillStyle || this.color;
561                     this._dataColors.push(clr);
562                     this.renderer.shapeRenderer.draw(ctx, points, opts);
563                 } 
564             }
565         }                
566         
567         if (this.highlightColors.length == 0) {
568             this.highlightColors = $.jqplot.computeHighlightColors(this._dataColors);
569         }
570         
571         else if (typeof(this.highlightColors) == 'string') {
572             var temp = this.highlightColors;
573             this.highlightColors = [];
574             for (var i=0; i<this._dataColors.length; i++) {
575                 this.highlightColors.push(temp);
576             }
577         }
578         
579     };
580     
581      
582     // for stacked plots, shadows will be pre drawn by drawShadow.
583     $.jqplot.BarRenderer.prototype.drawShadow = function(ctx, gridData, options, plot) {
584         var i;
585         var opts = (options != undefined) ? options : {};
586         var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
587         var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;
588         var fill = (opts.fill != undefined) ? opts.fill : this.fill;
589         var xaxis = this.xaxis;
590         var yaxis = this.yaxis;
591         var xp = this._xaxis.series_u2p;
592         var yp = this._yaxis.series_u2p;
593         var pointx, points, pointy, nvals, nseries, pos;
594         
595         if (this._stack && this.shadow) {
596             if (this.barWidth == null) {
597                 this.renderer.setBarWidth.call(this);
598             }
599         
600             var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this);
601             nvals = temp[0];
602             nseries = temp[1];
603             pos = temp[2];
604         
605             if (this._stack) {
606                 this._barNudge = 0;
607             }
608             else {
609                 this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding);
610             }
611             if (showLine) {
612             
613                 if (this.barDirection == 'vertical') {
614                     for (var i=0; i<gridData.length; i++) {
615                         if (this.data[i][1] == null) {
616                             continue;
617                         }
618                         points = [];
619                         var base = gridData[i][0] + this._barNudge;
620                         var ystart;
621                     
622                         if (this._stack && this._prevGridData.length) {
623                             ystart = getStart(this.index, i, this._plotData[i][1], plot, 'y');
624                         }
625                         else {
626                             if (this.fillToZero) {
627                                 ystart = this._yaxis.series_u2p(0);
628                             }
629                             else {
630                                 ystart = ctx.canvas.height;
631                             }
632                         }
633                     
634                         points.push([base-this.barWidth/2, ystart]);
635                         points.push([base-this.barWidth/2, gridData[i][1]]);
636                         points.push([base+this.barWidth/2, gridData[i][1]]);
637                         points.push([base+this.barWidth/2, ystart]);
638                         this.renderer.shadowRenderer.draw(ctx, points, opts);
639                     }
640                 }
641             
642                 else if (this.barDirection == 'horizontal'){
643                     for (var i=0; i<gridData.length; i++) {
644                         if (this.data[i][0] == null) {
645                             continue;
646                         }
647                         points = [];
648                         var base = gridData[i][1] - this._barNudge;
649                         var xstart;
650                     
651                         if (this._stack && this._prevGridData.length) {
652                             xstart = getStart(this.index, i, this._plotData[i][0], plot, 'x');
653                         }
654                         else {
655                             if (this.fillToZero) {
656                                 xstart = this._xaxis.series_u2p(0);
657                             }
658                             else {
659                                 xstart = 0;
660                             }
661                         }
662                     
663                         points.push([xstart, base+this.barWidth/2]);
664                         points.push([gridData[i][0], base+this.barWidth/2]);
665                         points.push([gridData[i][0], base-this.barWidth/2]);
666                         points.push([xstart, base-this.barWidth/2]);
667                         this.renderer.shadowRenderer.draw(ctx, points, opts);
668                     }  
669                 }
670             }   
671             
672         }
673     };
674     
675     function postInit(target, data, options) {
676         for (var i=0; i<this.series.length; i++) {
677             if (this.series[i].renderer.constructor == $.jqplot.BarRenderer) {
678                 // don't allow mouseover and mousedown at same time.
679                 if (this.series[i].highlightMouseOver) {
680                     this.series[i].highlightMouseDown = false;
681                 }
682             }
683         }
684     }
685     
686     // called within context of plot
687     // create a canvas which we can draw on.
688     // insert it before the eventCanvas, so eventCanvas will still capture events.
689     function postPlotDraw() {
690         // Memory Leaks patch    
691         if (this.plugins.barRenderer && this.plugins.barRenderer.highlightCanvas) {
692
693             this.plugins.barRenderer.highlightCanvas.resetCanvas();
694             this.plugins.barRenderer.highlightCanvas = null;
695         }
696          
697         this.plugins.barRenderer = {highlightedSeriesIndex:null};
698         this.plugins.barRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
699         
700         this.eventCanvas._elem.before(this.plugins.barRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-barRenderer-highlight-canvas', this._plotDimensions, this));
701         this.plugins.barRenderer.highlightCanvas.setContext();
702         this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });
703     }   
704     
705     function highlight (plot, sidx, pidx, points) {
706         var s = plot.series[sidx];
707         var canvas = plot.plugins.barRenderer.highlightCanvas;
708         canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);
709         s._highlightedPoint = pidx;
710         plot.plugins.barRenderer.highlightedSeriesIndex = sidx;
711         var opts = {fillStyle: s.highlightColors[pidx]};
712         s.renderer.shapeRenderer.draw(canvas._ctx, points, opts);
713         canvas = null;
714     }
715     
716     function unhighlight (plot) {
717         var canvas = plot.plugins.barRenderer.highlightCanvas;
718         canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);
719         for (var i=0; i<plot.series.length; i++) {
720             plot.series[i]._highlightedPoint = null;
721         }
722         plot.plugins.barRenderer.highlightedSeriesIndex = null;
723         plot.target.trigger('jqplotDataUnhighlight');
724         canvas =  null;
725     }
726     
727     
728     function handleMove(ev, gridpos, datapos, neighbor, plot) {
729         if (neighbor) {
730             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
731             var evt1 = jQuery.Event('jqplotDataMouseOver');
732             evt1.pageX = ev.pageX;
733             evt1.pageY = ev.pageY;
734             plot.target.trigger(evt1, ins);
735             if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
736                 var evt = jQuery.Event('jqplotDataHighlight');
737                 evt.which = ev.which;
738                 evt.pageX = ev.pageX;
739                 evt.pageY = ev.pageY;
740                 plot.target.trigger(evt, ins);
741                 highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points);
742             }
743         }
744         else if (neighbor == null) {
745             unhighlight (plot);
746         }
747     }
748     
749     function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
750         if (neighbor) {
751             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
752             if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
753                 var evt = jQuery.Event('jqplotDataHighlight');
754                 evt.which = ev.which;
755                 evt.pageX = ev.pageX;
756                 evt.pageY = ev.pageY;
757                 plot.target.trigger(evt, ins);
758                 highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points);
759             }
760         }
761         else if (neighbor == null) {
762             unhighlight (plot);
763         }
764     }
765     
766     function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {
767         var idx = plot.plugins.barRenderer.highlightedSeriesIndex;
768         if (idx != null && plot.series[idx].highlightMouseDown) {
769             unhighlight(plot);
770         }
771     }
772     
773     function handleClick(ev, gridpos, datapos, neighbor, plot) {
774         if (neighbor) {
775             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
776             var evt = jQuery.Event('jqplotDataClick');
777             evt.which = ev.which;
778             evt.pageX = ev.pageX;
779             evt.pageY = ev.pageY;
780             plot.target.trigger(evt, ins);
781         }
782     }
783     
784     function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
785         if (neighbor) {
786             var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
787             var idx = plot.plugins.barRenderer.highlightedSeriesIndex;
788             if (idx != null && plot.series[idx].highlightMouseDown) {
789                 unhighlight(plot);
790             }
791             var evt = jQuery.Event('jqplotDataRightClick');
792             evt.which = ev.which;
793             evt.pageX = ev.pageX;
794             evt.pageY = ev.pageY;
795             plot.target.trigger(evt, ins);
796         }
797     }
798     
799     
800 })(jQuery);