1 | /** |
---|
2 | * jqPlot |
---|
3 | * Pure JavaScript plotting plugin using jQuery |
---|
4 | * |
---|
5 | * Version: @VERSION |
---|
6 | * |
---|
7 | * Copyright (c) 2009-2011 Chris Leonello |
---|
8 | * jqPlot is currently available for use in all personal or commercial projects |
---|
9 | * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL |
---|
10 | * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can |
---|
11 | * choose the license that best suits your project and use it accordingly. |
---|
12 | * |
---|
13 | * Although not required, the author would appreciate an email letting him |
---|
14 | * know of any substantial use of jqPlot. You can reach the author at: |
---|
15 | * chris at jqplot dot com or see http://www.jqplot.com/info.php . |
---|
16 | * |
---|
17 | * If you are feeling kind and generous, consider supporting the project by |
---|
18 | * making a donation at: http://www.jqplot.com/donate.php . |
---|
19 | * |
---|
20 | * sprintf functions contained in jqplot.sprintf.js by Ash Searle: |
---|
21 | * |
---|
22 | * version 2007.04.27 |
---|
23 | * author Ash Searle |
---|
24 | * http://hexmen.com/blog/2007/03/printf-sprintf/ |
---|
25 | * http://hexmen.com/js/sprintf.js |
---|
26 | * The author (Ash Searle) has placed this code in the public domain: |
---|
27 | * "This code is unrestricted: you are free to use it however you like." |
---|
28 | * |
---|
29 | */ |
---|
30 | (function($) { |
---|
31 | |
---|
32 | /** |
---|
33 | * Class: $.jqplot.Dragable |
---|
34 | * Plugin to make plotted points dragable by the user. |
---|
35 | */ |
---|
36 | $.jqplot.Dragable = function(options) { |
---|
37 | // Group: Properties |
---|
38 | this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false}); |
---|
39 | this.shapeRenderer = new $.jqplot.ShapeRenderer(); |
---|
40 | this.isDragging = false; |
---|
41 | this.isOver = false; |
---|
42 | this._ctx; |
---|
43 | this._elem; |
---|
44 | this._point; |
---|
45 | this._gridData; |
---|
46 | // prop: color |
---|
47 | // CSS color spec for the dragged point (and adjacent line segment or bar). |
---|
48 | this.color; |
---|
49 | // prop: constrainTo |
---|
50 | // Constrain dragging motion to an axis or to none. |
---|
51 | // Allowable values are 'none', 'x', 'y' |
---|
52 | this.constrainTo = 'none'; // 'x', 'y', or 'none'; |
---|
53 | $.extend(true, this, options); |
---|
54 | }; |
---|
55 | |
---|
56 | function DragCanvas() { |
---|
57 | $.jqplot.GenericCanvas.call(this); |
---|
58 | this.isDragging = false; |
---|
59 | this.isOver = false; |
---|
60 | this._neighbor; |
---|
61 | this._cursors = []; |
---|
62 | } |
---|
63 | |
---|
64 | DragCanvas.prototype = new $.jqplot.GenericCanvas(); |
---|
65 | DragCanvas.prototype.constructor = DragCanvas; |
---|
66 | |
---|
67 | |
---|
68 | // called within scope of series |
---|
69 | $.jqplot.Dragable.parseOptions = function (defaults, opts) { |
---|
70 | var options = opts || {}; |
---|
71 | this.plugins.dragable = new $.jqplot.Dragable(options.dragable); |
---|
72 | // since this function is called before series options are parsed, |
---|
73 | // we can set this here and it will be overridden if needed. |
---|
74 | this.isDragable = $.jqplot.config.enablePlugins; |
---|
75 | }; |
---|
76 | |
---|
77 | // called within context of plot |
---|
78 | // create a canvas which we can draw on. |
---|
79 | // insert it before the eventCanvas, so eventCanvas will still capture events. |
---|
80 | // add a new DragCanvas object to the plot plugins to handle drawing on this new canvas. |
---|
81 | $.jqplot.Dragable.postPlotDraw = function() { |
---|
82 | // Memory Leaks patch |
---|
83 | if (this.plugins.dragable && this.plugins.dragable.highlightCanvas) { |
---|
84 | this.plugins.dragable.highlightCanvas.resetCanvas(); |
---|
85 | this.plugins.dragable.highlightCanvas = null; |
---|
86 | } |
---|
87 | |
---|
88 | this.plugins.dragable = {previousCursor:'auto', isOver:false}; |
---|
89 | this.plugins.dragable.dragCanvas = new DragCanvas(); |
---|
90 | |
---|
91 | this.eventCanvas._elem.before(this.plugins.dragable.dragCanvas.createElement(this._gridPadding, 'jqplot-dragable-canvas', this._plotDimensions, this)); |
---|
92 | var dctx = this.plugins.dragable.dragCanvas.setContext(); |
---|
93 | }; |
---|
94 | |
---|
95 | //$.jqplot.preInitHooks.push($.jqplot.Dragable.init); |
---|
96 | $.jqplot.preParseSeriesOptionsHooks.push($.jqplot.Dragable.parseOptions); |
---|
97 | $.jqplot.postDrawHooks.push($.jqplot.Dragable.postPlotDraw); |
---|
98 | $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]); |
---|
99 | $.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleDown]); |
---|
100 | $.jqplot.eventListenerHooks.push(['jqplotMouseUp', handleUp]); |
---|
101 | |
---|
102 | |
---|
103 | function initDragPoint(plot, neighbor) { |
---|
104 | var s = plot.series[neighbor.seriesIndex]; |
---|
105 | var drag = s.plugins.dragable; |
---|
106 | |
---|
107 | // first, init the mark renderer for the dragged point |
---|
108 | var smr = s.markerRenderer; |
---|
109 | var mr = drag.markerRenderer; |
---|
110 | mr.style = smr.style; |
---|
111 | mr.lineWidth = smr.lineWidth + 2.5; |
---|
112 | mr.size = smr.size + 5; |
---|
113 | if (!drag.color) { |
---|
114 | var rgba = $.jqplot.getColorComponents(smr.color); |
---|
115 | var newrgb = [rgba[0], rgba[1], rgba[2]]; |
---|
116 | var alpha = (rgba[3] >= 0.6) ? rgba[3]*0.6 : rgba[3]*(2-rgba[3]); |
---|
117 | drag.color = 'rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+alpha+')'; |
---|
118 | } |
---|
119 | mr.color = drag.color; |
---|
120 | mr.init(); |
---|
121 | |
---|
122 | var start = (neighbor.pointIndex > 0) ? neighbor.pointIndex - 1 : 0; |
---|
123 | var end = neighbor.pointIndex+2; |
---|
124 | drag._gridData = s.gridData.slice(start, end); |
---|
125 | } |
---|
126 | |
---|
127 | function handleMove(ev, gridpos, datapos, neighbor, plot) { |
---|
128 | if (plot.plugins.dragable.dragCanvas.isDragging) { |
---|
129 | var dc = plot.plugins.dragable.dragCanvas; |
---|
130 | var dp = dc._neighbor; |
---|
131 | var s = plot.series[dp.seriesIndex]; |
---|
132 | var drag = s.plugins.dragable; |
---|
133 | var gd = s.gridData; |
---|
134 | |
---|
135 | // compute the new grid position with any constraints. |
---|
136 | var x = (drag.constrainTo == 'y') ? dp.gridData[0] : gridpos.x; |
---|
137 | var y = (drag.constrainTo == 'x') ? dp.gridData[1] : gridpos.y; |
---|
138 | |
---|
139 | // compute data values for any listeners. |
---|
140 | var xu = s._xaxis.series_p2u(x); |
---|
141 | var yu = s._yaxis.series_p2u(y); |
---|
142 | |
---|
143 | // clear the canvas then redraw effect at new position. |
---|
144 | var ctx = dc._ctx; |
---|
145 | ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); |
---|
146 | |
---|
147 | // adjust our gridData for the new mouse position |
---|
148 | if (dp.pointIndex > 0) { |
---|
149 | drag._gridData[1] = [x, y]; |
---|
150 | } |
---|
151 | else { |
---|
152 | drag._gridData[0] = [x, y]; |
---|
153 | } |
---|
154 | plot.series[dp.seriesIndex].draw(dc._ctx, {gridData:drag._gridData, shadow:false, preventJqPlotSeriesDrawTrigger:true, color:drag.color, markerOptions:{color:drag.color, shadow:false}, trendline:{show:false}}); |
---|
155 | plot.target.trigger('jqplotSeriesPointChange', [dp.seriesIndex, dp.pointIndex, [xu,yu], [x,y]]); |
---|
156 | } |
---|
157 | else if (neighbor != null) { |
---|
158 | var series = plot.series[neighbor.seriesIndex]; |
---|
159 | if (series.isDragable) { |
---|
160 | var dc = plot.plugins.dragable.dragCanvas; |
---|
161 | if (!dc.isOver) { |
---|
162 | dc._cursors.push(ev.target.style.cursor); |
---|
163 | ev.target.style.cursor = "pointer"; |
---|
164 | } |
---|
165 | dc.isOver = true; |
---|
166 | } |
---|
167 | } |
---|
168 | else if (neighbor == null) { |
---|
169 | var dc = plot.plugins.dragable.dragCanvas; |
---|
170 | if (dc.isOver) { |
---|
171 | ev.target.style.cursor = dc._cursors.pop(); |
---|
172 | dc.isOver = false; |
---|
173 | } |
---|
174 | } |
---|
175 | } |
---|
176 | |
---|
177 | function handleDown(ev, gridpos, datapos, neighbor, plot) { |
---|
178 | var dc = plot.plugins.dragable.dragCanvas; |
---|
179 | dc._cursors.push(ev.target.style.cursor); |
---|
180 | if (neighbor != null) { |
---|
181 | var s = plot.series[neighbor.seriesIndex]; |
---|
182 | var drag = s.plugins.dragable; |
---|
183 | if (s.isDragable && !dc.isDragging) { |
---|
184 | dc._neighbor = neighbor; |
---|
185 | dc.isDragging = true; |
---|
186 | initDragPoint(plot, neighbor); |
---|
187 | drag.markerRenderer.draw(s.gridData[neighbor.pointIndex][0], s.gridData[neighbor.pointIndex][1], dc._ctx); |
---|
188 | ev.target.style.cursor = "move"; |
---|
189 | plot.target.trigger('jqplotDragStart', [neighbor.seriesIndex, neighbor.pointIndex, gridpos, datapos]); |
---|
190 | } |
---|
191 | } |
---|
192 | // Just in case of a hickup, we'll clear the drag canvas and reset. |
---|
193 | else { |
---|
194 | var ctx = dc._ctx; |
---|
195 | ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); |
---|
196 | dc.isDragging = false; |
---|
197 | } |
---|
198 | } |
---|
199 | |
---|
200 | function handleUp(ev, gridpos, datapos, neighbor, plot) { |
---|
201 | if (plot.plugins.dragable.dragCanvas.isDragging) { |
---|
202 | var dc = plot.plugins.dragable.dragCanvas; |
---|
203 | // clear the canvas |
---|
204 | var ctx = dc._ctx; |
---|
205 | ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); |
---|
206 | dc.isDragging = false; |
---|
207 | // redraw the series canvas at the new point. |
---|
208 | var dp = dc._neighbor; |
---|
209 | var s = plot.series[dp.seriesIndex]; |
---|
210 | var drag = s.plugins.dragable; |
---|
211 | // compute the new grid position with any constraints. |
---|
212 | var x = (drag.constrainTo == 'y') ? dp.data[0] : datapos[s.xaxis]; |
---|
213 | var y = (drag.constrainTo == 'x') ? dp.data[1] : datapos[s.yaxis]; |
---|
214 | // var x = datapos[s.xaxis]; |
---|
215 | // var y = datapos[s.yaxis]; |
---|
216 | s.data[dp.pointIndex][0] = x; |
---|
217 | s.data[dp.pointIndex][1] = y; |
---|
218 | plot.drawSeries({preventJqPlotSeriesDrawTrigger:true}, dp.seriesIndex); |
---|
219 | dc._neighbor = null; |
---|
220 | ev.target.style.cursor = dc._cursors.pop(); |
---|
221 | plot.target.trigger('jqplotDragStop', [gridpos, datapos]); |
---|
222 | } |
---|
223 | } |
---|
224 | })(jQuery); |
---|