jqplot-rails 0.1 → 0.3

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 (38) hide show
  1. data/lib/jqplot-rails.rb +6 -4
  2. data/lib/jqplot-rails/railtie.rb +9 -0
  3. data/lib/jqplot-rails/view_helpers.rb +11 -0
  4. data/vendor/assets/javascripts/jqplot/excanvas.js +1438 -0
  5. data/vendor/assets/javascripts/jqplot/index.js +66 -0
  6. data/vendor/assets/javascripts/{jqplot.1.0.0b2_r792.js → jqplot/jquery.jqplot.js} +3458 -793
  7. data/vendor/assets/javascripts/jqplot/plugins/BezierCurveRenderer.js +313 -0
  8. data/vendor/assets/javascripts/jqplot/plugins/barRenderer.js +797 -0
  9. data/vendor/assets/javascripts/jqplot/plugins/blockRenderer.js +235 -0
  10. data/vendor/assets/javascripts/jqplot/plugins/bubbleRenderer.js +759 -0
  11. data/vendor/assets/javascripts/jqplot/plugins/canvasAxisLabelRenderer.js +203 -0
  12. data/vendor/assets/javascripts/jqplot/plugins/canvasAxisTickRenderer.js +243 -0
  13. data/vendor/assets/javascripts/jqplot/plugins/canvasOverlay.js +865 -0
  14. data/vendor/assets/javascripts/jqplot/plugins/canvasTextRenderer.js +449 -0
  15. data/vendor/assets/javascripts/jqplot/plugins/categoryAxisRenderer.js +673 -0
  16. data/vendor/assets/javascripts/jqplot/plugins/ciParser.js +116 -0
  17. data/vendor/assets/javascripts/jqplot/plugins/cursor.js +1108 -0
  18. data/vendor/assets/javascripts/jqplot/plugins/dateAxisRenderer.js +737 -0
  19. data/vendor/assets/javascripts/jqplot/plugins/donutRenderer.js +805 -0
  20. data/vendor/assets/javascripts/jqplot/plugins/dragable.js +225 -0
  21. data/vendor/assets/javascripts/jqplot/plugins/enhancedLegendRenderer.js +305 -0
  22. data/vendor/assets/javascripts/jqplot/plugins/funnelRenderer.js +943 -0
  23. data/vendor/assets/javascripts/jqplot/plugins/highlighter.js +465 -0
  24. data/vendor/assets/javascripts/jqplot/plugins/json2.js +475 -0
  25. data/vendor/assets/javascripts/jqplot/plugins/logAxisRenderer.js +529 -0
  26. data/vendor/assets/javascripts/jqplot/plugins/mekkoAxisRenderer.js +611 -0
  27. data/vendor/assets/javascripts/jqplot/plugins/mekkoRenderer.js +437 -0
  28. data/vendor/assets/javascripts/jqplot/plugins/meterGaugeRenderer.js +1030 -0
  29. data/vendor/assets/javascripts/jqplot/plugins/mobile.js +45 -0
  30. data/vendor/assets/javascripts/jqplot/plugins/ohlcRenderer.js +373 -0
  31. data/vendor/assets/javascripts/jqplot/plugins/pieRenderer.js +904 -0
  32. data/vendor/assets/javascripts/jqplot/plugins/pointLabels.js +379 -0
  33. data/vendor/assets/javascripts/jqplot/plugins/pyramidAxisRenderer.js +728 -0
  34. data/vendor/assets/javascripts/jqplot/plugins/pyramidGridRenderer.js +429 -0
  35. data/vendor/assets/javascripts/jqplot/plugins/pyramidRenderer.js +514 -0
  36. data/vendor/assets/javascripts/jqplot/plugins/trendline.js +223 -0
  37. data/vendor/assets/stylesheets/{jqplot.1.0.0b2_r792.css → jqplot.css} +48 -15
  38. metadata +64 -25
@@ -0,0 +1,235 @@
1
+ /**
2
+ * jqPlot
3
+ * Pure JavaScript plotting plugin using jQuery
4
+ *
5
+ * Version: 1.0.5
6
+ * Revision: 1122+
7
+ *
8
+ * Copyright (c) 2009-2013 Chris Leonello
9
+ * jqPlot is currently available for use in all personal or commercial projects
10
+ * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
11
+ * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
12
+ * choose the license that best suits your project and use it accordingly.
13
+ *
14
+ * Although not required, the author would appreciate an email letting him
15
+ * know of any substantial use of jqPlot. You can reach the author at:
16
+ * chris at jqplot dot com or see http://www.jqplot.com/info.php .
17
+ *
18
+ * If you are feeling kind and generous, consider supporting the project by
19
+ * making a donation at: http://www.jqplot.com/donate.php .
20
+ *
21
+ * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
22
+ *
23
+ * version 2007.04.27
24
+ * author Ash Searle
25
+ * http://hexmen.com/blog/2007/03/printf-sprintf/
26
+ * http://hexmen.com/js/sprintf.js
27
+ * The author (Ash Searle) has placed this code in the public domain:
28
+ * "This code is unrestricted: you are free to use it however you like."
29
+ *
30
+ */
31
+ (function($) {
32
+ /**
33
+ * Class: $.jqplot.BlockRenderer
34
+ * Plugin renderer to draw a x-y block chart. A Block chart has data points displayed as
35
+ * colored squares with a text label inside. Data must be supplied in the form:
36
+ *
37
+ * > [[x1, y1, "label 1", {css}], [x2, y2, "label 2", {css}], ...]
38
+ *
39
+ * The label and css object are optional. If the label is ommitted, the
40
+ * box will collapse unless a css height and/or width is specified.
41
+ *
42
+ * The css object is an object specifying css properties
43
+ * such as:
44
+ *
45
+ * > {background:'#4f98a5', border:'3px solid gray', padding:'1px'}
46
+ *
47
+ * Note that css properties specified with the data point override defaults
48
+ * specified with the series.
49
+ *
50
+ */
51
+ $.jqplot.BlockRenderer = function(){
52
+ $.jqplot.LineRenderer.call(this);
53
+ };
54
+
55
+ $.jqplot.BlockRenderer.prototype = new $.jqplot.LineRenderer();
56
+ $.jqplot.BlockRenderer.prototype.constructor = $.jqplot.BlockRenderer;
57
+
58
+ // called with scope of a series
59
+ $.jqplot.BlockRenderer.prototype.init = function(options) {
60
+ // Group: Properties
61
+ //
62
+ // prop: css
63
+ // default css styles that will be applied to all data blocks.
64
+ // these values will be overridden by css styles supplied with the
65
+ // individulal data points.
66
+ this.css = {padding:'2px', border:'1px solid #999', textAlign:'center'};
67
+ // prop: escapeHtml
68
+ // true to escape html in the box label.
69
+ this.escapeHtml = false;
70
+ // prop: insertBreaks
71
+ // true to turn spaces in data block label into html breaks <br />.
72
+ this.insertBreaks = true;
73
+ // prop: varyBlockColors
74
+ // true to vary the color of each block in this series according to
75
+ // the seriesColors array. False to set each block to the color
76
+ // specified on this series. This has no effect if a css background color
77
+ // option is specified in the renderer css options.
78
+ this.varyBlockColors = false;
79
+ $.extend(true, this, options);
80
+ if (this.css.backgroundColor) {
81
+ this.color = this.css.backgroundColor;
82
+ }
83
+ else if (this.css.background) {
84
+ this.color = this.css.background;
85
+ }
86
+ else if (!this.varyBlockColors) {
87
+ this.css.background = this.color;
88
+ }
89
+ this.canvas = new $.jqplot.BlockCanvas();
90
+ this.shadowCanvas = new $.jqplot.BlockCanvas();
91
+ this.canvas._plotDimensions = this._plotDimensions;
92
+ this.shadowCanvas._plotDimensions = this._plotDimensions;
93
+ this._type = 'block';
94
+
95
+ // group: Methods
96
+ //
97
+ // Method: moveBlock
98
+ // Moves an individual block. More efficient than redrawing
99
+ // the whole series by calling plot.drawSeries().
100
+ // Properties:
101
+ // idx - the 0 based index of the block or point in this series.
102
+ // x - the x coordinate in data units (value on x axis) to move the block to.
103
+ // y - the y coordinate in data units (value on the y axis) to move the block to.
104
+ // duration - optional parameter to create an animated movement. Can be a
105
+ // number (higher is slower animation) or 'fast', 'normal' or 'slow'. If not
106
+ // provided, the element is moved without any animation.
107
+ this.moveBlock = function (idx, x, y, duration) {
108
+ // update plotData, stackData, data and gridData
109
+ // x and y are in data coordinates.
110
+ var el = this.canvas._elem.children(':eq('+idx+')');
111
+ this.data[idx][0] = x;
112
+ this.data[idx][1] = y;
113
+ this._plotData[idx][0] = x;
114
+ this._plotData[idx][1] = y;
115
+ this._stackData[idx][0] = x;
116
+ this._stackData[idx][1] = y;
117
+ this.gridData[idx][0] = this._xaxis.series_u2p(x);
118
+ this.gridData[idx][1] = this._yaxis.series_u2p(y);
119
+ var w = el.outerWidth();
120
+ var h = el.outerHeight();
121
+ var left = this.gridData[idx][0] - w/2 + 'px';
122
+ var top = this.gridData[idx][1] - h/2 + 'px';
123
+ if (duration) {
124
+ if (parseInt(duration, 10)) {
125
+ duration = parseInt(duration, 10);
126
+ }
127
+ el.animate({left:left, top:top}, duration);
128
+ }
129
+ else {
130
+ el.css({left:left, top:top});
131
+ }
132
+ el = null;
133
+ };
134
+ };
135
+
136
+ // called with scope of series
137
+ $.jqplot.BlockRenderer.prototype.draw = function (ctx, gd, options) {
138
+ if (this.plugins.pointLabels) {
139
+ this.plugins.pointLabels.show = false;
140
+ }
141
+ var i, el, d, gd, t, css, w, h, left, top;
142
+ var opts = (options != undefined) ? options : {};
143
+ var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);
144
+ this.canvas._elem.empty();
145
+ for (i=0; i<this.gridData.length; i++) {
146
+ d = this.data[i];
147
+ gd = this.gridData[i];
148
+ t = '';
149
+ css = {};
150
+ if (typeof d[2] == 'string') {
151
+ t = d[2];
152
+ }
153
+ else if (typeof d[2] == 'object') {
154
+ css = d[2];
155
+ }
156
+ if (typeof d[3] == 'object') {
157
+ css = d[3];
158
+ }
159
+ if (this.insertBreaks){
160
+ t = t.replace(/ /g, '<br />');
161
+ }
162
+ css = $.extend(true, {}, this.css, css);
163
+ // create a div
164
+ el = $('<div style="position:absolute;margin-left:auto;margin-right:auto;"></div>');
165
+ this.canvas._elem.append(el);
166
+ // set text
167
+ this.escapeHtml ? el.text(t) : el.html(t);
168
+ // style it
169
+ // remove styles we don't want overridden.
170
+ delete css.position;
171
+ delete css.marginRight;
172
+ delete css.marginLeft;
173
+ if (!css.background && !css.backgroundColor && !css.backgroundImage){
174
+ css.background = colorGenerator.next();
175
+ }
176
+ el.css(css);
177
+ w = el.outerWidth();
178
+ h = el.outerHeight();
179
+ left = gd[0] - w/2 + 'px';
180
+ top = gd[1] - h/2 + 'px';
181
+ el.css({left:left, top:top});
182
+ el = null;
183
+ }
184
+ };
185
+
186
+ $.jqplot.BlockCanvas = function() {
187
+ $.jqplot.ElemContainer.call(this);
188
+ this._ctx;
189
+ };
190
+
191
+ $.jqplot.BlockCanvas.prototype = new $.jqplot.ElemContainer();
192
+ $.jqplot.BlockCanvas.prototype.constructor = $.jqplot.BlockCanvas;
193
+
194
+ $.jqplot.BlockCanvas.prototype.createElement = function(offsets, clss, plotDimensions) {
195
+ this._offsets = offsets;
196
+ var klass = 'jqplot-blockCanvas';
197
+ if (clss != undefined) {
198
+ klass = clss;
199
+ }
200
+ var elem;
201
+ // if this canvas already has a dom element, don't make a new one.
202
+ if (this._elem) {
203
+ elem = this._elem.get(0);
204
+ }
205
+ else {
206
+ elem = document.createElement('div');
207
+ }
208
+ // if new plotDimensions supplied, use them.
209
+ if (plotDimensions != undefined) {
210
+ this._plotDimensions = plotDimensions;
211
+ }
212
+
213
+ var w = this._plotDimensions.width - this._offsets.left - this._offsets.right + 'px';
214
+ var h = this._plotDimensions.height - this._offsets.top - this._offsets.bottom + 'px';
215
+ this._elem = $(elem);
216
+ this._elem.css({ position: 'absolute', width:w, height:h, left: this._offsets.left, top: this._offsets.top });
217
+
218
+ this._elem.addClass(klass);
219
+ return this._elem;
220
+ };
221
+
222
+ $.jqplot.BlockCanvas.prototype.setContext = function() {
223
+ this._ctx = {
224
+ canvas:{
225
+ width:0,
226
+ height:0
227
+ },
228
+ clearRect:function(){return null;}
229
+ };
230
+ return this._ctx;
231
+ };
232
+
233
+ })(jQuery);
234
+
235
+
@@ -0,0 +1,759 @@
1
+ /**
2
+ * jqPlot
3
+ * Pure JavaScript plotting plugin using jQuery
4
+ *
5
+ * Version: 1.0.5
6
+ * Revision: 1122+
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
+
759
+