PageSourceSearch

https://www.merx.com/scripts/jquery/plugins/jqplot/jqplot.pieRenderer.js

js merx.com collected 2026-10-02 03:26:14 UTC 38,040 bytes, 963 lines download raw bytes

1/**
2 * jqPlot
3 * Pure JavaScript plotting plugin using jQuery
4 *
5 * Version: @VERSION
6 * Revision: @REVISION
7 *
8 * Copyright (c) 2009-2016 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.PieRenderer
34     * Plugin renderer to draw a pie chart.
35     * x values, if present, will be used as slice labels.
36     * y values give slice size.
37     * 
38     * To use this renderer, you need to include the 
39     * pie renderer plugin, for example:
40     * 
41     * > <script type="text/javascript" src="plugins/jqplot.pieRenderer.js"></script>
42     * 
43     * Properties described here are passed into the $.jqplot function
44     * as options on the series renderer.  For example:
45     * 
46     * > plot2 = $.jqplot('chart2', [s1, s2], {
47     * >     seriesDefaults: {
48     * >         renderer:$.jqplot.PieRenderer,
49     * >         rendererOptions:{
50     * >              sliceMargin: 2,
51     * >              startAngle: -90
52     * >          }
53     * >      }
54     * > });
55     * 
56     * A pie plot will trigger events on the plot target
57     * according to user interaction.  All events return the event object,
58     * the series index, the point (slice) index, and the point data for 
59     * the appropriate slice.
60     * 
61     * 'jqplotDataMouseOver' - triggered when user mouseing over a slice.
62     * 'jqplotDataHighlight' - triggered the first time user mouses over a slice,
63     *   if highlighting is enabled.
64     * 'jqplotDataUnhighlight' - triggered when a user moves the mouse out of
65     *   a highlighted slice.
66     * 'jqplotLegendHighlight' - triggered the first time user mouses over a legend,
67     *   if highlighting is enabled.
68     * 'jqplotLegendUnhighlight' - triggered when a user moves the mouse out of
69     *   a highlighted legend.
70     * 'jqplotDataClick' - triggered when the user clicks on a slice.
71     * 'jqplotDataRightClick' - tiggered when the user right clicks on a slice if
72     * the "captureRightClick" option is set to true on the plot.
73     */
74    $.jqplot.PieRenderer = function(){
75        $.jqplot.LineRenderer.call(this);
76    };
77    
78    $.jqplot.PieRenderer.prototype = new $.jqplot.LineRenderer();
79    $.jqplot.PieRenderer.prototype.constructor = $.jqplot.PieRenderer;
80    
81    // called with scope of a series
82    $.jqplot.PieRenderer.prototype.init = function(options, plot) {
83        // Group: Properties
84        //
85        // prop: diameter
86        // Outer diameter of the pie, auto computed by default
87        this.diameter = null;
88        // prop: padding
89        // padding between the pie and plot edges, legend, etc.
90        this.padding = 20;
91        // prop: sliceMargin
92        // angular spacing between pie slices in degrees.
93        this.sliceMargin = 0;
94        // prop: fill
95        // true or false, whether to fil the slices.
96        this.fill = true;
97        // prop: shadowOffset
98        // offset of the shadow from the slice and offset of 
99        // each succesive stroke of the shadow from the last.
100        this.shadowOffset = 2;
101        // prop: shadowAlpha
102        // transparency of the shadow (0 = transparent, 1 = opaque)
103        this.shadowAlpha = 0.07;
104        // prop: shadowDepth
105        // number of strokes to apply to the shadow, 
106        // each stroke offset shadowOffset from the last.
107        this.shadowDepth = 5;
108        // prop: highlightMouseOver
109        // True to highlight slice when moused over.
110        // This must be false to enable highlightMouseDown to highlight when clicking on a slice.
111        this.highlightMouseOver = true;
112        // prop: highlightMouseDown
113        // True to highlight when a mouse button is pressed over a slice.
114        // This will be disabled if highlightMouseOver is true.
115        this.highlightMouseDown = false;
116        // prop: highlightColors
117        // an array of colors to use when highlighting a slice.
118        this.highlightColors = [];
119        // prop: dataLabels
120        // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices.
121        // Defaults to percentage of each pie slice.
122        this.dataLabels = 'percent';
123        // prop: showDataLabels
124        // true to show data labels on slices.
125        this.showDataLabels = false;
126        // prop: dataLabelFormatString
127        // Format string for data labels.  If none, '%s' is used for "label" and for arrays, '%d' for value and '%d%%' for percentage.
128        this.dataLabelFormatString = null;
129        // prop: dataLabelThreshold
130        // Threshhold in percentage (0-100) of pie area, below which no label will be displayed.
131        // This applies to all label types, not just to percentage labels.
132        this.dataLabelThreshold = 3;
133        // prop: dataLabelPositionFactor
134        // A Multiplier (0-1) of the pie radius which controls position of label on slice.
135        // Increasing will slide label toward edge of pie, decreasing will slide label toward center of pie.
136        this.dataLabelPositionFactor = 0.52;
137        // prop: dataLabelNudge
138        // Number of pixels to slide the label away from (+) or toward (-) the center of the pie.
139        this.dataLabelNudge = 2;
140        // prop: dataLabelCenterOn
141        // True to center the data label at its position.
142        // False to set the inside facing edge of the label at its position.
143        this.dataLabelCenterOn = true;
144        // prop: startAngle
145        // Angle to start drawing pie in degrees.  
146        // According to orientation of canvas coordinate system:
147        // 0 = on the positive x axis
148        // -90 = on the positive y axis.
149        // 90 = on the negaive y axis.
150        // 180 or - 180 = on the negative x axis.
151        this.startAngle = 0;
152        this.tickRenderer = $.jqplot.PieTickRenderer;
153        // prop: showSlice
154        // Array for whether the pie chart slice for a data element should be displayed.
155        // Containsg true or false for each data element.  If not specified, defaults to true.
156        this.showSlice = [];
157        // Used as check for conditions where pie shouldn't be drawn.
158        this._drawData = true;
159        this._type = 'pie';
160        
161        // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver
162        if (options.highlightMouseDown && options.highlightMouseOver == null) {
163            options.highlightMouseOver = false;
164        }
165        
166        $.extend(true, this, options);
167
168        if (this.sliceMargin < 0) {
169            this.sliceMargin = 0;
170        }
171
172        this._diameter = null;
173        this._radius = null;
174        // array of [start,end] angles arrays, one for each slice.  In radians.
175        this._sliceAngles = [];
176        // index of the currenty highlighted point, if any
177        this._highlightedPoint = null;
178        
179        // set highlight colors if none provided
180        if (this.highlightColors.length == 0) {
181            for (var i=0; i<this.seriesColors.length; i++){
182                var rgba = $.jqplot.getColorComponents(this.seriesColors[i]);
183                var newrgb = [rgba[0], rgba[1], rgba[2]];
184                var sum = newrgb[0] + newrgb[1] + newrgb[2];
185                for (var j=0; j<3; j++) {
186                    // when darkening, lowest color component can be is 60.
187                    newrgb[j] = (sum > 570) ?  newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);
188                    newrgb[j] = parseInt(newrgb[j], 10);
189                }
190                this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')');
191            }
192        }
193        
194        this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors);
195        
196        plot.postParseOptionsHooks.addOnce(postParseOptions);
197        plot.postInitHooks.addOnce(postInit);
198        plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);
199        plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);
200        plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);
201        plot.eventListenerHooks.addOnce('jqplotClick', handleClick);
202        plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);
203        plot.postDrawHooks.addOnce(postPlotDraw);
204    };
205    
206    $.jqplot.PieRenderer.prototype.setGridData = function(plot) {
207        // set gridData property.  This will hold angle in radians of each data point.
208        var stack = [];
209        var td = [];
210        var sa = this.startAngle/180*Math.PI;
211        var tot = 0;
212        // don't know if we have any valid data yet, so set plot to not draw.
213        this._drawData = false;
214        for (var i=0; i<this.data.length; i++){
215            if (this.data[i][1] != 0) {
216                // we have data, O.K. to draw.
217                this._drawData = true;
218                if (this.showSlice[i] === undefined) {
219                  this.showSlice[i] = true;
220                }
221            }
222            stack.push(this.data[i][1]);
223            td.push([this.data[i][0]]);
224            if (i>0) {
225                stack[i] += stack[i-1];
226            }
227            tot += this.data[i][1];
228        }
229        var fact = Math.PI*2/stack[stack.length - 1];
230        
231        for (var i=0; i<stack.length; i++) {
232            td[i][1] = stack[i] * fact;
233            td[i][2] = this.data[i][1]/tot;
234        }
235        this.gridData = td;
236    };
237    
238    $.jqplot.PieRenderer.prototype.makeGridData = function(data, plot) {
239
240        var hdt = document.getElementsByClassName("jqplot-table-legend-label jqplot-seriesToggle jqplot-series-hidden");
241
242        var ndt = this.data.map(function(arr) {
243                    return arr.slice();
244        });
245
246        if (hdt[0] != null) {
247            for(i=0;i<hdt.length;i++){
248                for(j=0;j<ndt.length;j++){
249                    if(hdt[i].innerText == ndt[j][0]){
250                        ndt[j][1] = 0;
251                    }
252                }
253            }
254        }
255
256        var stack = [];
257        var td = [];
258        var tot = 0;
259        var sa = this.startAngle/180*Math.PI;
260        // don't know if we have any valid data yet, so set plot to not draw.
261        this._drawData = false;
262        for (var i=0; i<data.length; i++){
263            if (this.data[i][1] != 0) {
264                // we have data, O.K. to draw.
265                this._drawData = true;
266            }
267            stack.push(ndt[i][1]);
268            td.push([ndt[i][0]]);
269            if (i>0) {
270                stack[i] += stack[i-1];
271            }
272            tot += ndt[i][1];
273        }
274        var fact = Math.PI*2/stack[stack.length - 1];
275        
276        for (var i=0; i<stack.length; i++) {
277            td[i][1] = stack[i] * fact;
278            td[i][2] = ndt[i][1]/tot;
279        }
280        return td;
281    };
282
283    function calcRadiusAdjustment(ang) {
284        return Math.sin((ang - (ang-Math.PI) / 8 / Math.PI )/2.0);
285    }
286
287    function calcRPrime(ang1, ang2, sliceMargin, fill, lineWidth) {
288        var rprime = 0;
289        var ang = ang2 - ang1;
290        var absang = Math.abs(ang);
291        var sm = sliceMargin;
292        if (fill == false) {
293            sm += lineWidth;
294        }
295
296        if (sm > 0 && absang > 0.01 && absang < 6.282) {
297            rprime = parseFloat(sm) / 2.0 / calcRadiusAdjustment(ang);
298        }
299
300        return rprime;
301    }
302    
303    $.jqplot.PieRenderer.prototype.drawSlice = function (ctx, ang1, ang2, color, isShadow) {
304        if (this._drawData) {
305            var r = this._radius;
306            var fill = this.fill;
307            var lineWidth = this.lineWidth;
308            var sm = this.sliceMargin;
309            if (this.fill == false) {
310                sm += this.lineWidth;
311            }
312            ctx.save();
313            ctx.translate(this._center[0], this._center[1]);
314            
315            var rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);
316
317            var transx = rprime * Math.cos((ang1 + ang2) / 2.0);
318            var transy = rprime * Math.sin((ang1 + ang2) / 2.0);
319
320            if ((ang2 - ang1) <= Math.PI) {
321                r -= rprime;  
322            }
323            else {
324                r += rprime;
325            }
326
327            ctx.translate(transx, transy);
328            
329            if (isShadow) {
330                for (var i=0, l=this.shadowDepth; i<l; i++) {
331                    ctx.save();
332                    ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));
333                    doDraw(r);
334                }
335                for (var i=0, l=this.shadowDepth; i<l; i++) {
336                    ctx.restore();
337                }
338            }
339    
340            else {
341                doDraw(r);
342            }
343            ctx.restore();
344        }
345    
346        function doDraw (rad) {
347            // Fix for IE and Chrome that can't seem to draw circles correctly.
348            // ang2 should always be <= 2 pi since that is the way the data is converted.
349            // 2Pi = 6.2831853, Pi = 3.1415927
350             if (ang2 > 6.282 + this.startAngle) {
351                ang2 = 6.282 + this.startAngle;
352                if (ang1 > ang2) {
353                    ang1 = 6.281 + this.startAngle;
354                }
355            }
356            // Fix for IE, where it can't seem to handle 0 degree angles.  Also avoids
357            // ugly line on unfilled pies.
358            if (ang1 >= ang2) {
359                return;
360            }            
361        
362            ctx.beginPath();  
363            ctx.fillStyle = color;
364            ctx.strokeStyle = color;
365            ctx.lineWidth = lineWidth;
366            ctx.arc(0, 0, rad, ang1, ang2, false);
367            ctx.lineTo(0,0);
368            ctx.closePath();
369        
370            if (fill) {
371                ctx.fill();
372            }
373            else {
374                ctx.stroke();
375            }
376        }
377    };
378    
379    // called with scope of series
380    $.jqplot.PieRenderer.prototype.draw = function (ctx, gd, options, plot) {
381        var i;
382        var opts = (options != undefined) ? options : {};
383        // offset and direction of offset due to legend placement
384        var offx = 0;
385        var offy = 0;
386        var trans = 1;
387        var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);
388        var sliceColor;
389
390        if (options.legendInfo && options.legendInfo.placement == 'insideGrid') {
391            var li = options.legendInfo;
392            switch (li.location) {
393                case 'nw':
394                    offx = li.width + li.xoffset;
395                    break;
396                case 'w':
397                    offx = li.width + li.xoffset;
398                    break;
399                case 'sw':
400                    offx = li.width + li.xoffset;
401                    break;
402                case 'ne':
403                    offx = li.width + li.xoffset;
404                    trans = -1;
405                    break;
406                case 'e':
407                    offx = li.width + li.xoffset;
408                    trans = -1;
409                    break;
410                case 'se':
411                    offx = li.width + li.xoffset;
412                    trans = -1;
413                    break;
414                case 'n':
415                    offy = li.height + li.yoffset;
416                    break;
417                case 's':
418                    offy = li.height + li.yoffset;
419                    trans = -1;
420                    break;
421                default:
422                    break;
423            }
424        }
425        
426        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
427        var fill = (opts.fill != undefined) ? opts.fill : this.fill;
428        
429        //see http://stackoverflow.com/questions/20221461/hidpi-retina-plot-drawing
430        var cw = parseInt(ctx.canvas.style.width);
431        var ch = parseInt(ctx.canvas.style.height);
432        //
433        
434        var w = cw - offx - 2 * this.padding;
435        var h = ch - offy - 2 * this.padding;
436        var mindim = Math.min(w,h);
437        var d = mindim;
438        
439        // Fixes issue #272.  Thanks hugwijst!
440        // reset slice angles array.
441        this._sliceAngles = [];
442
443        var sm = this.sliceMargin;
444        if (this.fill == false) {
445            sm += this.lineWidth;
446        }
447        
448        var rprime;
449        var maxrprime = 0;
450
451        var ang, ang1, ang2, shadowColor;
452        var sa = this.startAngle / 180 * Math.PI;
453
454        // have to pre-draw shadows, so loop throgh here and calculate some values also.
455        for (var i=0, l=gd.length; i<l; i++) {
456            ang1 = (i == 0) ? sa : gd[i-1][1] + sa;
457            ang2 = gd[i][1] + sa;
458
459            this._sliceAngles.push([ang1, ang2]);
460
461            rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);
462
463            if (Math.abs(ang2-ang1) > Math.PI) {
464                maxrprime = Math.max(rprime, maxrprime);  
465            }
466        }
467
468        if (this.diameter != null && this.diameter > 0) {
469            this._diameter = this.diameter - 2*maxrprime;
470        }
471        else {
472            this._diameter = d - 2*maxrprime;
473        }
474
475        // Need to check for undersized pie.  This can happen if
476        // plot area too small and legend is too big.
477        if (this._diameter < 6) {
478            $.jqplot.log('Diameter of pie too small, not rendering.');
479            return;
480        }
481
482        var r = this._radius = this._diameter/2;
483
484        this._center = [(cw - trans * offx)/2 + trans * offx + maxrprime * Math.cos(sa), (ch - trans*offy)/2 + trans * offy + maxrprime * Math.sin(sa)];
485
486        if (this.shadow) {
487            for (var i=0, l=gd.length; i<l; i++) {
488                shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')';
489                this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], shadowColor, true);
490            }
491        }
492        
493        for (var i=0; i<gd.length; i++) {
494
495            sliceColor = colorGenerator.next();
496
497            if (this.showSlice[i]) {
498                this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], sliceColor, false);
499            
500                if (this.showDataLabels && gd[i][2]*100 >= this.dataLabelThreshold) {
501                    var fstr, avgang = (this._sliceAngles[i][0] + this._sliceAngles[i][1])/2, label;
502                
503                    if (this.dataLabels == 'label') {
504                        fstr = this.dataLabelFormatString || '%s';
505                        label = $.jqplot.sprintf(fstr, gd[i][0]);
506                    }
507                    else if (this.dataLabels == 'value') {
508                        fstr = this.dataLabelFormatString || '%d';
509                        label = $.jqplot.sprintf(fstr, this.data[i][1]);
510                    }
511                    else if (this.dataLabels == 'percent') {
512                        fstr = this.dataLabelFormatString || '%d%%';
513                        label = $.jqplot.sprintf(fstr, gd[i][2]*100);
514                    }
515                    else if (this.dataLabels.constructor == Array) {
516                        fstr = this.dataLabelFormatString || '%s';
517                        label = $.jqplot.sprintf(fstr, this.dataLabels[i]);
518                    }
519                
520                    var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge;
521                
522                    var x = this._center[0] + Math.cos(avgang) * fact + this.canvas._offsets.left;
523                    var y = this._center[1] + Math.sin(avgang) * fact + this.canvas._offsets.top;
524                
525                    var labelelem = $('<div class="jqplot-pie-series jqplot-data-label" style="position:absolute;">' + label + '</div>').insertBefore(plot.eventCanvas._elem);
526                    if (this.dataLabelCenterOn) {
527                        x -= labelelem.width()/2;
528                        y -= labelelem.height()/2;
529                    }
530                    else {
531                        x -= labelelem.width() * Math.sin(avgang/2);
532                        y -= labelelem.height()/2;
533                    }
534                    x = Math.round(x);
535                    y = Math.round(y);
536                    labelelem.css({left: x, top: y});
537                }
538            }
539        }            
540    };
541    
542    $.jqplot.PieAxisRenderer = function() {
543        $.jqplot.LinearAxisRenderer.call(this);
544    };
545    
546    $.jqplot.PieAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();
547    $.jqplot.PieAxisRenderer.prototype.constructor = $.jqplot.PieAxisRenderer;
548        
549    
550    // There are no traditional axes on a pie chart.  We just need to provide
551    // dummy objects with properties so the plot will render.
552    // called with scope of axis object.
553    $.jqplot.PieAxisRenderer.prototype.init = function(options){
554        //
555        this.tickRenderer = $.jqplot.PieTickRenderer;
556        $.extend(true, this, options);
557        // I don't think I'm going to need _dataBounds here.
558        // have to go Axis scaling in a way to fit chart onto plot area
559        // and provide u2p and p2u functionality for mouse cursor, etc.
560        // for convienence set _dataBounds to 0 and 100 and
561        // set min/max to 0 and 100.
562        this._dataBounds = {min:0, max:100};
563        this.min = 0;
564        this.max = 100;
565        this.showTicks = false;
566        this.ticks = [];
567        this.showMark = false;
568        this.show = false; 
569    };
570    
571    
572    
573    
574    $.jqplot.PieLegendRenderer = function(){
575        $.jqplot.TableLegendRenderer.call(this);
576    };
577    
578    $.jqplot.PieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();
579    $.jqplot.PieLegendRenderer.prototype.constructor = $.jqplot.PieLegendRenderer;
580    
581    /**
582     * Class: $.jqplot.PieLegendRenderer
583     * Legend Renderer specific to pie plots.  Set by default
584     * when user creates a pie plot.
585     */
586    $.jqplot.PieLegendRenderer.prototype.init = function(options) {
587        // Group: Properties
588        //
589        // prop: numberRows
590        // Maximum number of rows in the legend.  0 or null for unlimited.
591        this.numberRows = null;
592        // prop: numberColumns
593        // Maximum number of columns in the legend.  0 or null for unlimited.
594        this.numberColumns = null;
595        // prop: width
596        // Fixed with of legend.  0 or null for auto size
597        this.width = null;
598        $.extend(true, this, options);
599    };
600    
601    // called with context of legend
602    $.jqplot.PieLegendRenderer.prototype.draw = function() {
603        var legend = this;
604        if (this.show) {
605            var series = this._series;
606
607
608            this._elem = $(document.createElement('table'));
609            this._elem.addClass('jqplot-table-legend');
610
611            var ss = {position:'absolute'};
612            if (this.background) {
613                ss['background'] = this.background;
614            }
615            if (this.border) {
616                ss['border'] = this.border;
617            }
618            if (this.fontSize) {
619                ss['fontSize'] = this.fontSize;
620            }
621            if (this.fontFamily) {
622                ss['fontFamily'] = this.fontFamily;
623            }
624            if (this.textColor) {
625                ss['textColor'] = this.textColor;
626            }
627            if (this.marginTop != null) {
628                ss['marginTop'] = this.marginTop;
629            }
630            if (this.marginBottom != null) {
631                ss['marginBottom'] = this.marginBottom;
632            }
633            if (this.marginLeft != null) {
634                ss['marginLeft'] = this.marginLeft;
635            }
636            if (this.marginRight != null) {
637                ss['marginRight'] = this.marginRight;
638            }
639
640            this._elem.css(ss);
641
642            // Pie charts legends don't go by number of series, but by number of data points
643            // in the series.  Refactor things here for that.
644            
645            var pad = false, 
646                reverse = false,
647                nr, 
648                nc;
649            var s = series[0];
650            var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors);
651            
652            if (s.show) {
653                var pd = s.data;
654                if (this.numberRows) {
655                    nr = this.numberRows;
656                    if (!this.numberColumns){
657                        nc = Math.ceil(pd.length/nr);
658                    }
659                    else{
660                        nc = this.numberColumns;
661                    }
662                }
663                else if (this.numberColumns) {
664                    nc = this.numberColumns;
665                    nr = Math.ceil(pd.length/this.numberColumns);
666                }
667                else {
668                    nr = pd.length;
669                    nc = 1;
670                }
671                
672                var i, j;
673                var tr, td1, td2; 
674                var lt, tt, rs, color;
675                var idx = 0; 
676                var div0, div1;   
677                
678                for (i=0; i<nr; i++) {
679                    tr = $(document.createElement('tr'));
680                    tr.addClass('jqplot-table-legend');
681                    
682                    if (reverse){
683                        tr.prependTo(this._elem);
684                    }
685                    
686                    else{
687                        tr.appendTo(this._elem);
688                    }
689                    
690                    for (j=0; j<nc; j++) {
691                        if (idx < pd.length) {
692                            tt = '';
693                            if (this.labels[idx]) {
694                                lt = this.labels[idx];
695                            }
696                            else {
697                                if (typeof pd[idx][0] === 'object') {
698                                    lt = pd[idx][0][0].toString();
699                                    tt = pd[idx][0][1].toString();
700                                }
701                                else  {
702                                    lt = pd[idx][0].toString();
703                                }
704                            }
705                            //lt = this.labels[idx] || pd[idx][0].toString();
706                            color = colorGenerator.next();
707                            if (!reverse){
708                                if (i>0){
709                                    pad = true;
710                                }
711                                else{
712                                    pad = false;
713                                }
714                            }
715                            else{
716                                if (i == nr -1){
717                                    pad = false;
718                                }
719                                else{
720                                    pad = true;
721                                }
722                            }
723                            rs = (pad) ? this.rowSpacing : '0';
724
725
726
727                            td1 = $(document.createElement('td'));
728                            td1.addClass('jqplot-table-legend jqplot-table-legend-swatch');
729                            td1.css({textAlign: 'center', paddingTop: rs});
730
731                            div0 = $(document.createElement('div'));
732                            div0.addClass('jqplot-table-legend-swatch-outline');
733                            if (tt !== '') {
734                                div0.attr("title", tt);
735                            }
736                            div1 = $(document.createElement('div'));
737                            div1.addClass('jqplot-table-legend-swatch');
738                            div1.css({backgroundColor: color, borderColor: color});
739                            td1.append(div0.append(div1));
740
741                            td2 = $(document.createElement('td'));
742                            td2.addClass('jqplot-table-legend jqplot-table-legend-label');
743                            td2.css('paddingTop', rs);
744
745                            if (this.escapeHtml){
746                                td2.text(lt);
747                            }
748                            else {
749                                td2.html('<a title="' + tt + '">' + lt + "</a>");
750                            }
751                            if (reverse) {
752                                td2.prependTo(tr);
753                                td1.prependTo(tr);
754                            }
755                            else {
756                                td1.appendTo(tr);
757                                td2.appendTo(tr);
758                            }
759                            pad = true;
760                        }
761                        idx++;
762                    }   
763                }
764            }
765        }
766        return this._elem;                
767    };
768    
769    $.jqplot.PieRenderer.prototype.handleMove = function(ev, gridpos, datapos, neighbor, plot) {
770        if (neighbor) {
771            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
772            plot.target.trigger('jqplotDataMouseOver', ins);
773            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
774                plot.target.trigger('jqplotDataHighlight', ins);
775                highlight (plot, ins[0], ins[1]);
776            }
777        }
778        else if (neighbor == null) {
779            unhighlight (plot);
780        }
781    };
782    
783    
784    // this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]);
785    
786    // setup default renderers for axes and legend so user doesn't have to
787    // called with scope of plot
788    function preInit(target, data, options) {
789        options = options || {};
790        options.axesDefaults = options.axesDefaults || {};
791        options.legend = options.legend || {};
792        options.seriesDefaults = options.seriesDefaults || {};
793        // only set these if there is a pie series
794        var setopts = false;
vendor: 7,015 bytes, lines 795-963
795        if (options.seriesDefaults.renderer == $.jqplot.PieRenderer) {
796            setopts = true;
797        }
798        else if (options.series) {
799            for (var i=0; i < options.series.length; i++) {
800                if (options.series[i].renderer == $.jqplot.PieRenderer) {
801                    setopts = true;
802                }
803            }
804        }
805        
806        if (setopts) {
807            options.axesDefaults.renderer = $.jqplot.PieAxisRenderer;
808            options.legend.renderer = options.legend.renderer || $.jqplot.PieLegendRenderer;
809            options.legend.preDraw = true;
810            options.seriesDefaults.pointLabels = {show: false};
811        }
812    }
813    
814    function postInit(target, data, options) {
815        for (var i=0; i<this.series.length; i++) {
816            if (this.series[i].renderer.constructor == $.jqplot.PieRenderer) {
817                // don't allow mouseover and mousedown at same time.
818                if (this.series[i].highlightMouseOver) {
819                    this.series[i].highlightMouseDown = false;
820                }
821            }
822        }
823    }
824    
825    // called with scope of plot
826    function postParseOptions(options) {
827        for (var i=0; i<this.series.length; i++) {
828            this.series[i].seriesColors = this.seriesColors;
829            this.series[i].colorGenerator = $.jqplot.colorGenerator;
830        }
831    }
832    
833    function highlight (plot, sidx, pidx) {
834        if (plot.series[sidx].showSlice[pidx]) {
835            var s = plot.series[sidx];
836            var canvas = plot.plugins.pieRenderer.highlightCanvas;
837            canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);
838            s._highlightedPoint = pidx;
839            plot.plugins.pieRenderer.highlightedSeriesIndex = sidx;
840            s.renderer.drawSlice.call(s, canvas._ctx, s._sliceAngles[pidx][0], s._sliceAngles[pidx][1], s.highlightColorGenerator.get(pidx), false);
841        }
842    }
843    
844    function unhighlight (plot) {
845        var canvas = plot.plugins.pieRenderer.highlightCanvas;
846        canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);
847        for (var i=0; i<plot.series.length; i++) {
848            plot.series[i]._highlightedPoint = null;
849        }
850        plot.plugins.pieRenderer.highlightedSeriesIndex = null;
851        plot.target.trigger('jqplotDataUnhighlight');
852    }
853 
854    function handleMove(ev, gridpos, datapos, neighbor, plot) {
855        if (neighbor) {
856            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
857            var evt1 = jQuery.Event('jqplotDataMouseOver');
858            evt1.pageX = ev.pageX;
859            evt1.pageY = ev.pageY;
860            plot.target.trigger(evt1, ins);
861            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
862                var evt = jQuery.Event('jqplotDataHighlight');
863                evt.which = ev.which;
864                evt.pageX = ev.pageX;
865                evt.pageY = ev.pageY;
866                plot.target.trigger(evt, ins);
867                highlight (plot, ins[0], ins[1]);
868            }
869        }
870        else if (neighbor == null) {
871            unhighlight (plot);
872        }
873    } 
874    
875    function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
876        if (neighbor) {
877            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
878            if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
879                var evt = jQuery.Event('jqplotDataHighlight');
880                evt.which = ev.which;
881                evt.pageX = ev.pageX;
882                evt.pageY = ev.pageY;
883                plot.target.trigger(evt, ins);
884                highlight (plot, ins[0], ins[1]);
885            }
886        }
887        else if (neighbor == null) {
888            unhighlight (plot);
889        }
890    }
891    
892    function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {
893        var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;
894        if (idx != null && plot.series[idx].highlightMouseDown) {
895            unhighlight(plot);
896        }
897    }
898    
899    function handleClick(ev, gridpos, datapos, neighbor, plot) {
900        if (neighbor) {
901            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
902            var evt = jQuery.Event('jqplotDataClick');
903            evt.which = ev.which;
904            evt.pageX = ev.pageX;
905            evt.pageY = ev.pageY;
906            plot.target.trigger(evt, ins);
907        }
908    }
909    
910    function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
911        if (neighbor) {
912            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
913            var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;
914            if (idx != null && plot.series[idx].highlightMouseDown) {
915                unhighlight(plot);
916            }
917            var evt = jQuery.Event('jqplotDataRightClick');
918            evt.which = ev.which;
919            evt.pageX = ev.pageX;
920            evt.pageY = ev.pageY;
921            plot.target.trigger(evt, ins);
922        }
923    }    
924    
925    // called within context of plot
926    // create a canvas which we can draw on.
927    // insert it before the eventCanvas, so eventCanvas will still capture events.
928    function postPlotDraw() {
929        // Memory Leaks patch    
930        if (this.plugins.pieRenderer && this.plugins.pieRenderer.highlightCanvas) {
931            this.plugins.pieRenderer.highlightCanvas.resetCanvas();
932            this.plugins.pieRenderer.highlightCanvas = null;
933        }
934
935        this.plugins.pieRenderer = {highlightedSeriesIndex:null};
936        this.plugins.pieRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
937        
938        // do we have any data labels?  if so, put highlight canvas before those
939        var labels = $(this.targetId+' .jqplot-data-label');
940        if (labels.length) {
941            $(labels[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));
942        }
943        // else put highlight canvas before event canvas.
944        else {
945            this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));
946        }
947        
948        var hctx = this.plugins.pieRenderer.highlightCanvas.setContext();
949        this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });
950    }
951    
952    $.jqplot.preInitHooks.push(preInit);
953    
954    $.jqplot.PieTickRenderer = function() {
955        $.jqplot.AxisTickRenderer.call(this);
956    };
957    
958    $.jqplot.PieTickRenderer.prototype = new $.jqplot.AxisTickRenderer();
959    $.jqplot.PieTickRenderer.prototype.constructor = $.jqplot.PieTickRenderer;
960    
961})(jQuery);
962    
963    

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.