outfielding-jqplot-rails 1.0.8 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
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,1021 +1,1021 @@
1
- /**
2
- * jqPlot
3
- * Pure JavaScript plotting plugin using jQuery
4
- *
5
- * Version: 1.0.8
6
- * Revision: 1250
7
- *
8
- * Copyright (c) 2009-2013 Chris Leonello
9
- * jqPlot is currently available for use in all personal or commercial projects
10
- * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
11
- * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
12
- * choose the license that best suits your project and use it accordingly.
13
- *
14
- * Although not required, the author would appreciate an email letting him
15
- * know of any substantial use of jqPlot. You can reach the author at:
16
- * chris at jqplot dot com or see http://www.jqplot.com/info.php .
17
- *
18
- * If you are feeling kind and generous, consider supporting the project by
19
- * making a donation at: http://www.jqplot.com/donate.php .
20
- *
21
- * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
22
- *
23
- * version 2007.04.27
24
- * author Ash Searle
25
- * http://hexmen.com/blog/2007/03/printf-sprintf/
26
- * http://hexmen.com/js/sprintf.js
27
- * The author (Ash Searle) has placed this code in the public domain:
28
- * "This code is unrestricted: you are free to use it however you like."
29
- *
30
- */
31
- (function($) {
32
- var 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
- case 'rectangle':
70
- this.addRectangle(obj[n]);
71
- break;
72
- default:
73
- break;
74
- }
75
- }
76
- }
77
- }
78
- $.extend(true, this.options, options);
79
- };
80
-
81
- // called with scope of a plot object
82
- $.jqplot.CanvasOverlay.postPlotInit = function (target, data, opts) {
83
- var options = opts || {};
84
- // add a canvasOverlay attribute to the plot
85
- this.plugins.canvasOverlay = new $.jqplot.CanvasOverlay(options.canvasOverlay);
86
- };
87
-
88
-
89
- function LineBase() {
90
- this.uid = null;
91
- this.type = null;
92
- this.gridStart = null;
93
- this.gridStop = null;
94
- this.tooltipWidthFactor = 0;
95
- this.options = {
96
- // prop: name
97
- // Optional name for the overlay object.
98
- // Can be later used to retrieve the object by name.
99
- name: null,
100
- // prop: show
101
- // true to show (draw), false to not draw.
102
- show: true,
103
- // prop: lineWidth
104
- // Width of the line.
105
- lineWidth: 2,
106
- // prop: lineCap
107
- // Type of ending placed on the line ['round', 'butt', 'square']
108
- lineCap: 'round',
109
- // prop: color
110
- // color of the line
111
- color: '#666666',
112
- // prop: shadow
113
- // whether or not to draw a shadow on the line
114
- shadow: true,
115
- // prop: shadowAngle
116
- // Shadow angle in degrees
117
- shadowAngle: 45,
118
- // prop: shadowOffset
119
- // Shadow offset from line in pixels
120
- shadowOffset: 1,
121
- // prop: shadowDepth
122
- // Number of times shadow is stroked, each stroke offset shadowOffset from the last.
123
- shadowDepth: 3,
124
- // prop: shadowAlpha
125
- // Alpha channel transparency of shadow. 0 = transparent.
126
- shadowAlpha: '0.07',
127
- // prop: xaxis
128
- // X axis to use for positioning/scaling the line.
129
- xaxis: 'xaxis',
130
- // prop: yaxis
131
- // Y axis to use for positioning/scaling the line.
132
- yaxis: 'yaxis',
133
- // prop: showTooltip
134
- // Show a tooltip with data point values.
135
- showTooltip: false,
136
- // prop: showTooltipPrecision
137
- // Controls how close to line cursor must be to show tooltip.
138
- // Higher number = closer to line, lower number = farther from line.
139
- // 1.0 = cursor must be over line.
140
- showTooltipPrecision: 0.6,
141
- // prop: tooltipLocation
142
- // Where to position tooltip, 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'
143
- tooltipLocation: 'nw',
144
- // prop: fadeTooltip
145
- // true = fade in/out tooltip, flase = show/hide tooltip
146
- fadeTooltip: true,
147
- // prop: tooltipFadeSpeed
148
- // 'slow', 'def', 'fast', or number of milliseconds.
149
- tooltipFadeSpeed: "fast",
150
- // prop: tooltipOffset
151
- // Pixel offset of tooltip from the highlight.
152
- tooltipOffset: 4,
153
- // prop: tooltipFormatString
154
- // Format string passed the x and y values of the cursor on the line.
155
- // e.g., 'Dogs: %.2f, Cats: %d'.
156
- tooltipFormatString: '%d, %d'
157
- };
158
- }
159
-
160
-
161
- function Rectangle(options) {
162
- LineBase.call(this);
163
- this.type = 'rectangle';
164
- var opts = {
165
- // prop: xmin
166
- // x value for the start of the line, null to scale to axis min.
167
- xmin: null,
168
- // prop: xmax
169
- // x value for the end of the line, null to scale to axis max.
170
- xmax: null,
171
- // prop xOffset
172
- // offset ends of the line inside the grid. Number
173
- xOffset: '6px', // number or string. Number interpreted as units, string as pixels.
174
- xminOffset: null,
175
- xmaxOffset: null,
176
-
177
- ymin: null,
178
- ymax: null,
179
- yOffset: '6px', // number or string. Number interpreted as units, string as pixels.
180
- yminOffset: null,
181
- ymaxOffset: null
182
- };
183
- $.extend(true, this.options, opts, options);
184
-
185
- if (this.options.showTooltipPrecision < 0.01) {
186
- this.options.showTooltipPrecision = 0.01;
187
- }
188
- }
189
-
190
- Rectangle.prototype = new LineBase();
191
- Rectangle.prototype.constructor = Rectangle;
192
-
193
-
194
- /**
195
- * Class: Line
196
- * A straight line.
197
- */
198
- function Line(options) {
199
- LineBase.call(this);
200
- this.type = 'line';
201
- var opts = {
202
- // prop: start
203
- // [x, y] coordinates for the start of the line.
204
- start: [],
205
- // prop: stop
206
- // [x, y] coordinates for the end of the line.
207
- stop: []
208
- };
209
- $.extend(true, this.options, opts, options);
210
-
211
- if (this.options.showTooltipPrecision < 0.01) {
212
- this.options.showTooltipPrecision = 0.01;
213
- }
214
- }
215
-
216
- Line.prototype = new LineBase();
217
- Line.prototype.constructor = Line;
218
-
219
-
220
- /**
221
- * Class: HorizontalLine
222
- * A straight horizontal line.
223
- */
224
- function HorizontalLine(options) {
225
- LineBase.call(this);
226
- this.type = 'horizontalLine';
227
- var opts = {
228
- // prop: y
229
- // y value to position the line
230
- y: null,
231
- // prop: xmin
232
- // x value for the start of the line, null to scale to axis min.
233
- xmin: null,
234
- // prop: xmax
235
- // x value for the end of the line, null to scale to axis max.
236
- xmax: null,
237
- // prop xOffset
238
- // offset ends of the line inside the grid. Number
239
- xOffset: '6px', // number or string. Number interpreted as units, string as pixels.
240
- xminOffset: null,
241
- xmaxOffset: null
242
- };
243
- $.extend(true, this.options, opts, options);
244
-
245
- if (this.options.showTooltipPrecision < 0.01) {
246
- this.options.showTooltipPrecision = 0.01;
247
- }
248
- }
249
-
250
- HorizontalLine.prototype = new LineBase();
251
- HorizontalLine.prototype.constructor = HorizontalLine;
252
-
253
-
254
- /**
255
- * Class: DashedHorizontalLine
256
- * A straight dashed horizontal line.
257
- */
258
- function DashedHorizontalLine(options) {
259
- LineBase.call(this);
260
- this.type = 'dashedHorizontalLine';
261
- var opts = {
262
- y: null,
263
- xmin: null,
264
- xmax: null,
265
- xOffset: '6px', // number or string. Number interpreted as units, string as pixels.
266
- xminOffset: null,
267
- xmaxOffset: null,
268
- // prop: dashPattern
269
- // Array of line, space settings in pixels.
270
- // Default is 8 pixel of line, 8 pixel of space.
271
- // Note, limit to a 2 element array b/c of bug with higher order arrays.
272
- dashPattern: [8,8]
273
- };
274
- $.extend(true, this.options, opts, options);
275
-
276
- if (this.options.showTooltipPrecision < 0.01) {
277
- this.options.showTooltipPrecision = 0.01;
278
- }
279
- }
280
-
281
- DashedHorizontalLine.prototype = new LineBase();
282
- DashedHorizontalLine.prototype.constructor = DashedHorizontalLine;
283
-
284
-
285
- /**
286
- * Class: VerticalLine
287
- * A straight vertical line.
288
- */
289
- function VerticalLine(options) {
290
- LineBase.call(this);
291
- this.type = 'verticalLine';
292
- var opts = {
293
- x: null,
294
- ymin: null,
295
- ymax: null,
296
- yOffset: '6px', // number or string. Number interpreted as units, string as pixels.
297
- yminOffset: null,
298
- ymaxOffset: null
299
- };
300
- $.extend(true, this.options, opts, options);
301
-
302
- if (this.options.showTooltipPrecision < 0.01) {
303
- this.options.showTooltipPrecision = 0.01;
304
- }
305
- }
306
-
307
- VerticalLine.prototype = new LineBase();
308
- VerticalLine.prototype.constructor = VerticalLine;
309
-
310
-
311
- /**
312
- * Class: DashedVerticalLine
313
- * A straight dashed vertical line.
314
- */
315
- function DashedVerticalLine(options) {
316
- LineBase.call(this);
317
- this.type = 'dashedVerticalLine';
318
- this.start = null;
319
- this.stop = null;
320
- var opts = {
321
- x: null,
322
- ymin: null,
323
- ymax: null,
324
- yOffset: '6px', // number or string. Number interpreted as units, string as pixels.
325
- yminOffset: null,
326
- ymaxOffset: null,
327
- // prop: dashPattern
328
- // Array of line, space settings in pixels.
329
- // Default is 8 pixel of line, 8 pixel of space.
330
- // Note, limit to a 2 element array b/c of bug with higher order arrays.
331
- dashPattern: [8,8]
332
- };
333
- $.extend(true, this.options, opts, options);
334
-
335
- if (this.options.showTooltipPrecision < 0.01) {
336
- this.options.showTooltipPrecision = 0.01;
337
- }
338
- }
339
-
340
- DashedVerticalLine.prototype = new LineBase();
341
- DashedVerticalLine.prototype.constructor = DashedVerticalLine;
342
-
343
- $.jqplot.CanvasOverlay.prototype.addLine = function(opts) {
344
- var line = new Line(opts);
345
- line.uid = objCounter++;
346
- this.objects.push(line);
347
- this.objectNames.push(line.options.name);
348
- };
349
-
350
- $.jqplot.CanvasOverlay.prototype.addHorizontalLine = function(opts) {
351
- var line = new HorizontalLine(opts);
352
- line.uid = objCounter++;
353
- this.objects.push(line);
354
- this.objectNames.push(line.options.name);
355
- };
356
-
357
- $.jqplot.CanvasOverlay.prototype.addDashedHorizontalLine = function(opts) {
358
- var line = new DashedHorizontalLine(opts);
359
- line.uid = objCounter++;
360
- this.objects.push(line);
361
- this.objectNames.push(line.options.name);
362
- };
363
-
364
- $.jqplot.CanvasOverlay.prototype.addVerticalLine = function(opts) {
365
- var line = new VerticalLine(opts);
366
- line.uid = objCounter++;
367
- this.objects.push(line);
368
- this.objectNames.push(line.options.name);
369
- };
370
-
371
- $.jqplot.CanvasOverlay.prototype.addDashedVerticalLine = function(opts) {
372
- var line = new DashedVerticalLine(opts);
373
- line.uid = objCounter++;
374
- this.objects.push(line);
375
- this.objectNames.push(line.options.name);
376
- };
377
-
378
- $.jqplot.CanvasOverlay.prototype.addRectangle = function(opts) {
379
- var line = new Rectangle(opts);
380
- line.uid = objCounter++;
381
- this.objects.push(line);
382
- this.objectNames.push(line.options.name);
383
- };
384
-
385
- $.jqplot.CanvasOverlay.prototype.removeObject = function(idx) {
386
- // check if integer, remove by index
387
- if ($.type(idx) == 'number') {
388
- this.objects.splice(idx, 1);
389
- this.objectNames.splice(idx, 1);
390
- }
391
- // if string, remove by name
392
- else {
393
- var id = $.inArray(idx, this.objectNames);
394
- if (id != -1) {
395
- this.objects.splice(id, 1);
396
- this.objectNames.splice(id, 1);
397
- }
398
- }
399
- };
400
-
401
- $.jqplot.CanvasOverlay.prototype.getObject = function(idx) {
402
- // check if integer, remove by index
403
- if ($.type(idx) == 'number') {
404
- return this.objects[idx];
405
- }
406
- // if string, remove by name
407
- else {
408
- var id = $.inArray(idx, this.objectNames);
409
- if (id != -1) {
410
- return this.objects[id];
411
- }
412
- }
413
- };
414
-
415
- // Set get as alias for getObject.
416
- $.jqplot.CanvasOverlay.prototype.get = $.jqplot.CanvasOverlay.prototype.getObject;
417
-
418
- $.jqplot.CanvasOverlay.prototype.clear = function(plot) {
419
- this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight());
420
- };
421
-
422
- $.jqplot.CanvasOverlay.prototype.draw = function(plot) {
423
- var obj,
424
- objs = this.objects,
425
- mr = this.markerRenderer,
426
- start,
427
- stop;
428
- if (this.options.show) {
429
- this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight());
430
- for (var k=0; k<objs.length; k++) {
431
- obj = objs[k];
432
- var opts = $.extend(true, {}, obj.options);
433
- if (obj.options.show) {
434
- // style and shadow properties should be set before
435
- // every draw of marker renderer.
436
- mr.shadow = obj.options.shadow;
437
- obj.tooltipWidthFactor = obj.options.lineWidth / obj.options.showTooltipPrecision;
438
- switch (obj.type) {
439
- case 'line':
440
- // style and shadow properties should be set before
441
- // every draw of marker renderer.
442
- mr.style = 'line';
443
- opts.closePath = false;
444
- start = [plot.axes[obj.options.xaxis].series_u2p(obj.options.start[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.start[1])];
445
- stop = [plot.axes[obj.options.xaxis].series_u2p(obj.options.stop[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.stop[1])];
446
- obj.gridStart = start;
447
- obj.gridStop = stop;
448
- mr.draw(start, stop, this.canvas._ctx, opts);
449
- break;
450
- case 'horizontalLine':
451
-
452
- // style and shadow properties should be set before
453
- // every draw of marker renderer.
454
- if (obj.options.y != null) {
455
- mr.style = 'line';
456
- opts.closePath = false;
457
- var xaxis = plot.axes[obj.options.xaxis],
458
- xstart,
459
- xstop,
460
- y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),
461
- xminoff = obj.options.xminOffset || obj.options.xOffset,
462
- xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;
463
- if (obj.options.xmin != null) {
464
- xstart = xaxis.series_u2p(obj.options.xmin);
465
- }
466
- else if (xminoff != null) {
467
- if ($.type(xminoff) == "number") {
468
- xstart = xaxis.series_u2p(xaxis.min + xminoff);
469
- }
470
- else if ($.type(xminoff) == "string") {
471
- xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);
472
- }
473
- }
474
- if (obj.options.xmax != null) {
475
- xstop = xaxis.series_u2p(obj.options.xmax);
476
- }
477
- else if (xmaxoff != null) {
478
- if ($.type(xmaxoff) == "number") {
479
- xstop = xaxis.series_u2p(xaxis.max - xmaxoff);
480
- }
481
- else if ($.type(xmaxoff) == "string") {
482
- xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);
483
- }
484
- }
485
- if (xstop != null && xstart != null) {
486
- obj.gridStart = [xstart, y];
487
- obj.gridStop = [xstop, y];
488
- mr.draw([xstart, y], [xstop, y], this.canvas._ctx, opts);
489
- }
490
- }
491
- break;
492
-
493
- case 'dashedHorizontalLine':
494
-
495
- var dashPat = obj.options.dashPattern;
496
- var dashPatLen = 0;
497
- for (var i=0; i<dashPat.length; i++) {
498
- dashPatLen += dashPat[i];
499
- }
500
-
501
- // style and shadow properties should be set before
502
- // every draw of marker renderer.
503
- if (obj.options.y != null) {
504
- mr.style = 'line';
505
- opts.closePath = false;
506
- var xaxis = plot.axes[obj.options.xaxis],
507
- xstart,
508
- xstop,
509
- y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),
510
- xminoff = obj.options.xminOffset || obj.options.xOffset,
511
- xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;
512
- if (obj.options.xmin != null) {
513
- xstart = xaxis.series_u2p(obj.options.xmin);
514
- }
515
- else if (xminoff != null) {
516
- if ($.type(xminoff) == "number") {
517
- xstart = xaxis.series_u2p(xaxis.min + xminoff);
518
- }
519
- else if ($.type(xminoff) == "string") {
520
- xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);
521
- }
522
- }
523
- if (obj.options.xmax != null) {
524
- xstop = xaxis.series_u2p(obj.options.xmax);
525
- }
526
- else if (xmaxoff != null) {
527
- if ($.type(xmaxoff) == "number") {
528
- xstop = xaxis.series_u2p(xaxis.max - xmaxoff);
529
- }
530
- else if ($.type(xmaxoff) == "string") {
531
- xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);
532
- }
533
- }
534
- if (xstop != null && xstart != null) {
535
- obj.gridStart = [xstart, y];
536
- obj.gridStop = [xstop, y];
537
- var numDash = Math.ceil((xstop - xstart)/dashPatLen);
538
- var b=xstart, e;
539
- for (var i=0; i<numDash; i++) {
540
- for (var j=0; j<dashPat.length; j+=2) {
541
- e = b+dashPat[j];
542
- mr.draw([b, y], [e, y], this.canvas._ctx, opts);
543
- b += dashPat[j];
544
- if (j < dashPat.length-1) {
545
- b += dashPat[j+1];
546
- }
547
- }
548
- }
549
- }
550
- }
551
- break;
552
-
553
- case 'verticalLine':
554
-
555
- // style and shadow properties should be set before
556
- // every draw of marker renderer.
557
- if (obj.options.x != null) {
558
- mr.style = 'line';
559
- opts.closePath = false;
560
- var yaxis = plot.axes[obj.options.yaxis],
561
- ystart,
562
- ystop,
563
- x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),
564
- yminoff = obj.options.yminOffset || obj.options.yOffset,
565
- ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;
566
- if (obj.options.ymin != null) {
567
- ystart = yaxis.series_u2p(obj.options.ymin);
568
- }
569
- else if (yminoff != null) {
570
- if ($.type(yminoff) == "number") {
571
- ystart = yaxis.series_u2p(yaxis.min - yminoff);
572
- }
573
- else if ($.type(yminoff) == "string") {
574
- ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);
575
- }
576
- }
577
- if (obj.options.ymax != null) {
578
- ystop = yaxis.series_u2p(obj.options.ymax);
579
- }
580
- else if (ymaxoff != null) {
581
- if ($.type(ymaxoff) == "number") {
582
- ystop = yaxis.series_u2p(yaxis.max + ymaxoff);
583
- }
584
- else if ($.type(ymaxoff) == "string") {
585
- ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);
586
- }
587
- }
588
- if (ystop != null && ystart != null) {
589
- obj.gridStart = [x, ystart];
590
- obj.gridStop = [x, ystop];
591
- mr.draw([x, ystart], [x, ystop], this.canvas._ctx, opts);
592
- }
593
- }
594
- break;
595
-
596
- case 'dashedVerticalLine':
597
-
598
- var dashPat = obj.options.dashPattern;
599
- var dashPatLen = 0;
600
- for (var i=0; i<dashPat.length; i++) {
601
- dashPatLen += dashPat[i];
602
- }
603
-
604
- // style and shadow properties should be set before
605
- // every draw of marker renderer.
606
- if (obj.options.x != null) {
607
- mr.style = 'line';
608
- opts.closePath = false;
609
- var yaxis = plot.axes[obj.options.yaxis],
610
- ystart,
611
- ystop,
612
- x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),
613
- yminoff = obj.options.yminOffset || obj.options.yOffset,
614
- ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;
615
- if (obj.options.ymin != null) {
616
- ystart = yaxis.series_u2p(obj.options.ymin);
617
- }
618
- else if (yminoff != null) {
619
- if ($.type(yminoff) == "number") {
620
- ystart = yaxis.series_u2p(yaxis.min - yminoff);
621
- }
622
- else if ($.type(yminoff) == "string") {
623
- ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);
624
- }
625
- }
626
- if (obj.options.ymax != null) {
627
- ystop = yaxis.series_u2p(obj.options.ymax);
628
- }
629
- else if (ymaxoff != null) {
630
- if ($.type(ymaxoff) == "number") {
631
- ystop = yaxis.series_u2p(yaxis.max + ymaxoff);
632
- }
633
- else if ($.type(ymaxoff) == "string") {
634
- ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);
635
- }
636
- }
637
-
638
-
639
- if (ystop != null && ystart != null) {
640
- obj.gridStart = [x, ystart];
641
- obj.gridStop = [x, ystop];
642
- var numDash = Math.ceil((ystart - ystop)/dashPatLen);
643
- var firstDashAdjust = ((numDash * dashPatLen) - (ystart - ystop))/2.0;
644
- var b=ystart, e, bs, es;
645
- for (var i=0; i<numDash; i++) {
646
- for (var j=0; j<dashPat.length; j+=2) {
647
- e = b - dashPat[j];
648
- if (e < ystop) {
649
- e = ystop;
650
- }
651
- if (b < ystop) {
652
- b = ystop;
653
- }
654
- // es = e;
655
- // if (i == 0) {
656
- // es += firstDashAdjust;
657
- // }
658
- mr.draw([x, b], [x, e], this.canvas._ctx, opts);
659
- b -= dashPat[j];
660
- if (j < dashPat.length-1) {
661
- b -= dashPat[j+1];
662
- }
663
- }
664
- }
665
- }
666
- }
667
- break;
668
-
669
- case 'rectangle':
670
- // style and shadow properties should be set before
671
- // every draw of marker renderer.
672
- mr.style = 'line';
673
- opts.closePath = true;
674
-
675
- var xaxis = plot.axes[obj.options.xaxis],
676
- xstart,
677
- xstop,
678
- y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),
679
- xminoff = obj.options.xminOffset || obj.options.xOffset,
680
- xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;
681
- if (obj.options.xmin != null) {
682
- xstart = xaxis.series_u2p(obj.options.xmin);
683
- }
684
- else if (xminoff != null) {
685
- if ($.type(xminoff) == "number") {
686
- xstart = xaxis.series_u2p(xaxis.min + xminoff);
687
- }
688
- else if ($.type(xminoff) == "string") {
689
- xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);
690
- }
691
- }
692
- if (obj.options.xmax != null) {
693
- xstop = xaxis.series_u2p(obj.options.xmax);
694
- }
695
- else if (xmaxoff != null) {
696
- if ($.type(xmaxoff) == "number") {
697
- xstop = xaxis.series_u2p(xaxis.max - xmaxoff);
698
- }
699
- else if ($.type(xmaxoff) == "string") {
700
- xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);
701
- }
702
- }
703
-
704
- var yaxis = plot.axes[obj.options.yaxis],
705
- ystart,
706
- ystop,
707
- x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),
708
- yminoff = obj.options.yminOffset || obj.options.yOffset,
709
- ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;
710
- if (obj.options.ymin != null) {
711
- ystart = yaxis.series_u2p(obj.options.ymin);
712
- }
713
- else if (yminoff != null) {
714
- if ($.type(yminoff) == "number") {
715
- ystart = yaxis.series_u2p(yaxis.min - yminoff);
716
- }
717
- else if ($.type(yminoff) == "string") {
718
- ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);
719
- }
720
- }
721
- if (obj.options.ymax != null) {
722
- ystop = yaxis.series_u2p(obj.options.ymax);
723
- }
724
- else if (ymaxoff != null) {
725
- if ($.type(ymaxoff) == "number") {
726
- ystop = yaxis.series_u2p(yaxis.max + ymaxoff);
727
- }
728
- else if ($.type(ymaxoff) == "string") {
729
- ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);
730
- }
731
- }
732
-
733
-
734
- if (xstop != null && xstart != null && ystop != null && ystart != null) {
735
- obj.gridStart = [xstart, ystart];
736
- obj.gridStop = [xstop, ystop];
737
-
738
- this.canvas._ctx.fillStyle = obj.options.color;
739
- this.canvas._ctx.fillRect(xstart, ystart, xstop - xstart, ystop - ystart);
740
- }
741
- break;
742
-
743
- default:
744
- break;
745
- }
746
- }
747
- }
748
- }
749
- };
750
-
751
- // called within context of plot
752
- // create a canvas which we can draw on.
753
- // insert it before the eventCanvas, so eventCanvas will still capture events.
754
- $.jqplot.CanvasOverlay.postPlotDraw = function() {
755
- var co = this.plugins.canvasOverlay;
756
- // Memory Leaks patch
757
- if (co && co.highlightCanvas) {
758
- co.highlightCanvas.resetCanvas();
759
- co.highlightCanvas = null;
760
- }
761
- co.canvas = new $.jqplot.GenericCanvas();
762
-
763
- this.eventCanvas._elem.before(co.canvas.createElement(this._gridPadding, 'jqplot-overlayCanvas-canvas', this._plotDimensions, this));
764
- co.canvas.setContext();
765
- if (!co.deferDraw) {
766
- co.draw(this);
767
- }
768
-
769
- var elem = document.createElement('div');
770
- co._tooltipElem = $(elem);
771
- elem = null;
772
- co._tooltipElem.addClass('jqplot-canvasOverlay-tooltip');
773
- co._tooltipElem.css({position:'absolute', display:'none'});
774
-
775
- this.eventCanvas._elem.before(co._tooltipElem);
776
- this.eventCanvas._elem.bind('mouseleave', { elem: co._tooltipElem }, function (ev) { ev.data.elem.hide(); });
777
-
778
- var co = null;
779
- };
780
-
781
-
782
- function showTooltip(plot, obj, gridpos, datapos) {
783
- var co = plot.plugins.canvasOverlay;
784
- var elem = co._tooltipElem;
785
-
786
- var opts = obj.options, x, y;
787
-
788
- elem.html($.jqplot.sprintf(opts.tooltipFormatString, datapos[0], datapos[1]));
789
-
790
- switch (opts.tooltipLocation) {
791
- case 'nw':
792
- x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
793
- y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
794
- break;
795
- case 'n':
796
- x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true)/2;
797
- y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
798
- break;
799
- case 'ne':
800
- x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;
801
- y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
802
- break;
803
- case 'e':
804
- x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;
805
- y = gridpos[1] + plot._gridPadding.top - elem.outerHeight(true)/2;
806
- break;
807
- case 'se':
808
- x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;
809
- y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;
810
- break;
811
- case 's':
812
- x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true)/2;
813
- y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;
814
- break;
815
- case 'sw':
816
- x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
817
- y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;
818
- break;
819
- case 'w':
820
- x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
821
- y = gridpos[1] + plot._gridPadding.top - elem.outerHeight(true)/2;
822
- break;
823
- default: // same as 'nw'
824
- x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
825
- y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
826
- break;
827
- }
828
-
829
- elem.css('left', x);
830
- elem.css('top', y);
831
- if (opts.fadeTooltip) {
832
- // Fix for stacked up animations. Thnanks Trevor!
833
- elem.stop(true,true).fadeIn(opts.tooltipFadeSpeed);
834
- }
835
- else {
836
- elem.show();
837
- }
838
- elem = null;
839
- }
840
-
841
-
842
- function isNearLine(point, lstart, lstop, width) {
843
- // r is point to test, p and q are end points.
844
- var rx = point[0];
845
- var ry = point[1];
846
- var px = Math.round(lstop[0]);
847
- var py = Math.round(lstop[1]);
848
- var qx = Math.round(lstart[0]);
849
- var qy = Math.round(lstart[1]);
850
-
851
- var l = Math.sqrt(Math.pow(px-qx, 2) + Math.pow(py-qy, 2));
852
-
853
- // scale error term by length of line.
854
- var eps = width*l;
855
- var res = Math.abs((qx-px) * (ry-py) - (qy-py) * (rx-px));
856
- var ret = (res < eps) ? true : false;
857
- return ret;
858
- }
859
-
860
- function isNearRectangle(point, lstart, lstop, width) {
861
- // r is point to test, p and q are end points.
862
- var rx = point[0];
863
- var ry = point[1];
864
- var px = Math.round(lstop[0]);
865
- var py = Math.round(lstop[1]);
866
- var qx = Math.round(lstart[0]);
867
- var qy = Math.round(lstart[1]);
868
-
869
- var temp;
870
- if (px > qx) { temp = px; px = qx; qx = temp; }
871
- if (py > qy) { temp = py; py = qy; qy = temp; }
872
-
873
- var ret = (rx >= px && rx <= qx && ry >= py && ry <= qy);
874
-
875
- return ret;
876
- }
877
-
878
-
879
- function handleMove(ev, gridpos, datapos, neighbor, plot) {
880
- var co = plot.plugins.canvasOverlay;
881
- var objs = co.objects;
882
- var l = objs.length;
883
- var obj, haveHighlight=false;
884
- var elem;
885
- for (var i=0; i<l; i++) {
886
- obj = objs[i];
887
- if (obj.options.showTooltip) {
888
- var n;
889
- if (obj.type === 'rectangle') {
890
- n = isNearRectangle([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor);
891
- } else {
892
- n = isNearLine([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor);
893
- }
894
- datapos = [plot.axes[obj.options.xaxis].series_p2u(gridpos.x), plot.axes[obj.options.yaxis].series_p2u(gridpos.y)];
895
-
896
- // cases:
897
- // near line, no highlighting
898
- // near line, highliting on this line
899
- // near line, highlighting another line
900
- // not near any line, highlighting
901
- // not near any line, no highlighting
902
-
903
- // near line, not currently highlighting
904
- if (n && co.highlightObjectIndex == null) {
905
- switch (obj.type) {
906
- case 'line':
907
- showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);
908
- break;
909
-
910
- case 'horizontalLine':
911
- case 'dashedHorizontalLine':
912
- showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);
913
- break;
914
-
915
- case 'verticalLine':
916
- case 'dashedVerticalLine':
917
- showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
918
- break;
919
-
920
- case 'rectangle':
921
- showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
922
- break;
923
-
924
- default:
925
- break;
926
- }
927
- co.highlightObjectIndex = i;
928
- haveHighlight = true;
929
- break;
930
- }
931
-
932
- // near line, highlighting another line.
933
- else if (n && co.highlightObjectIndex !== i) {
934
- // turn off tooltip.
935
- elem = co._tooltipElem;
936
- if (obj.fadeTooltip) {
937
- elem.fadeOut(obj.tooltipFadeSpeed);
938
- }
939
- else {
940
- elem.hide();
941
- }
942
-
943
- // turn on right tooltip.
944
- switch (obj.type) {
945
- case 'line':
946
- showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);
947
- break;
948
-
949
- case 'horizontalLine':
950
- case 'dashedHorizontalLine':
951
- showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);
952
- break;
953
-
954
- case 'verticalLine':
955
- case 'dashedVerticalLine':
956
- showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
957
- break;
958
-
959
- case 'rectangle':
960
- showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
961
- break;
962
-
963
- default:
964
- break;
965
- }
966
-
967
- co.highlightObjectIndex = i;
968
- haveHighlight = true;
969
- break;
970
- }
971
-
972
- // near line, already highlighting this line, update
973
- else if (n) {
974
- switch (obj.type) {
975
- case 'line':
976
- showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);
977
- break;
978
-
979
- case 'horizontalLine':
980
- case 'dashedHorizontalLine':
981
- showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);
982
- break;
983
-
984
- case 'verticalLine':
985
- case 'dashedVerticalLine':
986
- showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
987
- break;
988
-
989
- case 'rectangle':
990
- showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
991
- break;
992
-
993
- default:
994
- break;
995
- }
996
-
997
- haveHighlight = true;
998
- break;
999
- }
1000
- }
1001
- }
1002
-
1003
- // check if we are highlighting and not near a line, turn it off.
1004
- if (!haveHighlight && co.highlightObjectIndex !== null) {
1005
- elem = co._tooltipElem;
1006
- obj = co.getObject(co.highlightObjectIndex);
1007
- if (obj.fadeTooltip) {
1008
- elem.fadeOut(obj.tooltipFadeSpeed);
1009
- }
1010
- else {
1011
- elem.hide();
1012
- }
1013
- co.highlightObjectIndex = null;
1014
- }
1015
- }
1016
-
1017
- $.jqplot.postInitHooks.push($.jqplot.CanvasOverlay.postPlotInit);
1018
- $.jqplot.postDrawHooks.push($.jqplot.CanvasOverlay.postPlotDraw);
1019
- $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]);
1020
-
1
+ /**
2
+ * jqPlot
3
+ * Pure JavaScript plotting plugin using jQuery
4
+ *
5
+ * Version: 1.0.9
6
+ * Revision: d96a669
7
+ *
8
+ * Copyright (c) 2009-2016 Chris Leonello
9
+ * jqPlot is currently available for use in all personal or commercial projects
10
+ * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
11
+ * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
12
+ * choose the license that best suits your project and use it accordingly.
13
+ *
14
+ * Although not required, the author would appreciate an email letting him
15
+ * know of any substantial use of jqPlot. You can reach the author at:
16
+ * chris at jqplot dot com or see http://www.jqplot.com/info.php .
17
+ *
18
+ * If you are feeling kind and generous, consider supporting the project by
19
+ * making a donation at: http://www.jqplot.com/donate.php .
20
+ *
21
+ * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
22
+ *
23
+ * version 2007.04.27
24
+ * author Ash Searle
25
+ * http://hexmen.com/blog/2007/03/printf-sprintf/
26
+ * http://hexmen.com/js/sprintf.js
27
+ * The author (Ash Searle) has placed this code in the public domain:
28
+ * "This code is unrestricted: you are free to use it however you like."
29
+ *
30
+ */
31
+ (function($) {
32
+ var 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
+ case 'rectangle':
70
+ this.addRectangle(obj[n]);
71
+ break;
72
+ default:
73
+ break;
74
+ }
75
+ }
76
+ }
77
+ }
78
+ $.extend(true, this.options, options);
79
+ };
80
+
81
+ // called with scope of a plot object
82
+ $.jqplot.CanvasOverlay.postPlotInit = function (target, data, opts) {
83
+ var options = opts || {};
84
+ // add a canvasOverlay attribute to the plot
85
+ this.plugins.canvasOverlay = new $.jqplot.CanvasOverlay(options.canvasOverlay);
86
+ };
87
+
88
+
89
+ function LineBase() {
90
+ this.uid = null;
91
+ this.type = null;
92
+ this.gridStart = null;
93
+ this.gridStop = null;
94
+ this.tooltipWidthFactor = 0;
95
+ this.options = {
96
+ // prop: name
97
+ // Optional name for the overlay object.
98
+ // Can be later used to retrieve the object by name.
99
+ name: null,
100
+ // prop: show
101
+ // true to show (draw), false to not draw.
102
+ show: true,
103
+ // prop: lineWidth
104
+ // Width of the line.
105
+ lineWidth: 2,
106
+ // prop: lineCap
107
+ // Type of ending placed on the line ['round', 'butt', 'square']
108
+ lineCap: 'round',
109
+ // prop: color
110
+ // color of the line
111
+ color: '#666666',
112
+ // prop: shadow
113
+ // whether or not to draw a shadow on the line
114
+ shadow: true,
115
+ // prop: shadowAngle
116
+ // Shadow angle in degrees
117
+ shadowAngle: 45,
118
+ // prop: shadowOffset
119
+ // Shadow offset from line in pixels
120
+ shadowOffset: 1,
121
+ // prop: shadowDepth
122
+ // Number of times shadow is stroked, each stroke offset shadowOffset from the last.
123
+ shadowDepth: 3,
124
+ // prop: shadowAlpha
125
+ // Alpha channel transparency of shadow. 0 = transparent.
126
+ shadowAlpha: '0.07',
127
+ // prop: xaxis
128
+ // X axis to use for positioning/scaling the line.
129
+ xaxis: 'xaxis',
130
+ // prop: yaxis
131
+ // Y axis to use for positioning/scaling the line.
132
+ yaxis: 'yaxis',
133
+ // prop: showTooltip
134
+ // Show a tooltip with data point values.
135
+ showTooltip: false,
136
+ // prop: showTooltipPrecision
137
+ // Controls how close to line cursor must be to show tooltip.
138
+ // Higher number = closer to line, lower number = farther from line.
139
+ // 1.0 = cursor must be over line.
140
+ showTooltipPrecision: 0.6,
141
+ // prop: tooltipLocation
142
+ // Where to position tooltip, 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'
143
+ tooltipLocation: 'nw',
144
+ // prop: fadeTooltip
145
+ // true = fade in/out tooltip, flase = show/hide tooltip
146
+ fadeTooltip: true,
147
+ // prop: tooltipFadeSpeed
148
+ // 'slow', 'def', 'fast', or number of milliseconds.
149
+ tooltipFadeSpeed: "fast",
150
+ // prop: tooltipOffset
151
+ // Pixel offset of tooltip from the highlight.
152
+ tooltipOffset: 4,
153
+ // prop: tooltipFormatString
154
+ // Format string passed the x and y values of the cursor on the line.
155
+ // e.g., 'Dogs: %.2f, Cats: %d'.
156
+ tooltipFormatString: '%d, %d'
157
+ };
158
+ }
159
+
160
+
161
+ function Rectangle(options) {
162
+ LineBase.call(this);
163
+ this.type = 'rectangle';
164
+ var opts = {
165
+ // prop: xmin
166
+ // x value for the start of the line, null to scale to axis min.
167
+ xmin: null,
168
+ // prop: xmax
169
+ // x value for the end of the line, null to scale to axis max.
170
+ xmax: null,
171
+ // prop xOffset
172
+ // offset ends of the line inside the grid. Number
173
+ xOffset: '6px', // number or string. Number interpreted as units, string as pixels.
174
+ xminOffset: null,
175
+ xmaxOffset: null,
176
+
177
+ ymin: null,
178
+ ymax: null,
179
+ yOffset: '6px', // number or string. Number interpreted as units, string as pixels.
180
+ yminOffset: null,
181
+ ymaxOffset: null
182
+ };
183
+ $.extend(true, this.options, opts, options);
184
+
185
+ if (this.options.showTooltipPrecision < 0.01) {
186
+ this.options.showTooltipPrecision = 0.01;
187
+ }
188
+ }
189
+
190
+ Rectangle.prototype = new LineBase();
191
+ Rectangle.prototype.constructor = Rectangle;
192
+
193
+
194
+ /**
195
+ * Class: Line
196
+ * A straight line.
197
+ */
198
+ function Line(options) {
199
+ LineBase.call(this);
200
+ this.type = 'line';
201
+ var opts = {
202
+ // prop: start
203
+ // [x, y] coordinates for the start of the line.
204
+ start: [],
205
+ // prop: stop
206
+ // [x, y] coordinates for the end of the line.
207
+ stop: []
208
+ };
209
+ $.extend(true, this.options, opts, options);
210
+
211
+ if (this.options.showTooltipPrecision < 0.01) {
212
+ this.options.showTooltipPrecision = 0.01;
213
+ }
214
+ }
215
+
216
+ Line.prototype = new LineBase();
217
+ Line.prototype.constructor = Line;
218
+
219
+
220
+ /**
221
+ * Class: HorizontalLine
222
+ * A straight horizontal line.
223
+ */
224
+ function HorizontalLine(options) {
225
+ LineBase.call(this);
226
+ this.type = 'horizontalLine';
227
+ var opts = {
228
+ // prop: y
229
+ // y value to position the line
230
+ y: null,
231
+ // prop: xmin
232
+ // x value for the start of the line, null to scale to axis min.
233
+ xmin: null,
234
+ // prop: xmax
235
+ // x value for the end of the line, null to scale to axis max.
236
+ xmax: null,
237
+ // prop xOffset
238
+ // offset ends of the line inside the grid. Number
239
+ xOffset: '6px', // number or string. Number interpreted as units, string as pixels.
240
+ xminOffset: null,
241
+ xmaxOffset: null
242
+ };
243
+ $.extend(true, this.options, opts, options);
244
+
245
+ if (this.options.showTooltipPrecision < 0.01) {
246
+ this.options.showTooltipPrecision = 0.01;
247
+ }
248
+ }
249
+
250
+ HorizontalLine.prototype = new LineBase();
251
+ HorizontalLine.prototype.constructor = HorizontalLine;
252
+
253
+
254
+ /**
255
+ * Class: DashedHorizontalLine
256
+ * A straight dashed horizontal line.
257
+ */
258
+ function DashedHorizontalLine(options) {
259
+ LineBase.call(this);
260
+ this.type = 'dashedHorizontalLine';
261
+ var opts = {
262
+ y: null,
263
+ xmin: null,
264
+ xmax: null,
265
+ xOffset: '6px', // number or string. Number interpreted as units, string as pixels.
266
+ xminOffset: null,
267
+ xmaxOffset: null,
268
+ // prop: dashPattern
269
+ // Array of line, space settings in pixels.
270
+ // Default is 8 pixel of line, 8 pixel of space.
271
+ // Note, limit to a 2 element array b/c of bug with higher order arrays.
272
+ dashPattern: [8,8]
273
+ };
274
+ $.extend(true, this.options, opts, options);
275
+
276
+ if (this.options.showTooltipPrecision < 0.01) {
277
+ this.options.showTooltipPrecision = 0.01;
278
+ }
279
+ }
280
+
281
+ DashedHorizontalLine.prototype = new LineBase();
282
+ DashedHorizontalLine.prototype.constructor = DashedHorizontalLine;
283
+
284
+
285
+ /**
286
+ * Class: VerticalLine
287
+ * A straight vertical line.
288
+ */
289
+ function VerticalLine(options) {
290
+ LineBase.call(this);
291
+ this.type = 'verticalLine';
292
+ var opts = {
293
+ x: null,
294
+ ymin: null,
295
+ ymax: null,
296
+ yOffset: '6px', // number or string. Number interpreted as units, string as pixels.
297
+ yminOffset: null,
298
+ ymaxOffset: null
299
+ };
300
+ $.extend(true, this.options, opts, options);
301
+
302
+ if (this.options.showTooltipPrecision < 0.01) {
303
+ this.options.showTooltipPrecision = 0.01;
304
+ }
305
+ }
306
+
307
+ VerticalLine.prototype = new LineBase();
308
+ VerticalLine.prototype.constructor = VerticalLine;
309
+
310
+
311
+ /**
312
+ * Class: DashedVerticalLine
313
+ * A straight dashed vertical line.
314
+ */
315
+ function DashedVerticalLine(options) {
316
+ LineBase.call(this);
317
+ this.type = 'dashedVerticalLine';
318
+ this.start = null;
319
+ this.stop = null;
320
+ var opts = {
321
+ x: null,
322
+ ymin: null,
323
+ ymax: null,
324
+ yOffset: '6px', // number or string. Number interpreted as units, string as pixels.
325
+ yminOffset: null,
326
+ ymaxOffset: null,
327
+ // prop: dashPattern
328
+ // Array of line, space settings in pixels.
329
+ // Default is 8 pixel of line, 8 pixel of space.
330
+ // Note, limit to a 2 element array b/c of bug with higher order arrays.
331
+ dashPattern: [8,8]
332
+ };
333
+ $.extend(true, this.options, opts, options);
334
+
335
+ if (this.options.showTooltipPrecision < 0.01) {
336
+ this.options.showTooltipPrecision = 0.01;
337
+ }
338
+ }
339
+
340
+ DashedVerticalLine.prototype = new LineBase();
341
+ DashedVerticalLine.prototype.constructor = DashedVerticalLine;
342
+
343
+ $.jqplot.CanvasOverlay.prototype.addLine = function(opts) {
344
+ var line = new Line(opts);
345
+ line.uid = objCounter++;
346
+ this.objects.push(line);
347
+ this.objectNames.push(line.options.name);
348
+ };
349
+
350
+ $.jqplot.CanvasOverlay.prototype.addHorizontalLine = function(opts) {
351
+ var line = new HorizontalLine(opts);
352
+ line.uid = objCounter++;
353
+ this.objects.push(line);
354
+ this.objectNames.push(line.options.name);
355
+ };
356
+
357
+ $.jqplot.CanvasOverlay.prototype.addDashedHorizontalLine = function(opts) {
358
+ var line = new DashedHorizontalLine(opts);
359
+ line.uid = objCounter++;
360
+ this.objects.push(line);
361
+ this.objectNames.push(line.options.name);
362
+ };
363
+
364
+ $.jqplot.CanvasOverlay.prototype.addVerticalLine = function(opts) {
365
+ var line = new VerticalLine(opts);
366
+ line.uid = objCounter++;
367
+ this.objects.push(line);
368
+ this.objectNames.push(line.options.name);
369
+ };
370
+
371
+ $.jqplot.CanvasOverlay.prototype.addDashedVerticalLine = function(opts) {
372
+ var line = new DashedVerticalLine(opts);
373
+ line.uid = objCounter++;
374
+ this.objects.push(line);
375
+ this.objectNames.push(line.options.name);
376
+ };
377
+
378
+ $.jqplot.CanvasOverlay.prototype.addRectangle = function(opts) {
379
+ var line = new Rectangle(opts);
380
+ line.uid = objCounter++;
381
+ this.objects.push(line);
382
+ this.objectNames.push(line.options.name);
383
+ };
384
+
385
+ $.jqplot.CanvasOverlay.prototype.removeObject = function(idx) {
386
+ // check if integer, remove by index
387
+ if ($.type(idx) == 'number') {
388
+ this.objects.splice(idx, 1);
389
+ this.objectNames.splice(idx, 1);
390
+ }
391
+ // if string, remove by name
392
+ else {
393
+ var id = $.inArray(idx, this.objectNames);
394
+ if (id != -1) {
395
+ this.objects.splice(id, 1);
396
+ this.objectNames.splice(id, 1);
397
+ }
398
+ }
399
+ };
400
+
401
+ $.jqplot.CanvasOverlay.prototype.getObject = function(idx) {
402
+ // check if integer, remove by index
403
+ if ($.type(idx) == 'number') {
404
+ return this.objects[idx];
405
+ }
406
+ // if string, remove by name
407
+ else {
408
+ var id = $.inArray(idx, this.objectNames);
409
+ if (id != -1) {
410
+ return this.objects[id];
411
+ }
412
+ }
413
+ };
414
+
415
+ // Set get as alias for getObject.
416
+ $.jqplot.CanvasOverlay.prototype.get = $.jqplot.CanvasOverlay.prototype.getObject;
417
+
418
+ $.jqplot.CanvasOverlay.prototype.clear = function(plot) {
419
+ this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight());
420
+ };
421
+
422
+ $.jqplot.CanvasOverlay.prototype.draw = function(plot) {
423
+ var obj,
424
+ objs = this.objects,
425
+ mr = this.markerRenderer,
426
+ start,
427
+ stop;
428
+ if (this.options.show) {
429
+ this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight());
430
+ for (var k=0; k<objs.length; k++) {
431
+ obj = objs[k];
432
+ var opts = $.extend(true, {}, obj.options);
433
+ if (obj.options.show) {
434
+ // style and shadow properties should be set before
435
+ // every draw of marker renderer.
436
+ mr.shadow = obj.options.shadow;
437
+ obj.tooltipWidthFactor = obj.options.lineWidth / obj.options.showTooltipPrecision;
438
+ switch (obj.type) {
439
+ case 'line':
440
+ // style and shadow properties should be set before
441
+ // every draw of marker renderer.
442
+ mr.style = 'line';
443
+ opts.closePath = false;
444
+ start = [plot.axes[obj.options.xaxis].series_u2p(obj.options.start[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.start[1])];
445
+ stop = [plot.axes[obj.options.xaxis].series_u2p(obj.options.stop[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.stop[1])];
446
+ obj.gridStart = start;
447
+ obj.gridStop = stop;
448
+ mr.draw(start, stop, this.canvas._ctx, opts);
449
+ break;
450
+ case 'horizontalLine':
451
+
452
+ // style and shadow properties should be set before
453
+ // every draw of marker renderer.
454
+ if (obj.options.y != null) {
455
+ mr.style = 'line';
456
+ opts.closePath = false;
457
+ var xaxis = plot.axes[obj.options.xaxis],
458
+ xstart,
459
+ xstop,
460
+ y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),
461
+ xminoff = obj.options.xminOffset || obj.options.xOffset,
462
+ xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;
463
+ if (obj.options.xmin != null) {
464
+ xstart = xaxis.series_u2p(obj.options.xmin);
465
+ }
466
+ else if (xminoff != null) {
467
+ if ($.type(xminoff) == "number") {
468
+ xstart = xaxis.series_u2p(xaxis.min + xminoff);
469
+ }
470
+ else if ($.type(xminoff) == "string") {
471
+ xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);
472
+ }
473
+ }
474
+ if (obj.options.xmax != null) {
475
+ xstop = xaxis.series_u2p(obj.options.xmax);
476
+ }
477
+ else if (xmaxoff != null) {
478
+ if ($.type(xmaxoff) == "number") {
479
+ xstop = xaxis.series_u2p(xaxis.max - xmaxoff);
480
+ }
481
+ else if ($.type(xmaxoff) == "string") {
482
+ xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);
483
+ }
484
+ }
485
+ if (xstop != null && xstart != null) {
486
+ obj.gridStart = [xstart, y];
487
+ obj.gridStop = [xstop, y];
488
+ mr.draw([xstart, y], [xstop, y], this.canvas._ctx, opts);
489
+ }
490
+ }
491
+ break;
492
+
493
+ case 'dashedHorizontalLine':
494
+
495
+ var dashPat = obj.options.dashPattern;
496
+ var dashPatLen = 0;
497
+ for (var i=0; i<dashPat.length; i++) {
498
+ dashPatLen += dashPat[i];
499
+ }
500
+
501
+ // style and shadow properties should be set before
502
+ // every draw of marker renderer.
503
+ if (obj.options.y != null) {
504
+ mr.style = 'line';
505
+ opts.closePath = false;
506
+ var xaxis = plot.axes[obj.options.xaxis],
507
+ xstart,
508
+ xstop,
509
+ y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),
510
+ xminoff = obj.options.xminOffset || obj.options.xOffset,
511
+ xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;
512
+ if (obj.options.xmin != null) {
513
+ xstart = xaxis.series_u2p(obj.options.xmin);
514
+ }
515
+ else if (xminoff != null) {
516
+ if ($.type(xminoff) == "number") {
517
+ xstart = xaxis.series_u2p(xaxis.min + xminoff);
518
+ }
519
+ else if ($.type(xminoff) == "string") {
520
+ xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);
521
+ }
522
+ }
523
+ if (obj.options.xmax != null) {
524
+ xstop = xaxis.series_u2p(obj.options.xmax);
525
+ }
526
+ else if (xmaxoff != null) {
527
+ if ($.type(xmaxoff) == "number") {
528
+ xstop = xaxis.series_u2p(xaxis.max - xmaxoff);
529
+ }
530
+ else if ($.type(xmaxoff) == "string") {
531
+ xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);
532
+ }
533
+ }
534
+ if (xstop != null && xstart != null) {
535
+ obj.gridStart = [xstart, y];
536
+ obj.gridStop = [xstop, y];
537
+ var numDash = Math.ceil((xstop - xstart)/dashPatLen);
538
+ var b=xstart, e;
539
+ for (var i=0; i<numDash; i++) {
540
+ for (var j=0; j<dashPat.length; j+=2) {
541
+ e = b+dashPat[j];
542
+ mr.draw([b, y], [e, y], this.canvas._ctx, opts);
543
+ b += dashPat[j];
544
+ if (j < dashPat.length-1) {
545
+ b += dashPat[j+1];
546
+ }
547
+ }
548
+ }
549
+ }
550
+ }
551
+ break;
552
+
553
+ case 'verticalLine':
554
+
555
+ // style and shadow properties should be set before
556
+ // every draw of marker renderer.
557
+ if (obj.options.x != null) {
558
+ mr.style = 'line';
559
+ opts.closePath = false;
560
+ var yaxis = plot.axes[obj.options.yaxis],
561
+ ystart,
562
+ ystop,
563
+ x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),
564
+ yminoff = obj.options.yminOffset || obj.options.yOffset,
565
+ ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;
566
+ if (obj.options.ymin != null) {
567
+ ystart = yaxis.series_u2p(obj.options.ymin);
568
+ }
569
+ else if (yminoff != null) {
570
+ if ($.type(yminoff) == "number") {
571
+ ystart = yaxis.series_u2p(yaxis.min - yminoff);
572
+ }
573
+ else if ($.type(yminoff) == "string") {
574
+ ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);
575
+ }
576
+ }
577
+ if (obj.options.ymax != null) {
578
+ ystop = yaxis.series_u2p(obj.options.ymax);
579
+ }
580
+ else if (ymaxoff != null) {
581
+ if ($.type(ymaxoff) == "number") {
582
+ ystop = yaxis.series_u2p(yaxis.max + ymaxoff);
583
+ }
584
+ else if ($.type(ymaxoff) == "string") {
585
+ ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);
586
+ }
587
+ }
588
+ if (ystop != null && ystart != null) {
589
+ obj.gridStart = [x, ystart];
590
+ obj.gridStop = [x, ystop];
591
+ mr.draw([x, ystart], [x, ystop], this.canvas._ctx, opts);
592
+ }
593
+ }
594
+ break;
595
+
596
+ case 'dashedVerticalLine':
597
+
598
+ var dashPat = obj.options.dashPattern;
599
+ var dashPatLen = 0;
600
+ for (var i=0; i<dashPat.length; i++) {
601
+ dashPatLen += dashPat[i];
602
+ }
603
+
604
+ // style and shadow properties should be set before
605
+ // every draw of marker renderer.
606
+ if (obj.options.x != null) {
607
+ mr.style = 'line';
608
+ opts.closePath = false;
609
+ var yaxis = plot.axes[obj.options.yaxis],
610
+ ystart,
611
+ ystop,
612
+ x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),
613
+ yminoff = obj.options.yminOffset || obj.options.yOffset,
614
+ ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;
615
+ if (obj.options.ymin != null) {
616
+ ystart = yaxis.series_u2p(obj.options.ymin);
617
+ }
618
+ else if (yminoff != null) {
619
+ if ($.type(yminoff) == "number") {
620
+ ystart = yaxis.series_u2p(yaxis.min - yminoff);
621
+ }
622
+ else if ($.type(yminoff) == "string") {
623
+ ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);
624
+ }
625
+ }
626
+ if (obj.options.ymax != null) {
627
+ ystop = yaxis.series_u2p(obj.options.ymax);
628
+ }
629
+ else if (ymaxoff != null) {
630
+ if ($.type(ymaxoff) == "number") {
631
+ ystop = yaxis.series_u2p(yaxis.max + ymaxoff);
632
+ }
633
+ else if ($.type(ymaxoff) == "string") {
634
+ ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);
635
+ }
636
+ }
637
+
638
+
639
+ if (ystop != null && ystart != null) {
640
+ obj.gridStart = [x, ystart];
641
+ obj.gridStop = [x, ystop];
642
+ var numDash = Math.ceil((ystart - ystop)/dashPatLen);
643
+ var firstDashAdjust = ((numDash * dashPatLen) - (ystart - ystop))/2.0;
644
+ var b=ystart, e, bs, es;
645
+ for (var i=0; i<numDash; i++) {
646
+ for (var j=0; j<dashPat.length; j+=2) {
647
+ e = b - dashPat[j];
648
+ if (e < ystop) {
649
+ e = ystop;
650
+ }
651
+ if (b < ystop) {
652
+ b = ystop;
653
+ }
654
+ // es = e;
655
+ // if (i == 0) {
656
+ // es += firstDashAdjust;
657
+ // }
658
+ mr.draw([x, b], [x, e], this.canvas._ctx, opts);
659
+ b -= dashPat[j];
660
+ if (j < dashPat.length-1) {
661
+ b -= dashPat[j+1];
662
+ }
663
+ }
664
+ }
665
+ }
666
+ }
667
+ break;
668
+
669
+ case 'rectangle':
670
+ // style and shadow properties should be set before
671
+ // every draw of marker renderer.
672
+ mr.style = 'line';
673
+ opts.closePath = true;
674
+
675
+ var xaxis = plot.axes[obj.options.xaxis],
676
+ xstart,
677
+ xstop,
678
+ y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),
679
+ xminoff = obj.options.xminOffset || obj.options.xOffset,
680
+ xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;
681
+ if (obj.options.xmin != null) {
682
+ xstart = xaxis.series_u2p(obj.options.xmin);
683
+ }
684
+ else if (xminoff != null) {
685
+ if ($.type(xminoff) == "number") {
686
+ xstart = xaxis.series_u2p(xaxis.min + xminoff);
687
+ }
688
+ else if ($.type(xminoff) == "string") {
689
+ xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);
690
+ }
691
+ }
692
+ if (obj.options.xmax != null) {
693
+ xstop = xaxis.series_u2p(obj.options.xmax);
694
+ }
695
+ else if (xmaxoff != null) {
696
+ if ($.type(xmaxoff) == "number") {
697
+ xstop = xaxis.series_u2p(xaxis.max - xmaxoff);
698
+ }
699
+ else if ($.type(xmaxoff) == "string") {
700
+ xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);
701
+ }
702
+ }
703
+
704
+ var yaxis = plot.axes[obj.options.yaxis],
705
+ ystart,
706
+ ystop,
707
+ x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),
708
+ yminoff = obj.options.yminOffset || obj.options.yOffset,
709
+ ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;
710
+ if (obj.options.ymin != null) {
711
+ ystart = yaxis.series_u2p(obj.options.ymin);
712
+ }
713
+ else if (yminoff != null) {
714
+ if ($.type(yminoff) == "number") {
715
+ ystart = yaxis.series_u2p(yaxis.min - yminoff);
716
+ }
717
+ else if ($.type(yminoff) == "string") {
718
+ ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);
719
+ }
720
+ }
721
+ if (obj.options.ymax != null) {
722
+ ystop = yaxis.series_u2p(obj.options.ymax);
723
+ }
724
+ else if (ymaxoff != null) {
725
+ if ($.type(ymaxoff) == "number") {
726
+ ystop = yaxis.series_u2p(yaxis.max + ymaxoff);
727
+ }
728
+ else if ($.type(ymaxoff) == "string") {
729
+ ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);
730
+ }
731
+ }
732
+
733
+
734
+ if (xstop != null && xstart != null && ystop != null && ystart != null) {
735
+ obj.gridStart = [xstart, ystart];
736
+ obj.gridStop = [xstop, ystop];
737
+
738
+ this.canvas._ctx.fillStyle = obj.options.color;
739
+ this.canvas._ctx.fillRect(xstart, ystart, xstop - xstart, ystop - ystart);
740
+ }
741
+ break;
742
+
743
+ default:
744
+ break;
745
+ }
746
+ }
747
+ }
748
+ }
749
+ };
750
+
751
+ // called within context of plot
752
+ // create a canvas which we can draw on.
753
+ // insert it before the eventCanvas, so eventCanvas will still capture events.
754
+ $.jqplot.CanvasOverlay.postPlotDraw = function() {
755
+ var co = this.plugins.canvasOverlay;
756
+ // Memory Leaks patch
757
+ if (co && co.highlightCanvas) {
758
+ co.highlightCanvas.resetCanvas();
759
+ co.highlightCanvas = null;
760
+ }
761
+ co.canvas = new $.jqplot.GenericCanvas();
762
+
763
+ this.eventCanvas._elem.before(co.canvas.createElement(this._gridPadding, 'jqplot-overlayCanvas-canvas', this._plotDimensions, this));
764
+ co.canvas.setContext();
765
+ if (!co.deferDraw) {
766
+ co.draw(this);
767
+ }
768
+
769
+ var elem = document.createElement('div');
770
+ co._tooltipElem = $(elem);
771
+ elem = null;
772
+ co._tooltipElem.addClass('jqplot-canvasOverlay-tooltip');
773
+ co._tooltipElem.css({position:'absolute', display:'none'});
774
+
775
+ this.eventCanvas._elem.before(co._tooltipElem);
776
+ this.eventCanvas._elem.bind('mouseleave', { elem: co._tooltipElem }, function (ev) { ev.data.elem.hide(); });
777
+
778
+ var co = null;
779
+ };
780
+
781
+
782
+ function showTooltip(plot, obj, gridpos, datapos) {
783
+ var co = plot.plugins.canvasOverlay;
784
+ var elem = co._tooltipElem;
785
+
786
+ var opts = obj.options, x, y;
787
+
788
+ elem.html($.jqplot.sprintf(opts.tooltipFormatString, datapos[0], datapos[1]));
789
+
790
+ switch (opts.tooltipLocation) {
791
+ case 'nw':
792
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
793
+ y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
794
+ break;
795
+ case 'n':
796
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true)/2;
797
+ y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
798
+ break;
799
+ case 'ne':
800
+ x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;
801
+ y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
802
+ break;
803
+ case 'e':
804
+ x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;
805
+ y = gridpos[1] + plot._gridPadding.top - elem.outerHeight(true)/2;
806
+ break;
807
+ case 'se':
808
+ x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;
809
+ y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;
810
+ break;
811
+ case 's':
812
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true)/2;
813
+ y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;
814
+ break;
815
+ case 'sw':
816
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
817
+ y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;
818
+ break;
819
+ case 'w':
820
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
821
+ y = gridpos[1] + plot._gridPadding.top - elem.outerHeight(true)/2;
822
+ break;
823
+ default: // same as 'nw'
824
+ x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;
825
+ y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);
826
+ break;
827
+ }
828
+
829
+ elem.css('left', x);
830
+ elem.css('top', y);
831
+ if (opts.fadeTooltip) {
832
+ // Fix for stacked up animations. Thnanks Trevor!
833
+ elem.stop(true,true).fadeIn(opts.tooltipFadeSpeed);
834
+ }
835
+ else {
836
+ elem.show();
837
+ }
838
+ elem = null;
839
+ }
840
+
841
+
842
+ function isNearLine(point, lstart, lstop, width) {
843
+ // r is point to test, p and q are end points.
844
+ var rx = point[0];
845
+ var ry = point[1];
846
+ var px = Math.round(lstop[0]);
847
+ var py = Math.round(lstop[1]);
848
+ var qx = Math.round(lstart[0]);
849
+ var qy = Math.round(lstart[1]);
850
+
851
+ var l = Math.sqrt(Math.pow(px-qx, 2) + Math.pow(py-qy, 2));
852
+
853
+ // scale error term by length of line.
854
+ var eps = width*l;
855
+ var res = Math.abs((qx-px) * (ry-py) - (qy-py) * (rx-px));
856
+ var ret = (res < eps) ? true : false;
857
+ return ret;
858
+ }
859
+
860
+ function isNearRectangle(point, lstart, lstop, width) {
861
+ // r is point to test, p and q are end points.
862
+ var rx = point[0];
863
+ var ry = point[1];
864
+ var px = Math.round(lstop[0]);
865
+ var py = Math.round(lstop[1]);
866
+ var qx = Math.round(lstart[0]);
867
+ var qy = Math.round(lstart[1]);
868
+
869
+ var temp;
870
+ if (px > qx) { temp = px; px = qx; qx = temp; }
871
+ if (py > qy) { temp = py; py = qy; qy = temp; }
872
+
873
+ var ret = (rx >= px && rx <= qx && ry >= py && ry <= qy);
874
+
875
+ return ret;
876
+ }
877
+
878
+
879
+ function handleMove(ev, gridpos, datapos, neighbor, plot) {
880
+ var co = plot.plugins.canvasOverlay;
881
+ var objs = co.objects;
882
+ var l = objs.length;
883
+ var obj, haveHighlight=false;
884
+ var elem;
885
+ for (var i=0; i<l; i++) {
886
+ obj = objs[i];
887
+ if (obj.options.showTooltip) {
888
+ var n;
889
+ if (obj.type === 'rectangle') {
890
+ n = isNearRectangle([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor);
891
+ } else {
892
+ n = isNearLine([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor);
893
+ }
894
+ datapos = [plot.axes[obj.options.xaxis].series_p2u(gridpos.x), plot.axes[obj.options.yaxis].series_p2u(gridpos.y)];
895
+
896
+ // cases:
897
+ // near line, no highlighting
898
+ // near line, highliting on this line
899
+ // near line, highlighting another line
900
+ // not near any line, highlighting
901
+ // not near any line, no highlighting
902
+
903
+ // near line, not currently highlighting
904
+ if (n && co.highlightObjectIndex == null) {
905
+ switch (obj.type) {
906
+ case 'line':
907
+ showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);
908
+ break;
909
+
910
+ case 'horizontalLine':
911
+ case 'dashedHorizontalLine':
912
+ showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);
913
+ break;
914
+
915
+ case 'verticalLine':
916
+ case 'dashedVerticalLine':
917
+ showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
918
+ break;
919
+
920
+ case 'rectangle':
921
+ showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
922
+ break;
923
+
924
+ default:
925
+ break;
926
+ }
927
+ co.highlightObjectIndex = i;
928
+ haveHighlight = true;
929
+ break;
930
+ }
931
+
932
+ // near line, highlighting another line.
933
+ else if (n && co.highlightObjectIndex !== i) {
934
+ // turn off tooltip.
935
+ elem = co._tooltipElem;
936
+ if (obj.fadeTooltip) {
937
+ elem.fadeOut(obj.tooltipFadeSpeed);
938
+ }
939
+ else {
940
+ elem.hide();
941
+ }
942
+
943
+ // turn on right tooltip.
944
+ switch (obj.type) {
945
+ case 'line':
946
+ showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);
947
+ break;
948
+
949
+ case 'horizontalLine':
950
+ case 'dashedHorizontalLine':
951
+ showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);
952
+ break;
953
+
954
+ case 'verticalLine':
955
+ case 'dashedVerticalLine':
956
+ showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
957
+ break;
958
+
959
+ case 'rectangle':
960
+ showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
961
+ break;
962
+
963
+ default:
964
+ break;
965
+ }
966
+
967
+ co.highlightObjectIndex = i;
968
+ haveHighlight = true;
969
+ break;
970
+ }
971
+
972
+ // near line, already highlighting this line, update
973
+ else if (n) {
974
+ switch (obj.type) {
975
+ case 'line':
976
+ showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);
977
+ break;
978
+
979
+ case 'horizontalLine':
980
+ case 'dashedHorizontalLine':
981
+ showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);
982
+ break;
983
+
984
+ case 'verticalLine':
985
+ case 'dashedVerticalLine':
986
+ showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
987
+ break;
988
+
989
+ case 'rectangle':
990
+ showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);
991
+ break;
992
+
993
+ default:
994
+ break;
995
+ }
996
+
997
+ haveHighlight = true;
998
+ break;
999
+ }
1000
+ }
1001
+ }
1002
+
1003
+ // check if we are highlighting and not near a line, turn it off.
1004
+ if (!haveHighlight && co.highlightObjectIndex !== null) {
1005
+ elem = co._tooltipElem;
1006
+ obj = co.getObject(co.highlightObjectIndex);
1007
+ if (obj.fadeTooltip) {
1008
+ elem.fadeOut(obj.tooltipFadeSpeed);
1009
+ }
1010
+ else {
1011
+ elem.hide();
1012
+ }
1013
+ co.highlightObjectIndex = null;
1014
+ }
1015
+ }
1016
+
1017
+ $.jqplot.postInitHooks.push($.jqplot.CanvasOverlay.postPlotInit);
1018
+ $.jqplot.postDrawHooks.push($.jqplot.CanvasOverlay.postPlotDraw);
1019
+ $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]);
1020
+
1021
1021
  })(jQuery);