outfielding-jqplot-rails 1.0.8 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +8 -4
  4. data/changes-jqplot.txt +48 -37
  5. data/copyright-jqplot.txt +17 -17
  6. data/lib/outfielding-jqplot-rails/version.rb +1 -1
  7. data/vendor/assets/javascripts/excanvas.js +1438 -1438
  8. data/vendor/assets/javascripts/jqplot-plugins/jqplot.BezierCurveRenderer.js +313 -313
  9. data/vendor/assets/javascripts/jqplot-plugins/jqplot.barRenderer.js +801 -801
  10. data/vendor/assets/javascripts/jqplot-plugins/jqplot.blockRenderer.js +234 -234
  11. data/vendor/assets/javascripts/jqplot-plugins/jqplot.bubbleRenderer.js +758 -758
  12. data/vendor/assets/javascripts/jqplot-plugins/jqplot.canvasAxisLabelRenderer.js +202 -202
  13. data/vendor/assets/javascripts/jqplot-plugins/jqplot.canvasAxisTickRenderer.js +252 -252
  14. data/vendor/assets/javascripts/jqplot-plugins/jqplot.canvasOverlay.js +1020 -1020
  15. data/vendor/assets/javascripts/jqplot-plugins/jqplot.canvasTextRenderer.js +448 -448
  16. data/vendor/assets/javascripts/jqplot-plugins/jqplot.categoryAxisRenderer.js +679 -679
  17. data/vendor/assets/javascripts/jqplot-plugins/jqplot.ciParser.js +115 -115
  18. data/vendor/assets/javascripts/jqplot-plugins/jqplot.cursor.js +1108 -1108
  19. data/vendor/assets/javascripts/jqplot-plugins/jqplot.dateAxisRenderer.js +741 -741
  20. data/vendor/assets/javascripts/jqplot-plugins/jqplot.donutRenderer.js +816 -805
  21. data/vendor/assets/javascripts/jqplot-plugins/jqplot.dragable.js +224 -224
  22. data/vendor/assets/javascripts/jqplot-plugins/jqplot.enhancedLegendRenderer.js +305 -305
  23. data/vendor/assets/javascripts/jqplot-plugins/jqplot.enhancedPieLegendRenderer.js +261 -0
  24. data/vendor/assets/javascripts/jqplot-plugins/jqplot.funnelRenderer.js +942 -942
  25. data/vendor/assets/javascripts/jqplot-plugins/jqplot.highlighter.js +464 -464
  26. data/vendor/assets/javascripts/jqplot-plugins/jqplot.json2.js +475 -475
  27. data/vendor/assets/javascripts/jqplot-plugins/jqplot.logAxisRenderer.js +533 -533
  28. data/vendor/assets/javascripts/jqplot-plugins/jqplot.mekkoAxisRenderer.js +611 -611
  29. data/vendor/assets/javascripts/jqplot-plugins/jqplot.mekkoRenderer.js +437 -437
  30. data/vendor/assets/javascripts/jqplot-plugins/jqplot.meterGaugeRenderer.js +1029 -1029
  31. data/vendor/assets/javascripts/jqplot-plugins/jqplot.mobile.js +2 -2
  32. data/vendor/assets/javascripts/jqplot-plugins/jqplot.ohlcRenderer.js +373 -373
  33. data/vendor/assets/javascripts/jqplot-plugins/jqplot.pieRenderer.js +945 -903
  34. data/vendor/assets/javascripts/jqplot-plugins/jqplot.pointLabels.js +379 -377
  35. data/vendor/assets/javascripts/jqplot-plugins/jqplot.pyramidAxisRenderer.js +728 -728
  36. data/vendor/assets/javascripts/jqplot-plugins/jqplot.pyramidGridRenderer.js +428 -428
  37. data/vendor/assets/javascripts/jqplot-plugins/jqplot.pyramidRenderer.js +513 -513
  38. data/vendor/assets/javascripts/jqplot-plugins/jqplot.trendline.js +222 -222
  39. data/vendor/assets/javascripts/jquery.jqplot.js +11477 -11411
  40. data/vendor/assets/stylesheets/jquery.jqplot.css +259 -259
  41. metadata +9 -10
@@ -1,759 +1,759 @@
1
- /**
2
- * jqPlot
3
- * Pure JavaScript plotting plugin using jQuery
4
- *
5
- * Version: 1.0.8
6
- * Revision: 1250
7
- *
8
- * Copyright (c) 2009-2013 Chris Leonello
9
- * jqPlot is currently available for use in all personal or commercial projects
10
- * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
11
- * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
12
- * choose the license that best suits your project and use it accordingly.
13
- *
14
- * Although not required, the author would appreciate an email letting him
15
- * know of any substantial use of jqPlot. You can reach the author at:
16
- * chris at jqplot dot com or see http://www.jqplot.com/info.php .
17
- *
18
- * If you are feeling kind and generous, consider supporting the project by
19
- * making a donation at: http://www.jqplot.com/donate.php .
20
- *
21
- * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
22
- *
23
- * version 2007.04.27
24
- * author Ash Searle
25
- * http://hexmen.com/blog/2007/03/printf-sprintf/
26
- * http://hexmen.com/js/sprintf.js
27
- * The author (Ash Searle) has placed this code in the public domain:
28
- * "This code is unrestricted: you are free to use it however you like."
29
- *
30
- */
31
- (function($) {
32
- var arrayMax = function( array ){
33
- return Math.max.apply( Math, array );
34
- };
35
- var arrayMin = function( array ){
36
- return Math.min.apply( Math, array );
37
- };
38
-
39
- /**
40
- * Class: $.jqplot.BubbleRenderer
41
- * Plugin renderer to draw a bubble chart. A Bubble chart has data points displayed as
42
- * colored circles with an optional text label inside. To use
43
- * the bubble renderer, you must include the bubble renderer like:
44
- *
45
- * > <script language="javascript" type="text/javascript" src="../src/plugins/jqplot.bubbleRenderer.js"></script>
46
- *
47
- * Data must be supplied in
48
- * the form:
49
- *
50
- * > [[x1, y1, r1, <label or {label:'text', color:color}>], ...]
51
- *
52
- * where the label or options
53
- * object is optional.
54
- *
55
- * Note that all bubble colors will be the same
56
- * unless the "varyBubbleColors" option is set to true. Colors can be specified in the data array
57
- * or in the seriesColors array option on the series. If no colors are defined, the default jqPlot
58
- * series of 16 colors are used. Colors are automatically cycled around again if there are more
59
- * bubbles than colors.
60
- *
61
- * Bubbles are autoscaled by default to fit within the chart area while maintaining
62
- * relative sizes. If the "autoscaleBubbles" option is set to false, the r(adius) values
63
- * in the data array a treated as literal pixel values for the radii of the bubbles.
64
- *
65
- * Properties are passed into the bubble renderer in the rendererOptions object of
66
- * the series options like:
67
- *
68
- * > seriesDefaults: {
69
- * > renderer: $.jqplot.BubbleRenderer,
70
- * > rendererOptions: {
71
- * > bubbleAlpha: 0.7,
72
- * > varyBubbleColors: false
73
- * > }
74
- * > }
75
- *
76
- */
77
- $.jqplot.BubbleRenderer = function(){
78
- $.jqplot.LineRenderer.call(this);
79
- };
80
-
81
- $.jqplot.BubbleRenderer.prototype = new $.jqplot.LineRenderer();
82
- $.jqplot.BubbleRenderer.prototype.constructor = $.jqplot.BubbleRenderer;
83
-
84
- // called with scope of a series
85
- $.jqplot.BubbleRenderer.prototype.init = function(options, plot) {
86
- // Group: Properties
87
- //
88
- // prop: varyBubbleColors
89
- // True to vary the color of each bubble in this series according to
90
- // the seriesColors array. False to set each bubble to the color
91
- // specified on this series. This has no effect if a css background color
92
- // option is specified in the renderer css options.
93
- this.varyBubbleColors = true;
94
- // prop: autoscaleBubbles
95
- // True to scale the bubble radius based on plot size.
96
- // False will use the radius value as provided as a raw pixel value for
97
- // bubble radius.
98
- this.autoscaleBubbles = true;
99
- // prop: autoscaleMultiplier
100
- // Multiplier the bubble size if autoscaleBubbles is true.
101
- this.autoscaleMultiplier = 1.0;
102
- // prop: autoscalePointsFactor
103
- // Factor which decreases bubble size based on how many bubbles on on the chart.
104
- // 0 means no adjustment for number of bubbles. Negative values will decrease
105
- // size of bubbles as more bubbles are added. Values between 0 and -0.2
106
- // should work well.
107
- this.autoscalePointsFactor = -0.07;
108
- // prop: escapeHtml
109
- // True to escape html in bubble label text.
110
- this.escapeHtml = true;
111
- // prop: highlightMouseOver
112
- // True to highlight bubbles when moused over.
113
- // This must be false to enable highlightMouseDown to highlight when clicking on a slice.
114
- this.highlightMouseOver = true;
115
- // prop: highlightMouseDown
116
- // True to highlight when a mouse button is pressed over a bubble.
117
- // This will be disabled if highlightMouseOver is true.
118
- this.highlightMouseDown = false;
119
- // prop: highlightColors
120
- // An array of colors to use when highlighting a slice. Calculated automatically
121
- // if not supplied.
122
- this.highlightColors = [];
123
- // prop: bubbleAlpha
124
- // Alpha transparency to apply to all bubbles in this series.
125
- this.bubbleAlpha = 1.0;
126
- // prop: highlightAlpha
127
- // Alpha transparency to apply when highlighting bubble.
128
- // Set to value of bubbleAlpha by default.
129
- this.highlightAlpha = null;
130
- // prop: bubbleGradients
131
- // True to color the bubbles with gradient fills instead of flat colors.
132
- // NOT AVAILABLE IN IE due to lack of excanvas support for radial gradient fills.
133
- // will be ignored in IE.
134
- this.bubbleGradients = false;
135
- // prop: showLabels
136
- // True to show labels on bubbles (if any), false to not show.
137
- this.showLabels = true;
138
- // array of [point index, radius] which will be sorted in descending order to plot
139
- // largest points below smaller points.
140
- this.radii = [];
141
- this.maxRadius = 0;
142
- // index of the currenty highlighted point, if any
143
- this._highlightedPoint = null;
144
- // array of jQuery labels.
145
- this.labels = [];
146
- this.bubbleCanvases = [];
147
- this._type = 'bubble';
148
-
149
- // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver
150
- if (options.highlightMouseDown && options.highlightMouseOver == null) {
151
- options.highlightMouseOver = false;
152
- }
153
-
154
- $.extend(true, this, options);
155
-
156
- if (this.highlightAlpha == null) {
157
- this.highlightAlpha = this.bubbleAlpha;
158
- if (this.bubbleGradients) {
159
- this.highlightAlpha = 0.35;
160
- }
161
- }
162
-
163
- this.autoscaleMultiplier = this.autoscaleMultiplier * Math.pow(this.data.length, this.autoscalePointsFactor);
164
-
165
- // index of the currenty highlighted point, if any
166
- this._highlightedPoint = null;
167
-
168
- // adjust the series colors for options colors passed in with data or for alpha.
169
- // note, this can leave undefined holes in the seriesColors array.
170
- var comps;
171
- for (var i=0; i<this.data.length; i++) {
172
- var color = null;
173
- var d = this.data[i];
174
- this.maxRadius = Math.max(this.maxRadius, d[2]);
175
- if (d[3]) {
176
- if (typeof(d[3]) == 'object') {
177
- color = d[3]['color'];
178
- }
179
- }
180
-
181
- if (color == null) {
182
- if (this.seriesColors[i] != null) {
183
- color = this.seriesColors[i];
184
- }
185
- }
186
-
187
- if (color && this.bubbleAlpha < 1.0) {
188
- comps = $.jqplot.getColorComponents(color);
189
- color = 'rgba('+comps[0]+', '+comps[1]+', '+comps[2]+', '+this.bubbleAlpha+')';
190
- }
191
-
192
- if (color) {
193
- this.seriesColors[i] = color;
194
- }
195
- }
196
-
197
- if (!this.varyBubbleColors) {
198
- this.seriesColors = [this.color];
199
- }
200
-
201
- this.colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);
202
-
203
- // set highlight colors if none provided
204
- if (this.highlightColors.length == 0) {
205
- for (var i=0; i<this.seriesColors.length; i++){
206
- var rgba = $.jqplot.getColorComponents(this.seriesColors[i]);
207
- var newrgb = [rgba[0], rgba[1], rgba[2]];
208
- var sum = newrgb[0] + newrgb[1] + newrgb[2];
209
- for (var j=0; j<3; j++) {
210
- // when darkening, lowest color component can be is 60.
211
- newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);
212
- newrgb[j] = parseInt(newrgb[j], 10);
213
- }
214
- this.highlightColors.push('rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+', '+this.highlightAlpha+')');
215
- }
216
- }
217
-
218
- this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors);
219
-
220
- var sopts = {fill:true, isarc:true, angle:this.shadowAngle, alpha:this.shadowAlpha, closePath:true};
221
-
222
- this.renderer.shadowRenderer.init(sopts);
223
-
224
- this.canvas = new $.jqplot.DivCanvas();
225
- this.canvas._plotDimensions = this._plotDimensions;
226
-
227
- plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);
228
- plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);
229
- plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);
230
- plot.eventListenerHooks.addOnce('jqplotClick', handleClick);
231
- plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);
232
- plot.postDrawHooks.addOnce(postPlotDraw);
233
-
234
- };
235
-
236
-
237
- // converts the user data values to grid coordinates and stores them
238
- // in the gridData array.
239
- // Called with scope of a series.
240
- $.jqplot.BubbleRenderer.prototype.setGridData = function(plot) {
241
- // recalculate the grid data
242
- var xp = this._xaxis.series_u2p;
243
- var yp = this._yaxis.series_u2p;
244
- var data = this._plotData;
245
- this.gridData = [];
246
- var radii = [];
247
- this.radii = [];
248
- var dim = Math.min(plot._height, plot._width);
249
- for (var i=0; i<this.data.length; i++) {
250
- if (data[i] != null) {
251
- this.gridData.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1]), data[i][2]]);
252
- this.radii.push([i, data[i][2]]);
253
- radii.push(data[i][2]);
254
- }
255
- }
256
- var r, val, maxr = this.maxRadius = arrayMax(radii);
257
- var l = this.gridData.length;
258
- if (this.autoscaleBubbles) {
259
- for (var i=0; i<l; i++) {
260
- val = radii[i]/maxr;
261
- r = this.autoscaleMultiplier * dim / 6;
262
- this.gridData[i][2] = r * val;
263
- }
264
- }
265
-
266
- this.radii.sort(function(a, b) { return b[1] - a[1]; });
267
- };
268
-
269
- // converts any arbitrary data values to grid coordinates and
270
- // returns them. This method exists so that plugins can use a series'
271
- // linerenderer to generate grid data points without overwriting the
272
- // grid data associated with that series.
273
- // Called with scope of a series.
274
- $.jqplot.BubbleRenderer.prototype.makeGridData = function(data, plot) {
275
- // recalculate the grid data
276
- var xp = this._xaxis.series_u2p;
277
- var yp = this._yaxis.series_u2p;
278
- var gd = [];
279
- var radii = [];
280
- this.radii = [];
281
- var dim = Math.min(plot._height, plot._width);
282
- for (var i=0; i<data.length; i++) {
283
- if (data[i] != null) {
284
- gd.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1]), data[i][2]]);
285
- radii.push(data[i][2]);
286
- this.radii.push([i, data[i][2]]);
287
- }
288
- }
289
- var r, val, maxr = this.maxRadius = arrayMax(radii);
290
- var l = this.gridData.length;
291
- if (this.autoscaleBubbles) {
292
- for (var i=0; i<l; i++) {
293
- val = radii[i]/maxr;
294
- r = this.autoscaleMultiplier * dim / 6;
295
- gd[i][2] = r * val;
296
- }
297
- }
298
- this.radii.sort(function(a, b) { return b[1] - a[1]; });
299
- return gd;
300
- };
301
-
302
- // called with scope of series
303
- $.jqplot.BubbleRenderer.prototype.draw = function (ctx, gd, options) {
304
- if (this.plugins.pointLabels) {
305
- this.plugins.pointLabels.show = false;
306
- }
307
- var opts = (options != undefined) ? options : {};
308
- var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
309
- this.canvas._elem.empty();
310
- for (var i=0; i<this.radii.length; i++) {
311
- var idx = this.radii[i][0];
312
- var t=null;
313
- var color = null;
314
- var el = null;
315
- var tel = null;
316
- var d = this.data[idx];
317
- var gd = this.gridData[idx];
318
- if (d[3]) {
319
- if (typeof(d[3]) == 'object') {
320
- t = d[3]['label'];
321
- }
322
- else if (typeof(d[3]) == 'string') {
323
- t = d[3];
324
- }
325
- }
326
-
327
- // color = (this.varyBubbleColors) ? this.colorGenerator.get(idx) : this.color;
328
- color = this.colorGenerator.get(idx);
329
-
330
- // If we're drawing a shadow, expand the canvas dimensions to accomodate.
331
- var canvasRadius = gd[2];
332
- var offset, depth;
333
- if (this.shadow) {
334
- offset = (0.7 + gd[2]/40).toFixed(1);
335
- depth = 1 + Math.ceil(gd[2]/15);
336
- canvasRadius += offset*depth;
337
- }
338
- this.bubbleCanvases[idx] = new $.jqplot.BubbleCanvas();
339
- this.canvas._elem.append(this.bubbleCanvases[idx].createElement(gd[0], gd[1], canvasRadius));
340
- this.bubbleCanvases[idx].setContext();
341
- var ctx = this.bubbleCanvases[idx]._ctx;
342
- var x = ctx.canvas.width/2;
343
- var y = ctx.canvas.height/2;
344
- if (this.shadow) {
345
- this.renderer.shadowRenderer.draw(ctx, [x, y, gd[2], 0, 2*Math.PI], {offset: offset, depth: depth});
346
- }
347
- this.bubbleCanvases[idx].draw(gd[2], color, this.bubbleGradients, this.shadowAngle/180*Math.PI);
348
-
349
- // now draw label.
350
- if (t && this.showLabels) {
351
- tel = $('<div style="position:absolute;" class="jqplot-bubble-label"></div>');
352
- if (this.escapeHtml) {
353
- tel.text(t);
354
- }
355
- else {
356
- tel.html(t);
357
- }
358
- this.canvas._elem.append(tel);
359
- var h = $(tel).outerHeight();
360
- var w = $(tel).outerWidth();
361
- var top = gd[1] - 0.5*h;
362
- var left = gd[0] - 0.5*w;
363
- tel.css({top: top, left: left});
364
- this.labels[idx] = $(tel);
365
- }
366
- }
367
- };
368
-
369
-
370
- $.jqplot.DivCanvas = function() {
371
- $.jqplot.ElemContainer.call(this);
372
- this._ctx;
373
- };
374
-
375
- $.jqplot.DivCanvas.prototype = new $.jqplot.ElemContainer();
376
- $.jqplot.DivCanvas.prototype.constructor = $.jqplot.DivCanvas;
377
-
378
- $.jqplot.DivCanvas.prototype.createElement = function(offsets, clss, plotDimensions) {
379
- this._offsets = offsets;
380
- var klass = 'jqplot-DivCanvas';
381
- if (clss != undefined) {
382
- klass = clss;
383
- }
384
- var elem;
385
- // if this canvas already has a dom element, don't make a new one.
386
- if (this._elem) {
387
- elem = this._elem.get(0);
388
- }
389
- else {
390
- elem = document.createElement('div');
391
- }
392
- // if new plotDimensions supplied, use them.
393
- if (plotDimensions != undefined) {
394
- this._plotDimensions = plotDimensions;
395
- }
396
-
397
- var w = this._plotDimensions.width - this._offsets.left - this._offsets.right + 'px';
398
- var h = this._plotDimensions.height - this._offsets.top - this._offsets.bottom + 'px';
399
- this._elem = $(elem);
400
- this._elem.css({ position: 'absolute', width:w, height:h, left: this._offsets.left, top: this._offsets.top });
401
-
402
- this._elem.addClass(klass);
403
- return this._elem;
404
- };
405
-
406
- $.jqplot.DivCanvas.prototype.setContext = function() {
407
- this._ctx = {
408
- canvas:{
409
- width:0,
410
- height:0
411
- },
412
- clearRect:function(){return null;}
413
- };
414
- return this._ctx;
415
- };
416
-
417
- $.jqplot.BubbleCanvas = function() {
418
- $.jqplot.ElemContainer.call(this);
419
- this._ctx;
420
- };
421
-
422
- $.jqplot.BubbleCanvas.prototype = new $.jqplot.ElemContainer();
423
- $.jqplot.BubbleCanvas.prototype.constructor = $.jqplot.BubbleCanvas;
424
-
425
- // initialize with the x,y pont of bubble center and the bubble radius.
426
- $.jqplot.BubbleCanvas.prototype.createElement = function(x, y, r) {
427
- var klass = 'jqplot-bubble-point';
428
-
429
- var elem;
430
- // if this canvas already has a dom element, don't make a new one.
431
- if (this._elem) {
432
- elem = this._elem.get(0);
433
- }
434
- else {
435
- elem = document.createElement('canvas');
436
- }
437
-
438
- elem.width = (r != null) ? 2*r : elem.width;
439
- elem.height = (r != null) ? 2*r : elem.height;
440
- this._elem = $(elem);
441
- var l = (x != null && r != null) ? x - r : this._elem.css('left');
442
- var t = (y != null && r != null) ? y - r : this._elem.css('top');
443
- this._elem.css({ position: 'absolute', left: l, top: t });
444
-
445
- this._elem.addClass(klass);
446
- if ($.jqplot.use_excanvas) {
447
- window.G_vmlCanvasManager.init_(document);
448
- elem = window.G_vmlCanvasManager.initElement(elem);
449
- }
450
-
451
- return this._elem;
452
- };
453
-
454
- $.jqplot.BubbleCanvas.prototype.draw = function(r, color, gradients, angle) {
455
- var ctx = this._ctx;
456
- // r = Math.floor(r*1.04);
457
- // var x = Math.round(ctx.canvas.width/2);
458
- // var y = Math.round(ctx.canvas.height/2);
459
- var x = ctx.canvas.width/2;
460
- var y = ctx.canvas.height/2;
461
- ctx.save();
462
- if (gradients && !$.jqplot.use_excanvas) {
463
- r = r*1.04;
464
- var comps = $.jqplot.getColorComponents(color);
465
- var colorinner = 'rgba('+Math.round(comps[0]+0.8*(255-comps[0]))+', '+Math.round(comps[1]+0.8*(255-comps[1]))+', '+Math.round(comps[2]+0.8*(255-comps[2]))+', '+comps[3]+')';
466
- var colorend = 'rgba('+comps[0]+', '+comps[1]+', '+comps[2]+', 0)';
467
- // var rinner = Math.round(0.35 * r);
468
- // var xinner = Math.round(x - Math.cos(angle) * 0.33 * r);
469
- // var yinner = Math.round(y - Math.sin(angle) * 0.33 * r);
470
- var rinner = 0.35 * r;
471
- var xinner = x - Math.cos(angle) * 0.33 * r;
472
- var yinner = y - Math.sin(angle) * 0.33 * r;
473
- var radgrad = ctx.createRadialGradient(xinner, yinner, rinner, x, y, r);
474
- radgrad.addColorStop(0, colorinner);
475
- radgrad.addColorStop(0.93, color);
476
- radgrad.addColorStop(0.96, colorend);
477
- radgrad.addColorStop(1, colorend);
478
- // radgrad.addColorStop(.98, colorend);
479
- ctx.fillStyle = radgrad;
480
- ctx.fillRect(0,0, ctx.canvas.width, ctx.canvas.height);
481
- }
482
- else {
483
- ctx.fillStyle = color;
484
- ctx.strokeStyle = color;
485
- ctx.lineWidth = 1;
486
- ctx.beginPath();
487
- var ang = 2*Math.PI;
488
- ctx.arc(x, y, r, 0, ang, 0);
489
- ctx.closePath();
490
- ctx.fill();
491
- }
492
- ctx.restore();
493
- };
494
-
495
- $.jqplot.BubbleCanvas.prototype.setContext = function() {
496
- this._ctx = this._elem.get(0).getContext("2d");
497
- return this._ctx;
498
- };
499
-
500
- $.jqplot.BubbleAxisRenderer = function() {
501
- $.jqplot.LinearAxisRenderer.call(this);
502
- };
503
-
504
- $.jqplot.BubbleAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();
505
- $.jqplot.BubbleAxisRenderer.prototype.constructor = $.jqplot.BubbleAxisRenderer;
506
-
507
- // called with scope of axis object.
508
- $.jqplot.BubbleAxisRenderer.prototype.init = function(options){
509
- $.extend(true, this, options);
510
- var db = this._dataBounds;
511
- var minsidx = 0,
512
- minpidx = 0,
513
- maxsidx = 0,
514
- maxpidx = 0,
515
- maxr = 0,
516
- minr = 0,
517
- minMaxRadius = 0,
518
- maxMaxRadius = 0,
519
- maxMult = 0,
520
- minMult = 0;
521
- // Go through all the series attached to this axis and find
522
- // the min/max bounds for this axis.
523
- for (var i=0; i<this._series.length; i++) {
524
- var s = this._series[i];
525
- var d = s._plotData;
526
-
527
- for (var j=0; j<d.length; j++) {
528
- if (this.name == 'xaxis' || this.name == 'x2axis') {
529
- if (d[j][0] < db.min || db.min == null) {
530
- db.min = d[j][0];
531
- minsidx=i;
532
- minpidx=j;
533
- minr = d[j][2];
534
- minMaxRadius = s.maxRadius;
535
- minMult = s.autoscaleMultiplier;
536
- }
537
- if (d[j][0] > db.max || db.max == null) {
538
- db.max = d[j][0];
539
- maxsidx=i;
540
- maxpidx=j;
541
- maxr = d[j][2];
542
- maxMaxRadius = s.maxRadius;
543
- maxMult = s.autoscaleMultiplier;
544
- }
545
- }
546
- else {
547
- if (d[j][1] < db.min || db.min == null) {
548
- db.min = d[j][1];
549
- minsidx=i;
550
- minpidx=j;
551
- minr = d[j][2];
552
- minMaxRadius = s.maxRadius;
553
- minMult = s.autoscaleMultiplier;
554
- }
555
- if (d[j][1] > db.max || db.max == null) {
556
- db.max = d[j][1];
557
- maxsidx=i;
558
- maxpidx=j;
559
- maxr = d[j][2];
560
- maxMaxRadius = s.maxRadius;
561
- maxMult = s.autoscaleMultiplier;
562
- }
563
- }
564
- }
565
- }
566
-
567
- var minRatio = minr/minMaxRadius;
568
- var maxRatio = maxr/maxMaxRadius;
569
-
570
- // need to estimate the effect of the radius on total axis span and adjust axis accordingly.
571
- var span = db.max - db.min;
572
- // var dim = (this.name == 'xaxis' || this.name == 'x2axis') ? this._plotDimensions.width : this._plotDimensions.height;
573
- var dim = Math.min(this._plotDimensions.width, this._plotDimensions.height);
574
-
575
- var minfact = minRatio * minMult/3 * span;
576
- var maxfact = maxRatio * maxMult/3 * span;
577
- db.max += maxfact;
578
- db.min -= minfact;
579
- };
580
-
581
- function highlight (plot, sidx, pidx) {
582
- plot.plugins.bubbleRenderer.highlightLabelCanvas.empty();
583
- var s = plot.series[sidx];
584
- var canvas = plot.plugins.bubbleRenderer.highlightCanvas;
585
- var ctx = canvas._ctx;
586
- ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
587
- s._highlightedPoint = pidx;
588
- plot.plugins.bubbleRenderer.highlightedSeriesIndex = sidx;
589
-
590
- var color = s.highlightColorGenerator.get(pidx);
591
- var x = s.gridData[pidx][0],
592
- y = s.gridData[pidx][1],
593
- r = s.gridData[pidx][2];
594
- ctx.save();
595
- ctx.fillStyle = color;
596
- ctx.strokeStyle = color;
597
- ctx.lineWidth = 1;
598
- ctx.beginPath();
599
- ctx.arc(x, y, r, 0, 2*Math.PI, 0);
600
- ctx.closePath();
601
- ctx.fill();
602
- ctx.restore();
603
- // bring label to front
604
- if (s.labels[pidx]) {
605
- plot.plugins.bubbleRenderer.highlightLabel = s.labels[pidx].clone();
606
- plot.plugins.bubbleRenderer.highlightLabel.appendTo(plot.plugins.bubbleRenderer.highlightLabelCanvas);
607
- plot.plugins.bubbleRenderer.highlightLabel.addClass('jqplot-bubble-label-highlight');
608
- }
609
- }
610
-
611
- function unhighlight (plot) {
612
- var canvas = plot.plugins.bubbleRenderer.highlightCanvas;
613
- var sidx = plot.plugins.bubbleRenderer.highlightedSeriesIndex;
614
- plot.plugins.bubbleRenderer.highlightLabelCanvas.empty();
615
- canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);
616
- for (var i=0; i<plot.series.length; i++) {
617
- plot.series[i]._highlightedPoint = null;
618
- }
619
- plot.plugins.bubbleRenderer.highlightedSeriesIndex = null;
620
- plot.target.trigger('jqplotDataUnhighlight');
621
- }
622
-
623
-
624
- function handleMove(ev, gridpos, datapos, neighbor, plot) {
625
- if (neighbor) {
626
- var si = neighbor.seriesIndex;
627
- var pi = neighbor.pointIndex;
628
- var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];
629
- var evt1 = jQuery.Event('jqplotDataMouseOver');
630
- evt1.pageX = ev.pageX;
631
- evt1.pageY = ev.pageY;
632
- plot.target.trigger(evt1, ins);
633
- if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.bubbleRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
634
- var evt = jQuery.Event('jqplotDataHighlight');
635
- evt.which = ev.which;
636
- evt.pageX = ev.pageX;
637
- evt.pageY = ev.pageY;
638
- plot.target.trigger(evt, ins);
639
- highlight (plot, ins[0], ins[1]);
640
- }
641
- }
642
- else if (neighbor == null) {
643
- unhighlight (plot);
644
- }
645
- }
646
-
647
- function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
648
- if (neighbor) {
649
- var si = neighbor.seriesIndex;
650
- var pi = neighbor.pointIndex;
651
- var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];
652
- if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.bubbleRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
653
- var evt = jQuery.Event('jqplotDataHighlight');
654
- evt.which = ev.which;
655
- evt.pageX = ev.pageX;
656
- evt.pageY = ev.pageY;
657
- plot.target.trigger(evt, ins);
658
- highlight (plot, ins[0], ins[1]);
659
- }
660
- }
661
- else if (neighbor == null) {
662
- unhighlight (plot);
663
- }
664
- }
665
-
666
- function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {
667
- var idx = plot.plugins.bubbleRenderer.highlightedSeriesIndex;
668
- if (idx != null && plot.series[idx].highlightMouseDown) {
669
- unhighlight(plot);
670
- }
671
- }
672
-
673
- function handleClick(ev, gridpos, datapos, neighbor, plot) {
674
- if (neighbor) {
675
- var si = neighbor.seriesIndex;
676
- var pi = neighbor.pointIndex;
677
- var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];
678
- var evt = jQuery.Event('jqplotDataClick');
679
- evt.which = ev.which;
680
- evt.pageX = ev.pageX;
681
- evt.pageY = ev.pageY;
682
- plot.target.trigger(evt, ins);
683
- }
684
- }
685
-
686
- function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
687
- if (neighbor) {
688
- var si = neighbor.seriesIndex;
689
- var pi = neighbor.pointIndex;
690
- var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];
691
- var idx = plot.plugins.bubbleRenderer.highlightedSeriesIndex;
692
- if (idx != null && plot.series[idx].highlightMouseDown) {
693
- unhighlight(plot);
694
- }
695
- var evt = jQuery.Event('jqplotDataRightClick');
696
- evt.which = ev.which;
697
- evt.pageX = ev.pageX;
698
- evt.pageY = ev.pageY;
699
- plot.target.trigger(evt, ins);
700
- }
701
- }
702
-
703
- // called within context of plot
704
- // create a canvas which we can draw on.
705
- // insert it before the eventCanvas, so eventCanvas will still capture events.
706
- function postPlotDraw() {
707
- // Memory Leaks patch
708
- if (this.plugins.bubbleRenderer && this.plugins.bubbleRenderer.highlightCanvas) {
709
- this.plugins.bubbleRenderer.highlightCanvas.resetCanvas();
710
- this.plugins.bubbleRenderer.highlightCanvas = null;
711
- }
712
-
713
- this.plugins.bubbleRenderer = {highlightedSeriesIndex:null};
714
- this.plugins.bubbleRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
715
- this.plugins.bubbleRenderer.highlightLabel = null;
716
- this.plugins.bubbleRenderer.highlightLabelCanvas = $('<div style="position:absolute;"></div>');
717
- var top = this._gridPadding.top;
718
- var left = this._gridPadding.left;
719
- var width = this._plotDimensions.width - this._gridPadding.left - this._gridPadding.right;
720
- var height = this._plotDimensions.height - this._gridPadding.top - this._gridPadding.bottom;
721
- this.plugins.bubbleRenderer.highlightLabelCanvas.css({top:top, left:left, width:width+'px', height:height+'px'});
722
-
723
- this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-bubbleRenderer-highlight-canvas', this._plotDimensions, this));
724
- this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightLabelCanvas);
725
-
726
- var hctx = this.plugins.bubbleRenderer.highlightCanvas.setContext();
727
- }
728
-
729
-
730
- // setup default renderers for axes and legend so user doesn't have to
731
- // called with scope of plot
732
- function preInit(target, data, options) {
733
- options = options || {};
734
- options.axesDefaults = options.axesDefaults || {};
735
- options.seriesDefaults = options.seriesDefaults || {};
736
- // only set these if there is a Bubble series
737
- var setopts = false;
738
- if (options.seriesDefaults.renderer == $.jqplot.BubbleRenderer) {
739
- setopts = true;
740
- }
741
- else if (options.series) {
742
- for (var i=0; i < options.series.length; i++) {
743
- if (options.series[i].renderer == $.jqplot.BubbleRenderer) {
744
- setopts = true;
745
- }
746
- }
747
- }
748
-
749
- if (setopts) {
750
- options.axesDefaults.renderer = $.jqplot.BubbleAxisRenderer;
751
- options.sortData = false;
752
- }
753
- }
754
-
755
- $.jqplot.preInitHooks.push(preInit);
756
-
757
- })(jQuery);
758
-
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
+ var arrayMax = function( array ){
33
+ return Math.max.apply( Math, array );
34
+ };
35
+ var arrayMin = function( array ){
36
+ return Math.min.apply( Math, array );
37
+ };
38
+
39
+ /**
40
+ * Class: $.jqplot.BubbleRenderer
41
+ * Plugin renderer to draw a bubble chart. A Bubble chart has data points displayed as
42
+ * colored circles with an optional text label inside. To use
43
+ * the bubble renderer, you must include the bubble renderer like:
44
+ *
45
+ * > <script language="javascript" type="text/javascript" src="../src/plugins/jqplot.bubbleRenderer.js"></script>
46
+ *
47
+ * Data must be supplied in
48
+ * the form:
49
+ *
50
+ * > [[x1, y1, r1, <label or {label:'text', color:color}>], ...]
51
+ *
52
+ * where the label or options
53
+ * object is optional.
54
+ *
55
+ * Note that all bubble colors will be the same
56
+ * unless the "varyBubbleColors" option is set to true. Colors can be specified in the data array
57
+ * or in the seriesColors array option on the series. If no colors are defined, the default jqPlot
58
+ * series of 16 colors are used. Colors are automatically cycled around again if there are more
59
+ * bubbles than colors.
60
+ *
61
+ * Bubbles are autoscaled by default to fit within the chart area while maintaining
62
+ * relative sizes. If the "autoscaleBubbles" option is set to false, the r(adius) values
63
+ * in the data array a treated as literal pixel values for the radii of the bubbles.
64
+ *
65
+ * Properties are passed into the bubble renderer in the rendererOptions object of
66
+ * the series options like:
67
+ *
68
+ * > seriesDefaults: {
69
+ * > renderer: $.jqplot.BubbleRenderer,
70
+ * > rendererOptions: {
71
+ * > bubbleAlpha: 0.7,
72
+ * > varyBubbleColors: false
73
+ * > }
74
+ * > }
75
+ *
76
+ */
77
+ $.jqplot.BubbleRenderer = function(){
78
+ $.jqplot.LineRenderer.call(this);
79
+ };
80
+
81
+ $.jqplot.BubbleRenderer.prototype = new $.jqplot.LineRenderer();
82
+ $.jqplot.BubbleRenderer.prototype.constructor = $.jqplot.BubbleRenderer;
83
+
84
+ // called with scope of a series
85
+ $.jqplot.BubbleRenderer.prototype.init = function(options, plot) {
86
+ // Group: Properties
87
+ //
88
+ // prop: varyBubbleColors
89
+ // True to vary the color of each bubble in this series according to
90
+ // the seriesColors array. False to set each bubble to the color
91
+ // specified on this series. This has no effect if a css background color
92
+ // option is specified in the renderer css options.
93
+ this.varyBubbleColors = true;
94
+ // prop: autoscaleBubbles
95
+ // True to scale the bubble radius based on plot size.
96
+ // False will use the radius value as provided as a raw pixel value for
97
+ // bubble radius.
98
+ this.autoscaleBubbles = true;
99
+ // prop: autoscaleMultiplier
100
+ // Multiplier the bubble size if autoscaleBubbles is true.
101
+ this.autoscaleMultiplier = 1.0;
102
+ // prop: autoscalePointsFactor
103
+ // Factor which decreases bubble size based on how many bubbles on on the chart.
104
+ // 0 means no adjustment for number of bubbles. Negative values will decrease
105
+ // size of bubbles as more bubbles are added. Values between 0 and -0.2
106
+ // should work well.
107
+ this.autoscalePointsFactor = -0.07;
108
+ // prop: escapeHtml
109
+ // True to escape html in bubble label text.
110
+ this.escapeHtml = true;
111
+ // prop: highlightMouseOver
112
+ // True to highlight bubbles when moused over.
113
+ // This must be false to enable highlightMouseDown to highlight when clicking on a slice.
114
+ this.highlightMouseOver = true;
115
+ // prop: highlightMouseDown
116
+ // True to highlight when a mouse button is pressed over a bubble.
117
+ // This will be disabled if highlightMouseOver is true.
118
+ this.highlightMouseDown = false;
119
+ // prop: highlightColors
120
+ // An array of colors to use when highlighting a slice. Calculated automatically
121
+ // if not supplied.
122
+ this.highlightColors = [];
123
+ // prop: bubbleAlpha
124
+ // Alpha transparency to apply to all bubbles in this series.
125
+ this.bubbleAlpha = 1.0;
126
+ // prop: highlightAlpha
127
+ // Alpha transparency to apply when highlighting bubble.
128
+ // Set to value of bubbleAlpha by default.
129
+ this.highlightAlpha = null;
130
+ // prop: bubbleGradients
131
+ // True to color the bubbles with gradient fills instead of flat colors.
132
+ // NOT AVAILABLE IN IE due to lack of excanvas support for radial gradient fills.
133
+ // will be ignored in IE.
134
+ this.bubbleGradients = false;
135
+ // prop: showLabels
136
+ // True to show labels on bubbles (if any), false to not show.
137
+ this.showLabels = true;
138
+ // array of [point index, radius] which will be sorted in descending order to plot
139
+ // largest points below smaller points.
140
+ this.radii = [];
141
+ this.maxRadius = 0;
142
+ // index of the currenty highlighted point, if any
143
+ this._highlightedPoint = null;
144
+ // array of jQuery labels.
145
+ this.labels = [];
146
+ this.bubbleCanvases = [];
147
+ this._type = 'bubble';
148
+
149
+ // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver
150
+ if (options.highlightMouseDown && options.highlightMouseOver == null) {
151
+ options.highlightMouseOver = false;
152
+ }
153
+
154
+ $.extend(true, this, options);
155
+
156
+ if (this.highlightAlpha == null) {
157
+ this.highlightAlpha = this.bubbleAlpha;
158
+ if (this.bubbleGradients) {
159
+ this.highlightAlpha = 0.35;
160
+ }
161
+ }
162
+
163
+ this.autoscaleMultiplier = this.autoscaleMultiplier * Math.pow(this.data.length, this.autoscalePointsFactor);
164
+
165
+ // index of the currenty highlighted point, if any
166
+ this._highlightedPoint = null;
167
+
168
+ // adjust the series colors for options colors passed in with data or for alpha.
169
+ // note, this can leave undefined holes in the seriesColors array.
170
+ var comps;
171
+ for (var i=0; i<this.data.length; i++) {
172
+ var color = null;
173
+ var d = this.data[i];
174
+ this.maxRadius = Math.max(this.maxRadius, d[2]);
175
+ if (d[3]) {
176
+ if (typeof(d[3]) == 'object') {
177
+ color = d[3]['color'];
178
+ }
179
+ }
180
+
181
+ if (color == null) {
182
+ if (this.seriesColors[i] != null) {
183
+ color = this.seriesColors[i];
184
+ }
185
+ }
186
+
187
+ if (color && this.bubbleAlpha < 1.0) {
188
+ comps = $.jqplot.getColorComponents(color);
189
+ color = 'rgba('+comps[0]+', '+comps[1]+', '+comps[2]+', '+this.bubbleAlpha+')';
190
+ }
191
+
192
+ if (color) {
193
+ this.seriesColors[i] = color;
194
+ }
195
+ }
196
+
197
+ if (!this.varyBubbleColors) {
198
+ this.seriesColors = [this.color];
199
+ }
200
+
201
+ this.colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);
202
+
203
+ // set highlight colors if none provided
204
+ if (this.highlightColors.length == 0) {
205
+ for (var i=0; i<this.seriesColors.length; i++){
206
+ var rgba = $.jqplot.getColorComponents(this.seriesColors[i]);
207
+ var newrgb = [rgba[0], rgba[1], rgba[2]];
208
+ var sum = newrgb[0] + newrgb[1] + newrgb[2];
209
+ for (var j=0; j<3; j++) {
210
+ // when darkening, lowest color component can be is 60.
211
+ newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);
212
+ newrgb[j] = parseInt(newrgb[j], 10);
213
+ }
214
+ this.highlightColors.push('rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+', '+this.highlightAlpha+')');
215
+ }
216
+ }
217
+
218
+ this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors);
219
+
220
+ var sopts = {fill:true, isarc:true, angle:this.shadowAngle, alpha:this.shadowAlpha, closePath:true};
221
+
222
+ this.renderer.shadowRenderer.init(sopts);
223
+
224
+ this.canvas = new $.jqplot.DivCanvas();
225
+ this.canvas._plotDimensions = this._plotDimensions;
226
+
227
+ plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);
228
+ plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);
229
+ plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);
230
+ plot.eventListenerHooks.addOnce('jqplotClick', handleClick);
231
+ plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);
232
+ plot.postDrawHooks.addOnce(postPlotDraw);
233
+
234
+ };
235
+
236
+
237
+ // converts the user data values to grid coordinates and stores them
238
+ // in the gridData array.
239
+ // Called with scope of a series.
240
+ $.jqplot.BubbleRenderer.prototype.setGridData = function(plot) {
241
+ // recalculate the grid data
242
+ var xp = this._xaxis.series_u2p;
243
+ var yp = this._yaxis.series_u2p;
244
+ var data = this._plotData;
245
+ this.gridData = [];
246
+ var radii = [];
247
+ this.radii = [];
248
+ var dim = Math.min(plot._height, plot._width);
249
+ for (var i=0; i<this.data.length; i++) {
250
+ if (data[i] != null) {
251
+ this.gridData.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1]), data[i][2]]);
252
+ this.radii.push([i, data[i][2]]);
253
+ radii.push(data[i][2]);
254
+ }
255
+ }
256
+ var r, val, maxr = this.maxRadius = arrayMax(radii);
257
+ var l = this.gridData.length;
258
+ if (this.autoscaleBubbles) {
259
+ for (var i=0; i<l; i++) {
260
+ val = radii[i]/maxr;
261
+ r = this.autoscaleMultiplier * dim / 6;
262
+ this.gridData[i][2] = r * val;
263
+ }
264
+ }
265
+
266
+ this.radii.sort(function(a, b) { return b[1] - a[1]; });
267
+ };
268
+
269
+ // converts any arbitrary data values to grid coordinates and
270
+ // returns them. This method exists so that plugins can use a series'
271
+ // linerenderer to generate grid data points without overwriting the
272
+ // grid data associated with that series.
273
+ // Called with scope of a series.
274
+ $.jqplot.BubbleRenderer.prototype.makeGridData = function(data, plot) {
275
+ // recalculate the grid data
276
+ var xp = this._xaxis.series_u2p;
277
+ var yp = this._yaxis.series_u2p;
278
+ var gd = [];
279
+ var radii = [];
280
+ this.radii = [];
281
+ var dim = Math.min(plot._height, plot._width);
282
+ for (var i=0; i<data.length; i++) {
283
+ if (data[i] != null) {
284
+ gd.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1]), data[i][2]]);
285
+ radii.push(data[i][2]);
286
+ this.radii.push([i, data[i][2]]);
287
+ }
288
+ }
289
+ var r, val, maxr = this.maxRadius = arrayMax(radii);
290
+ var l = this.gridData.length;
291
+ if (this.autoscaleBubbles) {
292
+ for (var i=0; i<l; i++) {
293
+ val = radii[i]/maxr;
294
+ r = this.autoscaleMultiplier * dim / 6;
295
+ gd[i][2] = r * val;
296
+ }
297
+ }
298
+ this.radii.sort(function(a, b) { return b[1] - a[1]; });
299
+ return gd;
300
+ };
301
+
302
+ // called with scope of series
303
+ $.jqplot.BubbleRenderer.prototype.draw = function (ctx, gd, options) {
304
+ if (this.plugins.pointLabels) {
305
+ this.plugins.pointLabels.show = false;
306
+ }
307
+ var opts = (options != undefined) ? options : {};
308
+ var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;
309
+ this.canvas._elem.empty();
310
+ for (var i=0; i<this.radii.length; i++) {
311
+ var idx = this.radii[i][0];
312
+ var t=null;
313
+ var color = null;
314
+ var el = null;
315
+ var tel = null;
316
+ var d = this.data[idx];
317
+ var gd = this.gridData[idx];
318
+ if (d[3]) {
319
+ if (typeof(d[3]) == 'object') {
320
+ t = d[3]['label'];
321
+ }
322
+ else if (typeof(d[3]) == 'string') {
323
+ t = d[3];
324
+ }
325
+ }
326
+
327
+ // color = (this.varyBubbleColors) ? this.colorGenerator.get(idx) : this.color;
328
+ color = this.colorGenerator.get(idx);
329
+
330
+ // If we're drawing a shadow, expand the canvas dimensions to accomodate.
331
+ var canvasRadius = gd[2];
332
+ var offset, depth;
333
+ if (this.shadow) {
334
+ offset = (0.7 + gd[2]/40).toFixed(1);
335
+ depth = 1 + Math.ceil(gd[2]/15);
336
+ canvasRadius += offset*depth;
337
+ }
338
+ this.bubbleCanvases[idx] = new $.jqplot.BubbleCanvas();
339
+ this.canvas._elem.append(this.bubbleCanvases[idx].createElement(gd[0], gd[1], canvasRadius));
340
+ this.bubbleCanvases[idx].setContext();
341
+ var ctx = this.bubbleCanvases[idx]._ctx;
342
+ var x = ctx.canvas.width/2;
343
+ var y = ctx.canvas.height/2;
344
+ if (this.shadow) {
345
+ this.renderer.shadowRenderer.draw(ctx, [x, y, gd[2], 0, 2*Math.PI], {offset: offset, depth: depth});
346
+ }
347
+ this.bubbleCanvases[idx].draw(gd[2], color, this.bubbleGradients, this.shadowAngle/180*Math.PI);
348
+
349
+ // now draw label.
350
+ if (t && this.showLabels) {
351
+ tel = $('<div style="position:absolute;" class="jqplot-bubble-label"></div>');
352
+ if (this.escapeHtml) {
353
+ tel.text(t);
354
+ }
355
+ else {
356
+ tel.html(t);
357
+ }
358
+ this.canvas._elem.append(tel);
359
+ var h = $(tel).outerHeight();
360
+ var w = $(tel).outerWidth();
361
+ var top = gd[1] - 0.5*h;
362
+ var left = gd[0] - 0.5*w;
363
+ tel.css({top: top, left: left});
364
+ this.labels[idx] = $(tel);
365
+ }
366
+ }
367
+ };
368
+
369
+
370
+ $.jqplot.DivCanvas = function() {
371
+ $.jqplot.ElemContainer.call(this);
372
+ this._ctx;
373
+ };
374
+
375
+ $.jqplot.DivCanvas.prototype = new $.jqplot.ElemContainer();
376
+ $.jqplot.DivCanvas.prototype.constructor = $.jqplot.DivCanvas;
377
+
378
+ $.jqplot.DivCanvas.prototype.createElement = function(offsets, clss, plotDimensions) {
379
+ this._offsets = offsets;
380
+ var klass = 'jqplot-DivCanvas';
381
+ if (clss != undefined) {
382
+ klass = clss;
383
+ }
384
+ var elem;
385
+ // if this canvas already has a dom element, don't make a new one.
386
+ if (this._elem) {
387
+ elem = this._elem.get(0);
388
+ }
389
+ else {
390
+ elem = document.createElement('div');
391
+ }
392
+ // if new plotDimensions supplied, use them.
393
+ if (plotDimensions != undefined) {
394
+ this._plotDimensions = plotDimensions;
395
+ }
396
+
397
+ var w = this._plotDimensions.width - this._offsets.left - this._offsets.right + 'px';
398
+ var h = this._plotDimensions.height - this._offsets.top - this._offsets.bottom + 'px';
399
+ this._elem = $(elem);
400
+ this._elem.css({ position: 'absolute', width:w, height:h, left: this._offsets.left, top: this._offsets.top });
401
+
402
+ this._elem.addClass(klass);
403
+ return this._elem;
404
+ };
405
+
406
+ $.jqplot.DivCanvas.prototype.setContext = function() {
407
+ this._ctx = {
408
+ canvas:{
409
+ width:0,
410
+ height:0
411
+ },
412
+ clearRect:function(){return null;}
413
+ };
414
+ return this._ctx;
415
+ };
416
+
417
+ $.jqplot.BubbleCanvas = function() {
418
+ $.jqplot.ElemContainer.call(this);
419
+ this._ctx;
420
+ };
421
+
422
+ $.jqplot.BubbleCanvas.prototype = new $.jqplot.ElemContainer();
423
+ $.jqplot.BubbleCanvas.prototype.constructor = $.jqplot.BubbleCanvas;
424
+
425
+ // initialize with the x,y pont of bubble center and the bubble radius.
426
+ $.jqplot.BubbleCanvas.prototype.createElement = function(x, y, r) {
427
+ var klass = 'jqplot-bubble-point';
428
+
429
+ var elem;
430
+ // if this canvas already has a dom element, don't make a new one.
431
+ if (this._elem) {
432
+ elem = this._elem.get(0);
433
+ }
434
+ else {
435
+ elem = document.createElement('canvas');
436
+ }
437
+
438
+ elem.width = (r != null) ? 2*r : elem.width;
439
+ elem.height = (r != null) ? 2*r : elem.height;
440
+ this._elem = $(elem);
441
+ var l = (x != null && r != null) ? x - r : this._elem.css('left');
442
+ var t = (y != null && r != null) ? y - r : this._elem.css('top');
443
+ this._elem.css({ position: 'absolute', left: l, top: t });
444
+
445
+ this._elem.addClass(klass);
446
+ if ($.jqplot.use_excanvas) {
447
+ window.G_vmlCanvasManager.init_(document);
448
+ elem = window.G_vmlCanvasManager.initElement(elem);
449
+ }
450
+
451
+ return this._elem;
452
+ };
453
+
454
+ $.jqplot.BubbleCanvas.prototype.draw = function(r, color, gradients, angle) {
455
+ var ctx = this._ctx;
456
+ // r = Math.floor(r*1.04);
457
+ // var x = Math.round(ctx.canvas.width/2);
458
+ // var y = Math.round(ctx.canvas.height/2);
459
+ var x = ctx.canvas.width/2;
460
+ var y = ctx.canvas.height/2;
461
+ ctx.save();
462
+ if (gradients && !$.jqplot.use_excanvas) {
463
+ r = r*1.04;
464
+ var comps = $.jqplot.getColorComponents(color);
465
+ var colorinner = 'rgba('+Math.round(comps[0]+0.8*(255-comps[0]))+', '+Math.round(comps[1]+0.8*(255-comps[1]))+', '+Math.round(comps[2]+0.8*(255-comps[2]))+', '+comps[3]+')';
466
+ var colorend = 'rgba('+comps[0]+', '+comps[1]+', '+comps[2]+', 0)';
467
+ // var rinner = Math.round(0.35 * r);
468
+ // var xinner = Math.round(x - Math.cos(angle) * 0.33 * r);
469
+ // var yinner = Math.round(y - Math.sin(angle) * 0.33 * r);
470
+ var rinner = 0.35 * r;
471
+ var xinner = x - Math.cos(angle) * 0.33 * r;
472
+ var yinner = y - Math.sin(angle) * 0.33 * r;
473
+ var radgrad = ctx.createRadialGradient(xinner, yinner, rinner, x, y, r);
474
+ radgrad.addColorStop(0, colorinner);
475
+ radgrad.addColorStop(0.93, color);
476
+ radgrad.addColorStop(0.96, colorend);
477
+ radgrad.addColorStop(1, colorend);
478
+ // radgrad.addColorStop(.98, colorend);
479
+ ctx.fillStyle = radgrad;
480
+ ctx.fillRect(0,0, ctx.canvas.width, ctx.canvas.height);
481
+ }
482
+ else {
483
+ ctx.fillStyle = color;
484
+ ctx.strokeStyle = color;
485
+ ctx.lineWidth = 1;
486
+ ctx.beginPath();
487
+ var ang = 2*Math.PI;
488
+ ctx.arc(x, y, r, 0, ang, 0);
489
+ ctx.closePath();
490
+ ctx.fill();
491
+ }
492
+ ctx.restore();
493
+ };
494
+
495
+ $.jqplot.BubbleCanvas.prototype.setContext = function() {
496
+ this._ctx = this._elem.get(0).getContext("2d");
497
+ return this._ctx;
498
+ };
499
+
500
+ $.jqplot.BubbleAxisRenderer = function() {
501
+ $.jqplot.LinearAxisRenderer.call(this);
502
+ };
503
+
504
+ $.jqplot.BubbleAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();
505
+ $.jqplot.BubbleAxisRenderer.prototype.constructor = $.jqplot.BubbleAxisRenderer;
506
+
507
+ // called with scope of axis object.
508
+ $.jqplot.BubbleAxisRenderer.prototype.init = function(options){
509
+ $.extend(true, this, options);
510
+ var db = this._dataBounds;
511
+ var minsidx = 0,
512
+ minpidx = 0,
513
+ maxsidx = 0,
514
+ maxpidx = 0,
515
+ maxr = 0,
516
+ minr = 0,
517
+ minMaxRadius = 0,
518
+ maxMaxRadius = 0,
519
+ maxMult = 0,
520
+ minMult = 0;
521
+ // Go through all the series attached to this axis and find
522
+ // the min/max bounds for this axis.
523
+ for (var i=0; i<this._series.length; i++) {
524
+ var s = this._series[i];
525
+ var d = s._plotData;
526
+
527
+ for (var j=0; j<d.length; j++) {
528
+ if (this.name == 'xaxis' || this.name == 'x2axis') {
529
+ if (d[j][0] < db.min || db.min == null) {
530
+ db.min = d[j][0];
531
+ minsidx=i;
532
+ minpidx=j;
533
+ minr = d[j][2];
534
+ minMaxRadius = s.maxRadius;
535
+ minMult = s.autoscaleMultiplier;
536
+ }
537
+ if (d[j][0] > db.max || db.max == null) {
538
+ db.max = d[j][0];
539
+ maxsidx=i;
540
+ maxpidx=j;
541
+ maxr = d[j][2];
542
+ maxMaxRadius = s.maxRadius;
543
+ maxMult = s.autoscaleMultiplier;
544
+ }
545
+ }
546
+ else {
547
+ if (d[j][1] < db.min || db.min == null) {
548
+ db.min = d[j][1];
549
+ minsidx=i;
550
+ minpidx=j;
551
+ minr = d[j][2];
552
+ minMaxRadius = s.maxRadius;
553
+ minMult = s.autoscaleMultiplier;
554
+ }
555
+ if (d[j][1] > db.max || db.max == null) {
556
+ db.max = d[j][1];
557
+ maxsidx=i;
558
+ maxpidx=j;
559
+ maxr = d[j][2];
560
+ maxMaxRadius = s.maxRadius;
561
+ maxMult = s.autoscaleMultiplier;
562
+ }
563
+ }
564
+ }
565
+ }
566
+
567
+ var minRatio = minr/minMaxRadius;
568
+ var maxRatio = maxr/maxMaxRadius;
569
+
570
+ // need to estimate the effect of the radius on total axis span and adjust axis accordingly.
571
+ var span = db.max - db.min;
572
+ // var dim = (this.name == 'xaxis' || this.name == 'x2axis') ? this._plotDimensions.width : this._plotDimensions.height;
573
+ var dim = Math.min(this._plotDimensions.width, this._plotDimensions.height);
574
+
575
+ var minfact = minRatio * minMult/3 * span;
576
+ var maxfact = maxRatio * maxMult/3 * span;
577
+ db.max += maxfact;
578
+ db.min -= minfact;
579
+ };
580
+
581
+ function highlight (plot, sidx, pidx) {
582
+ plot.plugins.bubbleRenderer.highlightLabelCanvas.empty();
583
+ var s = plot.series[sidx];
584
+ var canvas = plot.plugins.bubbleRenderer.highlightCanvas;
585
+ var ctx = canvas._ctx;
586
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
587
+ s._highlightedPoint = pidx;
588
+ plot.plugins.bubbleRenderer.highlightedSeriesIndex = sidx;
589
+
590
+ var color = s.highlightColorGenerator.get(pidx);
591
+ var x = s.gridData[pidx][0],
592
+ y = s.gridData[pidx][1],
593
+ r = s.gridData[pidx][2];
594
+ ctx.save();
595
+ ctx.fillStyle = color;
596
+ ctx.strokeStyle = color;
597
+ ctx.lineWidth = 1;
598
+ ctx.beginPath();
599
+ ctx.arc(x, y, r, 0, 2*Math.PI, 0);
600
+ ctx.closePath();
601
+ ctx.fill();
602
+ ctx.restore();
603
+ // bring label to front
604
+ if (s.labels[pidx]) {
605
+ plot.plugins.bubbleRenderer.highlightLabel = s.labels[pidx].clone();
606
+ plot.plugins.bubbleRenderer.highlightLabel.appendTo(plot.plugins.bubbleRenderer.highlightLabelCanvas);
607
+ plot.plugins.bubbleRenderer.highlightLabel.addClass('jqplot-bubble-label-highlight');
608
+ }
609
+ }
610
+
611
+ function unhighlight (plot) {
612
+ var canvas = plot.plugins.bubbleRenderer.highlightCanvas;
613
+ var sidx = plot.plugins.bubbleRenderer.highlightedSeriesIndex;
614
+ plot.plugins.bubbleRenderer.highlightLabelCanvas.empty();
615
+ canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);
616
+ for (var i=0; i<plot.series.length; i++) {
617
+ plot.series[i]._highlightedPoint = null;
618
+ }
619
+ plot.plugins.bubbleRenderer.highlightedSeriesIndex = null;
620
+ plot.target.trigger('jqplotDataUnhighlight');
621
+ }
622
+
623
+
624
+ function handleMove(ev, gridpos, datapos, neighbor, plot) {
625
+ if (neighbor) {
626
+ var si = neighbor.seriesIndex;
627
+ var pi = neighbor.pointIndex;
628
+ var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];
629
+ var evt1 = jQuery.Event('jqplotDataMouseOver');
630
+ evt1.pageX = ev.pageX;
631
+ evt1.pageY = ev.pageY;
632
+ plot.target.trigger(evt1, ins);
633
+ if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.bubbleRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
634
+ var evt = jQuery.Event('jqplotDataHighlight');
635
+ evt.which = ev.which;
636
+ evt.pageX = ev.pageX;
637
+ evt.pageY = ev.pageY;
638
+ plot.target.trigger(evt, ins);
639
+ highlight (plot, ins[0], ins[1]);
640
+ }
641
+ }
642
+ else if (neighbor == null) {
643
+ unhighlight (plot);
644
+ }
645
+ }
646
+
647
+ function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
648
+ if (neighbor) {
649
+ var si = neighbor.seriesIndex;
650
+ var pi = neighbor.pointIndex;
651
+ var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];
652
+ if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.bubbleRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {
653
+ var evt = jQuery.Event('jqplotDataHighlight');
654
+ evt.which = ev.which;
655
+ evt.pageX = ev.pageX;
656
+ evt.pageY = ev.pageY;
657
+ plot.target.trigger(evt, ins);
658
+ highlight (plot, ins[0], ins[1]);
659
+ }
660
+ }
661
+ else if (neighbor == null) {
662
+ unhighlight (plot);
663
+ }
664
+ }
665
+
666
+ function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {
667
+ var idx = plot.plugins.bubbleRenderer.highlightedSeriesIndex;
668
+ if (idx != null && plot.series[idx].highlightMouseDown) {
669
+ unhighlight(plot);
670
+ }
671
+ }
672
+
673
+ function handleClick(ev, gridpos, datapos, neighbor, plot) {
674
+ if (neighbor) {
675
+ var si = neighbor.seriesIndex;
676
+ var pi = neighbor.pointIndex;
677
+ var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];
678
+ var evt = jQuery.Event('jqplotDataClick');
679
+ evt.which = ev.which;
680
+ evt.pageX = ev.pageX;
681
+ evt.pageY = ev.pageY;
682
+ plot.target.trigger(evt, ins);
683
+ }
684
+ }
685
+
686
+ function handleRightClick(ev, gridpos, datapos, neighbor, plot) {
687
+ if (neighbor) {
688
+ var si = neighbor.seriesIndex;
689
+ var pi = neighbor.pointIndex;
690
+ var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];
691
+ var idx = plot.plugins.bubbleRenderer.highlightedSeriesIndex;
692
+ if (idx != null && plot.series[idx].highlightMouseDown) {
693
+ unhighlight(plot);
694
+ }
695
+ var evt = jQuery.Event('jqplotDataRightClick');
696
+ evt.which = ev.which;
697
+ evt.pageX = ev.pageX;
698
+ evt.pageY = ev.pageY;
699
+ plot.target.trigger(evt, ins);
700
+ }
701
+ }
702
+
703
+ // called within context of plot
704
+ // create a canvas which we can draw on.
705
+ // insert it before the eventCanvas, so eventCanvas will still capture events.
706
+ function postPlotDraw() {
707
+ // Memory Leaks patch
708
+ if (this.plugins.bubbleRenderer && this.plugins.bubbleRenderer.highlightCanvas) {
709
+ this.plugins.bubbleRenderer.highlightCanvas.resetCanvas();
710
+ this.plugins.bubbleRenderer.highlightCanvas = null;
711
+ }
712
+
713
+ this.plugins.bubbleRenderer = {highlightedSeriesIndex:null};
714
+ this.plugins.bubbleRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
715
+ this.plugins.bubbleRenderer.highlightLabel = null;
716
+ this.plugins.bubbleRenderer.highlightLabelCanvas = $('<div style="position:absolute;"></div>');
717
+ var top = this._gridPadding.top;
718
+ var left = this._gridPadding.left;
719
+ var width = this._plotDimensions.width - this._gridPadding.left - this._gridPadding.right;
720
+ var height = this._plotDimensions.height - this._gridPadding.top - this._gridPadding.bottom;
721
+ this.plugins.bubbleRenderer.highlightLabelCanvas.css({top:top, left:left, width:width+'px', height:height+'px'});
722
+
723
+ this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-bubbleRenderer-highlight-canvas', this._plotDimensions, this));
724
+ this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightLabelCanvas);
725
+
726
+ var hctx = this.plugins.bubbleRenderer.highlightCanvas.setContext();
727
+ }
728
+
729
+
730
+ // setup default renderers for axes and legend so user doesn't have to
731
+ // called with scope of plot
732
+ function preInit(target, data, options) {
733
+ options = options || {};
734
+ options.axesDefaults = options.axesDefaults || {};
735
+ options.seriesDefaults = options.seriesDefaults || {};
736
+ // only set these if there is a Bubble series
737
+ var setopts = false;
738
+ if (options.seriesDefaults.renderer == $.jqplot.BubbleRenderer) {
739
+ setopts = true;
740
+ }
741
+ else if (options.series) {
742
+ for (var i=0; i < options.series.length; i++) {
743
+ if (options.series[i].renderer == $.jqplot.BubbleRenderer) {
744
+ setopts = true;
745
+ }
746
+ }
747
+ }
748
+
749
+ if (setopts) {
750
+ options.axesDefaults.renderer = $.jqplot.BubbleAxisRenderer;
751
+ options.sortData = false;
752
+ }
753
+ }
754
+
755
+ $.jqplot.preInitHooks.push(preInit);
756
+
757
+ })(jQuery);
758
+
759
759