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,116 +1,116 @@
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
- /**
33
- * Class: $.jqplot.ciParser
34
- * Data Renderer function which converts a custom JSON data object into jqPlot data format.
35
- * Set this as a callable on the jqplot dataRenderer plot option:
36
- *
37
- * > plot = $.jqplot('mychart', [data], { dataRenderer: $.jqplot.ciParser, ... });
38
- *
39
- * Where data is an object in JSON format or a JSON encoded string conforming to the
40
- * City Index API spec.
41
- *
42
- * Note that calling the renderer function is handled internally by jqPlot. The
43
- * user does not have to call the function. The parameters described below will
44
- * automatically be passed to the ciParser function.
45
- *
46
- * Parameters:
47
- * data - JSON encoded string or object.
48
- * plot - reference to jqPlot Plot object.
49
- *
50
- * Returns:
51
- * data array in jqPlot format.
52
- *
53
- */
54
- $.jqplot.ciParser = function (data, plot) {
55
- var ret = [],
56
- line,
57
- temp,
58
- i, j, k, kk;
59
-
60
- if (typeof(data) == "string") {
61
- data = $.jqplot.JSON.parse(data, handleStrings);
62
- }
63
-
64
- else if (typeof(data) == "object") {
65
- for (k in data) {
66
- for (i=0; i<data[k].length; i++) {
67
- for (kk in data[k][i]) {
68
- data[k][i][kk] = handleStrings(kk, data[k][i][kk]);
69
- }
70
- }
71
- }
72
- }
73
-
74
- else {
75
- return null;
76
- }
77
-
78
- // function handleStrings
79
- // Checks any JSON encoded strings to see if they are
80
- // encoded dates. If so, pull out the timestamp.
81
- // Expects dates to be represented by js timestamps.
82
-
83
- function handleStrings(key, value) {
84
- var a;
85
- if (value != null) {
86
- if (value.toString().indexOf('Date') >= 0) {
87
- //here we will try to extract the ticks from the Date string in the "value" fields of JSON returned data
88
- a = /^\/Date\((-?[0-9]+)\)\/$/.exec(value);
89
- if (a) {
90
- return parseInt(a[1], 10);
91
- }
92
- }
93
- return value;
94
- }
95
- }
96
-
97
- for (var prop in data) {
98
- line = [];
99
- temp = data[prop];
100
- switch (prop) {
101
- case "PriceTicks":
102
- for (i=0; i<temp.length; i++) {
103
- line.push([temp[i]['TickDate'], temp[i]['Price']]);
104
- }
105
- break;
106
- case "PriceBars":
107
- for (i=0; i<temp.length; i++) {
108
- line.push([temp[i]['BarDate'], temp[i]['Open'], temp[i]['High'], temp[i]['Low'], temp[i]['Close']]);
109
- }
110
- break;
111
- }
112
- ret.push(line);
113
- }
114
- return ret;
115
- };
1
+ /**
2
+ * jqPlot
3
+ * Pure JavaScript plotting plugin using jQuery
4
+ *
5
+ * Version: 1.0.9
6
+ * Revision: d96a669
7
+ *
8
+ * Copyright (c) 2009-2016 Chris Leonello
9
+ * jqPlot is currently available for use in all personal or commercial projects
10
+ * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
11
+ * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
12
+ * choose the license that best suits your project and use it accordingly.
13
+ *
14
+ * Although not required, the author would appreciate an email letting him
15
+ * know of any substantial use of jqPlot. You can reach the author at:
16
+ * chris at jqplot dot com or see http://www.jqplot.com/info.php .
17
+ *
18
+ * If you are feeling kind and generous, consider supporting the project by
19
+ * making a donation at: http://www.jqplot.com/donate.php .
20
+ *
21
+ * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
22
+ *
23
+ * version 2007.04.27
24
+ * author Ash Searle
25
+ * http://hexmen.com/blog/2007/03/printf-sprintf/
26
+ * http://hexmen.com/js/sprintf.js
27
+ * The author (Ash Searle) has placed this code in the public domain:
28
+ * "This code is unrestricted: you are free to use it however you like."
29
+ *
30
+ */
31
+ (function($) {
32
+ /**
33
+ * Class: $.jqplot.ciParser
34
+ * Data Renderer function which converts a custom JSON data object into jqPlot data format.
35
+ * Set this as a callable on the jqplot dataRenderer plot option:
36
+ *
37
+ * > plot = $.jqplot('mychart', [data], { dataRenderer: $.jqplot.ciParser, ... });
38
+ *
39
+ * Where data is an object in JSON format or a JSON encoded string conforming to the
40
+ * City Index API spec.
41
+ *
42
+ * Note that calling the renderer function is handled internally by jqPlot. The
43
+ * user does not have to call the function. The parameters described below will
44
+ * automatically be passed to the ciParser function.
45
+ *
46
+ * Parameters:
47
+ * data - JSON encoded string or object.
48
+ * plot - reference to jqPlot Plot object.
49
+ *
50
+ * Returns:
51
+ * data array in jqPlot format.
52
+ *
53
+ */
54
+ $.jqplot.ciParser = function (data, plot) {
55
+ var ret = [],
56
+ line,
57
+ temp,
58
+ i, j, k, kk;
59
+
60
+ if (typeof(data) == "string") {
61
+ data = $.jqplot.JSON.parse(data, handleStrings);
62
+ }
63
+
64
+ else if (typeof(data) == "object") {
65
+ for (k in data) {
66
+ for (i=0; i<data[k].length; i++) {
67
+ for (kk in data[k][i]) {
68
+ data[k][i][kk] = handleStrings(kk, data[k][i][kk]);
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ else {
75
+ return null;
76
+ }
77
+
78
+ // function handleStrings
79
+ // Checks any JSON encoded strings to see if they are
80
+ // encoded dates. If so, pull out the timestamp.
81
+ // Expects dates to be represented by js timestamps.
82
+
83
+ function handleStrings(key, value) {
84
+ var a;
85
+ if (value != null) {
86
+ if (value.toString().indexOf('Date') >= 0) {
87
+ //here we will try to extract the ticks from the Date string in the "value" fields of JSON returned data
88
+ a = /^\/Date\((-?[0-9]+)\)\/$/.exec(value);
89
+ if (a) {
90
+ return parseInt(a[1], 10);
91
+ }
92
+ }
93
+ return value;
94
+ }
95
+ }
96
+
97
+ for (var prop in data) {
98
+ line = [];
99
+ temp = data[prop];
100
+ switch (prop) {
101
+ case "PriceTicks":
102
+ for (i=0; i<temp.length; i++) {
103
+ line.push([temp[i]['TickDate'], temp[i]['Price']]);
104
+ }
105
+ break;
106
+ case "PriceBars":
107
+ for (i=0; i<temp.length; i++) {
108
+ line.push([temp[i]['BarDate'], temp[i]['Open'], temp[i]['High'], temp[i]['Low'], temp[i]['Close']]);
109
+ }
110
+ break;
111
+ }
112
+ ret.push(line);
113
+ }
114
+ return ret;
115
+ };
116
116
  })(jQuery);
@@ -1,1108 +1,1108 @@
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
-
33
- /**
34
- * Class: $.jqplot.Cursor
35
- * Plugin class representing the cursor as displayed on the plot.
36
- */
37
- $.jqplot.Cursor = function(options) {
38
- // Group: Properties
39
- //
40
- // prop: style
41
- // CSS spec for cursor style
42
- this.style = 'crosshair';
43
- this.previousCursor = 'auto';
44
- // prop: show
45
- // whether to show the cursor or not.
46
- this.show = $.jqplot.config.enablePlugins;
47
- // prop: showTooltip
48
- // show a cursor position tooltip. Location of the tooltip
49
- // will be controlled by followMouse and tooltipLocation.
50
- this.showTooltip = true;
51
- // prop: followMouse
52
- // Tooltip follows the mouse, it is not at a fixed location.
53
- // Tooltip will show on the grid at the location given by
54
- // tooltipLocation, offset from the grid edge by tooltipOffset.
55
- this.followMouse = false;
56
- // prop: tooltipLocation
57
- // Where to position tooltip. If followMouse is true, this is
58
- // relative to the cursor, otherwise, it is relative to the grid.
59
- // One of 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'
60
- this.tooltipLocation = 'se';
61
- // prop: tooltipOffset
62
- // Pixel offset of tooltip from the grid boudaries or cursor center.
63
- this.tooltipOffset = 6;
64
- // prop: showTooltipGridPosition
65
- // show the grid pixel coordinates of the mouse.
66
- this.showTooltipGridPosition = false;
67
- // prop: showTooltipUnitPosition
68
- // show the unit (data) coordinates of the mouse.
69
- this.showTooltipUnitPosition = true;
70
- // prop: showTooltipDataPosition
71
- // Used with showVerticalLine to show intersecting data points in the tooltip.
72
- this.showTooltipDataPosition = false;
73
- // prop: tooltipFormatString
74
- // sprintf format string for the tooltip.
75
- // Uses Ash Searle's javascript sprintf implementation
76
- // found here: http://hexmen.com/blog/2007/03/printf-sprintf/
77
- // See http://perldoc.perl.org/functions/sprintf.html for reference
78
- // Note, if showTooltipDataPosition is true, the default tooltipFormatString
79
- // will be set to the cursorLegendFormatString, not the default given here.
80
- this.tooltipFormatString = '%.4P, %.4P';
81
- // prop: useAxesFormatters
82
- // Use the x and y axes formatters to format the text in the tooltip.
83
- this.useAxesFormatters = true;
84
- // prop: tooltipAxisGroups
85
- // Show position for the specified axes.
86
- // This is an array like [['xaxis', 'yaxis'], ['xaxis', 'y2axis']]
87
- // Default is to compute automatically for all visible axes.
88
- this.tooltipAxisGroups = [];
89
- // prop: zoom
90
- // Enable plot zooming.
91
- this.zoom = false;
92
- // zoomProxy and zoomTarget properties are not directly set by user.
93
- // They Will be set through call to zoomProxy method.
94
- this.zoomProxy = false;
95
- this.zoomTarget = false;
96
- // prop: looseZoom
97
- // Will expand zoom range to provide more rounded tick values.
98
- // Works only with linear, log and date axes.
99
- this.looseZoom = true;
100
- // prop: clickReset
101
- // Will reset plot zoom if single click on plot without drag.
102
- this.clickReset = false;
103
- // prop: dblClickReset
104
- // Will reset plot zoom if double click on plot without drag.
105
- this.dblClickReset = true;
106
- // prop: showVerticalLine
107
- // draw a vertical line across the plot which follows the cursor.
108
- // When the line is near a data point, a special legend and/or tooltip can
109
- // be updated with the data values.
110
- this.showVerticalLine = false;
111
- // prop: showHorizontalLine
112
- // draw a horizontal line across the plot which follows the cursor.
113
- this.showHorizontalLine = false;
114
- // prop: constrainZoomTo
115
- // 'none', 'x' or 'y'
116
- this.constrainZoomTo = 'none';
117
- // // prop: autoscaleConstraint
118
- // // when a constrained axis is specified, true will
119
- // // auatoscale the adjacent axis.
120
- // this.autoscaleConstraint = true;
121
- this.shapeRenderer = new $.jqplot.ShapeRenderer();
122
- this._zoom = {start:[], end:[], started: false, zooming:false, isZoomed:false, axes:{start:{}, end:{}}, gridpos:{}, datapos:{}};
123
- this._tooltipElem;
124
- this.zoomCanvas;
125
- this.cursorCanvas;
126
- // prop: intersectionThreshold
127
- // pixel distance from data point or marker to consider cursor lines intersecting with point.
128
- // If data point markers are not shown, this should be >= 1 or will often miss point intersections.
129
- this.intersectionThreshold = 2;
130
- // prop: showCursorLegend
131
- // Replace the plot legend with an enhanced legend displaying intersection information.
132
- this.showCursorLegend = false;
133
- // prop: cursorLegendFormatString
134
- // Format string used in the cursor legend. If showTooltipDataPosition is true,
135
- // this will also be the default format string used by tooltipFormatString.
136
- this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString;
137
- // whether the cursor is over the grid or not.
138
- this._oldHandlers = {onselectstart: null, ondrag: null, onmousedown: null};
139
- // prop: constrainOutsideZoom
140
- // True to limit actual zoom area to edges of grid, even when zooming
141
- // outside of plot area. That is, can't zoom out by mousing outside plot.
142
- this.constrainOutsideZoom = true;
143
- // prop: showTooltipOutsideZoom
144
- // True will keep updating the tooltip when zooming of the grid.
145
- this.showTooltipOutsideZoom = false;
146
- // true if mouse is over grid, false if not.
147
- this.onGrid = false;
148
- $.extend(true, this, options);
149
- };
150
-
151
- $.jqplot.Cursor.cursorLegendFormatString = '%s x:%s, y:%s';
152
-
153
- // called with scope of plot
154
- $.jqplot.Cursor.init = function (target, data, opts){
155
- // add a cursor attribute to the plot
156
- var options = opts || {};
157
- this.plugins.cursor = new $.jqplot.Cursor(options.cursor);
158
- var c = this.plugins.cursor;
159
-
160
- if (c.show) {
161
- $.jqplot.eventListenerHooks.push(['jqplotMouseEnter', handleMouseEnter]);
162
- $.jqplot.eventListenerHooks.push(['jqplotMouseLeave', handleMouseLeave]);
163
- $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMouseMove]);
164
-
165
- if (c.showCursorLegend) {
166
- opts.legend = opts.legend || {};
167
- opts.legend.renderer = $.jqplot.CursorLegendRenderer;
168
- opts.legend.formatString = this.plugins.cursor.cursorLegendFormatString;
169
- opts.legend.show = true;
170
- }
171
-
172
- if (c.zoom) {
173
- $.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleMouseDown]);
174
-
175
- if (c.clickReset) {
176
- $.jqplot.eventListenerHooks.push(['jqplotClick', handleClick]);
177
- }
178
-
179
- if (c.dblClickReset) {
180
- $.jqplot.eventListenerHooks.push(['jqplotDblClick', handleDblClick]);
181
- }
182
- }
183
-
184
- this.resetZoom = function() {
185
- var axes = this.axes;
186
- if (!c.zoomProxy) {
187
- for (var ax in axes) {
188
- axes[ax].reset();
189
- axes[ax]._ticks = [];
190
- // fake out tick creation algorithm to make sure original auto
191
- // computed format string is used if _overrideFormatString is true
192
- if (c._zoom.axes[ax] !== undefined) {
193
- axes[ax]._autoFormatString = c._zoom.axes[ax].tickFormatString;
194
- }
195
- }
196
- this.redraw();
197
- }
198
- else {
199
- var ctx = this.plugins.cursor.zoomCanvas._ctx;
200
- ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
201
- ctx = null;
202
- }
203
- this.plugins.cursor._zoom.isZoomed = false;
204
- this.target.trigger('jqplotResetZoom', [this, this.plugins.cursor]);
205
- };
206
-
207
-
208
- if (c.showTooltipDataPosition) {
209
- c.showTooltipUnitPosition = false;
210
- c.showTooltipGridPosition = false;
211
- if (options.cursor.tooltipFormatString == undefined) {
212
- c.tooltipFormatString = $.jqplot.Cursor.cursorLegendFormatString;
213
- }
214
- }
215
- }
216
- };
217
-
218
- // called with context of plot
219
- $.jqplot.Cursor.postDraw = function() {
220
- var c = this.plugins.cursor;
221
-
222
- // Memory Leaks patch
223
- if (c.zoomCanvas) {
224
- c.zoomCanvas.resetCanvas();
225
- c.zoomCanvas = null;
226
- }
227
-
228
- if (c.cursorCanvas) {
229
- c.cursorCanvas.resetCanvas();
230
- c.cursorCanvas = null;
231
- }
232
-
233
- if (c._tooltipElem) {
234
- c._tooltipElem.emptyForce();
235
- c._tooltipElem = null;
236
- }
237
-
238
-
239
- if (c.zoom) {
240
- c.zoomCanvas = new $.jqplot.GenericCanvas();
241
- this.eventCanvas._elem.before(c.zoomCanvas.createElement(this._gridPadding, 'jqplot-zoom-canvas', this._plotDimensions, this));
242
- c.zoomCanvas.setContext();
243
- }
244
-
245
- var elem = document.createElement('div');
246
- c._tooltipElem = $(elem);
247
- elem = null;
248
- c._tooltipElem.addClass('jqplot-cursor-tooltip');
249
- c._tooltipElem.css({position:'absolute', display:'none'});
250
-
251
-
252
- if (c.zoomCanvas) {
253
- c.zoomCanvas._elem.before(c._tooltipElem);
254
- }
255
-
256
- else {
257
- this.eventCanvas._elem.before(c._tooltipElem);
258
- }
259
-
260
- if (c.showVerticalLine || c.showHorizontalLine) {
261
- c.cursorCanvas = new $.jqplot.GenericCanvas();
262
- this.eventCanvas._elem.before(c.cursorCanvas.createElement(this._gridPadding, 'jqplot-cursor-canvas', this._plotDimensions, this));
263
- c.cursorCanvas.setContext();
264
- }
265
-
266
- // if we are showing the positions in unit coordinates, and no axes groups
267
- // were specified, create a default set.
268
- if (c.showTooltipUnitPosition){
269
- if (c.tooltipAxisGroups.length === 0) {
270
- var series = this.series;
271
- var s;
272
- var temp = [];
273
- for (var i=0; i<series.length; i++) {
274
- s = series[i];
275
- var ax = s.xaxis+','+s.yaxis;
276
- if ($.inArray(ax, temp) == -1) {
277
- temp.push(ax);
278
- }
279
- }
280
- for (var i=0; i<temp.length; i++) {
281
- c.tooltipAxisGroups.push(temp[i].split(','));
282
- }
283
- }
284
- }
285
- };
286
-
287
- // Group: methods
288
- //
289
- // method: $.jqplot.Cursor.zoomProxy
290
- // links targetPlot to controllerPlot so that plot zooming of
291
- // targetPlot will be controlled by zooming on the controllerPlot.
292
- // controllerPlot will not actually zoom, but acts as an
293
- // overview plot. Note, the zoom options must be set to true for
294
- // zoomProxy to work.
295
- $.jqplot.Cursor.zoomProxy = function(targetPlot, controllerPlot) {
296
- var tc = targetPlot.plugins.cursor;
297
- var cc = controllerPlot.plugins.cursor;
298
- tc.zoomTarget = true;
299
- tc.zoom = true;
300
- tc.style = 'auto';
301
- tc.dblClickReset = false;
302
- cc.zoom = true;
303
- cc.zoomProxy = true;
304
-
305
- controllerPlot.target.bind('jqplotZoom', plotZoom);
306
- controllerPlot.target.bind('jqplotResetZoom', plotReset);
307
-
308
- function plotZoom(ev, gridpos, datapos, plot, cursor) {
309
- tc.doZoom(gridpos, datapos, targetPlot, cursor);
310
- }
311
-
312
- function plotReset(ev, plot, cursor) {
313
- targetPlot.resetZoom();
314
- }
315
- };
316
-
317
- $.jqplot.Cursor.prototype.resetZoom = function(plot, cursor) {
318
- var axes = plot.axes;
319
- var cax = cursor._zoom.axes;
320
- if (!plot.plugins.cursor.zoomProxy && cursor._zoom.isZoomed) {
321
- for (var ax in axes) {
322
- // axes[ax]._ticks = [];
323
- // axes[ax].min = cax[ax].min;
324
- // axes[ax].max = cax[ax].max;
325
- // axes[ax].numberTicks = cax[ax].numberTicks;
326
- // axes[ax].tickInterval = cax[ax].tickInterval;
327
- // // for date axes
328
- // axes[ax].daTickInterval = cax[ax].daTickInterval;
329
- axes[ax].reset();
330
- axes[ax]._ticks = [];
331
- // fake out tick creation algorithm to make sure original auto
332
- // computed format string is used if _overrideFormatString is true
333
- axes[ax]._autoFormatString = cax[ax].tickFormatString;
334
- }
335
- plot.redraw();
336
- cursor._zoom.isZoomed = false;
337
- }
338
- else {
339
- var ctx = cursor.zoomCanvas._ctx;
340
- ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
341
- ctx = null;
342
- }
343
- plot.target.trigger('jqplotResetZoom', [plot, cursor]);
344
- };
345
-
346
- $.jqplot.Cursor.resetZoom = function(plot) {
347
- plot.resetZoom();
348
- };
349
-
350
- $.jqplot.Cursor.prototype.doZoom = function (gridpos, datapos, plot, cursor) {
351
- var c = cursor;
352
- var axes = plot.axes;
353
- var zaxes = c._zoom.axes;
354
- var start = zaxes.start;
355
- var end = zaxes.end;
356
- var min, max, dp, span,
357
- newmin, newmax, curax, _numberTicks, ret;
358
- var ctx = plot.plugins.cursor.zoomCanvas._ctx;
359
- // don't zoom if zoom area is too small (in pixels)
360
- if ((c.constrainZoomTo == 'none' && Math.abs(gridpos.x - c._zoom.start[0]) > 6 && Math.abs(gridpos.y - c._zoom.start[1]) > 6) || (c.constrainZoomTo == 'x' && Math.abs(gridpos.x - c._zoom.start[0]) > 6) || (c.constrainZoomTo == 'y' && Math.abs(gridpos.y - c._zoom.start[1]) > 6)) {
361
- if (!plot.plugins.cursor.zoomProxy) {
362
- for (var ax in datapos) {
363
- // make a copy of the original axes to revert back.
364
- if (c._zoom.axes[ax] == undefined) {
365
- c._zoom.axes[ax] = {};
366
- c._zoom.axes[ax].numberTicks = axes[ax].numberTicks;
367
- c._zoom.axes[ax].tickInterval = axes[ax].tickInterval;
368
- // for date axes...
369
- c._zoom.axes[ax].daTickInterval = axes[ax].daTickInterval;
370
- c._zoom.axes[ax].min = axes[ax].min;
371
- c._zoom.axes[ax].max = axes[ax].max;
372
- c._zoom.axes[ax].tickFormatString = (axes[ax].tickOptions != null) ? axes[ax].tickOptions.formatString : '';
373
- }
374
-
375
-
376
- if ((c.constrainZoomTo == 'none') || (c.constrainZoomTo == 'x' && ax.charAt(0) == 'x') || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'y')) {
377
- dp = datapos[ax];
378
- if (dp != null) {
379
- if (dp > start[ax]) {
380
- newmin = start[ax];
381
- newmax = dp;
382
- }
383
- else {
384
- span = start[ax] - dp;
385
- newmin = dp;
386
- newmax = start[ax];
387
- }
388
-
389
- curax = axes[ax];
390
-
391
- _numberTicks = null;
392
-
393
- // if aligning this axis, use number of ticks from previous axis.
394
- // Do I need to reset somehow if alignTicks is changed and then graph is replotted??
395
- if (curax.alignTicks) {
396
- if (curax.name === 'x2axis' && plot.axes.xaxis.show) {
397
- _numberTicks = plot.axes.xaxis.numberTicks;
398
- }
399
- else if (curax.name.charAt(0) === 'y' && curax.name !== 'yaxis' && curax.name !== 'yMidAxis' && plot.axes.yaxis.show) {
400
- _numberTicks = plot.axes.yaxis.numberTicks;
401
- }
402
- }
403
-
404
- if (this.looseZoom && (axes[ax].renderer.constructor === $.jqplot.LinearAxisRenderer || axes[ax].renderer.constructor === $.jqplot.LogAxisRenderer )) { //} || axes[ax].renderer.constructor === $.jqplot.DateAxisRenderer)) {
405
-
406
- ret = $.jqplot.LinearTickGenerator(newmin, newmax, curax._scalefact, _numberTicks);
407
-
408
- // if new minimum is less than "true" minimum of axis display, adjust it
409
- if (axes[ax].tickInset && ret[0] < axes[ax].min + axes[ax].tickInset * axes[ax].tickInterval) {
410
- ret[0] += ret[4];
411
- ret[2] -= 1;
412
- }
413
-
414
- // if new maximum is greater than "true" max of axis display, adjust it
415
- if (axes[ax].tickInset && ret[1] > axes[ax].max - axes[ax].tickInset * axes[ax].tickInterval) {
416
- ret[1] -= ret[4];
417
- ret[2] -= 1;
418
- }
419
-
420
- // for log axes, don't fall below current minimum, this will look bad and can't have 0 in range anyway.
421
- if (axes[ax].renderer.constructor === $.jqplot.LogAxisRenderer && ret[0] < axes[ax].min) {
422
- // remove a tick and shift min up
423
- ret[0] += ret[4];
424
- ret[2] -= 1;
425
- }
426
-
427
- axes[ax].min = ret[0];
428
- axes[ax].max = ret[1];
429
- axes[ax]._autoFormatString = ret[3];
430
- axes[ax].numberTicks = ret[2];
431
- axes[ax].tickInterval = ret[4];
432
- // for date axes...
433
- axes[ax].daTickInterval = [ret[4]/1000, 'seconds'];
434
- }
435
- else {
436
- axes[ax].min = newmin;
437
- axes[ax].max = newmax;
438
- axes[ax].tickInterval = null;
439
- axes[ax].numberTicks = null;
440
- // for date axes...
441
- axes[ax].daTickInterval = null;
442
- }
443
-
444
- axes[ax]._ticks = [];
445
- }
446
- }
447
-
448
- // if ((c.constrainZoomTo == 'x' && ax.charAt(0) == 'y' && c.autoscaleConstraint) || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'x' && c.autoscaleConstraint)) {
449
- // dp = datapos[ax];
450
- // if (dp != null) {
451
- // axes[ax].max == null;
452
- // axes[ax].min = null;
453
- // }
454
- // }
455
- }
456
- ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
457
- plot.redraw();
458
- c._zoom.isZoomed = true;
459
- ctx = null;
460
- }
461
- plot.target.trigger('jqplotZoom', [gridpos, datapos, plot, cursor]);
462
- }
463
- };
464
-
465
- $.jqplot.preInitHooks.push($.jqplot.Cursor.init);
466
- $.jqplot.postDrawHooks.push($.jqplot.Cursor.postDraw);
467
-
468
- function updateTooltip(gridpos, datapos, plot) {
469
- var c = plot.plugins.cursor;
470
- var s = '';
471
- var addbr = false;
472
- if (c.showTooltipGridPosition) {
473
- s = gridpos.x+', '+gridpos.y;
474
- addbr = true;
475
- }
476
- if (c.showTooltipUnitPosition) {
477
- var g;
478
- for (var i=0; i<c.tooltipAxisGroups.length; i++) {
479
- g = c.tooltipAxisGroups[i];
480
- if (addbr) {
481
- s += '<br />';
482
- }
483
- if (c.useAxesFormatters) {
484
- for (var j=0; j<g.length; j++) {
485
- if (j) {
486
- s += ', ';
487
- }
488
- var af = plot.axes[g[j]]._ticks[0].formatter;
489
- var afstr = plot.axes[g[j]]._ticks[0].formatString;
490
- s += af(afstr, datapos[g[j]]);
491
- }
492
- }
493
- else {
494
- s += $.jqplot.sprintf(c.tooltipFormatString, datapos[g[0]], datapos[g[1]]);
495
- }
496
- addbr = true;
497
- }
498
- }
499
-
500
- if (c.showTooltipDataPosition) {
501
- var series = plot.series;
502
- var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y);
503
- var addbr = false;
504
-
505
- for (var i = 0; i< series.length; i++) {
506
- if (series[i].show) {
507
- var idx = series[i].index;
508
- var label = series[i].label.toString();
509
- var cellid = $.inArray(idx, ret.indices);
510
- var sx = undefined;
511
- var sy = undefined;
512
- if (cellid != -1) {
513
- var data = ret.data[cellid].data;
514
- if (c.useAxesFormatters) {
515
- var xf = series[i]._xaxis._ticks[0].formatter;
516
- var yf = series[i]._yaxis._ticks[0].formatter;
517
- var xfstr = series[i]._xaxis._ticks[0].formatString;
518
- var yfstr = series[i]._yaxis._ticks[0].formatString;
519
- sx = xf(xfstr, data[0]);
520
- sy = yf(yfstr, data[1]);
521
- }
522
- else {
523
- sx = data[0];
524
- sy = data[1];
525
- }
526
- if (addbr) {
527
- s += '<br />';
528
- }
529
- s += $.jqplot.sprintf(c.tooltipFormatString, label, sx, sy);
530
- addbr = true;
531
- }
532
- }
533
- }
534
-
535
- }
536
- c._tooltipElem.html(s);
537
- }
538
-
539
- function moveLine(gridpos, plot) {
540
- var c = plot.plugins.cursor;
541
- var ctx = c.cursorCanvas._ctx;
542
- ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
543
- if (c.showVerticalLine) {
544
- c.shapeRenderer.draw(ctx, [[gridpos.x, 0], [gridpos.x, ctx.canvas.height]]);
545
- }
546
- if (c.showHorizontalLine) {
547
- c.shapeRenderer.draw(ctx, [[0, gridpos.y], [ctx.canvas.width, gridpos.y]]);
548
- }
549
- var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y);
550
- if (c.showCursorLegend) {
551
- var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label');
552
- for (var i=0; i<cells.length; i++) {
553
- var idx = $(cells[i]).data('seriesIndex');
554
- var series = plot.series[idx];
555
- var label = series.label.toString();
556
- var cellid = $.inArray(idx, ret.indices);
557
- var sx = undefined;
558
- var sy = undefined;
559
- if (cellid != -1) {
560
- var data = ret.data[cellid].data;
561
- if (c.useAxesFormatters) {
562
- var xf = series._xaxis._ticks[0].formatter;
563
- var yf = series._yaxis._ticks[0].formatter;
564
- var xfstr = series._xaxis._ticks[0].formatString;
565
- var yfstr = series._yaxis._ticks[0].formatString;
566
- sx = xf(xfstr, data[0]);
567
- sy = yf(yfstr, data[1]);
568
- }
569
- else {
570
- sx = data[0];
571
- sy = data[1];
572
- }
573
- }
574
- if (plot.legend.escapeHtml) {
575
- $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy));
576
- }
577
- else {
578
- $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy));
579
- }
580
- }
581
- }
582
- ctx = null;
583
- }
584
-
585
- function getIntersectingPoints(plot, x, y) {
586
- var ret = {indices:[], data:[]};
587
- var s, i, d0, d, j, r, p;
588
- var threshold;
589
- var c = plot.plugins.cursor;
590
- for (var i=0; i<plot.series.length; i++) {
591
- s = plot.series[i];
592
- r = s.renderer;
593
- if (s.show) {
594
- threshold = c.intersectionThreshold;
595
- if (s.showMarker) {
596
- threshold += s.markerRenderer.size/2;
597
- }
598
- for (var j=0; j<s.gridData.length; j++) {
599
- p = s.gridData[j];
600
- // check vertical line
601
- if (c.showVerticalLine) {
602
- if (Math.abs(x-p[0]) <= threshold) {
603
- ret.indices.push(i);
604
- ret.data.push({seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]});
605
- }
606
- }
607
- }
608
- }
609
- }
610
- return ret;
611
- }
612
-
613
- function moveTooltip(gridpos, plot) {
614
- var c = plot.plugins.cursor;
615
- var elem = c._tooltipElem;
616
- switch (c.tooltipLocation) {
617
- case 'nw':
618
- var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
619
- var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
620
- break;
621
- case 'n':
622
- var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;
623
- var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
624
- break;
625
- case 'ne':
626
- var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
627
- var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
628
- break;
629
- case 'e':
630
- var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
631
- var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;
632
- break;
633
- case 'se':
634
- var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
635
- var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
636
- break;
637
- case 's':
638
- var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;
639
- var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
640
- break;
641
- case 'sw':
642
- var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
643
- var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
644
- break;
645
- case 'w':
646
- var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
647
- var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;
648
- break;
649
- default:
650
- var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
651
- var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
652
- break;
653
- }
654
-
655
- elem.css('left', x);
656
- elem.css('top', y);
657
- elem = null;
658
- }
659
-
660
- function positionTooltip(plot) {
661
- // fake a grid for positioning
662
- var grid = plot._gridPadding;
663
- var c = plot.plugins.cursor;
664
- var elem = c._tooltipElem;
665
- switch (c.tooltipLocation) {
666
- case 'nw':
667
- var a = grid.left + c.tooltipOffset;
668
- var b = grid.top + c.tooltipOffset;
669
- elem.css('left', a);
670
- elem.css('top', b);
671
- break;
672
- case 'n':
673
- var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2;
674
- var b = grid.top + c.tooltipOffset;
675
- elem.css('left', a);
676
- elem.css('top', b);
677
- break;
678
- case 'ne':
679
- var a = grid.right + c.tooltipOffset;
680
- var b = grid.top + c.tooltipOffset;
681
- elem.css({right:a, top:b});
682
- break;
683
- case 'e':
684
- var a = grid.right + c.tooltipOffset;
685
- var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2;
686
- elem.css({right:a, top:b});
687
- break;
688
- case 'se':
689
- var a = grid.right + c.tooltipOffset;
690
- var b = grid.bottom + c.tooltipOffset;
691
- elem.css({right:a, bottom:b});
692
- break;
693
- case 's':
694
- var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2;
695
- var b = grid.bottom + c.tooltipOffset;
696
- elem.css({left:a, bottom:b});
697
- break;
698
- case 'sw':
699
- var a = grid.left + c.tooltipOffset;
700
- var b = grid.bottom + c.tooltipOffset;
701
- elem.css({left:a, bottom:b});
702
- break;
703
- case 'w':
704
- var a = grid.left + c.tooltipOffset;
705
- var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2;
706
- elem.css({left:a, top:b});
707
- break;
708
- default: // same as 'se'
709
- var a = grid.right - c.tooltipOffset;
710
- var b = grid.bottom + c.tooltipOffset;
711
- elem.css({right:a, bottom:b});
712
- break;
713
- }
714
- elem = null;
715
- }
716
-
717
- function handleClick (ev, gridpos, datapos, neighbor, plot) {
718
- ev.preventDefault();
719
- ev.stopImmediatePropagation();
720
- var c = plot.plugins.cursor;
721
- if (c.clickReset) {
722
- c.resetZoom(plot, c);
723
- }
724
- var sel = window.getSelection;
725
- if (document.selection && document.selection.empty)
726
- {
727
- document.selection.empty();
728
- }
729
- else if (sel && !sel().isCollapsed) {
730
- sel().collapse();
731
- }
732
- return false;
733
- }
734
-
735
- function handleDblClick (ev, gridpos, datapos, neighbor, plot) {
736
- ev.preventDefault();
737
- ev.stopImmediatePropagation();
738
- var c = plot.plugins.cursor;
739
- if (c.dblClickReset) {
740
- c.resetZoom(plot, c);
741
- }
742
- var sel = window.getSelection;
743
- if (document.selection && document.selection.empty)
744
- {
745
- document.selection.empty();
746
- }
747
- else if (sel && !sel().isCollapsed) {
748
- sel().collapse();
749
- }
750
- return false;
751
- }
752
-
753
- function handleMouseLeave(ev, gridpos, datapos, neighbor, plot) {
754
- var c = plot.plugins.cursor;
755
- c.onGrid = false;
756
- if (c.show) {
757
- $(ev.target).css('cursor', c.previousCursor);
758
- if (c.showTooltip && !(c._zoom.zooming && c.showTooltipOutsideZoom && !c.constrainOutsideZoom)) {
759
- c._tooltipElem.empty();
760
- c._tooltipElem.hide();
761
- }
762
- if (c.zoom) {
763
- c._zoom.gridpos = gridpos;
764
- c._zoom.datapos = datapos;
765
- }
766
- if (c.showVerticalLine || c.showHorizontalLine) {
767
- var ctx = c.cursorCanvas._ctx;
768
- ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
769
- ctx = null;
770
- }
771
- if (c.showCursorLegend) {
772
- var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label');
773
- for (var i=0; i<cells.length; i++) {
774
- var idx = $(cells[i]).data('seriesIndex');
775
- var series = plot.series[idx];
776
- var label = series.label.toString();
777
- if (plot.legend.escapeHtml) {
778
- $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined));
779
- }
780
- else {
781
- $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined));
782
- }
783
-
784
- }
785
- }
786
- }
787
- }
788
-
789
- function handleMouseEnter(ev, gridpos, datapos, neighbor, plot) {
790
- var c = plot.plugins.cursor;
791
- c.onGrid = true;
792
- if (c.show) {
793
- c.previousCursor = ev.target.style.cursor;
794
- ev.target.style.cursor = c.style;
795
- if (c.showTooltip) {
796
- updateTooltip(gridpos, datapos, plot);
797
- if (c.followMouse) {
798
- moveTooltip(gridpos, plot);
799
- }
800
- else {
801
- positionTooltip(plot);
802
- }
803
- c._tooltipElem.show();
804
- }
805
- if (c.showVerticalLine || c.showHorizontalLine) {
806
- moveLine(gridpos, plot);
807
- }
808
- }
809
-
810
- }
811
-
812
- function handleMouseMove(ev, gridpos, datapos, neighbor, plot) {
813
- var c = plot.plugins.cursor;
814
- if (c.show) {
815
- if (c.showTooltip) {
816
- updateTooltip(gridpos, datapos, plot);
817
- if (c.followMouse) {
818
- moveTooltip(gridpos, plot);
819
- }
820
- }
821
- if (c.showVerticalLine || c.showHorizontalLine) {
822
- moveLine(gridpos, plot);
823
- }
824
- }
825
- }
826
-
827
- function getEventPosition(ev) {
828
- var plot = ev.data.plot;
829
- var go = plot.eventCanvas._elem.offset();
830
- var gridPos = {x:ev.pageX - go.left, y:ev.pageY - go.top};
831
- //////
832
- // TO DO: handle yMidAxis
833
- //////
834
- var dataPos = {xaxis:null, yaxis:null, x2axis:null, y2axis:null, y3axis:null, y4axis:null, y5axis:null, y6axis:null, y7axis:null, y8axis:null, y9axis:null, yMidAxis:null};
835
- var an = ['xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis', 'yMidAxis'];
836
- var ax = plot.axes;
837
- var n, axis;
838
- for (n=11; n>0; n--) {
839
- axis = an[n-1];
840
- if (ax[axis].show) {
841
- dataPos[axis] = ax[axis].series_p2u(gridPos[axis.charAt(0)]);
842
- }
843
- }
844
-
845
- return {offsets:go, gridPos:gridPos, dataPos:dataPos};
846
- }
847
-
848
- function handleZoomMove(ev) {
849
- var plot = ev.data.plot;
850
- var c = plot.plugins.cursor;
851
- // don't do anything if not on grid.
852
- if (c.show && c.zoom && c._zoom.started && !c.zoomTarget) {
853
- ev.preventDefault();
854
- var ctx = c.zoomCanvas._ctx;
855
- var positions = getEventPosition(ev);
856
- var gridpos = positions.gridPos;
857
- var datapos = positions.dataPos;
858
- c._zoom.gridpos = gridpos;
859
- c._zoom.datapos = datapos;
860
- c._zoom.zooming = true;
861
- var xpos = gridpos.x;
862
- var ypos = gridpos.y;
863
- var height = ctx.canvas.height;
864
- var width = ctx.canvas.width;
865
- if (c.showTooltip && !c.onGrid && c.showTooltipOutsideZoom) {
866
- updateTooltip(gridpos, datapos, plot);
867
- if (c.followMouse) {
868
- moveTooltip(gridpos, plot);
869
- }
870
- }
871
- if (c.constrainZoomTo == 'x') {
872
- c._zoom.end = [xpos, height];
873
- }
874
- else if (c.constrainZoomTo == 'y') {
875
- c._zoom.end = [width, ypos];
876
- }
877
- else {
878
- c._zoom.end = [xpos, ypos];
879
- }
880
- var sel = window.getSelection;
881
- if (document.selection && document.selection.empty)
882
- {
883
- document.selection.empty();
884
- }
885
- else if (sel && !sel().isCollapsed) {
886
- sel().collapse();
887
- }
888
- drawZoomBox.call(c);
889
- ctx = null;
890
- }
891
- }
892
-
893
- function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
894
- var c = plot.plugins.cursor;
895
- if(plot.plugins.mobile){
896
- $(document).one('vmouseup.jqplot_cursor', {plot:plot}, handleMouseUp);
897
- } else {
898
- $(document).one('mouseup.jqplot_cursor', {plot:plot}, handleMouseUp);
899
- }
900
- var axes = plot.axes;
901
- if (document.onselectstart != undefined) {
902
- c._oldHandlers.onselectstart = document.onselectstart;
903
- document.onselectstart = function () { return false; };
904
- }
905
- if (document.ondrag != undefined) {
906
- c._oldHandlers.ondrag = document.ondrag;
907
- document.ondrag = function () { return false; };
908
- }
909
- if (document.onmousedown != undefined) {
910
- c._oldHandlers.onmousedown = document.onmousedown;
911
- document.onmousedown = function () { return false; };
912
- }
913
- if (c.zoom) {
914
- if (!c.zoomProxy) {
915
- var ctx = c.zoomCanvas._ctx;
916
- ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
917
- ctx = null;
918
- }
919
- if (c.constrainZoomTo == 'x') {
920
- c._zoom.start = [gridpos.x, 0];
921
- }
922
- else if (c.constrainZoomTo == 'y') {
923
- c._zoom.start = [0, gridpos.y];
924
- }
925
- else {
926
- c._zoom.start = [gridpos.x, gridpos.y];
927
- }
928
- c._zoom.started = true;
929
- for (var ax in datapos) {
930
- // get zoom starting position.
931
- c._zoom.axes.start[ax] = datapos[ax];
932
- }
933
- if(plot.plugins.mobile){
934
- $(document).bind('vmousemove.jqplotCursor', {plot:plot}, handleZoomMove);
935
- } else {
936
- $(document).bind('mousemove.jqplotCursor', {plot:plot}, handleZoomMove);
937
- }
938
-
939
- }
940
- }
941
-
942
- function handleMouseUp(ev) {
943
- var plot = ev.data.plot;
944
- var c = plot.plugins.cursor;
945
- if (c.zoom && c._zoom.zooming && !c.zoomTarget) {
946
- var xpos = c._zoom.gridpos.x;
947
- var ypos = c._zoom.gridpos.y;
948
- var datapos = c._zoom.datapos;
949
- var height = c.zoomCanvas._ctx.canvas.height;
950
- var width = c.zoomCanvas._ctx.canvas.width;
951
- var axes = plot.axes;
952
-
953
- if (c.constrainOutsideZoom && !c.onGrid) {
954
- if (xpos < 0) { xpos = 0; }
955
- else if (xpos > width) { xpos = width; }
956
- if (ypos < 0) { ypos = 0; }
957
- else if (ypos > height) { ypos = height; }
958
-
959
- for (var axis in datapos) {
960
- if (datapos[axis]) {
961
- if (axis.charAt(0) == 'x') {
962
- datapos[axis] = axes[axis].series_p2u(xpos);
963
- }
964
- else {
965
- datapos[axis] = axes[axis].series_p2u(ypos);
966
- }
967
- }
968
- }
969
- }
970
-
971
- if (c.constrainZoomTo == 'x') {
972
- ypos = height;
973
- }
974
- else if (c.constrainZoomTo == 'y') {
975
- xpos = width;
976
- }
977
- c._zoom.end = [xpos, ypos];
978
- c._zoom.gridpos = {x:xpos, y:ypos};
979
-
980
- c.doZoom(c._zoom.gridpos, datapos, plot, c);
981
- }
982
- c._zoom.started = false;
983
- c._zoom.zooming = false;
984
-
985
- $(document).unbind('mousemove.jqplotCursor', handleZoomMove);
986
-
987
- if (document.onselectstart != undefined && c._oldHandlers.onselectstart != null){
988
- document.onselectstart = c._oldHandlers.onselectstart;
989
- c._oldHandlers.onselectstart = null;
990
- }
991
- if (document.ondrag != undefined && c._oldHandlers.ondrag != null){
992
- document.ondrag = c._oldHandlers.ondrag;
993
- c._oldHandlers.ondrag = null;
994
- }
995
- if (document.onmousedown != undefined && c._oldHandlers.onmousedown != null){
996
- document.onmousedown = c._oldHandlers.onmousedown;
997
- c._oldHandlers.onmousedown = null;
998
- }
999
-
1000
- }
1001
-
1002
- function drawZoomBox() {
1003
- var start = this._zoom.start;
1004
- var end = this._zoom.end;
1005
- var ctx = this.zoomCanvas._ctx;
1006
- var l, t, h, w;
1007
- if (end[0] > start[0]) {
1008
- l = start[0];
1009
- w = end[0] - start[0];
1010
- }
1011
- else {
1012
- l = end[0];
1013
- w = start[0] - end[0];
1014
- }
1015
- if (end[1] > start[1]) {
1016
- t = start[1];
1017
- h = end[1] - start[1];
1018
- }
1019
- else {
1020
- t = end[1];
1021
- h = start[1] - end[1];
1022
- }
1023
- ctx.fillStyle = 'rgba(0,0,0,0.2)';
1024
- ctx.strokeStyle = '#999999';
1025
- ctx.lineWidth = 1.0;
1026
- ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
1027
- ctx.fillRect(0,0,ctx.canvas.width, ctx.canvas.height);
1028
- ctx.clearRect(l, t, w, h);
1029
- // IE won't show transparent fill rect, so stroke a rect also.
1030
- ctx.strokeRect(l,t,w,h);
1031
- ctx = null;
1032
- }
1033
-
1034
- $.jqplot.CursorLegendRenderer = function(options) {
1035
- $.jqplot.TableLegendRenderer.call(this, options);
1036
- this.formatString = '%s';
1037
- };
1038
-
1039
- $.jqplot.CursorLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();
1040
- $.jqplot.CursorLegendRenderer.prototype.constructor = $.jqplot.CursorLegendRenderer;
1041
-
1042
- // called in context of a Legend
1043
- $.jqplot.CursorLegendRenderer.prototype.draw = function() {
1044
- if (this._elem) {
1045
- this._elem.emptyForce();
1046
- this._elem = null;
1047
- }
1048
- if (this.show) {
1049
- var series = this._series, s;
1050
- // make a table. one line label per row.
1051
- var elem = document.createElement('table');
1052
- this._elem = $(elem);
1053
- elem = null;
1054
- this._elem.addClass('jqplot-legend jqplot-cursor-legend');
1055
- this._elem.css('position', 'absolute');
1056
-
1057
- var pad = false;
1058
- for (var i = 0; i< series.length; i++) {
1059
- s = series[i];
1060
- if (s.show && s.showLabel) {
1061
- var lt = $.jqplot.sprintf(this.formatString, s.label.toString());
1062
- if (lt) {
1063
- var color = s.color;
1064
- if (s._stack && !s.fill) {
1065
- color = '';
1066
- }
1067
- addrow.call(this, lt, color, pad, i);
1068
- pad = true;
1069
- }
1070
- // let plugins add more rows to legend. Used by trend line plugin.
1071
- for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) {
1072
- var item = $.jqplot.addLegendRowHooks[j].call(this, s);
1073
- if (item) {
1074
- addrow.call(this, item.label, item.color, pad);
1075
- pad = true;
1076
- }
1077
- }
1078
- }
1079
- }
1080
- series = s = null;
1081
- delete series;
1082
- delete s;
1083
- }
1084
-
1085
- function addrow(label, color, pad, idx) {
1086
- var rs = (pad) ? this.rowSpacing : '0';
1087
- var tr = $('<tr class="jqplot-legend jqplot-cursor-legend"></tr>').appendTo(this._elem);
1088
- tr.data('seriesIndex', idx);
1089
- $('<td class="jqplot-legend jqplot-cursor-legend-swatch" style="padding-top:'+rs+';">'+
1090
- '<div style="border:1px solid #cccccc;padding:0.2em;">'+
1091
- '<div class="jqplot-cursor-legend-swatch" style="background-color:'+color+';"></div>'+
1092
- '</div></td>').appendTo(tr);
1093
- var td = $('<td class="jqplot-legend jqplot-cursor-legend-label" style="vertical-align:middle;padding-top:'+rs+';"></td>');
1094
- td.appendTo(tr);
1095
- td.data('seriesIndex', idx);
1096
- if (this.escapeHtml) {
1097
- td.text(label);
1098
- }
1099
- else {
1100
- td.html(label);
1101
- }
1102
- tr = null;
1103
- td = null;
1104
- }
1105
- return this._elem;
1106
- };
1107
-
1108
- })(jQuery);
1
+ /**
2
+ * jqPlot
3
+ * Pure JavaScript plotting plugin using jQuery
4
+ *
5
+ * Version: 1.0.9
6
+ * Revision: d96a669
7
+ *
8
+ * Copyright (c) 2009-2016 Chris Leonello
9
+ * jqPlot is currently available for use in all personal or commercial projects
10
+ * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
11
+ * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
12
+ * choose the license that best suits your project and use it accordingly.
13
+ *
14
+ * Although not required, the author would appreciate an email letting him
15
+ * know of any substantial use of jqPlot. You can reach the author at:
16
+ * chris at jqplot dot com or see http://www.jqplot.com/info.php .
17
+ *
18
+ * If you are feeling kind and generous, consider supporting the project by
19
+ * making a donation at: http://www.jqplot.com/donate.php .
20
+ *
21
+ * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
22
+ *
23
+ * version 2007.04.27
24
+ * author Ash Searle
25
+ * http://hexmen.com/blog/2007/03/printf-sprintf/
26
+ * http://hexmen.com/js/sprintf.js
27
+ * The author (Ash Searle) has placed this code in the public domain:
28
+ * "This code is unrestricted: you are free to use it however you like."
29
+ *
30
+ */
31
+ (function($) {
32
+
33
+ /**
34
+ * Class: $.jqplot.Cursor
35
+ * Plugin class representing the cursor as displayed on the plot.
36
+ */
37
+ $.jqplot.Cursor = function(options) {
38
+ // Group: Properties
39
+ //
40
+ // prop: style
41
+ // CSS spec for cursor style
42
+ this.style = 'crosshair';
43
+ this.previousCursor = 'auto';
44
+ // prop: show
45
+ // whether to show the cursor or not.
46
+ this.show = $.jqplot.config.enablePlugins;
47
+ // prop: showTooltip
48
+ // show a cursor position tooltip. Location of the tooltip
49
+ // will be controlled by followMouse and tooltipLocation.
50
+ this.showTooltip = true;
51
+ // prop: followMouse
52
+ // Tooltip follows the mouse, it is not at a fixed location.
53
+ // Tooltip will show on the grid at the location given by
54
+ // tooltipLocation, offset from the grid edge by tooltipOffset.
55
+ this.followMouse = false;
56
+ // prop: tooltipLocation
57
+ // Where to position tooltip. If followMouse is true, this is
58
+ // relative to the cursor, otherwise, it is relative to the grid.
59
+ // One of 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'
60
+ this.tooltipLocation = 'se';
61
+ // prop: tooltipOffset
62
+ // Pixel offset of tooltip from the grid boudaries or cursor center.
63
+ this.tooltipOffset = 6;
64
+ // prop: showTooltipGridPosition
65
+ // show the grid pixel coordinates of the mouse.
66
+ this.showTooltipGridPosition = false;
67
+ // prop: showTooltipUnitPosition
68
+ // show the unit (data) coordinates of the mouse.
69
+ this.showTooltipUnitPosition = true;
70
+ // prop: showTooltipDataPosition
71
+ // Used with showVerticalLine to show intersecting data points in the tooltip.
72
+ this.showTooltipDataPosition = false;
73
+ // prop: tooltipFormatString
74
+ // sprintf format string for the tooltip.
75
+ // Uses Ash Searle's javascript sprintf implementation
76
+ // found here: http://hexmen.com/blog/2007/03/printf-sprintf/
77
+ // See http://perldoc.perl.org/functions/sprintf.html for reference
78
+ // Note, if showTooltipDataPosition is true, the default tooltipFormatString
79
+ // will be set to the cursorLegendFormatString, not the default given here.
80
+ this.tooltipFormatString = '%.4P, %.4P';
81
+ // prop: useAxesFormatters
82
+ // Use the x and y axes formatters to format the text in the tooltip.
83
+ this.useAxesFormatters = true;
84
+ // prop: tooltipAxisGroups
85
+ // Show position for the specified axes.
86
+ // This is an array like [['xaxis', 'yaxis'], ['xaxis', 'y2axis']]
87
+ // Default is to compute automatically for all visible axes.
88
+ this.tooltipAxisGroups = [];
89
+ // prop: zoom
90
+ // Enable plot zooming.
91
+ this.zoom = false;
92
+ // zoomProxy and zoomTarget properties are not directly set by user.
93
+ // They Will be set through call to zoomProxy method.
94
+ this.zoomProxy = false;
95
+ this.zoomTarget = false;
96
+ // prop: looseZoom
97
+ // Will expand zoom range to provide more rounded tick values.
98
+ // Works only with linear, log and date axes.
99
+ this.looseZoom = true;
100
+ // prop: clickReset
101
+ // Will reset plot zoom if single click on plot without drag.
102
+ this.clickReset = false;
103
+ // prop: dblClickReset
104
+ // Will reset plot zoom if double click on plot without drag.
105
+ this.dblClickReset = true;
106
+ // prop: showVerticalLine
107
+ // draw a vertical line across the plot which follows the cursor.
108
+ // When the line is near a data point, a special legend and/or tooltip can
109
+ // be updated with the data values.
110
+ this.showVerticalLine = false;
111
+ // prop: showHorizontalLine
112
+ // draw a horizontal line across the plot which follows the cursor.
113
+ this.showHorizontalLine = false;
114
+ // prop: constrainZoomTo
115
+ // 'none', 'x' or 'y'
116
+ this.constrainZoomTo = 'none';
117
+ // // prop: autoscaleConstraint
118
+ // // when a constrained axis is specified, true will
119
+ // // auatoscale the adjacent axis.
120
+ // this.autoscaleConstraint = true;
121
+ this.shapeRenderer = new $.jqplot.ShapeRenderer();
122
+ this._zoom = {start:[], end:[], started: false, zooming:false, isZoomed:false, axes:{start:{}, end:{}}, gridpos:{}, datapos:{}};
123
+ this._tooltipElem;
124
+ this.zoomCanvas;
125
+ this.cursorCanvas;
126
+ // prop: intersectionThreshold
127
+ // pixel distance from data point or marker to consider cursor lines intersecting with point.
128
+ // If data point markers are not shown, this should be >= 1 or will often miss point intersections.
129
+ this.intersectionThreshold = 2;
130
+ // prop: showCursorLegend
131
+ // Replace the plot legend with an enhanced legend displaying intersection information.
132
+ this.showCursorLegend = false;
133
+ // prop: cursorLegendFormatString
134
+ // Format string used in the cursor legend. If showTooltipDataPosition is true,
135
+ // this will also be the default format string used by tooltipFormatString.
136
+ this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString;
137
+ // whether the cursor is over the grid or not.
138
+ this._oldHandlers = {onselectstart: null, ondrag: null, onmousedown: null};
139
+ // prop: constrainOutsideZoom
140
+ // True to limit actual zoom area to edges of grid, even when zooming
141
+ // outside of plot area. That is, can't zoom out by mousing outside plot.
142
+ this.constrainOutsideZoom = true;
143
+ // prop: showTooltipOutsideZoom
144
+ // True will keep updating the tooltip when zooming of the grid.
145
+ this.showTooltipOutsideZoom = false;
146
+ // true if mouse is over grid, false if not.
147
+ this.onGrid = false;
148
+ $.extend(true, this, options);
149
+ };
150
+
151
+ $.jqplot.Cursor.cursorLegendFormatString = '%s x:%s, y:%s';
152
+
153
+ // called with scope of plot
154
+ $.jqplot.Cursor.init = function (target, data, opts){
155
+ // add a cursor attribute to the plot
156
+ var options = opts || {};
157
+ this.plugins.cursor = new $.jqplot.Cursor(options.cursor);
158
+ var c = this.plugins.cursor;
159
+
160
+ if (c.show) {
161
+ $.jqplot.eventListenerHooks.push(['jqplotMouseEnter', handleMouseEnter]);
162
+ $.jqplot.eventListenerHooks.push(['jqplotMouseLeave', handleMouseLeave]);
163
+ $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMouseMove]);
164
+
165
+ if (c.showCursorLegend) {
166
+ opts.legend = opts.legend || {};
167
+ opts.legend.renderer = $.jqplot.CursorLegendRenderer;
168
+ opts.legend.formatString = this.plugins.cursor.cursorLegendFormatString;
169
+ opts.legend.show = true;
170
+ }
171
+
172
+ if (c.zoom) {
173
+ $.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleMouseDown]);
174
+
175
+ if (c.clickReset) {
176
+ $.jqplot.eventListenerHooks.push(['jqplotClick', handleClick]);
177
+ }
178
+
179
+ if (c.dblClickReset) {
180
+ $.jqplot.eventListenerHooks.push(['jqplotDblClick', handleDblClick]);
181
+ }
182
+ }
183
+
184
+ this.resetZoom = function() {
185
+ var axes = this.axes;
186
+ if (!c.zoomProxy) {
187
+ for (var ax in axes) {
188
+ axes[ax].reset();
189
+ axes[ax]._ticks = [];
190
+ // fake out tick creation algorithm to make sure original auto
191
+ // computed format string is used if _overrideFormatString is true
192
+ if (c._zoom.axes[ax] !== undefined) {
193
+ axes[ax]._autoFormatString = c._zoom.axes[ax].tickFormatString;
194
+ }
195
+ }
196
+ this.redraw();
197
+ }
198
+ else {
199
+ var ctx = this.plugins.cursor.zoomCanvas._ctx;
200
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
201
+ ctx = null;
202
+ }
203
+ this.plugins.cursor._zoom.isZoomed = false;
204
+ this.target.trigger('jqplotResetZoom', [this, this.plugins.cursor]);
205
+ };
206
+
207
+
208
+ if (c.showTooltipDataPosition) {
209
+ c.showTooltipUnitPosition = false;
210
+ c.showTooltipGridPosition = false;
211
+ if (options.cursor.tooltipFormatString == undefined) {
212
+ c.tooltipFormatString = $.jqplot.Cursor.cursorLegendFormatString;
213
+ }
214
+ }
215
+ }
216
+ };
217
+
218
+ // called with context of plot
219
+ $.jqplot.Cursor.postDraw = function() {
220
+ var c = this.plugins.cursor;
221
+
222
+ // Memory Leaks patch
223
+ if (c.zoomCanvas) {
224
+ c.zoomCanvas.resetCanvas();
225
+ c.zoomCanvas = null;
226
+ }
227
+
228
+ if (c.cursorCanvas) {
229
+ c.cursorCanvas.resetCanvas();
230
+ c.cursorCanvas = null;
231
+ }
232
+
233
+ if (c._tooltipElem) {
234
+ c._tooltipElem.emptyForce();
235
+ c._tooltipElem = null;
236
+ }
237
+
238
+
239
+ if (c.zoom) {
240
+ c.zoomCanvas = new $.jqplot.GenericCanvas();
241
+ this.eventCanvas._elem.before(c.zoomCanvas.createElement(this._gridPadding, 'jqplot-zoom-canvas', this._plotDimensions, this));
242
+ c.zoomCanvas.setContext();
243
+ }
244
+
245
+ var elem = document.createElement('div');
246
+ c._tooltipElem = $(elem);
247
+ elem = null;
248
+ c._tooltipElem.addClass('jqplot-cursor-tooltip');
249
+ c._tooltipElem.css({position:'absolute', display:'none'});
250
+
251
+
252
+ if (c.zoomCanvas) {
253
+ c.zoomCanvas._elem.before(c._tooltipElem);
254
+ }
255
+
256
+ else {
257
+ this.eventCanvas._elem.before(c._tooltipElem);
258
+ }
259
+
260
+ if (c.showVerticalLine || c.showHorizontalLine) {
261
+ c.cursorCanvas = new $.jqplot.GenericCanvas();
262
+ this.eventCanvas._elem.before(c.cursorCanvas.createElement(this._gridPadding, 'jqplot-cursor-canvas', this._plotDimensions, this));
263
+ c.cursorCanvas.setContext();
264
+ }
265
+
266
+ // if we are showing the positions in unit coordinates, and no axes groups
267
+ // were specified, create a default set.
268
+ if (c.showTooltipUnitPosition){
269
+ if (c.tooltipAxisGroups.length === 0) {
270
+ var series = this.series;
271
+ var s;
272
+ var temp = [];
273
+ for (var i=0; i<series.length; i++) {
274
+ s = series[i];
275
+ var ax = s.xaxis+','+s.yaxis;
276
+ if ($.inArray(ax, temp) == -1) {
277
+ temp.push(ax);
278
+ }
279
+ }
280
+ for (var i=0; i<temp.length; i++) {
281
+ c.tooltipAxisGroups.push(temp[i].split(','));
282
+ }
283
+ }
284
+ }
285
+ };
286
+
287
+ // Group: methods
288
+ //
289
+ // method: $.jqplot.Cursor.zoomProxy
290
+ // links targetPlot to controllerPlot so that plot zooming of
291
+ // targetPlot will be controlled by zooming on the controllerPlot.
292
+ // controllerPlot will not actually zoom, but acts as an
293
+ // overview plot. Note, the zoom options must be set to true for
294
+ // zoomProxy to work.
295
+ $.jqplot.Cursor.zoomProxy = function(targetPlot, controllerPlot) {
296
+ var tc = targetPlot.plugins.cursor;
297
+ var cc = controllerPlot.plugins.cursor;
298
+ tc.zoomTarget = true;
299
+ tc.zoom = true;
300
+ tc.style = 'auto';
301
+ tc.dblClickReset = false;
302
+ cc.zoom = true;
303
+ cc.zoomProxy = true;
304
+
305
+ controllerPlot.target.bind('jqplotZoom', plotZoom);
306
+ controllerPlot.target.bind('jqplotResetZoom', plotReset);
307
+
308
+ function plotZoom(ev, gridpos, datapos, plot, cursor) {
309
+ tc.doZoom(gridpos, datapos, targetPlot, cursor);
310
+ }
311
+
312
+ function plotReset(ev, plot, cursor) {
313
+ targetPlot.resetZoom();
314
+ }
315
+ };
316
+
317
+ $.jqplot.Cursor.prototype.resetZoom = function(plot, cursor) {
318
+ var axes = plot.axes;
319
+ var cax = cursor._zoom.axes;
320
+ if (!plot.plugins.cursor.zoomProxy && cursor._zoom.isZoomed) {
321
+ for (var ax in axes) {
322
+ // axes[ax]._ticks = [];
323
+ // axes[ax].min = cax[ax].min;
324
+ // axes[ax].max = cax[ax].max;
325
+ // axes[ax].numberTicks = cax[ax].numberTicks;
326
+ // axes[ax].tickInterval = cax[ax].tickInterval;
327
+ // // for date axes
328
+ // axes[ax].daTickInterval = cax[ax].daTickInterval;
329
+ axes[ax].reset();
330
+ axes[ax]._ticks = [];
331
+ // fake out tick creation algorithm to make sure original auto
332
+ // computed format string is used if _overrideFormatString is true
333
+ axes[ax]._autoFormatString = cax[ax].tickFormatString;
334
+ }
335
+ plot.redraw();
336
+ cursor._zoom.isZoomed = false;
337
+ }
338
+ else {
339
+ var ctx = cursor.zoomCanvas._ctx;
340
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
341
+ ctx = null;
342
+ }
343
+ plot.target.trigger('jqplotResetZoom', [plot, cursor]);
344
+ };
345
+
346
+ $.jqplot.Cursor.resetZoom = function(plot) {
347
+ plot.resetZoom();
348
+ };
349
+
350
+ $.jqplot.Cursor.prototype.doZoom = function (gridpos, datapos, plot, cursor) {
351
+ var c = cursor;
352
+ var axes = plot.axes;
353
+ var zaxes = c._zoom.axes;
354
+ var start = zaxes.start;
355
+ var end = zaxes.end;
356
+ var min, max, dp, span,
357
+ newmin, newmax, curax, _numberTicks, ret;
358
+ var ctx = plot.plugins.cursor.zoomCanvas._ctx;
359
+ // don't zoom if zoom area is too small (in pixels)
360
+ if ((c.constrainZoomTo == 'none' && Math.abs(gridpos.x - c._zoom.start[0]) > 6 && Math.abs(gridpos.y - c._zoom.start[1]) > 6) || (c.constrainZoomTo == 'x' && Math.abs(gridpos.x - c._zoom.start[0]) > 6) || (c.constrainZoomTo == 'y' && Math.abs(gridpos.y - c._zoom.start[1]) > 6)) {
361
+ if (!plot.plugins.cursor.zoomProxy) {
362
+ for (var ax in datapos) {
363
+ // make a copy of the original axes to revert back.
364
+ if (c._zoom.axes[ax] == undefined) {
365
+ c._zoom.axes[ax] = {};
366
+ c._zoom.axes[ax].numberTicks = axes[ax].numberTicks;
367
+ c._zoom.axes[ax].tickInterval = axes[ax].tickInterval;
368
+ // for date axes...
369
+ c._zoom.axes[ax].daTickInterval = axes[ax].daTickInterval;
370
+ c._zoom.axes[ax].min = axes[ax].min;
371
+ c._zoom.axes[ax].max = axes[ax].max;
372
+ c._zoom.axes[ax].tickFormatString = (axes[ax].tickOptions != null) ? axes[ax].tickOptions.formatString : '';
373
+ }
374
+
375
+
376
+ if ((c.constrainZoomTo == 'none') || (c.constrainZoomTo == 'x' && ax.charAt(0) == 'x') || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'y')) {
377
+ dp = datapos[ax];
378
+ if (dp != null) {
379
+ if (dp > start[ax]) {
380
+ newmin = start[ax];
381
+ newmax = dp;
382
+ }
383
+ else {
384
+ span = start[ax] - dp;
385
+ newmin = dp;
386
+ newmax = start[ax];
387
+ }
388
+
389
+ curax = axes[ax];
390
+
391
+ _numberTicks = null;
392
+
393
+ // if aligning this axis, use number of ticks from previous axis.
394
+ // Do I need to reset somehow if alignTicks is changed and then graph is replotted??
395
+ if (curax.alignTicks) {
396
+ if (curax.name === 'x2axis' && plot.axes.xaxis.show) {
397
+ _numberTicks = plot.axes.xaxis.numberTicks;
398
+ }
399
+ else if (curax.name.charAt(0) === 'y' && curax.name !== 'yaxis' && curax.name !== 'yMidAxis' && plot.axes.yaxis.show) {
400
+ _numberTicks = plot.axes.yaxis.numberTicks;
401
+ }
402
+ }
403
+
404
+ if (this.looseZoom && (axes[ax].renderer.constructor === $.jqplot.LinearAxisRenderer || axes[ax].renderer.constructor === $.jqplot.LogAxisRenderer )) { //} || axes[ax].renderer.constructor === $.jqplot.DateAxisRenderer)) {
405
+
406
+ ret = $.jqplot.LinearTickGenerator(newmin, newmax, curax._scalefact, _numberTicks);
407
+
408
+ // if new minimum is less than "true" minimum of axis display, adjust it
409
+ if (axes[ax].tickInset && ret[0] < axes[ax].min + axes[ax].tickInset * axes[ax].tickInterval) {
410
+ ret[0] += ret[4];
411
+ ret[2] -= 1;
412
+ }
413
+
414
+ // if new maximum is greater than "true" max of axis display, adjust it
415
+ if (axes[ax].tickInset && ret[1] > axes[ax].max - axes[ax].tickInset * axes[ax].tickInterval) {
416
+ ret[1] -= ret[4];
417
+ ret[2] -= 1;
418
+ }
419
+
420
+ // for log axes, don't fall below current minimum, this will look bad and can't have 0 in range anyway.
421
+ if (axes[ax].renderer.constructor === $.jqplot.LogAxisRenderer && ret[0] < axes[ax].min) {
422
+ // remove a tick and shift min up
423
+ ret[0] += ret[4];
424
+ ret[2] -= 1;
425
+ }
426
+
427
+ axes[ax].min = ret[0];
428
+ axes[ax].max = ret[1];
429
+ axes[ax]._autoFormatString = ret[3];
430
+ axes[ax].numberTicks = ret[2];
431
+ axes[ax].tickInterval = ret[4];
432
+ // for date axes...
433
+ axes[ax].daTickInterval = [ret[4]/1000, 'seconds'];
434
+ }
435
+ else {
436
+ axes[ax].min = newmin;
437
+ axes[ax].max = newmax;
438
+ axes[ax].tickInterval = null;
439
+ axes[ax].numberTicks = null;
440
+ // for date axes...
441
+ axes[ax].daTickInterval = null;
442
+ }
443
+
444
+ axes[ax]._ticks = [];
445
+ }
446
+ }
447
+
448
+ // if ((c.constrainZoomTo == 'x' && ax.charAt(0) == 'y' && c.autoscaleConstraint) || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'x' && c.autoscaleConstraint)) {
449
+ // dp = datapos[ax];
450
+ // if (dp != null) {
451
+ // axes[ax].max == null;
452
+ // axes[ax].min = null;
453
+ // }
454
+ // }
455
+ }
456
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
457
+ plot.redraw();
458
+ c._zoom.isZoomed = true;
459
+ ctx = null;
460
+ }
461
+ plot.target.trigger('jqplotZoom', [gridpos, datapos, plot, cursor]);
462
+ }
463
+ };
464
+
465
+ $.jqplot.preInitHooks.push($.jqplot.Cursor.init);
466
+ $.jqplot.postDrawHooks.push($.jqplot.Cursor.postDraw);
467
+
468
+ function updateTooltip(gridpos, datapos, plot) {
469
+ var c = plot.plugins.cursor;
470
+ var s = '';
471
+ var addbr = false;
472
+ if (c.showTooltipGridPosition) {
473
+ s = gridpos.x+', '+gridpos.y;
474
+ addbr = true;
475
+ }
476
+ if (c.showTooltipUnitPosition) {
477
+ var g;
478
+ for (var i=0; i<c.tooltipAxisGroups.length; i++) {
479
+ g = c.tooltipAxisGroups[i];
480
+ if (addbr) {
481
+ s += '<br />';
482
+ }
483
+ if (c.useAxesFormatters) {
484
+ for (var j=0; j<g.length; j++) {
485
+ if (j) {
486
+ s += ', ';
487
+ }
488
+ var af = plot.axes[g[j]]._ticks[0].formatter;
489
+ var afstr = plot.axes[g[j]]._ticks[0].formatString;
490
+ s += af(afstr, datapos[g[j]]);
491
+ }
492
+ }
493
+ else {
494
+ s += $.jqplot.sprintf(c.tooltipFormatString, datapos[g[0]], datapos[g[1]]);
495
+ }
496
+ addbr = true;
497
+ }
498
+ }
499
+
500
+ if (c.showTooltipDataPosition) {
501
+ var series = plot.series;
502
+ var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y);
503
+ var addbr = false;
504
+
505
+ for (var i = 0; i< series.length; i++) {
506
+ if (series[i].show) {
507
+ var idx = series[i].index;
508
+ var label = series[i].label.toString();
509
+ var cellid = $.inArray(idx, ret.indices);
510
+ var sx = undefined;
511
+ var sy = undefined;
512
+ if (cellid != -1) {
513
+ var data = ret.data[cellid].data;
514
+ if (c.useAxesFormatters) {
515
+ var xf = series[i]._xaxis._ticks[0].formatter;
516
+ var yf = series[i]._yaxis._ticks[0].formatter;
517
+ var xfstr = series[i]._xaxis._ticks[0].formatString;
518
+ var yfstr = series[i]._yaxis._ticks[0].formatString;
519
+ sx = xf(xfstr, data[0]);
520
+ sy = yf(yfstr, data[1]);
521
+ }
522
+ else {
523
+ sx = data[0];
524
+ sy = data[1];
525
+ }
526
+ if (addbr) {
527
+ s += '<br />';
528
+ }
529
+ s += $.jqplot.sprintf(c.tooltipFormatString, label, sx, sy);
530
+ addbr = true;
531
+ }
532
+ }
533
+ }
534
+
535
+ }
536
+ c._tooltipElem.html(s);
537
+ }
538
+
539
+ function moveLine(gridpos, plot) {
540
+ var c = plot.plugins.cursor;
541
+ var ctx = c.cursorCanvas._ctx;
542
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
543
+ if (c.showVerticalLine) {
544
+ c.shapeRenderer.draw(ctx, [[gridpos.x, 0], [gridpos.x, ctx.canvas.height]]);
545
+ }
546
+ if (c.showHorizontalLine) {
547
+ c.shapeRenderer.draw(ctx, [[0, gridpos.y], [ctx.canvas.width, gridpos.y]]);
548
+ }
549
+ var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y);
550
+ if (c.showCursorLegend) {
551
+ var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label');
552
+ for (var i=0; i<cells.length; i++) {
553
+ var idx = $(cells[i]).data('seriesIndex');
554
+ var series = plot.series[idx];
555
+ var label = series.label.toString();
556
+ var cellid = $.inArray(idx, ret.indices);
557
+ var sx = undefined;
558
+ var sy = undefined;
559
+ if (cellid != -1) {
560
+ var data = ret.data[cellid].data;
561
+ if (c.useAxesFormatters) {
562
+ var xf = series._xaxis._ticks[0].formatter;
563
+ var yf = series._yaxis._ticks[0].formatter;
564
+ var xfstr = series._xaxis._ticks[0].formatString;
565
+ var yfstr = series._yaxis._ticks[0].formatString;
566
+ sx = xf(xfstr, data[0]);
567
+ sy = yf(yfstr, data[1]);
568
+ }
569
+ else {
570
+ sx = data[0];
571
+ sy = data[1];
572
+ }
573
+ }
574
+ if (plot.legend.escapeHtml) {
575
+ $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy));
576
+ }
577
+ else {
578
+ $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy));
579
+ }
580
+ }
581
+ }
582
+ ctx = null;
583
+ }
584
+
585
+ function getIntersectingPoints(plot, x, y) {
586
+ var ret = {indices:[], data:[]};
587
+ var s, i, d0, d, j, r, p;
588
+ var threshold;
589
+ var c = plot.plugins.cursor;
590
+ for (var i=0; i<plot.series.length; i++) {
591
+ s = plot.series[i];
592
+ r = s.renderer;
593
+ if (s.show) {
594
+ threshold = c.intersectionThreshold;
595
+ if (s.showMarker) {
596
+ threshold += s.markerRenderer.size/2;
597
+ }
598
+ for (var j=0; j<s.gridData.length; j++) {
599
+ p = s.gridData[j];
600
+ // check vertical line
601
+ if (c.showVerticalLine) {
602
+ if (Math.abs(x-p[0]) <= threshold) {
603
+ ret.indices.push(i);
604
+ ret.data.push({seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]});
605
+ }
606
+ }
607
+ }
608
+ }
609
+ }
610
+ return ret;
611
+ }
612
+
613
+ function moveTooltip(gridpos, plot) {
614
+ var c = plot.plugins.cursor;
615
+ var elem = c._tooltipElem;
616
+ switch (c.tooltipLocation) {
617
+ case 'nw':
618
+ var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
619
+ var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
620
+ break;
621
+ case 'n':
622
+ var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;
623
+ var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
624
+ break;
625
+ case 'ne':
626
+ var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
627
+ var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
628
+ break;
629
+ case 'e':
630
+ var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
631
+ var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;
632
+ break;
633
+ case 'se':
634
+ var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
635
+ var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
636
+ break;
637
+ case 's':
638
+ var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;
639
+ var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
640
+ break;
641
+ case 'sw':
642
+ var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
643
+ var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
644
+ break;
645
+ case 'w':
646
+ var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
647
+ var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;
648
+ break;
649
+ default:
650
+ var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
651
+ var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
652
+ break;
653
+ }
654
+
655
+ elem.css('left', x);
656
+ elem.css('top', y);
657
+ elem = null;
658
+ }
659
+
660
+ function positionTooltip(plot) {
661
+ // fake a grid for positioning
662
+ var grid = plot._gridPadding;
663
+ var c = plot.plugins.cursor;
664
+ var elem = c._tooltipElem;
665
+ switch (c.tooltipLocation) {
666
+ case 'nw':
667
+ var a = grid.left + c.tooltipOffset;
668
+ var b = grid.top + c.tooltipOffset;
669
+ elem.css('left', a);
670
+ elem.css('top', b);
671
+ break;
672
+ case 'n':
673
+ var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2;
674
+ var b = grid.top + c.tooltipOffset;
675
+ elem.css('left', a);
676
+ elem.css('top', b);
677
+ break;
678
+ case 'ne':
679
+ var a = grid.right + c.tooltipOffset;
680
+ var b = grid.top + c.tooltipOffset;
681
+ elem.css({right:a, top:b});
682
+ break;
683
+ case 'e':
684
+ var a = grid.right + c.tooltipOffset;
685
+ var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2;
686
+ elem.css({right:a, top:b});
687
+ break;
688
+ case 'se':
689
+ var a = grid.right + c.tooltipOffset;
690
+ var b = grid.bottom + c.tooltipOffset;
691
+ elem.css({right:a, bottom:b});
692
+ break;
693
+ case 's':
694
+ var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2;
695
+ var b = grid.bottom + c.tooltipOffset;
696
+ elem.css({left:a, bottom:b});
697
+ break;
698
+ case 'sw':
699
+ var a = grid.left + c.tooltipOffset;
700
+ var b = grid.bottom + c.tooltipOffset;
701
+ elem.css({left:a, bottom:b});
702
+ break;
703
+ case 'w':
704
+ var a = grid.left + c.tooltipOffset;
705
+ var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2;
706
+ elem.css({left:a, top:b});
707
+ break;
708
+ default: // same as 'se'
709
+ var a = grid.right - c.tooltipOffset;
710
+ var b = grid.bottom + c.tooltipOffset;
711
+ elem.css({right:a, bottom:b});
712
+ break;
713
+ }
714
+ elem = null;
715
+ }
716
+
717
+ function handleClick (ev, gridpos, datapos, neighbor, plot) {
718
+ ev.preventDefault();
719
+ ev.stopImmediatePropagation();
720
+ var c = plot.plugins.cursor;
721
+ if (c.clickReset) {
722
+ c.resetZoom(plot, c);
723
+ }
724
+ var sel = window.getSelection;
725
+ if (document.selection && document.selection.empty)
726
+ {
727
+ document.selection.empty();
728
+ }
729
+ else if (sel && !sel().isCollapsed) {
730
+ sel().collapse();
731
+ }
732
+ return false;
733
+ }
734
+
735
+ function handleDblClick (ev, gridpos, datapos, neighbor, plot) {
736
+ ev.preventDefault();
737
+ ev.stopImmediatePropagation();
738
+ var c = plot.plugins.cursor;
739
+ if (c.dblClickReset) {
740
+ c.resetZoom(plot, c);
741
+ }
742
+ var sel = window.getSelection;
743
+ if (document.selection && document.selection.empty)
744
+ {
745
+ document.selection.empty();
746
+ }
747
+ else if (sel && !sel().isCollapsed) {
748
+ sel().collapse();
749
+ }
750
+ return false;
751
+ }
752
+
753
+ function handleMouseLeave(ev, gridpos, datapos, neighbor, plot) {
754
+ var c = plot.plugins.cursor;
755
+ c.onGrid = false;
756
+ if (c.show) {
757
+ $(ev.target).css('cursor', c.previousCursor);
758
+ if (c.showTooltip && !(c._zoom.zooming && c.showTooltipOutsideZoom && !c.constrainOutsideZoom)) {
759
+ c._tooltipElem.empty();
760
+ c._tooltipElem.hide();
761
+ }
762
+ if (c.zoom) {
763
+ c._zoom.gridpos = gridpos;
764
+ c._zoom.datapos = datapos;
765
+ }
766
+ if (c.showVerticalLine || c.showHorizontalLine) {
767
+ var ctx = c.cursorCanvas._ctx;
768
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
769
+ ctx = null;
770
+ }
771
+ if (c.showCursorLegend) {
772
+ var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label');
773
+ for (var i=0; i<cells.length; i++) {
774
+ var idx = $(cells[i]).data('seriesIndex');
775
+ var series = plot.series[idx];
776
+ var label = series.label.toString();
777
+ if (plot.legend.escapeHtml) {
778
+ $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined));
779
+ }
780
+ else {
781
+ $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined));
782
+ }
783
+
784
+ }
785
+ }
786
+ }
787
+ }
788
+
789
+ function handleMouseEnter(ev, gridpos, datapos, neighbor, plot) {
790
+ var c = plot.plugins.cursor;
791
+ c.onGrid = true;
792
+ if (c.show) {
793
+ c.previousCursor = ev.target.style.cursor;
794
+ ev.target.style.cursor = c.style;
795
+ if (c.showTooltip) {
796
+ updateTooltip(gridpos, datapos, plot);
797
+ if (c.followMouse) {
798
+ moveTooltip(gridpos, plot);
799
+ }
800
+ else {
801
+ positionTooltip(plot);
802
+ }
803
+ c._tooltipElem.show();
804
+ }
805
+ if (c.showVerticalLine || c.showHorizontalLine) {
806
+ moveLine(gridpos, plot);
807
+ }
808
+ }
809
+
810
+ }
811
+
812
+ function handleMouseMove(ev, gridpos, datapos, neighbor, plot) {
813
+ var c = plot.plugins.cursor;
814
+ if (c.show) {
815
+ if (c.showTooltip) {
816
+ updateTooltip(gridpos, datapos, plot);
817
+ if (c.followMouse) {
818
+ moveTooltip(gridpos, plot);
819
+ }
820
+ }
821
+ if (c.showVerticalLine || c.showHorizontalLine) {
822
+ moveLine(gridpos, plot);
823
+ }
824
+ }
825
+ }
826
+
827
+ function getEventPosition(ev) {
828
+ var plot = ev.data.plot;
829
+ var go = plot.eventCanvas._elem.offset();
830
+ var gridPos = {x:ev.pageX - go.left, y:ev.pageY - go.top};
831
+ //////
832
+ // TO DO: handle yMidAxis
833
+ //////
834
+ var dataPos = {xaxis:null, yaxis:null, x2axis:null, y2axis:null, y3axis:null, y4axis:null, y5axis:null, y6axis:null, y7axis:null, y8axis:null, y9axis:null, yMidAxis:null};
835
+ var an = ['xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis', 'yMidAxis'];
836
+ var ax = plot.axes;
837
+ var n, axis;
838
+ for (n=11; n>0; n--) {
839
+ axis = an[n-1];
840
+ if (ax[axis].show) {
841
+ dataPos[axis] = ax[axis].series_p2u(gridPos[axis.charAt(0)]);
842
+ }
843
+ }
844
+
845
+ return {offsets:go, gridPos:gridPos, dataPos:dataPos};
846
+ }
847
+
848
+ function handleZoomMove(ev) {
849
+ var plot = ev.data.plot;
850
+ var c = plot.plugins.cursor;
851
+ // don't do anything if not on grid.
852
+ if (c.show && c.zoom && c._zoom.started && !c.zoomTarget) {
853
+ ev.preventDefault();
854
+ var ctx = c.zoomCanvas._ctx;
855
+ var positions = getEventPosition(ev);
856
+ var gridpos = positions.gridPos;
857
+ var datapos = positions.dataPos;
858
+ c._zoom.gridpos = gridpos;
859
+ c._zoom.datapos = datapos;
860
+ c._zoom.zooming = true;
861
+ var xpos = gridpos.x;
862
+ var ypos = gridpos.y;
863
+ var height = ctx.canvas.height;
864
+ var width = ctx.canvas.width;
865
+ if (c.showTooltip && !c.onGrid && c.showTooltipOutsideZoom) {
866
+ updateTooltip(gridpos, datapos, plot);
867
+ if (c.followMouse) {
868
+ moveTooltip(gridpos, plot);
869
+ }
870
+ }
871
+ if (c.constrainZoomTo == 'x') {
872
+ c._zoom.end = [xpos, height];
873
+ }
874
+ else if (c.constrainZoomTo == 'y') {
875
+ c._zoom.end = [width, ypos];
876
+ }
877
+ else {
878
+ c._zoom.end = [xpos, ypos];
879
+ }
880
+ var sel = window.getSelection;
881
+ if (document.selection && document.selection.empty)
882
+ {
883
+ document.selection.empty();
884
+ }
885
+ else if (sel && !sel().isCollapsed) {
886
+ sel().collapse();
887
+ }
888
+ drawZoomBox.call(c);
889
+ ctx = null;
890
+ }
891
+ }
892
+
893
+ function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
894
+ var c = plot.plugins.cursor;
895
+ if(plot.plugins.mobile){
896
+ $(document).one('vmouseup.jqplot_cursor', {plot:plot}, handleMouseUp);
897
+ } else {
898
+ $(document).one('mouseup.jqplot_cursor', {plot:plot}, handleMouseUp);
899
+ }
900
+ var axes = plot.axes;
901
+ if (document.onselectstart != undefined) {
902
+ c._oldHandlers.onselectstart = document.onselectstart;
903
+ document.onselectstart = function () { return false; };
904
+ }
905
+ if (document.ondrag != undefined) {
906
+ c._oldHandlers.ondrag = document.ondrag;
907
+ document.ondrag = function () { return false; };
908
+ }
909
+ if (document.onmousedown != undefined) {
910
+ c._oldHandlers.onmousedown = document.onmousedown;
911
+ document.onmousedown = function () { return false; };
912
+ }
913
+ if (c.zoom) {
914
+ if (!c.zoomProxy) {
915
+ var ctx = c.zoomCanvas._ctx;
916
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
917
+ ctx = null;
918
+ }
919
+ if (c.constrainZoomTo == 'x') {
920
+ c._zoom.start = [gridpos.x, 0];
921
+ }
922
+ else if (c.constrainZoomTo == 'y') {
923
+ c._zoom.start = [0, gridpos.y];
924
+ }
925
+ else {
926
+ c._zoom.start = [gridpos.x, gridpos.y];
927
+ }
928
+ c._zoom.started = true;
929
+ for (var ax in datapos) {
930
+ // get zoom starting position.
931
+ c._zoom.axes.start[ax] = datapos[ax];
932
+ }
933
+ if(plot.plugins.mobile){
934
+ $(document).bind('vmousemove.jqplotCursor', {plot:plot}, handleZoomMove);
935
+ } else {
936
+ $(document).bind('mousemove.jqplotCursor', {plot:plot}, handleZoomMove);
937
+ }
938
+
939
+ }
940
+ }
941
+
942
+ function handleMouseUp(ev) {
943
+ var plot = ev.data.plot;
944
+ var c = plot.plugins.cursor;
945
+ if (c.zoom && c._zoom.zooming && !c.zoomTarget) {
946
+ var xpos = c._zoom.gridpos.x;
947
+ var ypos = c._zoom.gridpos.y;
948
+ var datapos = c._zoom.datapos;
949
+ var height = c.zoomCanvas._ctx.canvas.height;
950
+ var width = c.zoomCanvas._ctx.canvas.width;
951
+ var axes = plot.axes;
952
+
953
+ if (c.constrainOutsideZoom && !c.onGrid) {
954
+ if (xpos < 0) { xpos = 0; }
955
+ else if (xpos > width) { xpos = width; }
956
+ if (ypos < 0) { ypos = 0; }
957
+ else if (ypos > height) { ypos = height; }
958
+
959
+ for (var axis in datapos) {
960
+ if (datapos[axis]) {
961
+ if (axis.charAt(0) == 'x') {
962
+ datapos[axis] = axes[axis].series_p2u(xpos);
963
+ }
964
+ else {
965
+ datapos[axis] = axes[axis].series_p2u(ypos);
966
+ }
967
+ }
968
+ }
969
+ }
970
+
971
+ if (c.constrainZoomTo == 'x') {
972
+ ypos = height;
973
+ }
974
+ else if (c.constrainZoomTo == 'y') {
975
+ xpos = width;
976
+ }
977
+ c._zoom.end = [xpos, ypos];
978
+ c._zoom.gridpos = {x:xpos, y:ypos};
979
+
980
+ c.doZoom(c._zoom.gridpos, datapos, plot, c);
981
+ }
982
+ c._zoom.started = false;
983
+ c._zoom.zooming = false;
984
+
985
+ $(document).unbind('mousemove.jqplotCursor', handleZoomMove);
986
+
987
+ if (document.onselectstart != undefined && c._oldHandlers.onselectstart != null){
988
+ document.onselectstart = c._oldHandlers.onselectstart;
989
+ c._oldHandlers.onselectstart = null;
990
+ }
991
+ if (document.ondrag != undefined && c._oldHandlers.ondrag != null){
992
+ document.ondrag = c._oldHandlers.ondrag;
993
+ c._oldHandlers.ondrag = null;
994
+ }
995
+ if (document.onmousedown != undefined && c._oldHandlers.onmousedown != null){
996
+ document.onmousedown = c._oldHandlers.onmousedown;
997
+ c._oldHandlers.onmousedown = null;
998
+ }
999
+
1000
+ }
1001
+
1002
+ function drawZoomBox() {
1003
+ var start = this._zoom.start;
1004
+ var end = this._zoom.end;
1005
+ var ctx = this.zoomCanvas._ctx;
1006
+ var l, t, h, w;
1007
+ if (end[0] > start[0]) {
1008
+ l = start[0];
1009
+ w = end[0] - start[0];
1010
+ }
1011
+ else {
1012
+ l = end[0];
1013
+ w = start[0] - end[0];
1014
+ }
1015
+ if (end[1] > start[1]) {
1016
+ t = start[1];
1017
+ h = end[1] - start[1];
1018
+ }
1019
+ else {
1020
+ t = end[1];
1021
+ h = start[1] - end[1];
1022
+ }
1023
+ ctx.fillStyle = 'rgba(0,0,0,0.2)';
1024
+ ctx.strokeStyle = '#999999';
1025
+ ctx.lineWidth = 1.0;
1026
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
1027
+ ctx.fillRect(0,0,ctx.canvas.width, ctx.canvas.height);
1028
+ ctx.clearRect(l, t, w, h);
1029
+ // IE won't show transparent fill rect, so stroke a rect also.
1030
+ ctx.strokeRect(l,t,w,h);
1031
+ ctx = null;
1032
+ }
1033
+
1034
+ $.jqplot.CursorLegendRenderer = function(options) {
1035
+ $.jqplot.TableLegendRenderer.call(this, options);
1036
+ this.formatString = '%s';
1037
+ };
1038
+
1039
+ $.jqplot.CursorLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();
1040
+ $.jqplot.CursorLegendRenderer.prototype.constructor = $.jqplot.CursorLegendRenderer;
1041
+
1042
+ // called in context of a Legend
1043
+ $.jqplot.CursorLegendRenderer.prototype.draw = function() {
1044
+ if (this._elem) {
1045
+ this._elem.emptyForce();
1046
+ this._elem = null;
1047
+ }
1048
+ if (this.show) {
1049
+ var series = this._series, s;
1050
+ // make a table. one line label per row.
1051
+ var elem = document.createElement('table');
1052
+ this._elem = $(elem);
1053
+ elem = null;
1054
+ this._elem.addClass('jqplot-legend jqplot-cursor-legend');
1055
+ this._elem.css('position', 'absolute');
1056
+
1057
+ var pad = false;
1058
+ for (var i = 0; i< series.length; i++) {
1059
+ s = series[i];
1060
+ if (s.show && s.showLabel) {
1061
+ var lt = $.jqplot.sprintf(this.formatString, s.label.toString());
1062
+ if (lt) {
1063
+ var color = s.color;
1064
+ if (s._stack && !s.fill) {
1065
+ color = '';
1066
+ }
1067
+ addrow.call(this, lt, color, pad, i);
1068
+ pad = true;
1069
+ }
1070
+ // let plugins add more rows to legend. Used by trend line plugin.
1071
+ for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) {
1072
+ var item = $.jqplot.addLegendRowHooks[j].call(this, s);
1073
+ if (item) {
1074
+ addrow.call(this, item.label, item.color, pad);
1075
+ pad = true;
1076
+ }
1077
+ }
1078
+ }
1079
+ }
1080
+ series = s = null;
1081
+ delete series;
1082
+ delete s;
1083
+ }
1084
+
1085
+ function addrow(label, color, pad, idx) {
1086
+ var rs = (pad) ? this.rowSpacing : '0';
1087
+ var tr = $('<tr class="jqplot-legend jqplot-cursor-legend"></tr>').appendTo(this._elem);
1088
+ tr.data('seriesIndex', idx);
1089
+ $('<td class="jqplot-legend jqplot-cursor-legend-swatch" style="padding-top:'+rs+';">'+
1090
+ '<div style="border:1px solid #cccccc;padding:0.2em;">'+
1091
+ '<div class="jqplot-cursor-legend-swatch" style="background-color:'+color+';"></div>'+
1092
+ '</div></td>').appendTo(tr);
1093
+ var td = $('<td class="jqplot-legend jqplot-cursor-legend-label" style="vertical-align:middle;padding-top:'+rs+';"></td>');
1094
+ td.appendTo(tr);
1095
+ td.data('seriesIndex', idx);
1096
+ if (this.escapeHtml) {
1097
+ td.text(label);
1098
+ }
1099
+ else {
1100
+ td.html(label);
1101
+ }
1102
+ tr = null;
1103
+ td = null;
1104
+ }
1105
+ return this._elem;
1106
+ };
1107
+
1108
+ })(jQuery);