[9062] | 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); |
---|