You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
5.8 KiB
211 lines
5.8 KiB
define([ |
|
"../_base/array", "../_base/declare", "../_base/lang", "../dom", "../dom-class", "../Evented", |
|
"../has", "../on", "../topic", "../touch", "./common", "./Mover", "../_base/window" |
|
], function(array, declare, lang, dom, domClass, Evented, has, on, topic, touch, dnd, Mover, win){ |
|
|
|
// module: |
|
// dojo/dnd/Moveable |
|
|
|
var touchActionPropertyName; |
|
var setTouchAction = function () {}; |
|
|
|
function setTouchActionPropertyName() { |
|
if ("touchAction" in document.body.style) { |
|
touchActionPropertyName = "touchAction"; |
|
} |
|
else if ("msTouchAction" in document.body.style) { |
|
touchActionPropertyName = "msTouchAction"; |
|
} |
|
setTouchAction = function setTouchAction(/* Node */ node, /* string */ action) { |
|
node.style[touchActionPropertyName] = action; |
|
} |
|
setTouchAction(arguments[0], arguments[1]); |
|
} |
|
|
|
if (has("touch-action")) { |
|
// Ensure that the logic to determine "touchActionPropertyName" runs |
|
setTouchAction = setTouchActionPropertyName; |
|
} |
|
|
|
var Moveable = declare("dojo.dnd.Moveable", [Evented], { |
|
// summary: |
|
// an object, which makes a node movable |
|
|
|
// object attributes (for markup) |
|
handle: "", |
|
delay: 0, |
|
skip: false, |
|
|
|
constructor: function(node, params){ |
|
// node: Node |
|
// a node (or node's id) to be moved |
|
// params: Moveable.__MoveableArgs? |
|
// optional parameters |
|
this.node = dom.byId(node); |
|
setTouchAction(this.node, "none"); |
|
if(!params){ params = {}; } |
|
this.handle = params.handle ? dom.byId(params.handle) : null; |
|
if(!this.handle){ this.handle = this.node; } |
|
this.delay = params.delay > 0 ? params.delay : 0; |
|
this.skip = params.skip; |
|
this.mover = params.mover ? params.mover : Mover; |
|
this.events = [ |
|
on(this.handle, touch.press, lang.hitch(this, "onMouseDown")), |
|
// cancel text selection and text dragging |
|
on(this.handle, "dragstart", lang.hitch(this, "onSelectStart")), |
|
on(this.handle, "selectstart", lang.hitch(this, "onSelectStart")) |
|
]; |
|
}, |
|
|
|
// markup methods |
|
markupFactory: function(params, node, Ctor){ |
|
return new Ctor(node, params); |
|
}, |
|
|
|
// methods |
|
destroy: function(){ |
|
// summary: |
|
// stops watching for possible move, deletes all references, so the object can be garbage-collected |
|
array.forEach(this.events, function(handle){ handle.remove(); }); |
|
setTouchAction(this.node, ""); |
|
this.events = this.node = this.handle = null; |
|
}, |
|
|
|
// mouse event processors |
|
onMouseDown: function(e){ |
|
// summary: |
|
// event processor for onmousedown/ontouchstart, creates a Mover for the node |
|
// e: Event |
|
// mouse/touch event |
|
if(this.skip && dnd.isFormElement(e)){ return; } |
|
if(this.delay){ |
|
this.events.push( |
|
on(this.handle, touch.move, lang.hitch(this, "onMouseMove")), |
|
on(this.handle.ownerDocument, touch.release, lang.hitch(this, "onMouseUp")) |
|
); |
|
this._lastX = e.pageX; |
|
this._lastY = e.pageY; |
|
}else{ |
|
this.onDragDetected(e); |
|
} |
|
e.stopPropagation(); |
|
e.preventDefault(); |
|
}, |
|
onMouseMove: function(e){ |
|
// summary: |
|
// event processor for onmousemove/ontouchmove, used only for delayed drags |
|
// e: Event |
|
// mouse/touch event |
|
if(Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay){ |
|
this.onMouseUp(e); |
|
this.onDragDetected(e); |
|
} |
|
e.stopPropagation(); |
|
e.preventDefault(); |
|
}, |
|
onMouseUp: function(e){ |
|
// summary: |
|
// event processor for onmouseup, used only for delayed drags |
|
// e: Event |
|
// mouse event |
|
for(var i = 0; i < 2; ++i){ |
|
this.events.pop().remove(); |
|
} |
|
e.stopPropagation(); |
|
e.preventDefault(); |
|
}, |
|
onSelectStart: function(e){ |
|
// summary: |
|
// event processor for onselectevent and ondragevent |
|
// e: Event |
|
// mouse event |
|
if(!this.skip || !dnd.isFormElement(e)){ |
|
e.stopPropagation(); |
|
e.preventDefault(); |
|
} |
|
}, |
|
|
|
// local events |
|
onDragDetected: function(/*Event*/ e){ |
|
// summary: |
|
// called when the drag is detected; |
|
// responsible for creation of the mover |
|
new this.mover(this.node, e, this); |
|
}, |
|
onMoveStart: function(/*Mover*/ mover){ |
|
// summary: |
|
// called before every move operation |
|
topic.publish("/dnd/move/start", mover); |
|
domClass.add(win.body(), "dojoMove"); |
|
domClass.add(this.node, "dojoMoveItem"); |
|
}, |
|
onMoveStop: function(/*Mover*/ mover){ |
|
// summary: |
|
// called after every move operation |
|
topic.publish("/dnd/move/stop", mover); |
|
domClass.remove(win.body(), "dojoMove"); |
|
domClass.remove(this.node, "dojoMoveItem"); |
|
}, |
|
onFirstMove: function(/*===== mover, e =====*/){ |
|
// summary: |
|
// called during the very first move notification; |
|
// can be used to initialize coordinates, can be overwritten. |
|
// mover: Mover |
|
// e: Event |
|
|
|
// default implementation does nothing |
|
}, |
|
onMove: function(mover, leftTop /*=====, e =====*/){ |
|
// summary: |
|
// called during every move notification; |
|
// should actually move the node; can be overwritten. |
|
// mover: Mover |
|
// leftTop: Object |
|
// e: Event |
|
this.onMoving(mover, leftTop); |
|
var s = mover.node.style; |
|
s.left = leftTop.l + "px"; |
|
s.top = leftTop.t + "px"; |
|
this.onMoved(mover, leftTop); |
|
}, |
|
onMoving: function(/*===== mover, leftTop =====*/){ |
|
// summary: |
|
// called before every incremental move; can be overwritten. |
|
// mover: Mover |
|
// leftTop: Object |
|
|
|
// default implementation does nothing |
|
}, |
|
onMoved: function(/*===== mover, leftTop =====*/){ |
|
// summary: |
|
// called after every incremental move; can be overwritten. |
|
// mover: Mover |
|
// leftTop: Object |
|
|
|
// default implementation does nothing |
|
} |
|
}); |
|
|
|
/*===== |
|
Moveable.__MoveableArgs = declare([], { |
|
// handle: Node||String |
|
// A node (or node's id), which is used as a mouse handle. |
|
// If omitted, the node itself is used as a handle. |
|
handle: null, |
|
|
|
// delay: Number |
|
// delay move by this number of pixels |
|
delay: 0, |
|
|
|
// skip: Boolean |
|
// skip move of form elements |
|
skip: false, |
|
|
|
// mover: Object |
|
// a constructor of custom Mover |
|
mover: dnd.Mover |
|
}); |
|
=====*/ |
|
|
|
return Moveable; |
|
});
|
|
|