Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OaaS/HeuristicLab.Services.Optimization.Web/Content/jqplot/src/plugins/jqplot.pieRenderer.js @ 9335

Last change on this file since 9335 was 9062, checked in by fschoepp, 12 years ago

#1888:
Backend changes:

  • Simplified job state detection (only one hive call will be made to detect all states now, instead of one additional call per job)
  • Reorganized classes (moved model classes into Model folder)

Website changes:

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