Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3284 vikas 1
/*
2
Flot plugin for adding panning and zooming capabilities to a plot.
3
 
4
The default behaviour is double click and scrollwheel up/down to zoom
5
in, drag to pan. The plugin defines plot.zoom({ center }),
6
plot.zoomOut() and plot.pan(offset) so you easily can add custom
7
controls. It also fires a "plotpan" and "plotzoom" event when
8
something happens, useful for synchronizing plots.
9
 
10
Options:
11
 
12
  zoom: {
13
    interactive: false
14
    trigger: "dblclick" // or "click" for single click
15
    amount: 1.5         // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
16
  }
17
 
18
  pan: {
19
    interactive: false
20
    cursor: "move"      // CSS mouse cursor value used when dragging, e.g. "pointer"
21
    frameRate: 20
22
  }
23
 
24
  xaxis, yaxis, x2axis, y2axis: {
25
    zoomRange: null  // or [number, number] (min range, max range) or false
26
    panRange: null   // or [number, number] (min, max) or false
27
  }
28
 
29
"interactive" enables the built-in drag/click behaviour. If you enable
30
interactive for pan, then you'll have a basic plot that supports
31
moving around; the same for zoom.
32
 
33
"amount" specifies the default amount to zoom in (so 1.5 = 150%)
34
relative to the current viewport.
35
 
36
"cursor" is a standard CSS mouse cursor string used for visual
37
feedback to the user when dragging.
38
 
39
"frameRate" specifies the maximum number of times per second the plot
40
will update itself while the user is panning around on it (set to null
41
to disable intermediate pans, the plot will then not update until the
42
mouse button is released).
43
 
44
"zoomRange" is the interval in which zooming can happen, e.g. with
45
zoomRange: [1, 100] the zoom will never scale the axis so that the
46
difference between min and max is smaller than 1 or larger than 100.
47
You can set either end to null to ignore, e.g. [1, null]. If you set
48
zoomRange to false, zooming on that axis will be disabled.
49
 
50
"panRange" confines the panning to stay within a range, e.g. with
51
panRange: [-10, 20] panning stops at -10 in one end and at 20 in the
52
other. Either can be null, e.g. [-10, null]. If you set
53
panRange to false, panning on that axis will be disabled.
54
 
55
Example API usage:
56
 
57
  plot = $.plot(...);
58
 
59
  // zoom default amount in on the pixel (10, 20) 
60
  plot.zoom({ center: { left: 10, top: 20 } });
61
 
62
  // zoom out again
63
  plot.zoomOut({ center: { left: 10, top: 20 } });
64
 
65
  // zoom 200% in on the pixel (10, 20) 
66
  plot.zoom({ amount: 2, center: { left: 10, top: 20 } });
67
 
68
  // pan 100 pixels to the left and 20 down
69
  plot.pan({ left: -100, top: 20 })
70
 
71
Here, "center" specifies where the center of the zooming should
72
happen. Note that this is defined in pixel space, not the space of the
73
data points (you can use the p2c helpers on the axes in Flot to help
74
you convert between these).
75
 
76
"amount" is the amount to zoom the viewport relative to the current
77
range, so 1 is 100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is
78
70% (zoom out). You can set the default in the options.
79
 
80
*/
81
 
82
 
83
// First two dependencies, jquery.event.drag.js and
84
// jquery.mousewheel.js, we put them inline here to save people the
85
// effort of downloading them.
86
 
87
/*
88
jquery.event.drag.js ~ v1.5 ~ Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)  
89
Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-LICENSE.txt
90
*/
91
(function(E){E.fn.drag=function(L,K,J){if(K){this.bind("dragstart",L)}if(J){this.bind("dragend",J)}return !L?this.trigger("drag"):this.bind("drag",K?K:L)};var A=E.event,B=A.special,F=B.drag={not:":input",distance:0,which:1,dragging:false,setup:function(J){J=E.extend({distance:F.distance,which:F.which,not:F.not},J||{});J.distance=I(J.distance);A.add(this,"mousedown",H,J);if(this.attachEvent){this.attachEvent("ondragstart",D)}},teardown:function(){A.remove(this,"mousedown",H);if(this===F.dragging){F.dragging=F.proxy=false}G(this,true);if(this.detachEvent){this.detachEvent("ondragstart",D)}}};B.dragstart=B.dragend={setup:function(){},teardown:function(){}};function H(L){var K=this,J,M=L.data||{};if(M.elem){K=L.dragTarget=M.elem;L.dragProxy=F.proxy||K;L.cursorOffsetX=M.pageX-M.left;L.cursorOffsetY=M.pageY-M.top;L.offsetX=L.pageX-L.cursorOffsetX;L.offsetY=L.pageY-L.cursorOffsetY}else{if(F.dragging||(M.which>0&&L.which!=M.which)||E(L.target).is(M.not)){return }}switch(L.type){case"mousedown":E.extend(M,E(K).offset(),{elem:K,target:L.target,pageX:L.pageX,pageY:L.pageY});A.add(document,"mousemove mouseup",H,M);G(K,false);F.dragging=null;return false;case !F.dragging&&"mousemove":if(I(L.pageX-M.pageX)+I(L.pageY-M.pageY)<M.distance){break}L.target=M.target;J=C(L,"dragstart",K);if(J!==false){F.dragging=K;F.proxy=L.dragProxy=E(J||K)[0]}case"mousemove":if(F.dragging){J=C(L,"drag",K);if(B.drop){B.drop.allowed=(J!==false);B.drop.handler(L)}if(J!==false){break}L.type="mouseup"}case"mouseup":A.remove(document,"mousemove mouseup",H);if(F.dragging){if(B.drop){B.drop.handler(L)}C(L,"dragend",K)}G(K,true);F.dragging=F.proxy=M.elem=false;break}return true}function C(M,K,L){M.type=K;var J=E.event.handle.call(L,M);return J===false?false:J||M.result}function I(J){return Math.pow(J,2)}function D(){return(F.dragging===false)}function G(K,J){if(!K){return }K.unselectable=J?"off":"on";K.onselectstart=function(){return J};if(K.style){K.style.MozUserSelect=J?"":"none"}}})(jQuery);
92
 
93
 
94
/* jquery.mousewheel.min.js
95
 * Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
96
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
97
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
98
 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
99
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
100
 *
101
 * Version: 3.0.2
102
 * 
103
 * Requires: 1.2.2+
104
 */
105
(function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery);
106
 
107
 
108
 
109
 
110
(function ($) {
111
    var options = {
112
        xaxis: {
113
            zoomRange: null, // or [number, number] (min range, max range)
114
            panRange: null // or [number, number] (min, max)
115
        },
116
        zoom: {
117
            interactive: false,
118
            trigger: "dblclick", // or "click" for single click
119
            amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
120
        },
121
        pan: {
122
            interactive: false,
123
            cursor: "move",
124
            frameRate: 20
125
        }
126
    };
127
 
128
    function init(plot) {
129
        function onZoomClick(e, zoomOut) {
130
            var c = plot.offset();
131
            c.left = e.pageX - c.left;
132
            c.top = e.pageY - c.top;
133
            if (zoomOut)
134
                plot.zoomOut({ center: c });
135
            else
136
                plot.zoom({ center: c });
137
        }
138
 
139
        function onMouseWheel(e, delta) {
140
            onZoomClick(e, delta < 0);
141
            return false;
142
        }
143
 
144
        var prevCursor = 'default', prevPageX = 0, prevPageY = 0,
145
            panTimeout = null;
146
 
147
        function onDragStart(e) {
148
            if (e.which != 1)  // only accept left-click
149
                return false;
150
            var c = plot.getPlaceholder().css('cursor');
151
            if (c)
152
                prevCursor = c;
153
            plot.getPlaceholder().css('cursor', plot.getOptions().pan.cursor);
154
            prevPageX = e.pageX;
155
            prevPageY = e.pageY;
156
        }
157
 
158
        function onDrag(e) {
159
            var frameRate = plot.getOptions().pan.frameRate;
160
            if (panTimeout || !frameRate)
161
                return;
162
 
163
            panTimeout = setTimeout(function () {
164
                plot.pan({ left: prevPageX - e.pageX,
165
                           top: prevPageY - e.pageY });
166
                prevPageX = e.pageX;
167
                prevPageY = e.pageY;
168
 
169
                panTimeout = null;
170
            }, 1 / frameRate * 1000);
171
        }
172
 
173
        function onDragEnd(e) {
174
            if (panTimeout) {
175
                clearTimeout(panTimeout);
176
                panTimeout = null;
177
            }
178
 
179
            plot.getPlaceholder().css('cursor', prevCursor);
180
            plot.pan({ left: prevPageX - e.pageX,
181
                       top: prevPageY - e.pageY });
182
        }
183
 
184
        function bindEvents(plot, eventHolder) {
185
            var o = plot.getOptions();
186
            if (o.zoom.interactive) {
187
                eventHolder[o.zoom.trigger](onZoomClick);
188
                eventHolder.mousewheel(onMouseWheel);
189
            }
190
 
191
            if (o.pan.interactive) {
192
                eventHolder.bind("dragstart", { distance: 10 }, onDragStart);
193
                eventHolder.bind("drag", onDrag);
194
                eventHolder.bind("dragend", onDragEnd);
195
            }
196
        }
197
 
198
        plot.zoomOut = function (args) {
199
            if (!args)
200
                args = {};
201
 
202
            if (!args.amount)
203
                args.amount = plot.getOptions().zoom.amount
204
 
205
            args.amount = 1 / args.amount;
206
            plot.zoom(args);
207
        }
208
 
209
        plot.zoom = function (args) {
210
            if (!args)
211
                args = {};
212
 
213
            var c = args.center,
214
                amount = args.amount || plot.getOptions().zoom.amount,
215
                w = plot.width(), h = plot.height();
216
 
217
            if (!c)
218
                c = { left: w / 2, top: h / 2 };
219
 
220
            var xf = c.left / w,
221
                yf = c.top / h,
222
                minmax = {
223
                    x: {
224
                        min: c.left - xf * w / amount,
225
                        max: c.left + (1 - xf) * w / amount
226
                    },
227
                    y: {
228
                        min: c.top - yf * h / amount,
229
                        max: c.top + (1 - yf) * h / amount
230
                    }
231
                };
232
 
233
            $.each(plot.getAxes(), function(_, axis) {
234
                var opts = axis.options,
235
                    min = minmax[axis.direction].min,
236
                    max = minmax[axis.direction].max,
237
                    zr = opts.zoomRange;
238
 
239
                if (zr === false) // no zooming on this axis
240
                    return;
241
 
242
                min = axis.c2p(min);
243
                max = axis.c2p(max);
244
                if (min > max) {
245
                    // make sure min < max
246
                    var tmp = min;
247
                    min = max;
248
                    max = tmp;
249
                }
250
 
251
                var range = max - min;
252
                if (zr &&
253
                    ((zr[0] != null && range < zr[0]) ||
254
                     (zr[1] != null && range > zr[1])))
255
                    return;
256
 
257
                opts.min = min;
258
                opts.max = max;
259
            });
260
 
261
            plot.setupGrid();
262
            plot.draw();
263
 
264
            if (!args.preventEvent)
265
                plot.getPlaceholder().trigger("plotzoom", [ plot ]);
266
        }
267
 
268
        plot.pan = function (args) {
269
            var delta = {
270
                x: +args.left,
271
                y: +args.top
272
            };
273
 
274
            if (isNaN(delta.x))
275
                delta.x = 0;
276
            if (isNaN(delta.y))
277
                delta.y = 0;
278
 
279
            $.each(plot.getAxes(), function (_, axis) {
280
                var opts = axis.options,
281
                    min, max, d = delta[axis.direction];
282
 
283
                min = axis.c2p(axis.p2c(axis.min) + d),
284
                max = axis.c2p(axis.p2c(axis.max) + d);
285
 
286
                var pr = opts.panRange;
287
                if (pr === false) // no panning on this axis
288
                    return;
289
 
290
                if (pr) {
291
                    // check whether we hit the wall
292
                    if (pr[0] != null && pr[0] > min) {
293
                        d = pr[0] - min;
294
                        min += d;
295
                        max += d;
296
                    }
297
 
298
                    if (pr[1] != null && pr[1] < max) {
299
                        d = pr[1] - max;
300
                        min += d;
301
                        max += d;
302
                    }
303
                }
304
 
305
                opts.min = min;
306
                opts.max = max;
307
            });
308
 
309
            plot.setupGrid();
310
            plot.draw();
311
 
312
            if (!args.preventEvent)
313
                plot.getPlaceholder().trigger("plotpan", [ plot ]);
314
        }
315
 
316
        function shutdown(plot, eventHolder) {
317
            eventHolder.unbind(plot.getOptions().zoom.trigger, onZoomClick);
318
            eventHolder.unbind("mousewheel", onMouseWheel);
319
            eventHolder.unbind("dragstart", onDragStart);
320
            eventHolder.unbind("drag", onDrag);
321
            eventHolder.unbind("dragend", onDragEnd);
322
            if (panTimeout)
323
                clearTimeout(panTimeout);
324
        }
325
 
326
        plot.hooks.bindEvents.push(bindEvents);
327
        plot.hooks.shutdown.push(shutdown);
328
    }
329
 
330
    $.plot.plugins.push({
331
        init: init,
332
        options: options,
333
        name: 'navigate',
334
        version: '1.3'
335
    });
336
})(jQuery);