jqplot-rails 0.1 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
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,203 @@
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.CanvasAxisLabelRenderer
34
+ * Renderer to draw axis labels with a canvas element to support advanced
35
+ * featrues such as rotated text. This renderer uses a separate rendering engine
36
+ * to draw the text on the canvas. Two modes of rendering the text are available.
37
+ * If the browser has native font support for canvas fonts (currently Mozila 3.5
38
+ * and Safari 4), you can enable text rendering with the canvas fillText method.
39
+ * You do so by setting the "enableFontSupport" option to true.
40
+ *
41
+ * Browsers lacking native font support will have the text drawn on the canvas
42
+ * using the Hershey font metrics. Even if the "enableFontSupport" option is true
43
+ * non-supporting browsers will still render with the Hershey font.
44
+ *
45
+ */
46
+ $.jqplot.CanvasAxisLabelRenderer = function(options) {
47
+ // Group: Properties
48
+
49
+ // prop: angle
50
+ // angle of text, measured clockwise from x axis.
51
+ this.angle = 0;
52
+ // name of the axis associated with this tick
53
+ this.axis;
54
+ // prop: show
55
+ // wether or not to show the tick (mark and label).
56
+ this.show = true;
57
+ // prop: showLabel
58
+ // wether or not to show the label.
59
+ this.showLabel = true;
60
+ // prop: label
61
+ // label for the axis.
62
+ this.label = '';
63
+ // prop: fontFamily
64
+ // CSS spec for the font-family css attribute.
65
+ // Applies only to browsers supporting native font rendering in the
66
+ // canvas tag. Currently Mozilla 3.5 and Safari 4.
67
+ this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif';
68
+ // prop: fontSize
69
+ // CSS spec for font size.
70
+ this.fontSize = '11pt';
71
+ // prop: fontWeight
72
+ // CSS spec for fontWeight: normal, bold, bolder, lighter or a number 100 - 900
73
+ this.fontWeight = 'normal';
74
+ // prop: fontStretch
75
+ // Multiplier to condense or expand font width.
76
+ // Applies only to browsers which don't support canvas native font rendering.
77
+ this.fontStretch = 1.0;
78
+ // prop: textColor
79
+ // css spec for the color attribute.
80
+ this.textColor = '#666666';
81
+ // prop: enableFontSupport
82
+ // true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.
83
+ // If true, label will be drawn with canvas tag native support for fonts.
84
+ // If false, label will be drawn with Hershey font metrics.
85
+ this.enableFontSupport = true;
86
+ // prop: pt2px
87
+ // Point to pixel scaling factor, used for computing height of bounding box
88
+ // around a label. The labels text renderer has a default setting of 1.4, which
89
+ // should be suitable for most fonts. Leave as null to use default. If tops of
90
+ // letters appear clipped, increase this. If bounding box seems too big, decrease.
91
+ // This is an issue only with the native font renderering capabilities of Mozilla
92
+ // 3.5 and Safari 4 since they do not provide a method to determine the font height.
93
+ this.pt2px = null;
94
+
95
+ this._elem;
96
+ this._ctx;
97
+ this._plotWidth;
98
+ this._plotHeight;
99
+ this._plotDimensions = {height:null, width:null};
100
+
101
+ $.extend(true, this, options);
102
+
103
+ if (options.angle == null && this.axis != 'xaxis' && this.axis != 'x2axis') {
104
+ this.angle = -90;
105
+ }
106
+
107
+ var ropts = {fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily};
108
+ if (this.pt2px) {
109
+ ropts.pt2px = this.pt2px;
110
+ }
111
+
112
+ if (this.enableFontSupport) {
113
+ if ($.jqplot.support_canvas_text()) {
114
+ this._textRenderer = new $.jqplot.CanvasFontRenderer(ropts);
115
+ }
116
+
117
+ else {
118
+ this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts);
119
+ }
120
+ }
121
+ else {
122
+ this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts);
123
+ }
124
+ };
125
+
126
+ $.jqplot.CanvasAxisLabelRenderer.prototype.init = function(options) {
127
+ $.extend(true, this, options);
128
+ this._textRenderer.init({fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily});
129
+ };
130
+
131
+ // return width along the x axis
132
+ // will check first to see if an element exists.
133
+ // if not, will return the computed text box width.
134
+ $.jqplot.CanvasAxisLabelRenderer.prototype.getWidth = function(ctx) {
135
+ if (this._elem) {
136
+ return this._elem.outerWidth(true);
137
+ }
138
+ else {
139
+ var tr = this._textRenderer;
140
+ var l = tr.getWidth(ctx);
141
+ var h = tr.getHeight(ctx);
142
+ var w = Math.abs(Math.sin(tr.angle)*h) + Math.abs(Math.cos(tr.angle)*l);
143
+ return w;
144
+ }
145
+ };
146
+
147
+ // return height along the y axis.
148
+ $.jqplot.CanvasAxisLabelRenderer.prototype.getHeight = function(ctx) {
149
+ if (this._elem) {
150
+ return this._elem.outerHeight(true);
151
+ }
152
+ else {
153
+ var tr = this._textRenderer;
154
+ var l = tr.getWidth(ctx);
155
+ var h = tr.getHeight(ctx);
156
+ var w = Math.abs(Math.cos(tr.angle)*h) + Math.abs(Math.sin(tr.angle)*l);
157
+ return w;
158
+ }
159
+ };
160
+
161
+ $.jqplot.CanvasAxisLabelRenderer.prototype.getAngleRad = function() {
162
+ var a = this.angle * Math.PI/180;
163
+ return a;
164
+ };
165
+
166
+ $.jqplot.CanvasAxisLabelRenderer.prototype.draw = function(ctx, plot) {
167
+ // Memory Leaks patch
168
+ if (this._elem) {
169
+ if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
170
+ window.G_vmlCanvasManager.uninitElement(this._elem.get(0));
171
+ }
172
+
173
+ this._elem.emptyForce();
174
+ this._elem = null;
175
+ }
176
+
177
+ // create a canvas here, but can't draw on it untill it is appended
178
+ // to dom for IE compatability.
179
+ var elem = plot.canvasManager.getCanvas();
180
+
181
+ this._textRenderer.setText(this.label, ctx);
182
+ var w = this.getWidth(ctx);
183
+ var h = this.getHeight(ctx);
184
+ elem.width = w;
185
+ elem.height = h;
186
+ elem.style.width = w;
187
+ elem.style.height = h;
188
+
189
+ elem = plot.canvasManager.initCanvas(elem);
190
+
191
+ this._elem = $(elem);
192
+ this._elem.css({ position: 'absolute'});
193
+ this._elem.addClass('jqplot-'+this.axis+'-label');
194
+
195
+ elem = null;
196
+ return this._elem;
197
+ };
198
+
199
+ $.jqplot.CanvasAxisLabelRenderer.prototype.pack = function() {
200
+ this._textRenderer.draw(this._elem.get(0).getContext("2d"), this.label);
201
+ };
202
+
203
+ })(jQuery);
@@ -0,0 +1,243 @@
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.CanvasAxisTickRenderer
34
+ * Renderer to draw axis ticks with a canvas element to support advanced
35
+ * featrues such as rotated text. This renderer uses a separate rendering engine
36
+ * to draw the text on the canvas. Two modes of rendering the text are available.
37
+ * If the browser has native font support for canvas fonts (currently Mozila 3.5
38
+ * and Safari 4), you can enable text rendering with the canvas fillText method.
39
+ * You do so by setting the "enableFontSupport" option to true.
40
+ *
41
+ * Browsers lacking native font support will have the text drawn on the canvas
42
+ * using the Hershey font metrics. Even if the "enableFontSupport" option is true
43
+ * non-supporting browsers will still render with the Hershey font.
44
+ */
45
+ $.jqplot.CanvasAxisTickRenderer = function(options) {
46
+ // Group: Properties
47
+
48
+ // prop: mark
49
+ // tick mark on the axis. One of 'inside', 'outside', 'cross', '' or null.
50
+ this.mark = 'outside';
51
+ // prop: showMark
52
+ // wether or not to show the mark on the axis.
53
+ this.showMark = true;
54
+ // prop: showGridline
55
+ // wether or not to draw the gridline on the grid at this tick.
56
+ this.showGridline = true;
57
+ // prop: isMinorTick
58
+ // if this is a minor tick.
59
+ this.isMinorTick = false;
60
+ // prop: angle
61
+ // angle of text, measured clockwise from x axis.
62
+ this.angle = 0;
63
+ // prop: markSize
64
+ // Length of the tick marks in pixels. For 'cross' style, length
65
+ // will be stoked above and below axis, so total length will be twice this.
66
+ this.markSize = 4;
67
+ // prop: show
68
+ // wether or not to show the tick (mark and label).
69
+ this.show = true;
70
+ // prop: showLabel
71
+ // wether or not to show the label.
72
+ this.showLabel = true;
73
+ // prop: labelPosition
74
+ // 'auto', 'start', 'middle' or 'end'.
75
+ // Whether tick label should be positioned so the start, middle, or end
76
+ // of the tick mark.
77
+ this.labelPosition = 'auto';
78
+ this.label = '';
79
+ this.value = null;
80
+ this._styles = {};
81
+ // prop: formatter
82
+ // A class of a formatter for the tick text.
83
+ // The default $.jqplot.DefaultTickFormatter uses sprintf.
84
+ this.formatter = $.jqplot.DefaultTickFormatter;
85
+ // prop: formatString
86
+ // string passed to the formatter.
87
+ this.formatString = '';
88
+ // prop: prefix
89
+ // String to prepend to the tick label.
90
+ // Prefix is prepended to the formatted tick label.
91
+ this.prefix = '';
92
+ // prop: fontFamily
93
+ // css spec for the font-family css attribute.
94
+ this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif';
95
+ // prop: fontSize
96
+ // CSS spec for font size.
97
+ this.fontSize = '10pt';
98
+ // prop: fontWeight
99
+ // CSS spec for fontWeight
100
+ this.fontWeight = 'normal';
101
+ // prop: fontStretch
102
+ // Multiplier to condense or expand font width.
103
+ // Applies only to browsers which don't support canvas native font rendering.
104
+ this.fontStretch = 1.0;
105
+ // prop: textColor
106
+ // css spec for the color attribute.
107
+ this.textColor = '#666666';
108
+ // prop: enableFontSupport
109
+ // true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.
110
+ // If true, tick label will be drawn with canvas tag native support for fonts.
111
+ // If false, tick label will be drawn with Hershey font metrics.
112
+ this.enableFontSupport = true;
113
+ // prop: pt2px
114
+ // Point to pixel scaling factor, used for computing height of bounding box
115
+ // around a label. The labels text renderer has a default setting of 1.4, which
116
+ // should be suitable for most fonts. Leave as null to use default. If tops of
117
+ // letters appear clipped, increase this. If bounding box seems too big, decrease.
118
+ // This is an issue only with the native font renderering capabilities of Mozilla
119
+ // 3.5 and Safari 4 since they do not provide a method to determine the font height.
120
+ this.pt2px = null;
121
+
122
+ this._elem;
123
+ this._ctx;
124
+ this._plotWidth;
125
+ this._plotHeight;
126
+ this._plotDimensions = {height:null, width:null};
127
+
128
+ $.extend(true, this, options);
129
+
130
+ var ropts = {fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily};
131
+ if (this.pt2px) {
132
+ ropts.pt2px = this.pt2px;
133
+ }
134
+
135
+ if (this.enableFontSupport) {
136
+ if ($.jqplot.support_canvas_text()) {
137
+ this._textRenderer = new $.jqplot.CanvasFontRenderer(ropts);
138
+ }
139
+
140
+ else {
141
+ this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts);
142
+ }
143
+ }
144
+ else {
145
+ this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts);
146
+ }
147
+ };
148
+
149
+ $.jqplot.CanvasAxisTickRenderer.prototype.init = function(options) {
150
+ $.extend(true, this, options);
151
+ this._textRenderer.init({fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily});
152
+ };
153
+
154
+ // return width along the x axis
155
+ // will check first to see if an element exists.
156
+ // if not, will return the computed text box width.
157
+ $.jqplot.CanvasAxisTickRenderer.prototype.getWidth = function(ctx) {
158
+ if (this._elem) {
159
+ return this._elem.outerWidth(true);
160
+ }
161
+ else {
162
+ var tr = this._textRenderer;
163
+ var l = tr.getWidth(ctx);
164
+ var h = tr.getHeight(ctx);
165
+ var w = Math.abs(Math.sin(tr.angle)*h) + Math.abs(Math.cos(tr.angle)*l);
166
+ return w;
167
+ }
168
+ };
169
+
170
+ // return height along the y axis.
171
+ $.jqplot.CanvasAxisTickRenderer.prototype.getHeight = function(ctx) {
172
+ if (this._elem) {
173
+ return this._elem.outerHeight(true);
174
+ }
175
+ else {
176
+ var tr = this._textRenderer;
177
+ var l = tr.getWidth(ctx);
178
+ var h = tr.getHeight(ctx);
179
+ var w = Math.abs(Math.cos(tr.angle)*h) + Math.abs(Math.sin(tr.angle)*l);
180
+ return w;
181
+ }
182
+ };
183
+
184
+ $.jqplot.CanvasAxisTickRenderer.prototype.getAngleRad = function() {
185
+ var a = this.angle * Math.PI/180;
186
+ return a;
187
+ };
188
+
189
+
190
+ $.jqplot.CanvasAxisTickRenderer.prototype.setTick = function(value, axisName, isMinor) {
191
+ this.value = value;
192
+ if (isMinor) {
193
+ this.isMinorTick = true;
194
+ }
195
+ return this;
196
+ };
197
+
198
+ $.jqplot.CanvasAxisTickRenderer.prototype.draw = function(ctx, plot) {
199
+ if (!this.label) {
200
+ this.label = this.prefix + this.formatter(this.formatString, this.value);
201
+ }
202
+
203
+ // Memory Leaks patch
204
+ if (this._elem) {
205
+ if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {
206
+ window.G_vmlCanvasManager.uninitElement(this._elem.get(0));
207
+ }
208
+
209
+ this._elem.emptyForce();
210
+ this._elem = null;
211
+ }
212
+
213
+ // create a canvas here, but can't draw on it untill it is appended
214
+ // to dom for IE compatability.
215
+
216
+ var elem = plot.canvasManager.getCanvas();
217
+
218
+ this._textRenderer.setText(this.label, ctx);
219
+ var w = this.getWidth(ctx);
220
+ var h = this.getHeight(ctx);
221
+ // canvases seem to need to have width and heigh attributes directly set.
222
+ elem.width = w;
223
+ elem.height = h;
224
+ elem.style.width = w;
225
+ elem.style.height = h;
226
+ elem.style.textAlign = 'left';
227
+ elem.style.position = 'absolute';
228
+
229
+ elem = plot.canvasManager.initCanvas(elem);
230
+
231
+ this._elem = $(elem);
232
+ this._elem.css(this._styles);
233
+ this._elem.addClass('jqplot-'+this.axis+'-tick');
234
+
235
+ elem = null;
236
+ return this._elem;
237
+ };
238
+
239
+ $.jqplot.CanvasAxisTickRenderer.prototype.pack = function() {
240
+ this._textRenderer.draw(this._elem.get(0).getContext("2d"), this.label);
241
+ };
242
+
243
+ })(jQuery);
@@ -0,0 +1,865 @@
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 objCounter = 0;
33
+ // class: $.jqplot.CanvasOverlay
34
+ $.jqplot.CanvasOverlay = function(opts){
35
+ var options = opts || {};
36
+ this.options = {
37
+ show: $.jqplot.config.enablePlugins,
38
+ deferDraw: false
39
+ };
40
+ // prop: objects
41
+ this.objects = [];
42
+ this.objectNames = [];
43
+ this.canvas = null;
44
+ this.markerRenderer = new $.jqplot.MarkerRenderer({style:'line'});
45
+ this.markerRenderer.init();
46
+ this.highlightObjectIndex = null;
47
+ if (options.objects) {
48
+ var objs = options.objects,
49
+ obj;
50
+ for (var i=0; i<objs.length; i++) {
51
+ obj = objs[i];
52
+ for (var n in obj) {
53
+ switch (n) {
54
+ case 'line':
55
+ this.addLine(obj[n]);
56
+ break;
57
+ case 'horizontalLine':
58
+ this.addHorizontalLine(obj[n]);
59
+ break;
60
+ case 'dashedHorizontalLine':
61
+ this.addDashedHorizontalLine(obj[n]);
62
+ break;
63
+ case 'verticalLine':
64
+ this.addVerticalLine(obj[n]);
65
+ break;
66
+ case 'dashedVerticalLine':
67
+ this.addDashedVerticalLine(obj[n]);
68
+ break;
69
+ default:
70
+ break;
71
+ }
72
+ }
73
+ }
74
+ }
75
+ $.extend(true, this.options, options);
76
+ };
77
+
78
+ // called with scope of a plot object
79
+ $.jqplot.CanvasOverlay.postPlotInit = function (target, data, opts) {
80
+ var options = opts || {};
81
+ // add a canvasOverlay attribute to the plot
82
+ this.plugins.canvasOverlay = new $.jqplot.CanvasOverlay(options.canvasOverlay);
83
+ };
84
+
85
+
86
+ function LineBase() {
87
+ this.uid = null;
88
+ this.type = null;
89
+ this.gridStart = null;
90
+ this.gridStop = null;
91
+ this.tooltipWidthFactor = 0;
92
+ this.options = {
93
+ // prop: name
94
+ // Optional name for the overlay object.
95
+ // Can be later used to retrieve the object by name.
96
+ name: null,
97
+ // prop: show
98
+ // true to show (draw), false to not draw.
99
+ show: true,
100
+ // prop: lineWidth
101
+ // Width of the line.
102
+ lineWidth: 2,
103
+ // prop: lineCap
104
+ // Type of ending placed on the line ['round', 'butt', 'square']
105
+ lineCap: 'round',
106
+ // prop: color
107
+ // color of the line
108
+ color: '#666666',
109
+ // prop: shadow
110
+ // wether or not to draw a shadow on the line
111
+ shadow: true,
112
+ // prop: shadowAngle
113
+ // Shadow angle in degrees
114
+ shadowAngle: 45,
115
+ // prop: shadowOffset
116
+ // Shadow offset from line in pixels
117
+ shadowOffset: 1,
118
+ // prop: shadowDepth
119
+ // Number of times shadow is stroked, each stroke offset shadowOffset from the last.
120
+ shadowDepth: 3,
121
+ // prop: shadowAlpha
122
+ // Alpha channel transparency of shadow. 0 = transparent.
123
+ shadowAlpha: '0.07',
124
+ // prop: xaxis
125
+ // X axis to use for positioning/scaling the line.
126
+ xaxis: 'xaxis',
127
+ // prop: yaxis
128
+ // Y axis to use for positioning/scaling the line.
129
+ yaxis: 'yaxis',
130
+ // prop: showTooltip
131
+ // Show a tooltip with data point values.
132
+ showTooltip: false,
133
+ // prop: showTooltipPrecision
134
+ // Controls how close to line cursor must be to show tooltip.
135
+ // Higher number = closer to line, lower number = farther from line.
136
+ // 1.0 = cursor must be over line.
137
+ showTooltipPrecision: 0.6,
138
+ // prop: tooltipLocation
139
+ // Where to position tooltip, 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'
140
+ tooltipLocation: 'nw',
141
+ // prop: fadeTooltip
142
+ // true = fade in/out tooltip, flase = show/hide tooltip
143
+ fadeTooltip: true,
144
+ // prop: tooltipFadeSpeed
145
+ // 'slow', 'def', 'fast', or number of milliseconds.
146
+ tooltipFadeSpeed: "fast",
147
+ // prop: tooltipOffset
148
+ // Pixel offset of tooltip from the highlight.
149
+ tooltipOffset: 4,
150
+ // prop: tooltipFormatString
151
+ // Format string passed the x and y values of the cursor on the line.
152
+ // e.g., 'Dogs: %.2f, Cats: %d'.
153
+ tooltipFormatString: '%d, %d'
154
+ };
155
+ }
156
+
157
+ /**
158
+ * Class: Line
159
+ * A straight line.
160
+ */
161
+ function Line(options) {
162
+ LineBase.call(this);
163
+ this.type = 'line';
164
+ var opts = {
165
+ // prop: start
166
+ // [x, y] coordinates for the start of the line.
167
+ start: [],
168
+ // prop: stop
169
+ // [x, y] coordinates for the end of the line.
170
+ stop: []
171
+ };
172
+ $.extend(true, this.options, opts, options);
173
+
174
+ if (this.options.showTooltipPrecision < 0.01) {
175
+ this.options.showTooltipPrecision = 0.01;
176
+ }
177
+ }
178
+
179
+ Line.prototype = new LineBase();
180
+ Line.prototype.constructor = Line;
181
+
182
+
183
+ /**
184
+ * Class: HorizontalLine
185
+ * A straight horizontal line.
186
+ */
187
+ function HorizontalLine(options) {
188
+ LineBase.call(this);
189
+ this.type = 'horizontalLine';
190
+ var opts = {
191
+ // prop: y
192
+ // y value to position the line
193
+ y: null,
194
+ // prop: xmin
195
+ // x value for the start of the line, null to scale to axis min.
196
+ xmin: null,
197
+ // prop: xmax
198
+ // x value for the end of the line, null to scale to axis max.
199
+ xmax: null,
200
+ // prop xOffset
201
+ // offset ends of the line inside the grid. Number
202
+ xOffset: '6px', // number or string. Number interpreted as units, string as pixels.
203
+ xminOffset: null,
204
+ xmaxOffset: null
205
+ };
206
+ $.extend(true, this.options, opts, options);
207
+
208
+ if (this.options.showTooltipPrecision < 0.01) {
209
+ this.options.showTooltipPrecision = 0.01;
210
+ }
211
+ }
212
+
213
+ HorizontalLine.prototype = new LineBase();
214
+ HorizontalLine.prototype.constructor = HorizontalLine;
215
+
216
+
217
+ /**
218
+ * Class: DashedHorizontalLine
219
+ * A straight dashed horizontal line.
220
+ */
221
+ function DashedHorizontalLine(options) {
222
+ LineBase.call(this);
223
+ this.type = 'dashedHorizontalLine';
224
+ var opts = {
225
+ y: null,
226
+ xmin: null,
227
+ xmax: null,
228
+ xOffset: '6px', // number or string. Number interpreted as units, string as pixels.
229
+ xminOffset: null,
230
+ xmaxOffset: null,
231
+ // prop: dashPattern
232
+ // Array of line, space settings in pixels.
233
+ // Default is 8 pixel of line, 8 pixel of space.
234
+ // Note, limit to a 2 element array b/c of bug with higher order arrays.
235
+ dashPattern: [8,8]
236
+ };
237
+ $.extend(true, this.options, opts, options);
238
+
239
+ if (this.options.showTooltipPrecision < 0.01) {
240
+ this.options.showTooltipPrecision = 0.01;
241
+ }
242
+ }
243
+
244
+ DashedHorizontalLine.prototype = new LineBase();
245
+ DashedHorizontalLine.prototype.constructor = DashedHorizontalLine;
246
+
247
+
248
+ /**
249
+ * Class: VerticalLine
250
+ * A straight vertical line.
251
+ */
252
+ function VerticalLine(options) {
253
+ LineBase.call(this);
254
+ this.type = 'verticalLine';
255
+ var opts = {
256
+ x: null,
257
+ ymin: null,
258
+ ymax: null,
259
+ yOffset: '6px', // number or string. Number interpreted as units, string as pixels.
260
+ yminOffset: null,
261
+ ymaxOffset: null
262
+ };
263
+ $.extend(true, this.options, opts, options);
264
+
265
+ if (this.options.showTooltipPrecision < 0.01) {
266
+ this.options.showTooltipPrecision = 0.01;
267
+ }
268
+ }
269
+
270
+ VerticalLine.prototype = new LineBase();
271
+ VerticalLine.prototype.constructor = VerticalLine;
272
+
273
+
274
+ /**
275
+ * Class: DashedVerticalLine
276
+ * A straight dashed vertical line.
277
+ */
278
+ function DashedVerticalLine(options) {
279
+ LineBase.call(this);
280
+ this.type = 'dashedVerticalLine';
281
+ this.start = null;
282
+ this.stop = null;
283
+ var opts = {
284
+ x: null,
285
+ ymin: null,
286
+ ymax: null,
287
+ yOffset: '6px', // number or string. Number interpreted as units, string as pixels.
288
+ yminOffset: null,
289
+ ymaxOffset: null,
290
+ // prop: dashPattern
291
+ // Array of line, space settings in pixels.
292
+ // Default is 8 pixel of line, 8 pixel of space.
293
+ // Note, limit to a 2 element array b/c of bug with higher order arrays.
294
+ dashPattern: [8,8]
295
+ };
296
+ $.extend(true, this.options, opts, options);
297
+
298
+ if (this.options.showTooltipPrecision < 0.01) {
299
+ this.options.showTooltipPrecision = 0.01;
300
+ }
301
+ }
302
+
303
+ DashedVerticalLine.prototype = new LineBase();
304
+ DashedVerticalLine.prototype.constructor = DashedVerticalLine;
305
+
306
+ $.jqplot.CanvasOverlay.prototype.addLine = function(opts) {
307
+ var line = new Line(opts);
308
+ line.uid = objCounter++;
309
+ this.objects.push(line);
310
+ this.objectNames.push(line.options.name);
311
+ };
312
+
313
+ $.jqplot.CanvasOverlay.prototype.addHorizontalLine = function(opts) {
314
+ var line = new HorizontalLine(opts);
315
+ line.uid = objCounter++;
316
+ this.objects.push(line);
317
+ this.objectNames.push(line.options.name);
318
+ };
319
+
320
+ $.jqplot.CanvasOverlay.prototype.addDashedHorizontalLine = function(opts) {
321
+ var line = new DashedHorizontalLine(opts);
322
+ line.uid = objCounter++;
323
+ this.objects.push(line);
324
+ this.objectNames.push(line.options.name);
325
+ };
326
+
327
+ $.jqplot.CanvasOverlay.prototype.addVerticalLine = function(opts) {
328
+ var line = new VerticalLine(opts);
329
+ line.uid = objCounter++;
330
+ this.objects.push(line);
331
+ this.objectNames.push(line.options.name);
332
+ };
333
+
334
+ $.jqplot.CanvasOverlay.prototype.addDashedVerticalLine = function(opts) {
335
+ var line = new DashedVerticalLine(opts);
336
+ line.uid = objCounter++;
337
+ this.objects.push(line);
338
+ this.objectNames.push(line.options.name);
339
+ };
340
+
341
+ $.jqplot.CanvasOverlay.prototype.removeObject = function(idx) {
342
+ // check if integer, remove by index
343
+ if ($.type(idx) == 'number') {
344
+ this.objects.splice(idx, 1);
345
+ this.objectNames.splice(idx, 1);
346
+ }
347
+ // if string, remove by name
348
+ else {
349
+ var id = $.inArray(idx, this.objectNames);
350
+ if (id != -1) {
351
+ this.objects.splice(id, 1);
352
+ this.objectNames.splice(id, 1);
353
+ }
354
+ }
355
+ };
356
+
357
+ $.jqplot.CanvasOverlay.prototype.getObject = function(idx) {
358
+ // check if integer, remove by index
359
+ if ($.type(idx) == 'number') {
360
+ return this.objects[idx];
361
+ }
362
+ // if string, remove by name
363
+ else {
364
+ var id = $.inArray(idx, this.objectNames);
365
+ if (id != -1) {
366
+ return this.objects[id];
367
+ }
368
+ }
369
+ };
370
+
371
+ // Set get as alias for getObject.
372
+ $.jqplot.CanvasOverlay.prototype.get = $.jqplot.CanvasOverlay.prototype.getObject;
373
+
374
+ $.jqplot.CanvasOverlay.prototype.clear = function(plot) {
375
+ this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight());
376
+ };
377
+
378
+ $.jqplot.CanvasOverlay.prototype.draw = function(plot) {
379
+ var obj,
380
+ objs = this.objects,
381
+ mr = this.markerRenderer,
382
+ start,
383
+ stop;
384
+ if (this.options.show) {
385
+ this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight());
386
+ for (var k=0; k<objs.length; k++) {
387
+ obj = objs[k];
388
+ var opts = $.extend(true, {}, obj.options);
389
+ if (obj.options.show) {
390
+ // style and shadow properties should be set before
391
+ // every draw of marker renderer.
392
+ mr.shadow = obj.options.shadow;
393
+ obj.tooltipWidthFactor = obj.options.lineWidth / obj.options.showTooltipPrecision;
394
+ switch (obj.type) {
395
+ case 'line':
396
+ // style and shadow properties should be set before
397
+ // every draw of marker renderer.
398
+ mr.style = 'line';
399
+ opts.closePath = false;
400
+ start = [plot.axes[obj.options.xaxis].series_u2p(obj.options.start[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.start[1])];
401
+ stop = [plot.axes[obj.options.xaxis].series_u2p(obj.options.stop[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.stop[1])];
402
+ obj.gridStart = start;
403
+ obj.gridStop = stop;
404
+ mr.draw(start, stop, this.canvas._ctx, opts);
405
+ break;
406
+ case 'horizontalLine':
407
+
408
+ // style and shadow properties should be set before
409
+ // every draw of marker renderer.
410
+ if (obj.options.y != null) {
411
+ mr.style = 'line';
412
+ opts.closePath = false;
413
+ var xaxis = plot.axes[obj.options.xaxis],
414
+ xstart,
415
+ xstop,
416
+ y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),
417
+ xminoff = obj.options.xminOffset || obj.options.xOffset,
418
+ xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;
419
+ if (obj.options.xmin != null) {
420
+ xstart = xaxis.series_u2p(obj.options.xmin);
421
+ }
422
+ else if (xminoff != null) {
423
+ if ($.type(xminoff) == "number") {
424
+ xstart = xaxis.series_u2p(xaxis.min + xminoff);
425
+ }
426
+ else if ($.type(xminoff) == "string") {
427
+ xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);
428
+ }
429
+ }
430
+ if (obj.options.xmax != null) {
431
+ xstop = xaxis.series_u2p(obj.options.xmax);
432
+ }
433
+ else if (xmaxoff != null) {
434
+ if ($.type(xmaxoff) == "number") {
435
+ xstop = xaxis.series_u2p(xaxis.max - xmaxoff);
436
+ }
437
+ else if ($.type(xmaxoff) == "string") {
438
+ xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);
439
+ }
440
+ }
441
+ if (xstop != null && xstart != null) {
442
+ obj.gridStart = [xstart, y];
443
+ obj.gridStop = [xstop, y];
444
+ mr.draw([xstart, y], [xstop, y], this.canvas._ctx, opts);
445
+ }
446
+ }
447
+ break;
448
+
449
+ case 'dashedHorizontalLine':
450
+
451
+ var dashPat = obj.options.dashPattern;
452
+ var dashPatLen = 0;
453
+ for (var i=0; i<dashPat.length; i++) {
454
+ dashPatLen += dashPat[i];
455
+ }
456
+
457
+ // style and shadow properties should be set before
458
+ // every draw of marker renderer.
459
+ if (obj.options.y != null) {
460
+ mr.style = 'line';
461
+ opts.closePath = false;
462
+ var xaxis = plot.axes[obj.options.xaxis],
463
+ xstart,
464
+ xstop,
465
+ y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),
466
+ xminoff = obj.options.xminOffset || obj.options.xOffset,
467
+ xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;
468
+ if (obj.options.xmin != null) {
469
+ xstart = xaxis.series_u2p(obj.options.xmin);
470
+ }
471
+ else if (xminoff != null) {
472
+ if ($.type(xminoff) == "number") {
473
+ xstart = xaxis.series_u2p(xaxis.min + xminoff);
474
+ }
475
+ else if ($.type(xminoff) == "string") {
476
+ xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);
477
+ }
478
+ }
479
+ if (obj.options.xmax != null) {
480
+ xstop = xaxis.series_u2p(obj.options.xmax);
481
+ }
482
+ else if (xmaxoff != null) {
483
+ if ($.type(xmaxoff) == "number") {
484
+ xstop = xaxis.series_u2p(xaxis.max - xmaxoff);
485
+ }
486
+ else if ($.type(xmaxoff) == "string") {
487
+ xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);
488
+ }
489
+ }
490
+ if (xstop != null && xstart != null) {
491
+ obj.gridStart = [xstart, y];
492
+ obj.gridStop = [xstop, y];
493
+ var numDash = Math.ceil((xstop - xstart)/dashPatLen);
494
+ var b=xstart, e;
495
+ for (var i=0; i<numDash; i++) {
496
+ for (var j=0; j<dashPat.length; j+=2) {
497
+ e = b+dashPat[j];
498
+ mr.draw([b, y], [e, y], this.canvas._ctx, opts);
499
+ b += dashPat[j];
500
+ if (j < dashPat.length-1) {
501
+ b += dashPat[j+1];
502
+ }
503
+ }
504
+ }
505
+ }
506
+ }
507
+ break;
508
+
509
+ case 'verticalLine':
510
+
511
+ // style and shadow properties should be set before
512
+ // every draw of marker renderer.
513
+ if (obj.options.x != null) {
514
+ mr.style = 'line';
515
+ opts.closePath = false;
516
+ var yaxis = plot.axes[obj.options.yaxis],
517
+ ystart,
518
+ ystop,
519
+ x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),
520
+ yminoff = obj.options.yminOffset || obj.options.yOffset,
521
+ ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;
522
+ if (obj.options.ymin != null) {
523
+ ystart = yaxis.series_u2p(obj.options.ymin);
524
+ }
525
+ else if (yminoff != null) {
526
+ if ($.type(yminoff) == "number") {
527
+ ystart = yaxis.series_u2p(yaxis.min - yminoff);
528
+ }
529
+ else if ($.type(yminoff) == "string") {
530
+ ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);
531
+ }
532
+ }
533
+ if (obj.options.ymax != null) {
534
+ ystop = yaxis.series_u2p(obj.options.ymax);
535
+ }
536
+ else if (ymaxoff != null) {
537
+ if ($.type(ymaxoff) == "number") {
538
+ ystop = yaxis.series_u2p(yaxis.max + ymaxoff);
539
+ }
540
+ else if ($.type(ymaxoff) == "string") {
541
+ ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);
542
+ }
543
+ }
544
+ if (ystop != null && ystart != null) {
545
+ obj.gridStart = [x, ystart];
546
+ obj.gridStop = [x, ystop];
547
+ mr.draw([x, ystart], [x, ystop], this.canvas._ctx, opts);
548
+ }
549
+ }
550
+ break;
551
+
552
+ case 'dashedVerticalLine':
553
+
554
+ var dashPat = obj.options.dashPattern;
555
+ var dashPatLen = 0;
556
+ for (var i=0; i<dashPat.length; i++) {
557
+ dashPatLen += dashPat[i];
558
+ }
559
+
560
+ // style and shadow properties should be set before
561
+ // every draw of marker renderer.
562
+ if (obj.options.x != null) {
563
+ mr.style = 'line';
564
+ opts.closePath = false;
565
+ var yaxis = plot.axes[obj.options.yaxis],
566
+ ystart,
567
+ ystop,
568
+ x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),
569
+ yminoff = obj.options.yminOffset || obj.options.yOffset,
570
+ ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;
571
+ if (obj.options.ymin != null) {
572
+ ystart = yaxis.series_u2p(obj.options.ymin);
573
+ }
574
+ else if (yminoff != null) {
575
+ if ($.type(yminoff) == "number") {
576
+ ystart = yaxis.series_u2p(yaxis.min - yminoff);
577
+ }
578
+ else if ($.type(yminoff) == "string") {
579
+ ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);
580
+ }
581
+ }
582
+ if (obj.options.ymax != null) {
583
+ ystop = yaxis.series_u2p(obj.options.ymax);
584
+ }
585
+ else if (ymaxoff != null) {
586
+ if ($.type(ymaxoff) == "number") {
587
+ ystop = yaxis.series_u2p(yaxis.max + ymaxoff);
588
+ }
589
+ else if ($.type(ymaxoff) == "string") {
590
+ ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);
591
+ }
592
+ }
593
+
594
+
595
+ if (ystop != null && ystart != null) {
596
+ obj.gridStart = [x, ystart];
597
+ obj.gridStop = [x, ystop];
598
+ var numDash = Math.ceil((ystart - ystop)/dashPatLen);
599
+ var firstDashAdjust = ((numDash * dashPatLen) - (ystart - ystop))/2.0;
600
+ var b=ystart, e, bs, es;
601
+ for (var i=0; i<numDash; i++) {
602
+ for (var j=0; j<dashPat.length; j+=2) {
603
+ e = b - dashPat[j];
604
+ if (e < ystop) {
605
+ e = ystop;
606
+ }
607
+ if (b < ystop) {
608
+ b = ystop;
609
+ }
610
+ // es = e;
611
+ // if (i == 0) {
612
+ // es += firstDashAdjust;
613
+ // }
614
+ mr.draw([x, b], [x, e], this.canvas._ctx, opts);
615
+ b -= dashPat[j];
616
+ if (j < dashPat.length-1) {
617
+ b -= dashPat[j+1];
618
+ }
619
+ }
620
+ }
621
+ }
622
+ }
623
+ break;
624
+
625
+ default:
626
+ break;
627
+ }
628
+ }
629
+ }
630
+ }
631
+ };
632
+
633
+ // called within context of plot
634
+ // create a canvas which we can draw on.
635
+ // insert it before the eventCanvas, so eventCanvas will still capture events.
636
+ $.jqplot.CanvasOverlay.postPlotDraw = function() {
637
+ var co = this.plugins.canvasOverlay;
638
+ // Memory Leaks patch
639
+ if (co && co.highlightCanvas) {
640
+ co.highlightCanvas.resetCanvas();
641
+ co.highlightCanvas = null;
642
+ }
643
+ co.canvas = new $.jqplot.GenericCanvas();
644
+
645
+ this.eventCanvas._elem.before(co.canvas.createElement(this._gridPadding, 'jqplot-overlayCanvas-canvas', this._plotDimensions, this));
646
+ co.canvas.setContext();
647
+ if (!co.deferDraw) {
648
+ co.draw(this);
649
+ }
650
+
651
+ var elem = document.createElement('div');
652
+ co._tooltipElem = $(elem);
653
+ elem = null;
654
+ co._tooltipElem.addClass('jqplot-canvasOverlay-tooltip');
655
+ co._tooltipElem.css({position:'absolute', display:'none'});
656
+
657
+ this.eventCanvas._elem.before(co._tooltipElem);
658
+ this.eventCanvas._elem.bind('mouseleave', { elem: co._tooltipElem }, function (ev) { ev.data.elem.hide(); });
659
+
660
+ var co = null;
661
+ };
662
+
663
+
664
+ function showTooltip(plot, obj, gridpos, datapos) {
665
+ var co = plot.plugins.canvasOverlay;
666
+ var elem = co._tooltipElem;
667
+
668
+ var opts = obj.options, x, y;
669
+
670
+ elem.html($.jqplot.sprintf(opts.tooltipFormatString, datapos[0], datapos[1]));
671
+
672
+ switch (opts.tooltipLocation) {
673
+ case 'nw':
674
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
675
+ y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
676
+ break;
677
+ case 'n':
678
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true)/2;
679
+ y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
680
+ break;
681
+ case 'ne':
682
+ x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;
683
+ y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
684
+ break;
685
+ case 'e':
686
+ x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;
687
+ y = gridpos[1] + plot._gridPadding.top - elem.outerHeight(true)/2;
688
+ break;
689
+ case 'se':
690
+ x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;
691
+ y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;
692
+ break;
693
+ case 's':
694
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true)/2;
695
+ y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;
696
+ break;
697
+ case 'sw':
698
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
699
+ y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;
700
+ break;
701
+ case 'w':
702
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
703
+ y = gridpos[1] + plot._gridPadding.top - elem.outerHeight(true)/2;
704
+ break;
705
+ default: // same as 'nw'
706
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
707
+ y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
708
+ break;
709
+ }
710
+
711
+ elem.css('left', x);
712
+ elem.css('top', y);
713
+ if (opts.fadeTooltip) {
714
+ // Fix for stacked up animations. Thnanks Trevor!
715
+ elem.stop(true,true).fadeIn(opts.tooltipFadeSpeed);
716
+ }
717
+ else {
718
+ elem.show();
719
+ }
720
+ elem = null;
721
+ }
722
+
723
+
724
+ function isNearLine(point, lstart, lstop, width) {
725
+ // r is point to test, p and q are end points.
726
+ var rx = point[0];
727
+ var ry = point[1];
728
+ var px = Math.round(lstop[0]);
729
+ var py = Math.round(lstop[1]);
730
+ var qx = Math.round(lstart[0]);
731
+ var qy = Math.round(lstart[1]);
732
+
733
+ var l = Math.sqrt(Math.pow(px-qx, 2) + Math.pow(py-qy, 2));
734
+
735
+ // scale error term by length of line.
736
+ var eps = width*l;
737
+ var res = Math.abs((qx-px) * (ry-py) - (qy-py) * (rx-px));
738
+ var ret = (res < eps) ? true : false;
739
+ return ret;
740
+ }
741
+
742
+
743
+ function handleMove(ev, gridpos, datapos, neighbor, plot) {
744
+ var co = plot.plugins.canvasOverlay;
745
+ var objs = co.objects;
746
+ var l = objs.length;
747
+ var obj, haveHighlight=false;
748
+ var elem;
749
+ for (var i=0; i<l; i++) {
750
+ obj = objs[i];
751
+ if (obj.options.showTooltip) {
752
+ var n = isNearLine([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor);
753
+ datapos = [plot.axes[obj.options.xaxis].series_p2u(gridpos.x), plot.axes[obj.options.yaxis].series_p2u(gridpos.y)];
754
+
755
+ // cases:
756
+ // near line, no highlighting
757
+ // near line, highliting on this line
758
+ // near line, highlighting another line
759
+ // not near any line, highlighting
760
+ // not near any line, no highlighting
761
+
762
+ // near line, not currently highlighting
763
+ if (n && co.highlightObjectIndex == null) {
764
+ switch (obj.type) {
765
+ case 'line':
766
+ showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);
767
+ break;
768
+
769
+ case 'horizontalLine':
770
+ case 'dashedHorizontalLine':
771
+ showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);
772
+ break;
773
+
774
+ case 'verticalLine':
775
+ case 'dashedVerticalLine':
776
+ showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
777
+ break;
778
+ default:
779
+ break;
780
+ }
781
+ co.highlightObjectIndex = i;
782
+ haveHighlight = true;
783
+ break;
784
+ }
785
+
786
+ // near line, highlighting another line.
787
+ else if (n && co.highlightObjectIndex !== i) {
788
+ // turn off tooltip.
789
+ elem = co._tooltipElem;
790
+ if (obj.fadeTooltip) {
791
+ elem.fadeOut(obj.tooltipFadeSpeed);
792
+ }
793
+ else {
794
+ elem.hide();
795
+ }
796
+
797
+ // turn on right tooltip.
798
+ switch (obj.type) {
799
+ case 'line':
800
+ showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);
801
+ break;
802
+
803
+ case 'horizontalLine':
804
+ case 'dashedHorizontalLine':
805
+ showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);
806
+ break;
807
+
808
+ case 'verticalLine':
809
+ case 'dashedVerticalLine':
810
+ showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
811
+ break;
812
+ default:
813
+ break;
814
+ }
815
+
816
+ co.highlightObjectIndex = i;
817
+ haveHighlight = true;
818
+ break;
819
+ }
820
+
821
+ // near line, already highlighting this line, update
822
+ else if (n) {
823
+ switch (obj.type) {
824
+ case 'line':
825
+ showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);
826
+ break;
827
+
828
+ case 'horizontalLine':
829
+ case 'dashedHorizontalLine':
830
+ showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);
831
+ break;
832
+
833
+ case 'verticalLine':
834
+ case 'dashedVerticalLine':
835
+ showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
836
+ break;
837
+ default:
838
+ break;
839
+ }
840
+
841
+ haveHighlight = true;
842
+ break;
843
+ }
844
+ }
845
+ }
846
+
847
+ // check if we are highlighting and not near a line, turn it off.
848
+ if (!haveHighlight && co.highlightObjectIndex !== null) {
849
+ elem = co._tooltipElem;
850
+ obj = co.getObject(co.highlightObjectIndex);
851
+ if (obj.fadeTooltip) {
852
+ elem.fadeOut(obj.tooltipFadeSpeed);
853
+ }
854
+ else {
855
+ elem.hide();
856
+ }
857
+ co.highlightObjectIndex = null;
858
+ }
859
+ }
860
+
861
+ $.jqplot.postInitHooks.push($.jqplot.CanvasOverlay.postPlotInit);
862
+ $.jqplot.postDrawHooks.push($.jqplot.CanvasOverlay.postPlotDraw);
863
+ $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]);
864
+
865
+ })(jQuery);