2010-09-16 23:32:55 +08:00
|
|
|
/*
|
|
|
|
* L.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too.
|
|
|
|
*/
|
|
|
|
|
2010-09-16 21:05:55 +08:00
|
|
|
L.Draggable = L.Class.extend({
|
|
|
|
includes: L.Mixin.Events,
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2010-09-16 21:05:55 +08:00
|
|
|
statics: {
|
2012-11-12 06:13:15 +08:00
|
|
|
START: L.Browser.touch ? ['touchstart', 'mousedown'] : ['mousedown'],
|
2012-11-12 06:52:02 +08:00
|
|
|
END: { 'mousedown': 'mouseup', 'touchstart' : 'touchend', 'MSPointerDown': 'touchend' },
|
|
|
|
MOVE: { 'mousedown': 'mousemove', 'touchstart': 'touchmove', 'MSPointerDown': 'touchmove' },
|
2011-06-17 20:52:39 +08:00
|
|
|
TAP_TOLERANCE: 15
|
2010-09-16 21:05:55 +08:00
|
|
|
},
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2012-10-31 08:05:38 +08:00
|
|
|
initialize: function (element, dragStartTarget, longPress) {
|
2010-09-16 21:05:55 +08:00
|
|
|
this._element = element;
|
|
|
|
this._dragStartTarget = dragStartTarget || element;
|
2012-10-31 08:26:56 +08:00
|
|
|
this._longPress = longPress && !L.Browser.msTouch;
|
2010-09-16 21:05:55 +08:00
|
|
|
},
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-12-09 22:51:31 +08:00
|
|
|
enable: function () {
|
2012-11-08 00:46:59 +08:00
|
|
|
if (this._enabled) { return; }
|
|
|
|
|
2012-11-12 06:13:15 +08:00
|
|
|
for (var i = L.Draggable.START.length - 1; i >= 0; i--) {
|
|
|
|
L.DomEvent.on(this._dragStartTarget, L.Draggable.START[i], this._onDown, this);
|
|
|
|
}
|
2010-09-16 21:05:55 +08:00
|
|
|
this._enabled = true;
|
|
|
|
},
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-12-09 22:51:31 +08:00
|
|
|
disable: function () {
|
2012-11-08 00:46:59 +08:00
|
|
|
if (!this._enabled) { return; }
|
|
|
|
|
2012-11-13 04:09:46 +08:00
|
|
|
for (var i = L.Draggable.START.length - 1; i >= 0; i--) {
|
|
|
|
L.DomEvent.off(this._dragStartTarget, L.Draggable.START[i], this._onDown, this);
|
|
|
|
}
|
2010-09-16 21:05:55 +08:00
|
|
|
this._enabled = false;
|
2012-02-16 01:26:17 +08:00
|
|
|
this._moved = false;
|
2010-09-16 21:05:55 +08:00
|
|
|
},
|
2011-03-22 01:09:43 +08:00
|
|
|
|
2011-12-09 22:51:31 +08:00
|
|
|
_onDown: function (e) {
|
2012-08-13 20:41:20 +08:00
|
|
|
if ((!L.Browser.touch && e.shiftKey) ||
|
2012-11-08 00:46:59 +08:00
|
|
|
((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; }
|
2012-08-13 20:41:20 +08:00
|
|
|
|
|
|
|
L.DomEvent.preventDefault(e);
|
2012-09-03 11:41:06 +08:00
|
|
|
L.DomEvent.stopPropagation(e);
|
2012-08-13 20:41:20 +08:00
|
|
|
|
|
|
|
if (L.Draggable._disabled) { return; }
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2012-02-21 20:58:01 +08:00
|
|
|
this._simulateClick = true;
|
|
|
|
|
2011-12-10 19:48:45 +08:00
|
|
|
if (e.touches && e.touches.length > 1) {
|
2012-02-21 20:58:01 +08:00
|
|
|
this._simulateClick = false;
|
2012-10-31 08:25:29 +08:00
|
|
|
clearTimeout(this._longPressTimeout);
|
2011-12-10 19:48:45 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-06-17 18:50:50 +08:00
|
|
|
|
2011-12-09 22:35:15 +08:00
|
|
|
var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
|
2012-11-08 00:46:59 +08:00
|
|
|
el = first.target;
|
2011-09-09 17:52:28 +08:00
|
|
|
|
|
|
|
if (L.Browser.touch && el.tagName.toLowerCase() === 'a') {
|
2012-07-05 22:59:00 +08:00
|
|
|
L.DomUtil.addClass(el, 'leaflet-active');
|
2011-06-17 18:50:50 +08:00
|
|
|
}
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-09-23 22:03:36 +08:00
|
|
|
this._moved = false;
|
2012-11-08 00:46:59 +08:00
|
|
|
if (this._moving) { return; }
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-06-17 18:50:50 +08:00
|
|
|
this._startPoint = new L.Point(first.clientX, first.clientY);
|
2012-09-11 17:33:54 +08:00
|
|
|
this._startPos = this._newPos = L.DomUtil.getPosition(this._element);
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2012-09-03 10:18:29 +08:00
|
|
|
//Touch contextmenu event emulation
|
2012-10-31 08:05:38 +08:00
|
|
|
if (e.touches && e.touches.length === 1 && L.Browser.touch && this._longPress) {
|
2012-11-08 02:30:56 +08:00
|
|
|
this._longPressTimeout = setTimeout(L.bind(function () {
|
2012-10-31 08:11:16 +08:00
|
|
|
var dist = (this._newPos && this._newPos.distanceTo(this._startPos)) || 0;
|
2012-09-03 10:18:29 +08:00
|
|
|
|
|
|
|
if (dist < L.Draggable.TAP_TOLERANCE) {
|
2012-10-31 08:11:16 +08:00
|
|
|
this._simulateClick = false;
|
|
|
|
this._onUp();
|
|
|
|
this._simulateEvent('contextmenu', first);
|
2012-09-03 10:18:29 +08:00
|
|
|
}
|
2012-10-31 08:11:16 +08:00
|
|
|
}, this), 1000);
|
2012-09-03 10:18:29 +08:00
|
|
|
}
|
|
|
|
|
2012-11-12 06:52:02 +08:00
|
|
|
L.DomEvent.on(document, L.Draggable.MOVE[e.type], this._onMove, this);
|
|
|
|
L.DomEvent.on(document, L.Draggable.END[e.type], this._onUp, this);
|
2010-09-16 21:05:55 +08:00
|
|
|
},
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-12-09 22:51:31 +08:00
|
|
|
_onMove: function (e) {
|
2012-06-26 06:51:04 +08:00
|
|
|
if (e.touches && e.touches.length > 1) { return; }
|
2011-06-17 18:50:50 +08:00
|
|
|
|
2012-06-26 06:51:04 +08:00
|
|
|
var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
|
2012-11-08 00:46:59 +08:00
|
|
|
newPoint = new L.Point(first.clientX, first.clientY),
|
|
|
|
diffVec = newPoint.subtract(this._startPoint);
|
2012-05-28 23:08:33 +08:00
|
|
|
|
2012-06-26 06:51:04 +08:00
|
|
|
if (!diffVec.x && !diffVec.y) { return; }
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2012-06-26 06:51:04 +08:00
|
|
|
L.DomEvent.preventDefault(e);
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2010-09-21 20:48:31 +08:00
|
|
|
if (!this._moved) {
|
2010-09-16 21:05:55 +08:00
|
|
|
this.fire('dragstart');
|
2010-09-21 20:48:31 +08:00
|
|
|
this._moved = true;
|
2012-08-02 17:46:58 +08:00
|
|
|
|
2012-08-10 23:37:21 +08:00
|
|
|
this._startPos = L.DomUtil.getPosition(this._element).subtract(diffVec);
|
|
|
|
|
2012-08-02 17:46:58 +08:00
|
|
|
if (!L.Browser.touch) {
|
|
|
|
L.DomUtil.disableTextSelection();
|
|
|
|
this._setMovingCursor();
|
|
|
|
}
|
2010-09-16 21:05:55 +08:00
|
|
|
}
|
2011-06-16 23:52:37 +08:00
|
|
|
|
2012-05-28 23:08:33 +08:00
|
|
|
this._newPos = this._startPos.add(diffVec);
|
|
|
|
this._moving = true;
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2012-02-22 15:00:54 +08:00
|
|
|
L.Util.cancelAnimFrame(this._animRequest);
|
2012-07-21 02:34:21 +08:00
|
|
|
this._animRequest = L.Util.requestAnimFrame(this._updatePosition, this, true, this._dragStartTarget);
|
2010-09-16 21:05:55 +08:00
|
|
|
},
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-12-09 22:51:31 +08:00
|
|
|
_updatePosition: function () {
|
2011-09-23 21:55:47 +08:00
|
|
|
this.fire('predrag');
|
2010-09-21 23:36:00 +08:00
|
|
|
L.DomUtil.setPosition(this._element, this._newPos);
|
2011-07-20 15:18:59 +08:00
|
|
|
this.fire('drag');
|
2010-09-21 23:36:00 +08:00
|
|
|
},
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-12-09 22:51:31 +08:00
|
|
|
_onUp: function (e) {
|
2012-10-15 05:19:30 +08:00
|
|
|
var simulateClickTouch;
|
2012-10-31 08:25:29 +08:00
|
|
|
clearTimeout(this._longPressTimeout);
|
2012-02-21 20:58:01 +08:00
|
|
|
if (this._simulateClick && e.changedTouches) {
|
2011-06-17 20:52:39 +08:00
|
|
|
var first = e.changedTouches[0],
|
2012-11-08 00:46:59 +08:00
|
|
|
el = first.target,
|
|
|
|
dist = (this._newPos && this._newPos.distanceTo(this._startPos)) || 0;
|
2011-09-09 17:52:28 +08:00
|
|
|
|
|
|
|
if (el.tagName.toLowerCase() === 'a') {
|
2012-07-01 20:46:31 +08:00
|
|
|
L.DomUtil.removeClass(el, 'leaflet-active');
|
2011-09-09 17:52:28 +08:00
|
|
|
}
|
|
|
|
|
2011-06-17 20:52:39 +08:00
|
|
|
if (dist < L.Draggable.TAP_TOLERANCE) {
|
2012-10-15 05:19:30 +08:00
|
|
|
simulateClickTouch = first;
|
2011-06-17 20:52:39 +08:00
|
|
|
}
|
2011-06-17 18:50:50 +08:00
|
|
|
}
|
2011-09-09 17:52:28 +08:00
|
|
|
|
|
|
|
if (!L.Browser.touch) {
|
|
|
|
L.DomUtil.enableTextSelection();
|
|
|
|
this._restoreCursor();
|
|
|
|
}
|
|
|
|
|
2012-11-12 06:52:02 +08:00
|
|
|
for (var i in L.Draggable.MOVE) {
|
|
|
|
if (L.Draggable.MOVE.hasOwnProperty(i))
|
|
|
|
{
|
|
|
|
L.DomEvent.off(document, L.Draggable.MOVE[i], this._onMove);
|
|
|
|
L.DomEvent.off(document, L.Draggable.END[i], this._onUp);
|
|
|
|
}
|
2012-11-12 06:13:15 +08:00
|
|
|
}
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2012-10-15 05:19:30 +08:00
|
|
|
if (this._moved) {
|
2012-06-25 23:08:00 +08:00
|
|
|
// ensure drag is not fired after dragend
|
|
|
|
L.Util.cancelAnimFrame(this._animRequest);
|
|
|
|
|
2010-09-21 21:10:31 +08:00
|
|
|
this.fire('dragend');
|
|
|
|
}
|
2011-09-23 22:03:36 +08:00
|
|
|
this._moving = false;
|
2012-10-15 05:19:30 +08:00
|
|
|
|
|
|
|
if (simulateClickTouch) {
|
|
|
|
this._moved = false;
|
|
|
|
this._simulateEvent('click', simulateClickTouch);
|
|
|
|
}
|
2011-06-17 18:50:50 +08:00
|
|
|
},
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-12-09 22:51:31 +08:00
|
|
|
_setMovingCursor: function () {
|
2012-07-01 20:46:31 +08:00
|
|
|
L.DomUtil.addClass(document.body, 'leaflet-dragging');
|
2010-09-16 21:05:55 +08:00
|
|
|
},
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-12-09 22:51:31 +08:00
|
|
|
_restoreCursor: function () {
|
2012-07-01 20:46:31 +08:00
|
|
|
L.DomUtil.removeClass(document.body, 'leaflet-dragging');
|
2011-06-16 23:52:37 +08:00
|
|
|
},
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-12-09 22:51:31 +08:00
|
|
|
_simulateEvent: function (type, e) {
|
2011-09-09 17:52:28 +08:00
|
|
|
var simulatedEvent = document.createEvent('MouseEvents');
|
|
|
|
|
2011-06-17 18:50:50 +08:00
|
|
|
simulatedEvent.initMouseEvent(
|
2012-11-08 00:46:59 +08:00
|
|
|
type, true, true, window, 1,
|
|
|
|
e.screenX, e.screenY,
|
|
|
|
e.clientX, e.clientY,
|
|
|
|
false, false, false, false, 0, null);
|
2011-09-09 17:52:28 +08:00
|
|
|
|
2011-06-16 23:52:37 +08:00
|
|
|
e.target.dispatchEvent(simulatedEvent);
|
2010-09-16 21:05:55 +08:00
|
|
|
}
|
2011-05-31 02:30:18 +08:00
|
|
|
});
|