PageSourceSearch

https://www.dmcr.go.th/front/controller/script/vote/js/jqplot.pieRenderer.js?v=20180125

js dmcr.go.th collected 2026-10-02 05:55:13 UTC 38,489 bytes, 946 lines download raw bytes

1/**
2 * jqPlot
3 * Pure JavaScript plotting plugin using jQuery
4 *
5 * Version: 1.0.9
6 * Revision: d96a669
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        var stack = [];
240        var td = [];
241        var tot = 0;
242        var sa = this.startAngle/180*Math.PI;
243        // don't know if we have any valid data yet, so set plot to not draw.
244        this._drawData = false;
245        for (var i=0; i<data.length; i++){
246            if (this.data[i][1] != 0) {
247                // we have data, O.K. to draw.
248                this._drawData = true;
249            }
250            stack.push(data[i][1]);
251            td.push([data[i][0]]);
252            if (i>0) {
253                stack[i] += stack[i-1];
254            }
255            tot += data[i][1];
256        }
257        var fact = Math.PI*2/stack[stack.length - 1];
258        
259        for (var i=0; i<stack.length; i++) {
260            td[i][1] = stack[i] * fact;
261            td[i][2] = data[i][1]/tot;
262        }
263        return td;
264    };
265
266    function calcRadiusAdjustment(ang) {
267        return Math.sin((ang - (ang-Math.PI) / 8 / Math.PI )/2.0);
268    }
269
270    function calcRPrime(ang1, ang2, sliceMargin, fill, lineWidth) {
271        var rprime = 0;
272        var ang = ang2 - ang1;
273        var absang = Math.abs(ang);
274        var sm = sliceMargin;
275        if (fill == false) {
276            sm += lineWidth;
277        }
278
279        if (sm > 0 && absang > 0.01 && absang < 6.282) {
280            rprime = parseFloat(sm) / 2.0 / calcRadiusAdjustment(ang);
281        }
282
283        return rprime;
284    }
285    
286    $.jqplot.PieRenderer.prototype.drawSlice = function (ctx, ang1, ang2, color, isShadow) {
287        if (this._drawData) {
288            var r = this._radius;
289            var fill = this.fill;
290            var lineWidth = this.lineWidth;
291            var sm = this.sliceMargin;
292            if (this.fill == false) {
293                sm += this.lineWidth;
294            }
295            ctx.save();
296            ctx.translate(this._center[0], this._center[1]);
297            
298            var rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);
299
300            var transx = rprime * Math.cos((ang1 + ang2) / 2.0);
301            var transy = rprime * Math.sin((ang1 + ang2) / 2.0);
302
303            if ((ang2 - ang1) <= Math.PI) {
304                r -= rprime;  
305            }
306            else {
307                r += rprime;
308            }
309
310            ctx.translate(transx, transy);
311            
312            if (isShadow) {
313                for (var i=0, l=this.shadowDepth; i<l; i++) {
314                    ctx.save();
315                    ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));
316                    doDraw(r);
317                }
318                for (var i=0, l=this.shadowDepth; i<l; i++) {
319                    ctx.restore();
320                }
321            }
322    
323            else {
324                doDraw(r);
325            }
326            ctx.restore();
327        }
328    
329        function doDraw (rad) {
330            // Fix for IE and Chrome that can't seem to draw circles correctly.
331            // ang2 should always be <= 2 pi since that is the way the data is converted.
332            // 2Pi = 6.2831853, Pi = 3.1415927
333             if (ang2 > 6.282 + this.startAngle) {
334                ang2 = 6.282 + this.startAngle;
335                if (ang1 > ang2) {
336                    ang1 = 6.281 + this.startAngle;
337                }
338            }
339            // Fix for IE, where it can't seem to handle 0 degree angles.  Also avoids
340            // ugly line on unfilled pies.
341            if (ang1 >= ang2) {
342                return;
343            }            
344        
345            ctx.beginPath();  
346            ctx.fillStyle = color;
347            ctx.strokeStyle = color;
348            ctx.lineWidth = lineWidth;
349            ctx.arc(0, 0, rad, ang1, ang2, false);
350            ctx.lineTo(0,0);
351            ctx.closePath();
352        
353            if (fill) {
354                ctx.fill();
355            }
356            else {
357                ctx.stroke();
358            }
359        }
360    };
361    
362    // called with scope of series
363    $.jqplot.PieRenderer.prototype.draw = function (ctx, gd, options, plot) {
364        var i;
365        var opts = (options != undefined) ? options : {};
366        // offset and direction of offset due to legend placement
367        var offx = 0;
368        var offy = 0;
369        var trans = 1;
370        var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);
371        var sliceColor;
372
373        if (options.legendInfo && options.legendInfo.placement == 'insideGrid') {
374            var li = options.legendInfo;
375            switch (li.location) {
376                case 'nw':
377                    offx = li.width + li.xoffset;
378                    break;
379                case 'w':
380                    offx = li.width + li.xoffset;
381                    break;
382                case 'sw':
383                    offx = li.width + li.xoffset;
384                    break;
385                case 'ne':
386                    offx = li.width + li.xoffset;
387                    trans = -1;
388                    break;
389                case 'e':
390                    offx = li.width + li.xoffset;
391                    trans = -1;
392                    break;
393                case 'se':
394                    offx = li.width + li.xoffset;
395                    trans = -1;
396                    break;
397                case 'n':
398                    offy = li.height + li.yoffset;
399                    break;
400                case 's':
401                    offy = li.height + li.yoffset;
402                    trans = -1;
403                    break;
404                default:
405                    break;
406            }
407        }
408        
409        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
410        var fill = (opts.fill != undefined) ? opts.fill : this.fill;
411        
412        //see http://stackoverflow.com/questions/20221461/hidpi-retina-plot-drawing
413        var cw = parseInt(ctx.canvas.style.width);
414        var ch = parseInt(ctx.canvas.style.height);
415        //
416        
417        var w = cw - offx - 2 * this.padding;
418        var h = ch - offy - 2 * this.padding;
419        var mindim = Math.min(w,h);
420        var d = mindim;
421        
422        // Fixes issue #272.  Thanks hugwijst!
423        // reset slice angles array.
424        this._sliceAngles = [];
425
426        var sm = this.sliceMargin;
427        if (this.fill == false) {
428            sm += this.lineWidth;
429        }
430        
431        var rprime;
432        var maxrprime = 0;
433
434        var ang, ang1, ang2, shadowColor;
435        var sa = this.startAngle / 180 * Math.PI;
436
437        // have to pre-draw shadows, so loop throgh here and calculate some values also.
438        for (var i=0, l=gd.length; i<l; i++) {
439            ang1 = (i == 0) ? sa : gd[i-1][1] + sa;
440            ang2 = gd[i][1] + sa;
441
442            this._sliceAngles.push([ang1, ang2]);
443
444            rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);
445
446            if (Math.abs(ang2-ang1) > Math.PI) {
447                maxrprime = Math.max(rprime, maxrprime);  
448            }
449        }
450
451        if (this.diameter != null && this.diameter > 0) {
452            this._diameter = this.diameter - 2*maxrprime;
453        }
454        else {
455            this._diameter = d - 2*maxrprime;
456        }
457
458        // Need to check for undersized pie.  This can happen if
459        // plot area too small and legend is too big.
460        if (this._diameter < 6) {
461            $.jqplot.log('Diameter of pie too small, not rendering.');
462            return;
463        }
464
465        var r = this._radius = this._diameter/2;
466
467        this._center = [(cw - trans * offx)/2 + trans * offx + maxrprime * Math.cos(sa), (ch - trans*offy)/2 + trans * offy + maxrprime * Math.sin(sa)];
468
469        if (this.shadow) {
470            for (var i=0, l=gd.length; i<l; i++) {
471                shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')';
472                this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], shadowColor, true);
473            }
474        }
475        
476        for (var i=0; i<gd.length; i++) {
477
478            sliceColor = colorGenerator.next();
479
480            if (this.showSlice[i]) {
481                this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], sliceColor, false);
482            
483                if (this.showDataLabels && gd[i][2]*100 >= this.dataLabelThreshold) {
484                    var fstr, avgang = (this._sliceAngles[i][0] + this._sliceAngles[i][1])/2, label;
485                
486                    if (this.dataLabels == 'label') {
487                        fstr = this.dataLabelFormatString || '%s';
488                        label = $.jqplot.sprintf(fstr, gd[i][0]);
489                    }
490                    else if (this.dataLabels == 'value') {
491                        fstr = this.dataLabelFormatString || '%d';
492                        label = $.jqplot.sprintf(fstr, this.data[i][1]);
493                    }
494                    else if (this.dataLabels == 'percent') {
495                        fstr = this.dataLabelFormatString || '%d%%';
496                        label = $.jqplot.sprintf(fstr, gd[i][2]*100);
497                    }
498                    else if (this.dataLabels.constructor == Array) {
499                        fstr = this.dataLabelFormatString || '%s';
500                        label = $.jqplot.sprintf(fstr, this.dataLabels[i]);
501                    }
502                
503                    var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge;
504                
505                    var x = this._center[0] + Math.cos(avgang) * fact + this.canvas._offsets.left;
506                    var y = this._center[1] + Math.sin(avgang) * fact + this.canvas._offsets.top;
507                
508                    var labelelem = $('<div class="jqplot-pie-series jqplot-data-label" style="position:absolute;">' + label + '</div>').insertBefore(plot.eventCanvas._elem);
509                    if (this.dataLabelCenterOn) {
510                        x -= labelelem.width()/2;
511                        y -= labelelem.height()/2;
512                    }
513                    else {
514                        x -= labelelem.width() * Math.sin(avgang/2);
515                        y -= labelelem.height()/2;
516                    }
517                    x = Math.round(x);
518                    y = Math.round(y);
519                    labelelem.css({left: x, top: y});
520                }
521            }
522        }            
523    };
524    
525    $.jqplot.PieAxisRenderer = function() {
526        $.jqplot.LinearAxisRenderer.call(this);
527    };
528    
529    $.jqplot.PieAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();
530    $.jqplot.PieAxisRenderer.prototype.constructor = $.jqplot.PieAxisRenderer;
531        
532    
533    // There are no traditional axes on a pie chart.  We just need to provide
534    // dummy objects with properties so the plot will render.
535    // called with scope of axis object.
536    $.jqplot.PieAxisRenderer.prototype.init = function(options){
537        //
538        this.tickRenderer = $.jqplot.PieTickRenderer;
539        $.extend(true, this, options);
540        // I don't think I'm going to need _dataBounds here.
541        // have to go Axis scaling in a way to fit chart onto plot area
542        // and provide u2p and p2u functionality for mouse cursor, etc.
543        // for convienence set _dataBounds to 0 and 100 and
544        // set min/max to 0 and 100.
545        this._dataBounds = {min:0, max:100};
546        this.min = 0;
547        this.max = 100;
548        this.showTicks = false;
549        this.ticks = [];
550        this.showMark = false;
551        this.show = false; 
552    };
553    
554    
555    
556    
557    $.jqplot.PieLegendRenderer = function(){
558        $.jqplot.TableLegendRenderer.call(this);
559    };
560    
561    $.jqplot.PieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();
562    $.jqplot.PieLegendRenderer.prototype.constructor = $.jqplot.PieLegendRenderer;
563    
564    /**
565     * Class: $.jqplot.PieLegendRenderer
566     * Legend Renderer specific to pie plots.  Set by default
567     * when user creates a pie plot.
568     */
569    $.jqplot.PieLegendRenderer.prototype.init = function(options) {
570        // Group: Properties
571        //
572        // prop: numberRows
573        // Maximum number of rows in the legend.  0 or null for unlimited.
574        this.numberRows = null;
575        // prop: numberColumns
576        // Maximum number of columns in the legend.  0 or null for unlimited.
577        this.numberColumns = null;
578        // prop: width
579        // Fixed with of legend.  0 or null for auto size
580        this.width = null;
581        $.extend(true, this, options);
582    };
583    
584    // called with context of legend
585    $.jqplot.PieLegendRenderer.prototype.draw = function() {
586        var legend = this;
587        if (this.show) {
588            var series = this._series;
589
590
591            this._elem = $(document.createElement('table'));
592            this._elem.addClass('jqplot-table-legend');
593
594            var ss = {position:'absolute'};
595            if (this.background) {
596                ss['background'] = this.background;
597            }
598            if (this.border) {
599                ss['border'] = this.border;
600            }
601            if (this.fontSize) {
602                ss['fontSize'] = this.fontSize;
603            }
604            if (this.fontFamily) {
605                ss['fontFamily'] = this.fontFamily;
606            }
607            if (this.textColor) {
608                ss['textColor'] = this.textColor;
609            }
610            if (this.marginTop != null) {
611                ss['marginTop'] = this.marginTop;
612            }
613            if (this.marginBottom != null) {
614                ss['marginBottom'] = this.marginBottom;
615            }
616            if (this.marginLeft != null) {
617                ss['marginLeft'] = this.marginLeft;
618            }
619            if (this.marginRight != null) {
620                ss['marginRight'] = this.marginRight;
621            }
622
623            this._elem.css(ss);
624
625            // Pie charts legends don't go by number of series, but by number of data points
626            // in the series.  Refactor things here for that.
627            
628            var pad = false, 
629                reverse = false,
630                nr, 
631                nc;
632            var s = series[0];
633            var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors);
634            
635            if (s.show) {
636                var pd = s.data;
637                if (this.numberRows) {
638                    nr = this.numberRows;
639                    if (!this.numberColumns){
640                        nc = Math.ceil(pd.length/nr);
641                    }
642                    else{
643                        nc = this.numberColumns;
644                    }
645                }
646                else if (this.numberColumns) {
647                    nc = this.numberColumns;
648                    nr = Math.ceil(pd.length/this.numberColumns);
649                }
650                else {
651                    nr = pd.length;
652                    nc = 1;
653                }
654                
655                var i, j;
656                var tr, td1, td2; 
657                var lt, tt, rs, color;
658                var idx = 0; 
659                var div0, div1;   
660                
661                for (i=0; i<nr; i++) {
662                    tr = $(document.createElement('tr'));
663                    tr.addClass('jqplot-table-legend');
664                    
665                    if (reverse){
666                        tr.prependTo(this._elem);
667                    }
668                    
669                    else{
670                        tr.appendTo(this._elem);
671                    }
672                    
673                    for (j=0; j<nc; j++) {
674                        if (idx < pd.length) {
675                            tt = '';
676                            if (this.labels[idx]) {
677                                lt = this.labels[idx];
678                            }
679                            else {
680                                if (typeof pd[idx][0] === 'object') {
681                                    lt = pd[idx][0][0].toString();
682                                    tt = pd[idx][0][1].toString();
683                                }
684                                else  {
685                                    lt = pd[idx][0].toString();
686                                }
687                            }
688                            //lt = this.labels[idx] || pd[idx][0].toString();
689                            color = colorGenerator.next();
690                            if (!reverse){
691                                if (i>0){
692                                    pad = true;
693                                }
694                                else{
695                                    pad = false;
696                                }
697                            }
698                            else{
699                                if (i == nr -1){
700                                    pad = false;
701                                }
702                                else{
703                                    pad = true;
704                                }
705                            }
706                            rs = (pad) ? this.rowSpacing : '0';
707
708
709
710                            td1 = $(document.createElement('td'));
711                            td1.addClass('jqplot-table-legend jqplot-table-legend-swatch');
712                            td1.css({textAlign: 'center', paddingTop: rs});
713
714                            div0 = $(document.createElement('div'));
715                            div0.addClass('jqplot-table-legend-swatch-outline');
716                            if (tt !== '') {
717                                div0.attr("title", tt);
718                            }
719                            div1 = $(document.createElement('div'));
720                            div1.addClass('jqplot-table-legend-swatch');
721                            div1.css({backgroundColor: color, borderColor: color});
722                            td1.append(div0.append(div1));
723
724                            td2 = $(document.createElement('td'));
725                            td2.addClass('jqplot-table-legend jqplot-table-legend-label');
726                            td2.css('paddingTop', rs);
727
728                            if (this.escapeHtml){
729                                td2.text(lt);
730                            }
731                            else {
732                                td2.html('<a title="' + tt + '">' + lt + "</a>");
733                            }
734                            if (reverse) {
735                                td2.prependTo(tr);
736                                td1.prependTo(tr);
737                            }
738                            else {
739                                td1.appendTo(tr);
740                                td2.appendTo(tr);
741                            }
742                            pad = true;
743                        }
744                        idx++;
745                    }   
746                }
747            }
748        }
749        return this._elem;                
750    };
751    
752    $.jqplot.PieRenderer.prototype.handleMove = function(ev, gridpos, datapos, neighbor, plot) {
753        if (neighbor) {
754            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
755            plot.target.trigger('jqplotDataMouseOver', ins);
756            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
757                plot.target.trigger('jqplotDataHighlight', ins);
758                highlight (plot, ins[0], ins[1]);
759            }
760        }
761        else if (neighbor == null) {
762            unhighlight (plot);
763        }
764    };
765    
766    
767    // this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]);
768    
769    // setup default renderers for axes and legend so user doesn't have to
770    // called with scope of plot
771    function preInit(target, data, options) {
772        options = options || {};
773        options.axesDefaults = options.axesDefaults || {};
774        options.legend = options.legend || {};
775        options.seriesDefaults = options.seriesDefaults || {};
776        // only set these if there is a pie series
777        var setopts = false;
778        if (options.seriesDefaults.renderer == $.jqplot.PieRenderer) {
779            setopts = true;
780        }
781        else if (options.series) {
782            for (var i=0; i < options.series.length; i++) {
783                if (options.series[i].renderer == $.jqplot.PieRenderer) {
784                    setopts = true;
785                }
786            }
787        }
788        
789        if (setopts) {
790            options.axesDefaults.renderer = $.jqplot.PieAxisRenderer;
791            options.legend.renderer = options.legend.renderer || $.jqplot.PieLegendRenderer;
792            options.legend.preDraw = true;
793            options.seriesDefaults.pointLabels = {show: false};
794        }
795    }
796    
797    function postInit(target, data, options) {
798        for (var i=0; i<this.series.length; i++) {
799            if (this.series[i].renderer.constructor == $.jqplot.PieRenderer) {
800                // don't allow mouseover and mousedown at same time.
801                if (this.series[i].highlightMouseOver) {
802                    this.series[i].highlightMouseDown = false;
803                }
804            }
805        }
806    }
807    
808    // called with scope of plot
809    function postParseOptions(options) {
810        for (var i=0; i<this.series.length; i++) {
811            this.series[i].seriesColors = this.seriesColors;
812            this.series[i].colorGenerator = $.jqplot.colorGenerator;
813        }
814    }
815    
816    function highlight (plot, sidx, pidx) {
817        if (plot.series[sidx].showSlice[pidx]) {
818            var s = plot.series[sidx];
819            var canvas = plot.plugins.pieRenderer.highlightCanvas;
820            canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);
821            s._highlightedPoint = pidx;
822            plot.plugins.pieRenderer.highlightedSeriesIndex = sidx;
823            s.renderer.drawSlice.call(s, canvas._ctx, s._sliceAngles[pidx][0], s._sliceAngles[pidx][1], s.highlightColorGenerator.get(pidx), false);
824        }
825    }
826    
827    function unhighlight (plot) {
828        var canvas = plot.plugins.pieRenderer.highlightCanvas;
829        canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);
830        for (var i=0; i<plot.series.length; i++) {
831            plot.series[i]._highlightedPoint = null;
832        }
833        plot.plugins.pieRenderer.highlightedSeriesIndex = null;
834        plot.target.trigger('jqplotDataUnhighlight');
835    }
836 
837    function handleMove(ev, gridpos, datapos, neighbor, plot) {
838        if (neighbor) {
839            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
840            var evt1 = jQuery.Event('jqplotDataMouseOver');
841            evt1.pageX = ev.pageX;
842            evt1.pageY = ev.pageY;
843            plot.target.trigger(evt1, ins);
844            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
845                var evt = jQuery.Event('jqplotDataHighlight');
846                evt.which = ev.which;
847                evt.pageX = ev.pageX;
848                evt.pageY = ev.pageY;
849                plot.target.trigger(evt, ins);
vendor: 4,001 bytes, lines 850-946
850                highlight (plot, ins[0], ins[1]);
851            }
852        }
853        else if (neighbor == null) {
854            unhighlight (plot);
855        }
856    } 
857    
858    function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
859        if (neighbor) {
860            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
861            if (plot.series[ins[0]].highlightMouseDown && !(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 handleMouseUp(ev, gridpos, datapos, neighbor, plot) {
876        var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;
877        if (idx != null && plot.series[idx].highlightMouseDown) {
878            unhighlight(plot);
879        }
880    }
881    
882    function handleClick(ev, gridpos, datapos, neighbor, plot) {
883        if (neighbor) {
884            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
885            var evt = jQuery.Event('jqplotDataClick');
886            evt.which = ev.which;
887            evt.pageX = ev.pageX;
888            evt.pageY = ev.pageY;
889            plot.target.trigger(evt, ins);
890        }
891    }
892    
893    function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
894        if (neighbor) {
895            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];
896            var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;
897            if (idx != null && plot.series[idx].highlightMouseDown) {
898                unhighlight(plot);
899            }
900            var evt = jQuery.Event('jqplotDataRightClick');
901            evt.which = ev.which;
902            evt.pageX = ev.pageX;
903            evt.pageY = ev.pageY;
904            plot.target.trigger(evt, ins);
905        }
906    }    
907    
908    // called within context of plot
909    // create a canvas which we can draw on.
910    // insert it before the eventCanvas, so eventCanvas will still capture events.
911    function postPlotDraw() {
912        // Memory Leaks patch    
913        if (this.plugins.pieRenderer && this.plugins.pieRenderer.highlightCanvas) {
914            this.plugins.pieRenderer.highlightCanvas.resetCanvas();
915            this.plugins.pieRenderer.highlightCanvas = null;
916        }
917
918        this.plugins.pieRenderer = {highlightedSeriesIndex:null};
919        this.plugins.pieRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
920        
921        // do we have any data labels?  if so, put highlight canvas before those
922        var labels = $(this.targetId+' .jqplot-data-label');
923        if (labels.length) {
924            $(labels[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));
925        }
926        // else put highlight canvas before event canvas.
927        else {
928            this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));
929        }
930        
931        var hctx = this.plugins.pieRenderer.highlightCanvas.setContext();
932        this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });
933    }
934    
935    $.jqplot.preInitHooks.push(preInit);
936    
937    $.jqplot.PieTickRenderer = function() {
938        $.jqplot.AxisTickRenderer.call(this);
939    };
940    
941    $.jqplot.PieTickRenderer.prototype = new $.jqplot.AxisTickRenderer();
942    $.jqplot.PieTickRenderer.prototype.constructor = $.jqplot.PieTickRenderer;
943    
944})(jQuery);
945    
946    

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.