1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 | (function($) {
|
105 | 'use strict';
|
106 |
|
107 | var options = {
|
108 | zoom: {
|
109 | interactive: false,
|
110 | active: false,
|
111 | amount: 1.5
|
112 | },
|
113 | pan: {
|
114 | interactive: false,
|
115 | active: false,
|
116 | cursor: "move",
|
117 | frameRate: 60,
|
118 | mode: 'smart'
|
119 | },
|
120 | recenter: {
|
121 | interactive: true
|
122 | },
|
123 | xaxis: {
|
124 | axisZoom: true,
|
125 | plotZoom: true,
|
126 | axisPan: true,
|
127 | plotPan: true
|
128 | },
|
129 | yaxis: {
|
130 | axisZoom: true,
|
131 | plotZoom: true,
|
132 | axisPan: true,
|
133 | plotPan: true
|
134 | }
|
135 | };
|
136 |
|
137 | var saturated = $.plot.saturated;
|
138 | var browser = $.plot.browser;
|
139 | var SNAPPING_CONSTANT = $.plot.uiConstants.SNAPPING_CONSTANT;
|
140 | var PANHINT_LENGTH_CONSTANT = $.plot.uiConstants.PANHINT_LENGTH_CONSTANT;
|
141 |
|
142 | function init(plot) {
|
143 | plot.hooks.processOptions.push(initNevigation);
|
144 | }
|
145 |
|
146 | function initNevigation(plot, options) {
|
147 | var panAxes = null;
|
148 | var canDrag = false;
|
149 | var useManualPan = options.pan.mode === 'manual',
|
150 | smartPanLock = options.pan.mode === 'smartLock',
|
151 | useSmartPan = smartPanLock || options.pan.mode === 'smart';
|
152 |
|
153 | function onZoomClick(e, zoomOut, amount) {
|
154 | var page = browser.getPageXY(e);
|
155 |
|
156 | var c = plot.offset();
|
157 | c.left = page.X - c.left;
|
158 | c.top = page.Y - c.top;
|
159 |
|
160 | var ec = plot.getPlaceholder().offset();
|
161 | ec.left = page.X - ec.left;
|
162 | ec.top = page.Y - ec.top;
|
163 |
|
164 | var axes = plot.getXAxes().concat(plot.getYAxes()).filter(function (axis) {
|
165 | var box = axis.box;
|
166 | if (box !== undefined) {
|
167 | return (ec.left > box.left) && (ec.left < box.left + box.width) &&
|
168 | (ec.top > box.top) && (ec.top < box.top + box.height);
|
169 | }
|
170 | });
|
171 |
|
172 | if (axes.length === 0) {
|
173 | axes = undefined;
|
174 | }
|
175 |
|
176 | if (zoomOut) {
|
177 | plot.zoomOut({
|
178 | center: c,
|
179 | axes: axes,
|
180 | amount: amount
|
181 | });
|
182 | } else {
|
183 | plot.zoom({
|
184 | center: c,
|
185 | axes: axes,
|
186 | amount: amount
|
187 | });
|
188 | }
|
189 | }
|
190 |
|
191 | var prevCursor = 'default',
|
192 | panHint = null,
|
193 | panTimeout = null,
|
194 | plotState,
|
195 | prevDragPosition = { x: 0, y: 0 },
|
196 | isPanAction = false;
|
197 |
|
198 | function onMouseWheel(e, delta) {
|
199 | var maxAbsoluteDeltaOnMac = 1,
|
200 | isMacScroll = Math.abs(e.originalEvent.deltaY) <= maxAbsoluteDeltaOnMac,
|
201 | defaultNonMacScrollAmount = null,
|
202 | macMagicRatio = 50,
|
203 | amount = isMacScroll ? 1 + Math.abs(e.originalEvent.deltaY) / macMagicRatio : defaultNonMacScrollAmount;
|
204 |
|
205 | if (isPanAction) {
|
206 | onDragEnd(e);
|
207 | }
|
208 |
|
209 | if (plot.getOptions().zoom.active) {
|
210 | e.preventDefault();
|
211 | onZoomClick(e, delta < 0, amount);
|
212 | return false;
|
213 | }
|
214 | }
|
215 |
|
216 | plot.navigationState = function(startPageX, startPageY) {
|
217 | var axes = this.getAxes();
|
218 | var result = {};
|
219 | Object.keys(axes).forEach(function(axisName) {
|
220 | var axis = axes[axisName];
|
221 | result[axisName] = {
|
222 | navigationOffset: { below: axis.options.offset.below || 0,
|
223 | above: axis.options.offset.above || 0},
|
224 | axisMin: axis.min,
|
225 | axisMax: axis.max,
|
226 | diagMode: false
|
227 | }
|
228 | });
|
229 |
|
230 | result.startPageX = startPageX || 0;
|
231 | result.startPageY = startPageY || 0;
|
232 | return result;
|
233 | }
|
234 |
|
235 | function onMouseDown(e) {
|
236 | canDrag = true;
|
237 | }
|
238 |
|
239 | function onMouseUp(e) {
|
240 | canDrag = false;
|
241 | }
|
242 |
|
243 | function isLeftMouseButtonPressed(e) {
|
244 | return e.button === 0;
|
245 | }
|
246 |
|
247 | function onDragStart(e) {
|
248 | if (!canDrag || !isLeftMouseButtonPressed(e)) {
|
249 | return false;
|
250 | }
|
251 |
|
252 | isPanAction = true;
|
253 | var page = browser.getPageXY(e);
|
254 |
|
255 | var ec = plot.getPlaceholder().offset();
|
256 | ec.left = page.X - ec.left;
|
257 | ec.top = page.Y - ec.top;
|
258 |
|
259 | panAxes = plot.getXAxes().concat(plot.getYAxes()).filter(function (axis) {
|
260 | var box = axis.box;
|
261 | if (box !== undefined) {
|
262 | return (ec.left > box.left) && (ec.left < box.left + box.width) &&
|
263 | (ec.top > box.top) && (ec.top < box.top + box.height);
|
264 | }
|
265 | });
|
266 |
|
267 | if (panAxes.length === 0) {
|
268 | panAxes = undefined;
|
269 | }
|
270 |
|
271 | var c = plot.getPlaceholder().css('cursor');
|
272 | if (c) {
|
273 | prevCursor = c;
|
274 | }
|
275 |
|
276 | plot.getPlaceholder().css('cursor', plot.getOptions().pan.cursor);
|
277 |
|
278 | if (useSmartPan) {
|
279 | plotState = plot.navigationState(page.X, page.Y);
|
280 | } else if (useManualPan) {
|
281 | prevDragPosition.x = page.X;
|
282 | prevDragPosition.y = page.Y;
|
283 | }
|
284 | }
|
285 |
|
286 | function onDrag(e) {
|
287 | if (!isPanAction) {
|
288 | return;
|
289 | }
|
290 |
|
291 | var page = browser.getPageXY(e);
|
292 | var frameRate = plot.getOptions().pan.frameRate;
|
293 |
|
294 | if (frameRate === -1) {
|
295 | if (useSmartPan) {
|
296 | plot.smartPan({
|
297 | x: plotState.startPageX - page.X,
|
298 | y: plotState.startPageY - page.Y
|
299 | }, plotState, panAxes, false, smartPanLock);
|
300 | } else if (useManualPan) {
|
301 | plot.pan({
|
302 | left: prevDragPosition.x - page.X,
|
303 | top: prevDragPosition.y - page.Y,
|
304 | axes: panAxes
|
305 | });
|
306 | prevDragPosition.x = page.X;
|
307 | prevDragPosition.y = page.Y;
|
308 | }
|
309 | return;
|
310 | }
|
311 |
|
312 | if (panTimeout || !frameRate) return;
|
313 |
|
314 | panTimeout = setTimeout(function() {
|
315 | if (useSmartPan) {
|
316 | plot.smartPan({
|
317 | x: plotState.startPageX - page.X,
|
318 | y: plotState.startPageY - page.Y
|
319 | }, plotState, panAxes, false, smartPanLock);
|
320 | } else if (useManualPan) {
|
321 | plot.pan({
|
322 | left: prevDragPosition.x - page.X,
|
323 | top: prevDragPosition.y - page.Y,
|
324 | axes: panAxes
|
325 | });
|
326 | prevDragPosition.x = page.X;
|
327 | prevDragPosition.y = page.Y;
|
328 | }
|
329 |
|
330 | panTimeout = null;
|
331 | }, 1 / frameRate * 1000);
|
332 | }
|
333 |
|
334 | function onDragEnd(e) {
|
335 | if (!isPanAction) {
|
336 | return;
|
337 | }
|
338 |
|
339 | if (panTimeout) {
|
340 | clearTimeout(panTimeout);
|
341 | panTimeout = null;
|
342 | }
|
343 |
|
344 | isPanAction = false;
|
345 | var page = browser.getPageXY(e);
|
346 |
|
347 | plot.getPlaceholder().css('cursor', prevCursor);
|
348 |
|
349 | if (useSmartPan) {
|
350 | plot.smartPan({
|
351 | x: plotState.startPageX - page.X,
|
352 | y: plotState.startPageY - page.Y
|
353 | }, plotState, panAxes, false, smartPanLock);
|
354 | plot.smartPan.end();
|
355 | } else if (useManualPan) {
|
356 | plot.pan({
|
357 | left: prevDragPosition.x - page.X,
|
358 | top: prevDragPosition.y - page.Y,
|
359 | axes: panAxes
|
360 | });
|
361 | prevDragPosition.x = 0;
|
362 | prevDragPosition.y = 0;
|
363 | }
|
364 | }
|
365 |
|
366 | function onDblClick(e) {
|
367 | plot.activate();
|
368 | var o = plot.getOptions()
|
369 |
|
370 | if (!o.recenter.interactive) { return; }
|
371 |
|
372 | var axes = plot.getTouchedAxis(e.clientX, e.clientY),
|
373 | event;
|
374 |
|
375 | plot.recenter({ axes: axes[0] ? axes : null });
|
376 |
|
377 | if (axes[0]) {
|
378 | event = new $.Event('re-center', { detail: {
|
379 | axisTouched: axes[0]
|
380 | }});
|
381 | } else {
|
382 | event = new $.Event('re-center', { detail: e });
|
383 | }
|
384 | plot.getPlaceholder().trigger(event);
|
385 | }
|
386 |
|
387 | function onClick(e) {
|
388 | plot.activate();
|
389 |
|
390 | if (isPanAction) {
|
391 | onDragEnd(e);
|
392 | }
|
393 |
|
394 | return false;
|
395 | }
|
396 |
|
397 | plot.activate = function() {
|
398 | var o = plot.getOptions();
|
399 | if (!o.pan.active || !o.zoom.active) {
|
400 | o.pan.active = true;
|
401 | o.zoom.active = true;
|
402 | plot.getPlaceholder().trigger("plotactivated", [plot]);
|
403 | }
|
404 | }
|
405 |
|
406 | function bindEvents(plot, eventHolder) {
|
407 | var o = plot.getOptions();
|
408 | if (o.zoom.interactive) {
|
409 | eventHolder.mousewheel(onMouseWheel);
|
410 | }
|
411 |
|
412 | if (o.pan.interactive) {
|
413 | plot.addEventHandler("dragstart", onDragStart, eventHolder, 0);
|
414 | plot.addEventHandler("drag", onDrag, eventHolder, 0);
|
415 | plot.addEventHandler("dragend", onDragEnd, eventHolder, 0);
|
416 | eventHolder.bind("mousedown", onMouseDown);
|
417 | eventHolder.bind("mouseup", onMouseUp);
|
418 | }
|
419 |
|
420 | eventHolder.dblclick(onDblClick);
|
421 | eventHolder.click(onClick);
|
422 | }
|
423 |
|
424 | plot.zoomOut = function(args) {
|
425 | if (!args) {
|
426 | args = {};
|
427 | }
|
428 |
|
429 | if (!args.amount) {
|
430 | args.amount = plot.getOptions().zoom.amount;
|
431 | }
|
432 |
|
433 | args.amount = 1 / args.amount;
|
434 | plot.zoom(args);
|
435 | };
|
436 |
|
437 | plot.zoom = function(args) {
|
438 | if (!args) {
|
439 | args = {};
|
440 | }
|
441 |
|
442 | var c = args.center,
|
443 | amount = args.amount || plot.getOptions().zoom.amount,
|
444 | w = plot.width(),
|
445 | h = plot.height(),
|
446 | axes = args.axes || plot.getAxes();
|
447 |
|
448 | if (!c) {
|
449 | c = {
|
450 | left: w / 2,
|
451 | top: h / 2
|
452 | };
|
453 | }
|
454 |
|
455 | var xf = c.left / w,
|
456 | yf = c.top / h,
|
457 | minmax = {
|
458 | x: {
|
459 | min: c.left - xf * w / amount,
|
460 | max: c.left + (1 - xf) * w / amount
|
461 | },
|
462 | y: {
|
463 | min: c.top - yf * h / amount,
|
464 | max: c.top + (1 - yf) * h / amount
|
465 | }
|
466 | };
|
467 |
|
468 | for (var key in axes) {
|
469 | if (!axes.hasOwnProperty(key)) {
|
470 | continue;
|
471 | }
|
472 |
|
473 | var axis = axes[key],
|
474 | opts = axis.options,
|
475 | min = minmax[axis.direction].min,
|
476 | max = minmax[axis.direction].max,
|
477 | navigationOffset = axis.options.offset;
|
478 |
|
479 |
|
480 | if ((!opts.axisZoom && args.axes) || (!args.axes && !opts.plotZoom)) {
|
481 | continue;
|
482 | }
|
483 |
|
484 | min = $.plot.saturated.saturate(axis.c2p(min));
|
485 | max = $.plot.saturated.saturate(axis.c2p(max));
|
486 | if (min > max) {
|
487 |
|
488 | var tmp = min;
|
489 | min = max;
|
490 | max = tmp;
|
491 | }
|
492 |
|
493 | var offsetBelow = $.plot.saturated.saturate(navigationOffset.below - (axis.min - min));
|
494 | var offsetAbove = $.plot.saturated.saturate(navigationOffset.above - (axis.max - max));
|
495 | opts.offset = { below: offsetBelow, above: offsetAbove };
|
496 | };
|
497 |
|
498 | plot.setupGrid(true);
|
499 | plot.draw();
|
500 |
|
501 | if (!args.preventEvent) {
|
502 | plot.getPlaceholder().trigger("plotzoom", [plot, args]);
|
503 | }
|
504 | };
|
505 |
|
506 | plot.pan = function(args) {
|
507 | var delta = {
|
508 | x: +args.left,
|
509 | y: +args.top
|
510 | };
|
511 |
|
512 | if (isNaN(delta.x)) delta.x = 0;
|
513 | if (isNaN(delta.y)) delta.y = 0;
|
514 |
|
515 | $.each(args.axes || plot.getAxes(), function(_, axis) {
|
516 | var opts = axis.options,
|
517 | d = delta[axis.direction];
|
518 |
|
519 |
|
520 | if ((!opts.axisPan && args.axes) || (!opts.plotPan && !args.axes)) {
|
521 | return;
|
522 | }
|
523 |
|
524 | if (d !== 0) {
|
525 | var navigationOffsetBelow = saturated.saturate(axis.c2p(axis.p2c(axis.min) + d) - axis.c2p(axis.p2c(axis.min))),
|
526 | navigationOffsetAbove = saturated.saturate(axis.c2p(axis.p2c(axis.max) + d) - axis.c2p(axis.p2c(axis.max)));
|
527 |
|
528 | if (!isFinite(navigationOffsetBelow)) {
|
529 | navigationOffsetBelow = 0;
|
530 | }
|
531 |
|
532 | if (!isFinite(navigationOffsetAbove)) {
|
533 | navigationOffsetAbove = 0;
|
534 | }
|
535 |
|
536 | opts.offset = {
|
537 | below: saturated.saturate(navigationOffsetBelow + (opts.offset.below || 0)),
|
538 | above: saturated.saturate(navigationOffsetAbove + (opts.offset.above || 0))
|
539 | };
|
540 | }
|
541 | });
|
542 |
|
543 | plot.setupGrid(true);
|
544 | plot.draw();
|
545 | if (!args.preventEvent) {
|
546 | plot.getPlaceholder().trigger("plotpan", [plot, args]);
|
547 | }
|
548 | };
|
549 |
|
550 | plot.recenter = function(args) {
|
551 | $.each(args.axes || plot.getAxes(), function(_, axis) {
|
552 | if (args.axes) {
|
553 | if (this.direction === 'x') {
|
554 | axis.options.offset = { below: 0 };
|
555 | } else if (this.direction === 'y') {
|
556 | axis.options.offset = { above: 0 };
|
557 | }
|
558 | } else {
|
559 | axis.options.offset = { below: 0, above: 0 };
|
560 | }
|
561 | });
|
562 | plot.setupGrid(true);
|
563 | plot.draw();
|
564 | };
|
565 |
|
566 | var shouldSnap = function(delta) {
|
567 | return (Math.abs(delta.y) < SNAPPING_CONSTANT && Math.abs(delta.x) >= SNAPPING_CONSTANT) ||
|
568 | (Math.abs(delta.x) < SNAPPING_CONSTANT && Math.abs(delta.y) >= SNAPPING_CONSTANT);
|
569 | }
|
570 |
|
571 |
|
572 |
|
573 | var adjustDeltaToSnap = function(delta) {
|
574 | if (Math.abs(delta.x) < SNAPPING_CONSTANT && Math.abs(delta.y) >= SNAPPING_CONSTANT) {
|
575 | return {x: 0, y: delta.y};
|
576 | }
|
577 |
|
578 | if (Math.abs(delta.y) < SNAPPING_CONSTANT && Math.abs(delta.x) >= SNAPPING_CONSTANT) {
|
579 | return {x: delta.x, y: 0};
|
580 | }
|
581 |
|
582 | return delta;
|
583 | }
|
584 |
|
585 | var lockedDirection = null;
|
586 | var lockDeltaDirection = function(delta) {
|
587 | if (!lockedDirection && Math.max(Math.abs(delta.x), Math.abs(delta.y)) >= SNAPPING_CONSTANT) {
|
588 | lockedDirection = Math.abs(delta.x) < Math.abs(delta.y) ? 'y' : 'x';
|
589 | }
|
590 |
|
591 | switch (lockedDirection) {
|
592 | case 'x':
|
593 | return { x: delta.x, y: 0 };
|
594 | case 'y':
|
595 | return { x: 0, y: delta.y };
|
596 | default:
|
597 | return { x: 0, y: 0 };
|
598 | }
|
599 | }
|
600 |
|
601 | var isDiagonalMode = function(delta) {
|
602 | if (Math.abs(delta.x) > 0 && Math.abs(delta.y) > 0) {
|
603 | return true;
|
604 | }
|
605 | return false;
|
606 | }
|
607 |
|
608 | var restoreAxisOffset = function(axes, initialState, delta) {
|
609 | var axis;
|
610 | Object.keys(axes).forEach(function(axisName) {
|
611 | axis = axes[axisName];
|
612 | if (delta[axis.direction] === 0) {
|
613 | axis.options.offset.below = initialState[axisName].navigationOffset.below;
|
614 | axis.options.offset.above = initialState[axisName].navigationOffset.above;
|
615 | }
|
616 | });
|
617 | }
|
618 |
|
619 | var prevDelta = { x: 0, y: 0 };
|
620 | plot.smartPan = function(delta, initialState, panAxes, preventEvent, smartLock) {
|
621 | var snap = smartLock ? true : shouldSnap(delta),
|
622 | axes = plot.getAxes(),
|
623 | opts;
|
624 | delta = smartLock ? lockDeltaDirection(delta) : adjustDeltaToSnap(delta);
|
625 |
|
626 | if (isDiagonalMode(delta)) {
|
627 | initialState.diagMode = true;
|
628 | }
|
629 |
|
630 | if (snap && initialState.diagMode === true) {
|
631 | initialState.diagMode = false;
|
632 | restoreAxisOffset(axes, initialState, delta);
|
633 | }
|
634 |
|
635 | if (snap) {
|
636 | panHint = {
|
637 | start: {
|
638 | x: initialState.startPageX - plot.offset().left + plot.getPlotOffset().left,
|
639 | y: initialState.startPageY - plot.offset().top + plot.getPlotOffset().top
|
640 | },
|
641 | end: {
|
642 | x: initialState.startPageX - delta.x - plot.offset().left + plot.getPlotOffset().left,
|
643 | y: initialState.startPageY - delta.y - plot.offset().top + plot.getPlotOffset().top
|
644 | }
|
645 | }
|
646 | } else {
|
647 | panHint = {
|
648 | start: {
|
649 | x: initialState.startPageX - plot.offset().left + plot.getPlotOffset().left,
|
650 | y: initialState.startPageY - plot.offset().top + plot.getPlotOffset().top
|
651 | },
|
652 | end: false
|
653 | }
|
654 | }
|
655 |
|
656 | if (isNaN(delta.x)) delta.x = 0;
|
657 | if (isNaN(delta.y)) delta.y = 0;
|
658 |
|
659 | if (panAxes) {
|
660 | axes = panAxes;
|
661 | }
|
662 |
|
663 | var axis, axisMin, axisMax, p, d;
|
664 | Object.keys(axes).forEach(function(axisName) {
|
665 | axis = axes[axisName];
|
666 | axisMin = axis.min;
|
667 | axisMax = axis.max;
|
668 | opts = axis.options;
|
669 |
|
670 | d = delta[axis.direction];
|
671 | p = prevDelta[axis.direction];
|
672 |
|
673 |
|
674 | if ((!opts.axisPan && panAxes) || (!panAxes && !opts.plotPan)) {
|
675 | return;
|
676 | }
|
677 |
|
678 | if (d !== 0) {
|
679 | var navigationOffsetBelow = saturated.saturate(axis.c2p(axis.p2c(axisMin) - (p - d)) - axis.c2p(axis.p2c(axisMin))),
|
680 | navigationOffsetAbove = saturated.saturate(axis.c2p(axis.p2c(axisMax) - (p - d)) - axis.c2p(axis.p2c(axisMax)));
|
681 |
|
682 | if (!isFinite(navigationOffsetBelow)) {
|
683 | navigationOffsetBelow = 0;
|
684 | }
|
685 |
|
686 | if (!isFinite(navigationOffsetAbove)) {
|
687 | navigationOffsetAbove = 0;
|
688 | }
|
689 |
|
690 | axis.options.offset.below = saturated.saturate(navigationOffsetBelow + (axis.options.offset.below || 0));
|
691 | axis.options.offset.above = saturated.saturate(navigationOffsetAbove + (axis.options.offset.above || 0));
|
692 | }
|
693 | });
|
694 |
|
695 | prevDelta = delta;
|
696 | plot.setupGrid(true);
|
697 | plot.draw();
|
698 |
|
699 | if (!preventEvent) {
|
700 | plot.getPlaceholder().trigger("plotpan", [plot, delta, panAxes, initialState]);
|
701 | }
|
702 | };
|
703 |
|
704 | plot.smartPan.end = function() {
|
705 | panHint = null;
|
706 | lockedDirection = null;
|
707 | prevDelta = { x: 0, y: 0 };
|
708 | plot.triggerRedrawOverlay();
|
709 | }
|
710 |
|
711 | function shutdown(plot, eventHolder) {
|
712 | eventHolder.unbind("mousewheel", onMouseWheel);
|
713 | eventHolder.unbind("mousedown", onMouseDown);
|
714 | eventHolder.unbind("mouseup", onMouseUp);
|
715 | eventHolder.unbind("dragstart", onDragStart);
|
716 | eventHolder.unbind("drag", onDrag);
|
717 | eventHolder.unbind("dragend", onDragEnd);
|
718 | eventHolder.unbind("dblclick", onDblClick);
|
719 | eventHolder.unbind("click", onClick);
|
720 |
|
721 | if (panTimeout) clearTimeout(panTimeout);
|
722 | }
|
723 |
|
724 | function drawOverlay(plot, ctx) {
|
725 | if (panHint) {
|
726 | ctx.strokeStyle = 'rgba(96, 160, 208, 0.7)';
|
727 | ctx.lineWidth = 2;
|
728 | ctx.lineJoin = "round";
|
729 | var startx = Math.round(panHint.start.x),
|
730 | starty = Math.round(panHint.start.y),
|
731 | endx, endy;
|
732 |
|
733 | if (panAxes) {
|
734 | if (panAxes[0].direction === 'x') {
|
735 | endy = Math.round(panHint.start.y);
|
736 | endx = Math.round(panHint.end.x);
|
737 | } else if (panAxes[0].direction === 'y') {
|
738 | endx = Math.round(panHint.start.x);
|
739 | endy = Math.round(panHint.end.y);
|
740 | }
|
741 | } else {
|
742 | endx = Math.round(panHint.end.x);
|
743 | endy = Math.round(panHint.end.y);
|
744 | }
|
745 |
|
746 | ctx.beginPath();
|
747 |
|
748 | if (panHint.end === false) {
|
749 | ctx.moveTo(startx, starty - PANHINT_LENGTH_CONSTANT);
|
750 | ctx.lineTo(startx, starty + PANHINT_LENGTH_CONSTANT);
|
751 |
|
752 | ctx.moveTo(startx + PANHINT_LENGTH_CONSTANT, starty);
|
753 | ctx.lineTo(startx - PANHINT_LENGTH_CONSTANT, starty);
|
754 | } else {
|
755 | var dirX = starty === endy;
|
756 |
|
757 | ctx.moveTo(startx - (dirX ? 0 : PANHINT_LENGTH_CONSTANT), starty - (dirX ? PANHINT_LENGTH_CONSTANT : 0));
|
758 | ctx.lineTo(startx + (dirX ? 0 : PANHINT_LENGTH_CONSTANT), starty + (dirX ? PANHINT_LENGTH_CONSTANT : 0));
|
759 |
|
760 | ctx.moveTo(startx, starty);
|
761 | ctx.lineTo(endx, endy);
|
762 |
|
763 | ctx.moveTo(endx - (dirX ? 0 : PANHINT_LENGTH_CONSTANT), endy - (dirX ? PANHINT_LENGTH_CONSTANT : 0));
|
764 | ctx.lineTo(endx + (dirX ? 0 : PANHINT_LENGTH_CONSTANT), endy + (dirX ? PANHINT_LENGTH_CONSTANT : 0));
|
765 | }
|
766 |
|
767 | ctx.stroke();
|
768 | }
|
769 | }
|
770 |
|
771 | plot.getTouchedAxis = function(touchPointX, touchPointY) {
|
772 | var ec = plot.getPlaceholder().offset();
|
773 | ec.left = touchPointX - ec.left;
|
774 | ec.top = touchPointY - ec.top;
|
775 |
|
776 | var axis = plot.getXAxes().concat(plot.getYAxes()).filter(function (axis) {
|
777 | var box = axis.box;
|
778 | if (box !== undefined) {
|
779 | return (ec.left > box.left) && (ec.left < box.left + box.width) &&
|
780 | (ec.top > box.top) && (ec.top < box.top + box.height);
|
781 | }
|
782 | });
|
783 |
|
784 | return axis;
|
785 | }
|
786 |
|
787 | plot.hooks.drawOverlay.push(drawOverlay);
|
788 | plot.hooks.bindEvents.push(bindEvents);
|
789 | plot.hooks.shutdown.push(shutdown);
|
790 | }
|
791 |
|
792 | $.plot.plugins.push({
|
793 | init: init,
|
794 | options: options,
|
795 | name: 'navigate',
|
796 | version: '1.3'
|
797 | });
|
798 | })(jQuery);
|