3 Copyright 2012 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
7 YUI.add('dd-drag', function(Y) {
11 * Provides the ability to drag a Node.
16 * Provides the ability to drag a Node.
25 DRAGGING = 'dragging',
26 DRAG_NODE = 'dragNode',
27 OFFSET_HEIGHT = 'offsetHeight',
28 OFFSET_WIDTH = 'offsetWidth',
31 * @description Handles the mouseup DOM event, does nothing internally just fires.
36 * @event drag:mouseDown
37 * @description Handles the mousedown DOM event, checks to see if you have a valid handle then starts the drag timers.
38 * @preventable _defMouseDownFn
39 * @param {EventFacade} event An Event Facade object with the following specific property added:
40 * <dl><dt>ev</dt><dd>The original mousedown event.</dd></dl>
44 EV_MOUSE_DOWN = 'drag:mouseDown',
46 * @event drag:afterMouseDown
47 * @description Fires after the mousedown event has been cleared.
48 * @param {EventFacade} event An Event Facade object with the following specific property added:
49 * <dl><dt>ev</dt><dd>The original mousedown event.</dd></dl>
53 EV_AFTER_MOUSE_DOWN = 'drag:afterMouseDown',
55 * @event drag:removeHandle
56 * @description Fires after a handle is removed.
57 * @param {EventFacade} event An Event Facade object with the following specific property added:
58 * <dl><dt>handle</dt><dd>The handle that was removed.</dd></dl>
62 EV_REMOVE_HANDLE = 'drag:removeHandle',
64 * @event drag:addHandle
65 * @description Fires after a handle is added.
66 * @param {EventFacade} event An Event Facade object with the following specific property added:
67 * <dl><dt>handle</dt><dd>The handle that was added.</dd></dl>
71 EV_ADD_HANDLE = 'drag:addHandle',
73 * @event drag:removeInvalid
74 * @description Fires after an invalid selector is removed.
75 * @param {EventFacade} event An Event Facade object with the following specific property added:
76 * <dl><dt>handle</dt><dd>The handle that was removed.</dd></dl>
80 EV_REMOVE_INVALID = 'drag:removeInvalid',
82 * @event drag:addInvalid
83 * @description Fires after an invalid selector is added.
84 * @param {EventFacade} event An Event Facade object with the following specific property added:
85 * <dl><dt>handle</dt><dd>The handle that was added.</dd></dl>
89 EV_ADD_INVALID = 'drag:addInvalid',
92 * @description Fires at the start of a drag operation.
93 * @param {EventFacade} event An Event Facade object with the following specific property added:
95 * <dt>pageX</dt><dd>The original node position X.</dd>
96 * <dt>pageY</dt><dd>The original node position Y.</dd>
97 * <dt>startTime</dt><dd>The startTime of the event. getTime on the current Date object.</dd>
100 * @type {CustomEvent}
102 EV_START = 'drag:start',
105 * @description Fires at the end of a drag operation.
106 * @param {EventFacade} event An Event Facade object with the following specific property added:
108 * <dt>pageX</dt><dd>The current node position X.</dd>
109 * <dt>pageY</dt><dd>The current node position Y.</dd>
110 * <dt>startTime</dt><dd>The startTime of the event, from the start event.</dd>
111 * <dt>endTime</dt><dd>The endTime of the event. getTime on the current Date object.</dd>
114 * @type {CustomEvent}
119 * @description Fires every mousemove during a drag operation.
120 * @param {EventFacade} event An Event Facade object with the following specific property added:
122 * <dt>pageX</dt><dd>The current node position X.</dd>
123 * <dt>pageY</dt><dd>The current node position Y.</dd>
124 * <dt>scroll</dt><dd>Should a scroll action occur.</dd>
125 * <dt>info</dt><dd>Object hash containing calculated XY arrays: start, xy, delta, offset</dd>
128 * @type {CustomEvent}
130 EV_DRAG = 'drag:drag',
133 * @preventable _defAlignFn
134 * @description Fires when this node is aligned.
135 * @param {EventFacade} event An Event Facade object with the following specific property added:
137 * <dt>pageX</dt><dd>The current node position X.</dd>
138 * <dt>pageY</dt><dd>The current node position Y.</dd>
141 * @type {CustomEvent}
143 EV_ALIGN = 'drag:align',
146 * @description Fires when this node is over a Drop Target. (Fired from dd-drop)
147 * @param {EventFacade} event An Event Facade object with the following specific property added:
149 * <dt>drop</dt><dd>The drop object at the time of the event.</dd>
150 * <dt>drag</dt><dd>The drag object at the time of the event.</dd>
153 * @type {CustomEvent}
157 * @description Fires when this node enters a Drop Target. (Fired from dd-drop)
158 * @param {EventFacade} event An Event Facade object with the following specific property added:
160 * <dt>drop</dt><dd>The drop object at the time of the event.</dd>
161 * <dt>drag</dt><dd>The drag object at the time of the event.</dd>
164 * @type {CustomEvent}
168 * @description Fires when this node exits a Drop Target. (Fired from dd-drop)
169 * @param {EventFacade} event An Event Facade object with the following specific property added:
171 * <dt>drop</dt><dd>The drop object at the time of the event.</dd>
174 * @type {CustomEvent}
177 * @event drag:drophit
178 * @description Fires when this node is dropped on a valid Drop Target. (Fired from dd-ddm-drop)
179 * @param {EventFacade} event An Event Facade object with the following specific property added:
181 * <dt>drop</dt><dd>The best guess on what was dropped on.</dd>
182 * <dt>drag</dt><dd>The drag object at the time of the event.</dd>
183 * <dt>others</dt><dd>An array of all the other drop targets that was dropped on.</dd>
186 * @type {CustomEvent}
189 * @event drag:dropmiss
190 * @description Fires when this node is dropped on an invalid Drop Target. (Fired from dd-ddm-drop)
191 * @param {EventFacade} event An Event Facade object with the following specific property added:
193 * <dt>pageX</dt><dd>The current node position X.</dd>
194 * <dt>pageY</dt><dd>The current node position Y.</dd>
197 * @type {CustomEvent}
201 this._lazyAddAttrs = false;
202 Drag.superclass.constructor.apply(this, arguments);
204 var valid = DDM._regDrag(this);
206 Y.error('Failed to register node, already in use: ' + o.node);
213 * This property defaults to "mousedown", but when drag-gestures is loaded, it is changed to "gesturemovestart"
215 * @property START_EVENT
217 Drag.START_EVENT = 'mousedown';
222 * @description Y.Node instance to use as the element to initiate a drag operation
226 setter: function(node) {
227 if (this._canDrag(node)) {
232 Y.error('DD.Drag: Invalid Node Given: ' + node);
238 * @attribute dragNode
239 * @description Y.Node instance to use as the draggable element, defaults to node
243 setter: function(node) {
244 if (this._canDrag(node)) {
249 Y.error('DD.Drag: Invalid dragNode Given: ' + node);
255 * @attribute offsetNode
256 * @description Offset the drag element by the difference in cursor position: default true
263 * @attribute startCentered
264 * @description Center the dragNode to the mouse position on drag:start: default false
271 * @attribute clickPixelThresh
272 * @description The number of pixels to move to start a drag operation, default is 3.
276 value: DDM.get('clickPixelThresh')
279 * @attribute clickTimeThresh
280 * @description The number of milliseconds a mousedown has to pass to start a drag operation, default is 1000.
284 value: DDM.get('clickTimeThresh')
288 * @description Set to lock this drag element so that it can't be dragged: default false.
293 setter: function(lock) {
295 this.get(NODE).addClass(DDM.CSS_PREFIX + '-locked');
297 this.get(NODE).removeClass(DDM.CSS_PREFIX + '-locked');
304 * @description A payload holder to store arbitrary data about this drag object, can be used to store any value.
312 * @description If this is false, the drag element will not move with the cursor: default true. Can be used to "resize" the element.
320 * @description Use the protective shim on all drag operations: default true. Only works with dd-ddm, not dd-ddm-base.
327 * @attribute activeHandle
328 * @description This config option is set by Drag to inform you of which handle fired the drag event (in the case that there are several handles): default false.
335 * @attribute primaryButtonOnly
336 * @description By default a drag operation will only begin if the mousedown occurred with the primary mouse button. Setting this to false will allow for all mousedown events to trigger a drag.
343 * @attribute dragging
344 * @description This attribute is not meant to be used by the implementor, it is meant to be used as an Event tracker so you can listen for it to change.
355 * @description This attribute only works if the dd-drop module has been loaded. It will make this node a drop target as well as draggable.
360 setter: function(config) {
361 this._handleTarget(config);
366 * @attribute dragMode
367 * @description This attribute only works if the dd-drop module is active. It will set the dragMode (point, intersect, strict) of this Drag instance.
372 setter: function(mode) {
373 return DDM._setDragMode(mode);
378 * @description Array of groups to add this drag into.
388 Y.each(this._groups, function(v, k) {
393 setter: function(g) {
395 Y.each(g, function(v, k) {
396 this._groups[v] = true;
403 * @description Array of valid handles to add. Adding something here will set all handles, even if previously added with addHandle
408 setter: function(g) {
411 Y.each(g, function(v, k) {
413 if (v instanceof Y.Node || v instanceof Y.NodeList) {
416 this._handles[key] = v;
419 this._handles = null;
427 * @description Controls the default bubble parent for this Drag instance. Default: Y.DD.DDM. Set to false to disable bubbling. Use bubbleTargets in config
431 setter: function(t) {
437 * @attribute haltDown
438 * @description Should the mousedown event be halted. Default: true
446 Y.extend(Drag, Y.Base, {
448 * Checks the object for the methods needed to drag the object around.
449 * Normally this would be a node instance, but in the case of Graphics, it
450 * may be an SVG node or something similar.
453 * @param {Object} n The object to check
454 * @return {Boolean} True or false if the Object contains the methods needed to Drag
456 _canDrag: function(n) {
457 if (n && n.setXY && n.getXY && n.test && n.contains) {
464 * @property _bubbleTargets
465 * @description The default bubbleTarget for this object. Default: Y.DD.DDM
467 _bubbleTargets: Y.DD.DDM,
470 * @description Add this Drag instance to a group, this should be used for on-the-fly group additions.
471 * @param {String} g The group to add this Drag Instance to.
475 addToGroup: function(g) {
476 this._groups[g] = true;
477 DDM._activateTargets();
481 * @method removeFromGroup
482 * @description Remove this Drag instance from a group, this should be used for on-the-fly group removals.
483 * @param {String} g The group to remove this Drag Instance from.
487 removeFromGroup: function(g) {
488 delete this._groups[g];
489 DDM._activateTargets();
494 * @description This will be a reference to the Drop instance associated with this drag if the target: true config attribute is set..
500 * @method _handleTarget
501 * @description Attribute handler for the target config attribute.
502 * @param {Boolean/Object} config The Config
504 _handleTarget: function(config) {
506 if (config === false) {
508 DDM._unregTarget(this.target);
513 if (!Y.Lang.isObject(config)) {
516 config.bubbleTargets = ('bubbleTargets' in config) ? config.bubbleTargets : Y.Object.values(this._yuievt.targets);
517 config.node = this.get(NODE);
518 config.groups = config.groups || this.get('groups');
519 this.target = new Y.DD.Drop(config);
528 * @description Storage Array for the groups this drag belongs to.
534 * @method _createEvents
535 * @description This method creates all the events for this Event Target and publishes them so we get Event Bubbling.
537 _createEvents: function() {
539 this.publish(EV_MOUSE_DOWN, {
540 defaultFn: this._defMouseDownFn,
547 this.publish(EV_ALIGN, {
548 defaultFn: this._defAlignFn,
555 this.publish(EV_DRAG, {
556 defaultFn: this._defDragFn,
563 this.publish(EV_END, {
564 defaultFn: this._defEndFn,
565 preventedFn: this._prevEndFn,
586 Y.each(ev, function(v, k) {
600 * @description A private reference to the mousedown DOM event
601 * @type {EventFacade}
606 * @property _startTime
607 * @description The getTime of the mousedown event. Not used, just here in case someone wants/needs to use it.
614 * @description The getTime of the mouseup event. Not used, just here in case someone wants/needs to use it.
621 * @description A private hash of the valid drag handles
627 * @property _invalids
628 * @description A private hash of the invalid selector strings
634 * @property _invalidsDefault
635 * @description A private hash of the default invalid selector strings: {'textarea': true, 'input': true, 'a': true, 'button': true, 'select': true}
638 _invalidsDefault: {'textarea': true, 'input': true, 'a': true, 'button': true, 'select': true },
641 * @property _dragThreshMet
642 * @description Private flag to see if the drag threshhold was met
645 _dragThreshMet: null,
648 * @property _fromTimeout
649 * @description Flag to determine if the drag operation came from a timeout
655 * @property _clickTimeout
656 * @description Holder for the setTimeout call
662 * @description The offset of the mouse position to the element's position
668 * @description The initial mouse position
674 * @description The initial element position
680 * @description The position of the element as it's moving (for offset calculations)
686 * @description The xy that the node will be set to. Changing this will alter the position as it's dragged.
692 * @description The real xy position of the node.
698 * @description The XY coords of the mousemove
704 * @description A region object associated with this drag, used for checking regions while dragging.
710 * @method _handleMouseUp
711 * @description Handler for the mouseup DOM event
712 * @param {EventFacade} ev The Event
714 _handleMouseUp: function(ev) {
715 this.fire('drag:mouseup');
716 this._fixIEMouseUp();
717 if (DDM.activeDrag) {
723 * @method _fixDragStart
724 * @description The function we use as the ondragstart handler when we start a drag in Internet Explorer. This keeps IE from blowing up on images as drag handles.
725 * @param {Event} e The Event
727 _fixDragStart: function(e) {
732 * @method _ieSelectFix
733 * @description The function we use as the onselectstart handler when we start a drag in Internet Explorer
735 _ieSelectFix: function() {
740 * @property _ieSelectBack
741 * @description We will hold a copy of the current "onselectstart" method on this property, and reset it after we are done using it.
746 * @method _fixIEMouseDown
747 * @description This method copies the onselectstart listner on the document to the _ieSelectFix property
749 _fixIEMouseDown: function(e) {
751 this._ieSelectBack = Y.config.doc.body.onselectstart;
752 Y.config.doc.body.onselectstart = this._ieSelectFix;
757 * @method _fixIEMouseUp
758 * @description This method copies the _ieSelectFix property back to the onselectstart listner on the document.
760 _fixIEMouseUp: function() {
762 Y.config.doc.body.onselectstart = this._ieSelectBack;
767 * @method _handleMouseDownEvent
768 * @description Handler for the mousedown DOM event
769 * @param {EventFacade} ev The Event
771 _handleMouseDownEvent: function(ev) {
772 this.fire(EV_MOUSE_DOWN, { ev: ev });
776 * @method _defMouseDownFn
777 * @description Handler for the mousedown DOM event
778 * @param {EventFacade} e The Event
780 _defMouseDownFn: function(e) {
783 this._dragThreshMet = false;
786 if (this.get('primaryButtonOnly') && ev.button > 1) {
789 if (this.validClick(ev)) {
790 this._fixIEMouseDown(ev);
791 if (this.get('haltDown')) {
797 this._setStartPosition([ev.pageX, ev.pageY]);
799 DDM.activeDrag = this;
801 this._clickTimeout = Y.later(this.get('clickTimeThresh'), this, this._timeoutCheck);
803 this.fire(EV_AFTER_MOUSE_DOWN, { ev: ev });
807 * @description Method first checks to see if we have handles, if so it validates the click against the handle. Then if it finds a valid handle, it checks it against the invalid handles list. Returns true if a good handle was used, false otherwise.
808 * @param {EventFacade} ev The Event
811 validClick: function(ev) {
812 var r = false, n = false,
819 Y.each(this._handles, function(i, n) {
820 if (i instanceof Y.Node || i instanceof Y.NodeList) {
823 if (nlist instanceof Y.Node) {
824 nlist = new Y.NodeList(i._node);
826 nlist.each(function(nl) {
827 if (nl.contains(tar)) {
832 } else if (Y.Lang.isString(n)) {
833 //Am I this or am I inside this
834 if (tar.test(n + ', ' + n + ' *') && !hTest) {
842 if (n.contains(tar) || n.compareTo(tar)) {
847 if (this._invalids) {
848 Y.each(this._invalids, function(i, n) {
849 if (Y.Lang.isString(n)) {
850 //Am I this or am I inside this
851 if (tar.test(n + ', ' + n + ' *')) {
860 els = ev.currentTarget.all(hTest);
862 els.each(function(n, i) {
863 if ((n.contains(tar) || n.compareTo(tar)) && !set) {
865 this.set('activeHandle', n);
869 this.set('activeHandle', this.get(NODE));
876 * @method _setStartPosition
877 * @description Sets the current position of the Element and calculates the offset
878 * @param {Array} xy The XY coords to set the position to.
880 _setStartPosition: function(xy) {
883 this.nodeXY = this.lastXY = this.realXY = this.get(NODE).getXY();
885 if (this.get('offsetNode')) {
886 this.deltaXY = [(this.startXY[0] - this.nodeXY[0]), (this.startXY[1] - this.nodeXY[1])];
888 this.deltaXY = [0, 0];
893 * @method _timeoutCheck
894 * @description The method passed to setTimeout to determine if the clickTimeThreshold was met.
896 _timeoutCheck: function() {
897 if (!this.get('lock') && !this._dragThreshMet && this._ev_md) {
898 this._fromTimeout = this._dragThreshMet = true;
900 this._alignNode([this._ev_md.pageX, this._ev_md.pageY], true);
904 * @method removeHandle
905 * @description Remove a Selector added by addHandle
906 * @param {String} str The selector for the handle to be removed.
910 removeHandle: function(str) {
912 if (str instanceof Y.Node || str instanceof Y.NodeList) {
915 if (this._handles[key]) {
916 delete this._handles[key];
917 this.fire(EV_REMOVE_HANDLE, { handle: str });
923 * @description Add a handle to a drag element. Drag only initiates when a mousedown happens on this element.
924 * @param {String} str The selector to test for a valid handle. Must be a child of the element.
928 addHandle: function(str) {
929 if (!this._handles) {
933 if (str instanceof Y.Node || str instanceof Y.NodeList) {
936 this._handles[key] = str;
937 this.fire(EV_ADD_HANDLE, { handle: str });
941 * @method removeInvalid
942 * @description Remove an invalid handle added by addInvalid
943 * @param {String} str The invalid handle to remove from the internal list.
947 removeInvalid: function(str) {
948 if (this._invalids[str]) {
949 this._invalids[str] = null;
950 delete this._invalids[str];
951 this.fire(EV_REMOVE_INVALID, { handle: str });
957 * @description Add a selector string to test the handle against. If the test passes the drag operation will not continue.
958 * @param {String} str The selector to test against to determine if this is an invalid drag handle.
962 addInvalid: function(str) {
963 if (Y.Lang.isString(str)) {
964 this._invalids[str] = true;
965 this.fire(EV_ADD_INVALID, { handle: str });
971 * @method initializer
972 * @description Internal init handler
974 initializer: function(cfg) {
976 this.get(NODE).dd = this;
978 if (!this.get(NODE).get('id')) {
979 var id = Y.stamp(this.get(NODE));
980 this.get(NODE).set('id', id);
985 this._invalids = Y.clone(this._invalidsDefault, true);
987 this._createEvents();
989 if (!this.get(DRAG_NODE)) {
990 this.set(DRAG_NODE, this.get(NODE));
994 //Don't prep the DD instance until all plugins are loaded.
995 this.on('initializedChange', Y.bind(this._prep, this));
997 //Shouldn't have to do this..
998 this.set('groups', this.get('groups'));
1003 * @description Attach event listners and add classname
1006 this._dragThreshMet = false;
1007 var node = this.get(NODE);
1008 node.addClass(DDM.CSS_PREFIX + '-draggable');
1009 node.on(Drag.START_EVENT, Y.bind(this._handleMouseDownEvent, this));
1010 node.on('mouseup', Y.bind(this._handleMouseUp, this));
1011 node.on('dragstart', Y.bind(this._fixDragStart, this));
1016 * @description Detach event listeners and remove classname
1018 _unprep: function() {
1019 var node = this.get(NODE);
1020 node.removeClass(DDM.CSS_PREFIX + '-draggable');
1021 node.detachAll('mouseup');
1022 node.detachAll('dragstart');
1023 node.detachAll(Drag.START_EVENT);
1025 this.deltaXY = [0,0];
1034 * @description Starts the drag operation
1039 if (!this.get('lock') && !this.get(DRAGGING)) {
1040 var node = this.get(NODE), ow, oh, xy;
1041 this._startTime = (new Date()).getTime();
1044 node.addClass(DDM.CSS_PREFIX + '-dragging');
1045 this.fire(EV_START, {
1046 pageX: this.nodeXY[0],
1047 pageY: this.nodeXY[1],
1048 startTime: this._startTime
1050 node = this.get(DRAG_NODE);
1053 ow = node.get(OFFSET_WIDTH);
1054 oh = node.get(OFFSET_HEIGHT);
1056 if (this.get('startCentered')) {
1057 this._setStartPosition([xy[0] + (ow / 2), xy[1] + (oh / 2)]);
1070 this.set(DRAGGING, true);
1076 * @description Ends the drag operation
1081 this._endTime = (new Date()).getTime();
1082 if (this._clickTimeout) {
1083 this._clickTimeout.cancel();
1085 this._dragThreshMet = this._fromTimeout = false;
1087 if (!this.get('lock') && this.get(DRAGGING)) {
1089 pageX: this.lastXY[0],
1090 pageY: this.lastXY[1],
1091 startTime: this._startTime,
1092 endTime: this._endTime
1095 this.get(NODE).removeClass(DDM.CSS_PREFIX + '-dragging');
1096 this.set(DRAGGING, false);
1097 this.deltaXY = [0, 0];
1104 * @description Handler for fixing the selection in IE
1106 _defEndFn: function(e) {
1107 this._fixIEMouseUp();
1112 * @method _prevEndFn
1113 * @description Handler for preventing the drag:end event. It will reset the node back to it's start position
1115 _prevEndFn: function(e) {
1116 this._fixIEMouseUp();
1118 this.get(DRAG_NODE).setXY(this.nodeXY);
1125 * @description Calculates the offsets and set's the XY that the element will move to.
1126 * @param {Array} xy The xy coords to align with.
1128 _align: function(xy) {
1129 this.fire(EV_ALIGN, {pageX: xy[0], pageY: xy[1] });
1133 * @method _defAlignFn
1134 * @description Calculates the offsets and set's the XY that the element will move to.
1135 * @param {EventFacade} e The drag:align event.
1137 _defAlignFn: function(e) {
1138 this.actXY = [e.pageX - this.deltaXY[0], e.pageY - this.deltaXY[1]];
1142 * @method _alignNode
1143 * @description This method performs the alignment before the element move.
1144 * @param {Array} eXY The XY to move the element to, usually comes from the mousemove DOM event.
1146 _alignNode: function(eXY) {
1153 * @description This method performs the actual element move.
1155 _moveNode: function(scroll) {
1156 //if (!this.get(DRAGGING)) {
1159 var diffXY = [], diffXY2 = [], startXY = this.nodeXY, xy = this.actXY;
1161 diffXY[0] = (xy[0] - this.lastXY[0]);
1162 diffXY[1] = (xy[1] - this.lastXY[1]);
1164 diffXY2[0] = (xy[0] - this.nodeXY[0]);
1165 diffXY2[1] = (xy[1] - this.nodeXY[1]);
1173 right: xy[0] + this.get(DRAG_NODE).get(OFFSET_WIDTH),
1174 bottom: xy[1] + this.get(DRAG_NODE).get(OFFSET_HEIGHT),
1178 this.fire(EV_DRAG, {
1194 * @method _defDragFn
1195 * @description Default function for drag:drag. Fired from _moveNode.
1196 * @param {EventFacade} ev The drag:drag event
1198 _defDragFn: function(e) {
1199 if (this.get('move')) {
1201 e.scroll.node.set('scrollTop', e.scroll.top);
1202 e.scroll.node.set('scrollLeft', e.scroll.left);
1204 this.get(DRAG_NODE).setXY([e.pageX, e.pageY]);
1205 this.realXY = [e.pageX, e.pageY];
1211 * @description Fired from DragDropMgr (DDM) on mousemove.
1212 * @param {EventFacade} ev The mousemove DOM event
1214 _move: function(ev) {
1215 if (this.get('lock')) {
1218 this.mouseXY = [ev.pageX, ev.pageY];
1219 if (!this._dragThreshMet) {
1220 var diffX = Math.abs(this.startXY[0] - ev.pageX),
1221 diffY = Math.abs(this.startXY[1] - ev.pageY);
1222 if (diffX > this.get('clickPixelThresh') || diffY > this.get('clickPixelThresh')) {
1223 this._dragThreshMet = true;
1225 this._alignNode([ev.pageX, ev.pageY]);
1228 if (this._clickTimeout) {
1229 this._clickTimeout.cancel();
1231 this._alignNode([ev.pageX, ev.pageY]);
1237 * @description Method will forcefully stop a drag operation. For example calling this from inside an ESC keypress handler will stop this drag.
1241 stopDrag: function() {
1242 if (this.get(DRAGGING)) {
1249 * @method destructor
1250 * @description Lifecycle destructor, unreg the drag from the DDM and remove listeners
1252 destructor: function() {
1255 this.target.destroy();
1257 DDM._unregDrag(this);
1266 }, '3.5.1' ,{skinnable:false, requires:['dd-ddm-base']});