acts_as_dashboard 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +54 -0
  5. data/Rakefile +23 -0
  6. data/VERSION +1 -0
  7. data/acts_as_dashboard.gemspec +166 -0
  8. data/generators/dashboard/USAGE +23 -0
  9. data/generators/dashboard/dashboard_generator.rb +105 -0
  10. data/generators/dashboard/templates/controller.erb +39 -0
  11. data/generators/dashboard/templates/dashboard.css +66 -0
  12. data/generators/dashboard/templates/dashboard.js +305 -0
  13. data/generators/dashboard/templates/jqplot-0.9.7/jquery.jqplot.min.js +14 -0
  14. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.barRenderer.js +404 -0
  15. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.barRenderer.min.js +14 -0
  16. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.canvasAxisLabelRenderer.js +200 -0
  17. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.canvasAxisLabelRenderer.min.js +14 -0
  18. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.canvasAxisTickRenderer.js +232 -0
  19. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.canvasAxisTickRenderer.min.js +14 -0
  20. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.canvasTextRenderer.js +408 -0
  21. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.canvasTextRenderer.min.js +14 -0
  22. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.categoryAxisRenderer.js +238 -0
  23. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.categoryAxisRenderer.min.js +14 -0
  24. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.cursor.js +812 -0
  25. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.cursor.min.js +14 -0
  26. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.dateAxisRenderer.js +313 -0
  27. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.dateAxisRenderer.min.js +14 -0
  28. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.dragable.js +203 -0
  29. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.dragable.min.js +14 -0
  30. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.highlighter.js +359 -0
  31. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.highlighter.min.js +14 -0
  32. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.logAxisRenderer.js +434 -0
  33. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.logAxisRenderer.min.js +14 -0
  34. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.mekkoAxisRenderer.js +595 -0
  35. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.mekkoAxisRenderer.min.js +14 -0
  36. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.mekkoRenderer.js +308 -0
  37. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.mekkoRenderer.min.js +14 -0
  38. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.ohlcRenderer.js +343 -0
  39. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.ohlcRenderer.min.js +14 -0
  40. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.pieRenderer.js +333 -0
  41. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.pieRenderer.min.js +14 -0
  42. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.pointLabels.js +307 -0
  43. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.pointLabels.js.orig +273 -0
  44. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.pointLabels.min.js +14 -0
  45. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.trendline.js +208 -0
  46. data/generators/dashboard/templates/jqplot-0.9.7/plugins/jqplot.trendline.min.js +14 -0
  47. data/generators/dashboard/templates/jquery.jqplot.min.css +1 -0
  48. data/generators/dashboard/templates/js.class-2.1.4/CHANGELOG +269 -0
  49. data/generators/dashboard/templates/js.class-2.1.4/MIT-LICENSE +30 -0
  50. data/generators/dashboard/templates/js.class-2.1.4/README +30 -0
  51. data/generators/dashboard/templates/js.class-2.1.4/min/command.js +1 -0
  52. data/generators/dashboard/templates/js.class-2.1.4/min/comparable.js +1 -0
  53. data/generators/dashboard/templates/js.class-2.1.4/min/constant_scope.js +1 -0
  54. data/generators/dashboard/templates/js.class-2.1.4/min/core.js +1 -0
  55. data/generators/dashboard/templates/js.class-2.1.4/min/decorator.js +1 -0
  56. data/generators/dashboard/templates/js.class-2.1.4/min/enumerable.js +1 -0
  57. data/generators/dashboard/templates/js.class-2.1.4/min/forwardable.js +1 -0
  58. data/generators/dashboard/templates/js.class-2.1.4/min/hash.js +1 -0
  59. data/generators/dashboard/templates/js.class-2.1.4/min/linked_list.js +1 -0
  60. data/generators/dashboard/templates/js.class-2.1.4/min/loader.js +1 -0
  61. data/generators/dashboard/templates/js.class-2.1.4/min/method_chain.js +1 -0
  62. data/generators/dashboard/templates/js.class-2.1.4/min/observable.js +1 -0
  63. data/generators/dashboard/templates/js.class-2.1.4/min/package.js +1 -0
  64. data/generators/dashboard/templates/js.class-2.1.4/min/proxy.js +1 -0
  65. data/generators/dashboard/templates/js.class-2.1.4/min/ruby.js +1 -0
  66. data/generators/dashboard/templates/js.class-2.1.4/min/set.js +1 -0
  67. data/generators/dashboard/templates/js.class-2.1.4/min/stack_trace.js +1 -0
  68. data/generators/dashboard/templates/js.class-2.1.4/min/state.js +1 -0
  69. data/generators/dashboard/templates/js.class-2.1.4/min/stdlib.js +16 -0
  70. data/generators/dashboard/templates/js.class-2.1.4/src/command.js +93 -0
  71. data/generators/dashboard/templates/js.class-2.1.4/src/comparable.js +37 -0
  72. data/generators/dashboard/templates/js.class-2.1.4/src/constant_scope.js +48 -0
  73. data/generators/dashboard/templates/js.class-2.1.4/src/core.js +1060 -0
  74. data/generators/dashboard/templates/js.class-2.1.4/src/decorator.js +50 -0
  75. data/generators/dashboard/templates/js.class-2.1.4/src/enumerable.js +505 -0
  76. data/generators/dashboard/templates/js.class-2.1.4/src/forwardable.js +22 -0
  77. data/generators/dashboard/templates/js.class-2.1.4/src/hash.js +334 -0
  78. data/generators/dashboard/templates/js.class-2.1.4/src/linked_list.js +114 -0
  79. data/generators/dashboard/templates/js.class-2.1.4/src/loader.js +458 -0
  80. data/generators/dashboard/templates/js.class-2.1.4/src/method_chain.js +172 -0
  81. data/generators/dashboard/templates/js.class-2.1.4/src/observable.js +55 -0
  82. data/generators/dashboard/templates/js.class-2.1.4/src/package.js +377 -0
  83. data/generators/dashboard/templates/js.class-2.1.4/src/proxy.js +58 -0
  84. data/generators/dashboard/templates/js.class-2.1.4/src/ruby.js +44 -0
  85. data/generators/dashboard/templates/js.class-2.1.4/src/set.js +332 -0
  86. data/generators/dashboard/templates/js.class-2.1.4/src/stack_trace.js +151 -0
  87. data/generators/dashboard/templates/js.class-2.1.4/src/state.js +95 -0
  88. data/generators/dashboard/templates/js.class-2.1.4/src/stdlib.js +2517 -0
  89. data/generators/dashboard/templates/show.html.erb +67 -0
  90. data/lib/acts_as_dashboard/app/views/dashboards/show.html.erb +67 -0
  91. data/lib/acts_as_dashboard/class_methods.rb +58 -0
  92. data/lib/acts_as_dashboard/config.rb +25 -0
  93. data/lib/acts_as_dashboard/instance_methods.rb +32 -0
  94. data/lib/acts_as_dashboard/line_graph_widget.rb +68 -0
  95. data/lib/acts_as_dashboard/public/javascripts/dashboard.js +305 -0
  96. data/lib/acts_as_dashboard/public/stylesheets/dashboard.css +66 -0
  97. data/lib/acts_as_dashboard/short_messages_widget.rb +25 -0
  98. data/lib/acts_as_dashboard/widget.rb +55 -0
  99. data/lib/acts_as_dashboard.rb +17 -0
  100. data/spec/acts_as_dashboard/class_method_specs.rb +188 -0
  101. data/spec/acts_as_dashboard/config_spec.rb +57 -0
  102. data/spec/acts_as_dashboard/instance_methods_spec.rb +134 -0
  103. data/spec/acts_as_dashboard/line_graph_widget_spec.rb +165 -0
  104. data/spec/acts_as_dashboard/short_messages_widget_spec.rb +69 -0
  105. data/spec/acts_as_dashboard/widget_spec.rb +6 -0
  106. data/spec/acts_as_dashboard_spec.rb +15 -0
  107. data/spec/shared/widget_behaviours.rb +171 -0
  108. data/spec/spec.opts +1 -0
  109. data/spec/spec_helper.rb +10 -0
  110. data/tasks/install.rake +8 -0
  111. data/tasks/install_javascript.rake +7 -0
  112. data/tasks/install_stylesheets.rake +7 -0
  113. metadata +209 -0
@@ -0,0 +1,812 @@
1
+ /**
2
+ * Copyright (c) 2009 Chris Leonello
3
+ * jqPlot is currently available for use in all personal or commercial projects
4
+ * under both the MIT and GPL version 2.0 licenses. This means that you can
5
+ * choose the license that best suits your project and use it accordingly.
6
+ *
7
+ * The author would appreciate an email letting him know of any substantial
8
+ * use of jqPlot. You can reach the author at: chris dot leonello at gmail
9
+ * dot com or see http://www.jqplot.com/info.php . This is, of course,
10
+ * not required.
11
+ *
12
+ * If you are feeling kind and generous, consider supporting the project by
13
+ * making a donation at: http://www.jqplot.com/donate.php .
14
+ *
15
+ * Thanks for using jqPlot!
16
+ *
17
+ */
18
+ (function($) {
19
+
20
+ /**
21
+ * Class: $.jqplot.Cursor
22
+ * Plugin class representing the cursor as displayed on the plot.
23
+ */
24
+ $.jqplot.Cursor = function(options) {
25
+ // Group: Properties
26
+ //
27
+ // prop: style
28
+ // CSS spec for cursor style
29
+ this.style = 'crosshair';
30
+ this.previousCursor = 'auto';
31
+ // prop: show
32
+ // wether to show the cursor or not.
33
+ this.show = $.jqplot.config.enablePlugins;
34
+ // prop: showTooltip
35
+ // show a cursor position tooltip near the cursor
36
+ this.showTooltip = true;
37
+ // prop: followMouse
38
+ // Tooltip follows the mouse, it is not at a fixed location.
39
+ // Tooltip will show on the grid at the location given by
40
+ // tooltipLocation, offset from the grid edge by tooltipOffset.
41
+ this.followMouse = false;
42
+ // prop: tooltipLocation
43
+ // Where to position tooltip. If followMouse is true, this is
44
+ // relative to the cursor, otherwise, it is relative to the grid.
45
+ // One of 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'
46
+ this.tooltipLocation = 'se';
47
+ // prop: tooltipOffset
48
+ // Pixel offset of tooltip from the grid boudaries or cursor center.
49
+ this.tooltipOffset = 6;
50
+ // prop: showTooltipGridPosition
51
+ // show the grid pixel coordinates of the mouse.
52
+ this.showTooltipGridPosition = false;
53
+ // prop: showTooltipUnitPosition
54
+ // show the unit (data) coordinates of the mouse.
55
+ this.showTooltipUnitPosition = true;
56
+ // prop: showTooltipDataPosition
57
+ // Used with showVerticalLine to show intersecting data points in the tooltip.
58
+ this.showTooltipDataPosition = false;
59
+ // prop: tooltipFormatString
60
+ // sprintf format string for the tooltip.
61
+ // Uses Ash Searle's javascript sprintf implementation
62
+ // found here: http://hexmen.com/blog/2007/03/printf-sprintf/
63
+ // See http://perldoc.perl.org/functions/sprintf.html for reference
64
+ // Note, if showTooltipDataPosition is true, the default tooltipFormatString
65
+ // will be set to the cursorLegendFormatString, not the default given here.
66
+ this.tooltipFormatString = '%.4P, %.4P';
67
+ // prop: useAxesFormatters
68
+ // Use the x and y axes formatters to format the text in the tooltip.
69
+ this.useAxesFormatters = true;
70
+ // prop: tooltipAxisGroups
71
+ // Show position for the specified axes.
72
+ // This is an array like [['xaxis', 'yaxis'], ['xaxis', 'y2axis']]
73
+ // Default is to compute automatically for all visible axes.
74
+ this.tooltipAxisGroups = [];
75
+ // prop: zoom
76
+ // Enable plot zooming.
77
+ this.zoom = false;
78
+ // zoomProxy and zoomTarget properties are not directly set by user.
79
+ // They Will be set through call to zoomProxy method.
80
+ this.zoomProxy = false;
81
+ this.zoomTarget = false;
82
+ // prop: clickReset
83
+ // Will reset plot zoom if single click on plot without drag.
84
+ this.clickReset = false;
85
+ // prop: dblClickReset
86
+ // Will reset plot zoom if double click on plot without drag.
87
+ this.dblClickReset = true;
88
+ // prop: showVerticalLine
89
+ // draw a vertical line across the plot which follows the cursor.
90
+ // When the line is near a data point, a special legend and/or tooltip can
91
+ // be updated with the data values.
92
+ this.showVerticalLine = false;
93
+ // prop: showHorizontalLine
94
+ // draw a horizontal line across the plot which follows the cursor.
95
+ this.showHorizontalLine = false;
96
+ // prop: constrainZoomTo
97
+ // 'none', 'x' or 'y'
98
+ this.constrainZoomTo = 'none';
99
+ // // prop: autoscaleConstraint
100
+ // // when a constrained axis is specified, true will
101
+ // // auatoscale the adjacent axis.
102
+ // this.autoscaleConstraint = true;
103
+ this.shapeRenderer = new $.jqplot.ShapeRenderer();
104
+ this._zoom = {start:[], end:[], started: false, zooming:false, isZoomed:false, axes:{start:{}, end:{}}};
105
+ this._tooltipElem;
106
+ this.zoomCanvas;
107
+ this.cursorCanvas;
108
+ // prop: intersectionThreshold
109
+ // pixel distance from data point or marker to consider cursor lines intersecting with point.
110
+ // If data point markers are not shown, this should be >= 1 or will often miss point intersections.
111
+ this.intersectionThreshold = 2;
112
+ // prop: showCursorLegend
113
+ // Replace the plot legend with an enhanced legend displaying intersection information.
114
+ this.showCursorLegend = false;
115
+ // prop: cursorLegendFormatString
116
+ // Format string used in the cursor legend. If showTooltipDataPosition is true,
117
+ // this will also be the default format string used by tooltipFormatString.
118
+ this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString;
119
+ $.extend(true, this, options);
120
+ };
121
+
122
+ $.jqplot.Cursor.cursorLegendFormatString = '%s x:%s, y:%s';
123
+
124
+ // called with scope of plot
125
+ $.jqplot.Cursor.init = function (target, data, opts){
126
+ // add a cursor attribute to the plot
127
+ var options = opts || {};
128
+ this.plugins.cursor = new $.jqplot.Cursor(options.cursor);
129
+ var c = this.plugins.cursor;
130
+
131
+ if (c.show) {
132
+ $.jqplot.eventListenerHooks.push(['jqplotMouseEnter', handleMouseEnter]);
133
+ $.jqplot.eventListenerHooks.push(['jqplotMouseLeave', handleMouseLeave]);
134
+ $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMouseMove]);
135
+
136
+ if (c.showCursorLegend) {
137
+ opts.legend = opts.legend || {};
138
+ opts.legend.renderer = $.jqplot.CursorLegendRenderer;
139
+ opts.legend.formatString = this.plugins.cursor.cursorLegendFormatString;
140
+ opts.legend.show = true;
141
+ }
142
+
143
+ if (c.zoom) {
144
+ $.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleMouseDown]);
145
+ $.jqplot.eventListenerHooks.push(['jqplotMouseUp', handleMouseUp]);
146
+
147
+ if (c.clickReset) {
148
+ $.jqplot.eventListenerHooks.push(['jqplotClick', handleClick]);
149
+ }
150
+
151
+ if (c.dblClickReset) {
152
+ $.jqplot.eventListenerHooks.push(['jqplotDblClick', handleDblClick]);
153
+ }
154
+ }
155
+
156
+ this.resetZoom = function() {
157
+ var axes = this.axes;
158
+ if (!c.zoomProxy) {
159
+ for (var ax in axes) {
160
+ axes[ax].reset();
161
+ }
162
+ this.redraw();
163
+ }
164
+ else {
165
+ var ctx = this.plugins.cursor.zoomCanvas._ctx;
166
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
167
+ }
168
+ this.plugins.cursor._zoom.isZoomed = false;
169
+ this.target.trigger('jqplotResetZoom', [this, this.plugins.cursor]);
170
+ };
171
+
172
+
173
+ if (c.showTooltipDataPosition) {
174
+ c.showTooltipUnitPosition = false;
175
+ c.showTooltipGridPosition = false;
176
+ if (options.cursor.tooltipFormatString == undefined) {
177
+ c.tooltipFormatString = $.jqplot.Cursor.cursorLegendFormatString;
178
+ }
179
+ }
180
+ }
181
+ };
182
+
183
+ // called with context of plot
184
+ $.jqplot.Cursor.postDraw = function() {
185
+ var c = this.plugins.cursor;
186
+ // if (c.zoom) {
187
+ c.zoomCanvas = new $.jqplot.GenericCanvas();
188
+ this.eventCanvas._elem.before(c.zoomCanvas.createElement(this._gridPadding, 'jqplot-zoom-canvas', this._plotDimensions));
189
+ var zctx = c.zoomCanvas.setContext();
190
+ // }
191
+ c._tooltipElem = $('<div class="jqplot-cursor-tooltip" style="position:absolute;display:none"></div>');
192
+ c.zoomCanvas._elem.before(c._tooltipElem);
193
+ if (c.showVerticalLine || c.showHorizontalLine) {
194
+ c.cursorCanvas = new $.jqplot.GenericCanvas();
195
+ this.eventCanvas._elem.before(c.cursorCanvas.createElement(this._gridPadding, 'jqplot-cursor-canvas', this._plotDimensions));
196
+ var zctx = c.cursorCanvas.setContext();
197
+ }
198
+
199
+ // if we are showing the positions in unit coordinates, and no axes groups
200
+ // were specified, create a default set.
201
+ if (c.showTooltipUnitPosition){
202
+ if (c.tooltipAxisGroups.length === 0) {
203
+ var series = this.series;
204
+ var s;
205
+ var temp = [];
206
+ for (var i=0; i<series.length; i++) {
207
+ s = series[i];
208
+ var ax = s.xaxis+','+s.yaxis;
209
+ if ($.inArray(ax, temp) == -1) {
210
+ temp.push(ax);
211
+ }
212
+ }
213
+ for (var i=0; i<temp.length; i++) {
214
+ c.tooltipAxisGroups.push(temp[i].split(','));
215
+ }
216
+ }
217
+ }
218
+ };
219
+
220
+ // Group: methods
221
+ //
222
+ // method: $.jqplot.Cursor.zoomProxy
223
+ // links targetPlot to controllerPlot so that plot zooming of
224
+ // targetPlot will be controlled by zooming on the controllerPlot.
225
+ // controllerPlot will not actually zoom, but acts as an
226
+ // overview plot. Note, the zoom options must be set to true for
227
+ // zoomProxy to work.
228
+ $.jqplot.Cursor.zoomProxy = function(targetPlot, controllerPlot) {
229
+ var tc = targetPlot.plugins.cursor;
230
+ var cc = controllerPlot.plugins.cursor;
231
+ tc.zoomTarget = true;
232
+ tc.zoom = true;
233
+ tc.style = 'auto';
234
+ tc.dblClickReset = false;
235
+ cc.zoom = true;
236
+ cc.zoomProxy = true;
237
+
238
+ controllerPlot.target.bind('jqplotZoom', plotZoom);
239
+ controllerPlot.target.bind('jqplotResetZoom', plotReset);
240
+
241
+ function plotZoom(ev, gridpos, datapos, plot, cursor) {
242
+ tc.doZoom(gridpos, datapos, targetPlot, cursor);
243
+ }
244
+
245
+ function plotReset(ev, plot, cursor) {
246
+ targetPlot.resetZoom();
247
+ }
248
+ };
249
+
250
+ $.jqplot.Cursor.prototype.resetZoom = function(plot, cursor) {
251
+ var axes = plot.axes;
252
+ var cax = cursor._zoom.axes;
253
+ if (!plot.plugins.cursor.zoomProxy && cursor._zoom.isZoomed) {
254
+ for (var ax in axes) {
255
+ axes[ax]._ticks = [];
256
+ axes[ax].min = cax[ax].min;
257
+ axes[ax].max = cax[ax].max;
258
+ axes[ax].numberTicks = cax[ax].numberTicks;
259
+ axes[ax].tickInterval = cax[ax].tickInterval;
260
+ // for date axes
261
+ axes[ax].daTickInterval = cax[ax].daTickInterval;
262
+ }
263
+ plot.redraw();
264
+ cursor._zoom.isZoomed = false;
265
+ }
266
+ else {
267
+ var ctx = cursor.zoomCanvas._ctx;
268
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
269
+ }
270
+ plot.target.trigger('jqplotResetZoom', [plot, cursor]);
271
+ };
272
+
273
+ $.jqplot.Cursor.resetZoom = function(plot) {
274
+ plot.resetZoom();
275
+ };
276
+
277
+ $.jqplot.Cursor.prototype.doZoom = function (gridpos, datapos, plot, cursor) {
278
+ var c = cursor;
279
+ var axes = plot.axes;
280
+ var zaxes = c._zoom.axes;
281
+ var start = zaxes.start;
282
+ var end = zaxes.end;
283
+ var min, max;
284
+ var ctx = plot.plugins.cursor.zoomCanvas._ctx;
285
+ // don't zoom is zoom area is too small (in pixels)
286
+ 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)) {
287
+ if (!plot.plugins.cursor.zoomProxy) {
288
+ for (var ax in datapos) {
289
+ // make a copy of the original axes to revert back.
290
+ if (c._zoom.axes[ax] == undefined) {
291
+ c._zoom.axes[ax] = {};
292
+ c._zoom.axes[ax].numberTicks = axes[ax].numberTicks;
293
+ c._zoom.axes[ax].tickInterval = axes[ax].tickInterval;
294
+ // for date axes...
295
+ c._zoom.axes[ax].daTickInterval = axes[ax].daTickInterval;
296
+ c._zoom.axes[ax].min = axes[ax].min;
297
+ c._zoom.axes[ax].max = axes[ax].max;
298
+ }
299
+ if ((c.constrainZoomTo == 'none') || (c.constrainZoomTo == 'x' && ax.charAt(0) == 'x') || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'y')) {
300
+ dp = datapos[ax];
301
+ if (dp != null) {
302
+ if (dp > start[ax]) {
303
+ axes[ax].min = start[ax];
304
+ axes[ax].max = dp;
305
+ }
306
+ else {
307
+ span = start[ax] - dp;
308
+ axes[ax].max = start[ax];
309
+ axes[ax].min = dp;
310
+ }
311
+ axes[ax].tickInterval = null;
312
+ // for date axes...
313
+ axes[ax].daTickInterval = null;
314
+ axes[ax]._ticks = [];
315
+ }
316
+ }
317
+
318
+ // if ((c.constrainZoomTo == 'x' && ax.charAt(0) == 'y' && c.autoscaleConstraint) || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'x' && c.autoscaleConstraint)) {
319
+ // dp = datapos[ax];
320
+ // if (dp != null) {
321
+ // axes[ax].max == null;
322
+ // axes[ax].min = null;
323
+ // }
324
+ // }
325
+ }
326
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
327
+ plot.redraw();
328
+ c._zoom.isZoomed = true;
329
+ }
330
+ plot.target.trigger('jqplotZoom', [gridpos, datapos, plot, cursor]);
331
+ }
332
+ };
333
+
334
+ $.jqplot.preInitHooks.push($.jqplot.Cursor.init);
335
+ $.jqplot.postDrawHooks.push($.jqplot.Cursor.postDraw);
336
+
337
+ function updateTooltip(gridpos, datapos, plot) {
338
+ var c = plot.plugins.cursor;
339
+ var s = '';
340
+ var addbr = false;
341
+ if (c.showTooltipGridPosition) {
342
+ s = gridpos.x+', '+gridpos.y;
343
+ addbr = true;
344
+ }
345
+ if (c.showTooltipUnitPosition) {
346
+ var g;
347
+ for (var i=0; i<c.tooltipAxisGroups.length; i++) {
348
+ g = c.tooltipAxisGroups[i];
349
+ if (addbr) {
350
+ s += '<br />';
351
+ }
352
+ if (c.useAxesFormatters) {
353
+ var xf = plot.axes[g[0]]._ticks[0].formatter;
354
+ var yf = plot.axes[g[1]]._ticks[0].formatter;
355
+ var xfstr = plot.axes[g[0]]._ticks[0].formatString;
356
+ var yfstr = plot.axes[g[1]]._ticks[0].formatString;
357
+ s += xf(xfstr, datapos[g[0]]) + ', '+ yf(yfstr, datapos[g[1]]);
358
+ }
359
+ else {
360
+ s += $.jqplot.sprintf(c.tooltipFormatString, datapos[g[0]], datapos[g[1]]);
361
+ }
362
+ addbr = true;
363
+ }
364
+ }
365
+
366
+ if (c.showTooltipDataPosition) {
367
+ var series = plot.series;
368
+ var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y);
369
+ var addbr = false;
370
+
371
+ for (var i = 0; i< series.length; i++) {
372
+ if (series[i].show) {
373
+ var idx = series[i].index;
374
+ var label = series[i].label.toString();
375
+ var cellid = $.inArray(idx, ret.indices);
376
+ var sx = undefined;
377
+ var sy = undefined;
378
+ if (cellid != -1) {
379
+ var data = ret.data[cellid].data;
380
+ if (c.useAxesFormatters) {
381
+ var xf = series[i]._xaxis._ticks[0].formatter;
382
+ var yf = series[i]._yaxis._ticks[0].formatter;
383
+ var xfstr = series[i]._xaxis._ticks[0].formatString;
384
+ var yfstr = series[i]._yaxis._ticks[0].formatString;
385
+ sx = xf(xfstr, data[0]);
386
+ sy = yf(yfstr, data[1]);
387
+ }
388
+ else {
389
+ sx = data[0];
390
+ sy = data[1];
391
+ }
392
+ if (addbr) {
393
+ s += '<br />';
394
+ }
395
+ s += $.jqplot.sprintf(c.tooltipFormatString, label, sx, sy);
396
+ addbr = true;
397
+ }
398
+ }
399
+ }
400
+
401
+ }
402
+ c._tooltipElem.html(s);
403
+ }
404
+
405
+ function moveLine(gridpos, plot) {
406
+ var c = plot.plugins.cursor;
407
+ var ctx = c.cursorCanvas._ctx;
408
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
409
+ if (c.showVerticalLine) {
410
+ c.shapeRenderer.draw(ctx, [[gridpos.x, 0], [gridpos.x, ctx.canvas.height]]);
411
+ }
412
+ if (c.showHorizontalLine) {
413
+ c.shapeRenderer.draw(ctx, [[0, gridpos.y], [ctx.canvas.width, gridpos.y]]);
414
+ }
415
+ var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y);
416
+ if (c.showCursorLegend) {
417
+ var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label');
418
+ for (var i=0; i<cells.length; i++) {
419
+ var idx = $(cells[i]).data('seriesIndex');
420
+ var series = plot.series[idx];
421
+ var label = series.label.toString();
422
+ var cellid = $.inArray(idx, ret.indices);
423
+ var sx = undefined;
424
+ var sy = undefined;
425
+ if (cellid != -1) {
426
+ var data = ret.data[cellid].data;
427
+ if (c.useAxesFormatters) {
428
+ var xf = series._xaxis._ticks[0].formatter;
429
+ var yf = series._yaxis._ticks[0].formatter;
430
+ var xfstr = series._xaxis._ticks[0].formatString;
431
+ var yfstr = series._yaxis._ticks[0].formatString;
432
+ sx = xf(xfstr, data[0]);
433
+ sy = yf(yfstr, data[1]);
434
+ }
435
+ else {
436
+ sx = data[0];
437
+ sy = data[1];
438
+ }
439
+ }
440
+ if (plot.legend.escapeHtml) {
441
+ $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy));
442
+ }
443
+ else {
444
+ $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy));
445
+ }
446
+ }
447
+ }
448
+ }
449
+
450
+ function getIntersectingPoints(plot, x, y) {
451
+ var ret = {indices:[], data:[]};
452
+ var s, i, d0, d, j, r;
453
+ var threshold;
454
+ var c = plot.plugins.cursor;
455
+ for (var i=0; i<plot.series.length; i++) {
456
+ s = plot.series[i];
457
+ r = s.renderer;
458
+ if (s.show) {
459
+ threshold = c.intersectionThreshold;
460
+ if (s.showMarker) {
461
+ threshold += s.markerRenderer.size/2;
462
+ }
463
+ for (var j=0; j<s.gridData.length; j++) {
464
+ p = s.gridData[j];
465
+ // check vertical line
466
+ if (c.showVerticalLine) {
467
+ if (Math.abs(x-p[0]) <= threshold) {
468
+ ret.indices.push(i);
469
+ ret.data.push({seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]});
470
+ }
471
+ }
472
+ }
473
+ }
474
+ }
475
+ return ret;
476
+ }
477
+
478
+ function moveTooltip(gridpos, plot) {
479
+ var c = plot.plugins.cursor;
480
+ var elem = c._tooltipElem;
481
+ switch (c.tooltipLocation) {
482
+ case 'nw':
483
+ var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
484
+ var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
485
+ break;
486
+ case 'n':
487
+ var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;
488
+ var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
489
+ break;
490
+ case 'ne':
491
+ var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
492
+ var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);
493
+ break;
494
+ case 'e':
495
+ var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
496
+ var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;
497
+ break;
498
+ case 'se':
499
+ var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
500
+ var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
501
+ break;
502
+ case 's':
503
+ var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;
504
+ var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
505
+ break;
506
+ case 'sw':
507
+ var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
508
+ var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
509
+ break;
510
+ case 'w':
511
+ var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;
512
+ var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;
513
+ break;
514
+ default:
515
+ var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;
516
+ var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;
517
+ break;
518
+ }
519
+
520
+ c._tooltipElem.css('left', x);
521
+ c._tooltipElem.css('top', y);
522
+ }
523
+
524
+ function positionTooltip(plot) {
525
+ // fake a grid for positioning
526
+ var grid = plot._gridPadding;
527
+ var c = plot.plugins.cursor;
528
+ var elem = c._tooltipElem;
529
+ switch (c.tooltipLocation) {
530
+ case 'nw':
531
+ var a = grid.left + c.tooltipOffset;
532
+ var b = grid.top + c.tooltipOffset;
533
+ elem.css('left', a);
534
+ elem.css('top', b);
535
+ break;
536
+ case 'n':
537
+ var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2;
538
+ var b = grid.top + c.tooltipOffset;
539
+ elem.css('left', a);
540
+ elem.css('top', b);
541
+ break;
542
+ case 'ne':
543
+ var a = grid.right + c.tooltipOffset;
544
+ var b = grid.top + c.tooltipOffset;
545
+ elem.css({right:a, top:b});
546
+ break;
547
+ case 'e':
548
+ var a = grid.right + c.tooltipOffset;
549
+ var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2;
550
+ elem.css({right:a, top:b});
551
+ break;
552
+ case 'se':
553
+ var a = grid.right + c.tooltipOffset;
554
+ var b = grid.bottom + c.tooltipOffset;
555
+ elem.css({right:a, bottom:b});
556
+ break;
557
+ case 's':
558
+ var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2;
559
+ var b = grid.bottom + c.tooltipOffset;
560
+ elem.css({left:a, bottom:b});
561
+ break;
562
+ case 'sw':
563
+ var a = grid.left + c.tooltipOffset;
564
+ var b = grid.bottom + c.tooltipOffset;
565
+ elem.css({left:a, bottom:b});
566
+ break;
567
+ case 'w':
568
+ var a = grid.left + c.tooltipOffset;
569
+ var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2;
570
+ elem.css({left:a, top:b});
571
+ break;
572
+ default: // same as 'se'
573
+ var a = grid.right - c.tooltipOffset;
574
+ var b = grid.bottom + c.tooltipOffset;
575
+ elem.css({right:a, bottom:b});
576
+ break;
577
+ }
578
+ }
579
+
580
+ function handleClick (ev, gridpos, datapos, neighbor, plot) {
581
+ ev.stopPropagation();
582
+ ev.preventDefault();
583
+ var c = plot.plugins.cursor;
584
+ if (c.clickReset) {
585
+ c.resetZoom(plot, c);
586
+ }
587
+ return false;
588
+ }
589
+
590
+ function handleDblClick (ev, gridpos, datapos, neighbor, plot) {
591
+ ev.stopPropagation();
592
+ ev.preventDefault();
593
+ var c = plot.plugins.cursor;
594
+ if (c.dblClickReset) {
595
+ c.resetZoom(plot, c);
596
+ }
597
+ return false;
598
+ }
599
+
600
+ function handleMouseLeave(ev, gridpos, datapos, neighbor, plot) {
601
+ var c = plot.plugins.cursor;
602
+ if (c.show) {
603
+ $(ev.target).css('cursor', c.previousCursor);
604
+ if (c.showTooltip) {
605
+ c._tooltipElem.hide();
606
+ }
607
+ if (c.zoom) {
608
+ c._zoom.started = false;
609
+ c._zoom.zooming = false;
610
+ if (!c.zoomProxy) {
611
+ var ctx = c.zoomCanvas._ctx;
612
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
613
+ }
614
+ }
615
+ if (c.showVerticalLine || c.showHorizontalLine) {
616
+ var ctx = c.cursorCanvas._ctx;
617
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
618
+ } if (c.showCursorLegend) {
619
+ var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label');
620
+ for (var i=0; i<cells.length; i++) {
621
+ var idx = $(cells[i]).data('seriesIndex');
622
+ var series = plot.series[idx];
623
+ var label = series.label.toString();
624
+ if (plot.legend.escapeHtml) {
625
+ $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined));
626
+ }
627
+ else {
628
+ $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined));
629
+ }
630
+
631
+ }
632
+ }
633
+ }
634
+ }
635
+
636
+ function handleMouseEnter(ev, gridpos, datapos, neighbor, plot) {
637
+ var c = plot.plugins.cursor;
638
+ if (c.show) {
639
+ c.previousCursor = ev.target.style.cursor;
640
+ ev.target.style.cursor = c.style;
641
+ if (c.showTooltip) {
642
+ updateTooltip(gridpos, datapos, plot);
643
+ if (c.followMouse) {
644
+ moveTooltip(gridpos, plot);
645
+ }
646
+ else {
647
+ positionTooltip(plot);
648
+ }
649
+ c._tooltipElem.show();
650
+ }
651
+ if (c.showVerticalLine || c.showHorizontalLine) {
652
+ moveLine(gridpos, plot);
653
+ }
654
+ }
655
+ }
656
+
657
+ function handleMouseMove(ev, gridpos, datapos, neighbor, plot) {
658
+ var c = plot.plugins.cursor;
659
+ var ctx = c.zoomCanvas._ctx;
660
+ if (c.show) {
661
+ if (c.showTooltip) {
662
+ updateTooltip(gridpos, datapos, plot);
663
+ if (c.followMouse) {
664
+ moveTooltip(gridpos, plot);
665
+ }
666
+ }
667
+ if (c.zoom && c._zoom.started && !c.zoomTarget) {
668
+ c._zoom.zooming = true;
669
+ if (c.constrainZoomTo == 'x') {
670
+ c._zoom.end = [gridpos.x, ctx.canvas.height];
671
+ }
672
+ else if (c.constrainZoomTo == 'y') {
673
+ c._zoom.end = [ctx.canvas.width, gridpos.y];
674
+ }
675
+ else {
676
+ c._zoom.end = [gridpos.x, gridpos.y];
677
+ }
678
+ drawZoomBox.call(c);
679
+ }
680
+ if (c.showVerticalLine || c.showHorizontalLine) {
681
+ moveLine(gridpos, plot);
682
+ }
683
+ }
684
+ }
685
+
686
+ function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {
687
+ var c = plot.plugins.cursor;
688
+ var axes = plot.axes;
689
+ if (c.zoom) {
690
+ if (!c.zoomProxy) {
691
+ var ctx = c.zoomCanvas._ctx;
692
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
693
+ }
694
+ if (c.constrainZoomTo == 'x') {
695
+ c._zoom.start = [gridpos.x, 0];
696
+ }
697
+ else if (c.constrainZoomTo == 'y') {
698
+ c._zoom.start = [0, gridpos.y];
699
+ }
700
+ else {
701
+ c._zoom.start = [gridpos.x, gridpos.y];
702
+ }
703
+ c._zoom.started = true;
704
+ for (var ax in datapos) {
705
+ // get zoom starting position.
706
+ c._zoom.axes.start[ax] = datapos[ax];
707
+ }
708
+ }
709
+ }
710
+
711
+ function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {
712
+ var c = plot.plugins.cursor;
713
+ if (c.zoom && c._zoom.zooming && !c.zoomTarget) {
714
+ c.doZoom(gridpos, datapos, plot, c);
715
+ }
716
+ c._zoom.started = false;
717
+ c._zoom.zooming = false;
718
+ }
719
+
720
+ function drawZoomBox() {
721
+ var start = this._zoom.start;
722
+ var end = this._zoom.end;
723
+ var ctx = this.zoomCanvas._ctx;
724
+ var l, t, h, w;
725
+ if (end[0] > start[0]) {
726
+ l = start[0];
727
+ w = end[0] - start[0];
728
+ }
729
+ else {
730
+ l = end[0];
731
+ w = start[0] - end[0];
732
+ }
733
+ if (end[1] > start[1]) {
734
+ t = start[1];
735
+ h = end[1] - start[1];
736
+ }
737
+ else {
738
+ t = end[1];
739
+ h = start[1] - end[1];
740
+ }
741
+ ctx.fillStyle = 'rgba(0,0,0,0.2)';
742
+ ctx.strokeStyle = '#999999';
743
+ ctx.lineWidth = 1.0;
744
+ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
745
+ ctx.fillRect(0,0,ctx.canvas.width, ctx.canvas.height);
746
+ ctx.clearRect(l, t, w, h);
747
+ // IE won't show transparent fill rect, so stroke a rect also.
748
+ ctx.strokeRect(l,t,w,h);
749
+ }
750
+
751
+ $.jqplot.CursorLegendRenderer = function(options) {
752
+ $.jqplot.TableLegendRenderer.call(this, options);
753
+ this.formatString = '%s';
754
+ };
755
+
756
+ $.jqplot.CursorLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();
757
+ $.jqplot.CursorLegendRenderer.prototype.constructor = $.jqplot.CursorLegendRenderer;
758
+
759
+ // called in context of a Legend
760
+ $.jqplot.CursorLegendRenderer.prototype.draw = function() {
761
+ if (this.show) {
762
+ var series = this._series;
763
+ // make a table. one line label per row.
764
+ this._elem = $('<table class="jqplot-legend jqplot-cursor-legend" style="position:absolute"></table>');
765
+
766
+ var pad = false;
767
+ for (var i = 0; i< series.length; i++) {
768
+ s = series[i];
769
+ if (s.show) {
770
+ var lt = $.jqplot.sprintf(this.formatString, s.label.toString());
771
+ if (lt) {
772
+ var color = s.color;
773
+ if (s._stack && !s.fill) {
774
+ color = '';
775
+ }
776
+ addrow.call(this, lt, color, pad, i);
777
+ pad = true;
778
+ }
779
+ // let plugins add more rows to legend. Used by trend line plugin.
780
+ for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) {
781
+ var item = $.jqplot.addLegendRowHooks[j].call(this, s);
782
+ if (item) {
783
+ addrow.call(this, item.label, item.color, pad);
784
+ pad = true;
785
+ }
786
+ }
787
+ }
788
+ }
789
+ }
790
+
791
+ function addrow(label, color, pad, idx) {
792
+ var rs = (pad) ? this.rowSpacing : '0';
793
+ var tr = $('<tr class="jqplot-legend jqplot-cursor-legend"></tr>').appendTo(this._elem);
794
+ tr.data('seriesIndex', idx);
795
+ $('<td class="jqplot-legend jqplot-cursor-legend-swatch" style="padding-top:'+rs+';">'+
796
+ '<div style="border:1px solid #cccccc;padding:0.2em;">'+
797
+ '<div class="jqplot-cursor-legend-swatch" style="background-color:'+color+';"></div>'+
798
+ '</div></td>').appendTo(tr);
799
+ var td = $('<td class="jqplot-legend jqplot-cursor-legend-label" style="vertical-align:middle;padding-top:'+rs+';"></td>');
800
+ td.appendTo(tr);
801
+ td.data('seriesIndex', idx);
802
+ if (this.escapeHtml) {
803
+ td.text(label);
804
+ }
805
+ else {
806
+ td.html(label);
807
+ }
808
+ }
809
+ return this._elem;
810
+ };
811
+
812
+ })(jQuery);