3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * This is a derivative of the similarly named class in the YUI Library.
17 * The original license:
18 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
19 * Code licensed under the BSD License:
20 * http://developer.yahoo.net/yui/license.txt
25 * Defines the interface and base operation of items that that can be
26 * dragged or can be drop targets. It was designed to be extended, overriding
27 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
28 * Up to three html elements can be associated with a DragDrop instance:
30 * - linked element: the element that is passed into the constructor.
31 * This is the element which defines the boundaries for interaction with
32 * other DragDrop objects.
34 * - handle element(s): The drag operation only occurs if the element that
35 * was clicked matches a handle element. By default this is the linked
36 * element, but there are times that you will want only a portion of the
37 * linked element to initiate the drag operation, and the setHandleElId()
38 * method provides a way to define this.
40 * - drag element: this represents the element that would be moved along
41 * with the cursor during a drag operation. By default, this is the linked
42 * element itself as in {@link Ext.dd.DD}. setDragElId() lets you define
43 * a separate element that would be moved, as in {@link Ext.dd.DDProxy}.
45 * This class should not be instantiated until the onload event to ensure that
46 * the associated elements are available.
47 * The following would define a DragDrop obj that would interact with any
48 * other DragDrop obj in the "group1" group:
50 * dd = new Ext.dd.DragDrop("div1", "group1");
52 * Since none of the event handlers have been implemented, nothing would
53 * actually happen if you were to run the code above. Normally you would
54 * override this class or one of the default implementations, but you can
55 * also override the methods you want on an instance of the class...
57 * dd.onDragDrop = function(e, id) {
58 * alert("dd was dropped on " + id);
62 Ext.define('Ext.dd.DragDrop', {
63 requires: ['Ext.dd.DragDropManager'],
66 * Creates new DragDrop.
67 * @param {String} id of the element that is linked to this instance
68 * @param {String} sGroup the group of related DragDrop objects
69 * @param {object} config an object containing configurable attributes.
70 * Valid properties for DragDrop:
77 constructor: function(id, sGroup, config) {
79 this.init(id, sGroup, config);
84 * Set to false to enable a DragDrop object to fire drag events while dragging
85 * over its own Element. Defaults to true - DragDrop objects do not by default
86 * fire drag events to themselves.
87 * @property ignoreSelf
92 * The id of the element associated with this object. This is what we
93 * refer to as the "linked element" because the size and position of
94 * this element is used to determine when the drag and drop objects have
102 * Configuration attributes passed into the constructor
109 * The id of the element that will be dragged. By default this is same
110 * as the linked element, but could be changed to another element. Ex:
119 * The ID of the element that initiates the drag operation. By default
120 * this is the linked element, but could be changed to be a child of this
121 * element. This lets us do things like only starting the drag when the
122 * header element within the linked html element is clicked.
123 * @property handleElId
130 * An object who's property names identify HTML tags to be considered invalid as drag handles.
131 * A non-null property value identifies the tag as invalid. Defaults to the
132 * following value which prevents drag operations from being initiated by <a> elements:<pre><code>
136 * @property invalidHandleTypes
139 invalidHandleTypes: null,
142 * An object who's property names identify the IDs of elements to be considered invalid as drag handles.
143 * A non-null property value identifies the ID as invalid. For example, to prevent
144 * dragging from being initiated on element ID "foo", use:<pre><code>
148 * @property invalidHandleIds
151 invalidHandleIds: null,
154 * An Array of CSS class names for elements to be considered in valid as drag handles.
155 * @property invalidHandleClasses
158 invalidHandleClasses: null,
161 * The linked element's absolute X position at the time the drag was
163 * @property startPageX
170 * The linked element's absolute X position at the time the drag was
172 * @property startPageY
179 * The group defines a logical collection of DragDrop objects that are
180 * related. Instances only get events when interacting with other
181 * DragDrop object in the same group. This lets us define multiple
182 * groups using a single DragDrop subclass if we want.
184 * @type object An object in the format {'group1':true, 'group2':true}
189 * Individual drag/drop instances can be locked. This will prevent
190 * onmousedown start drag.
198 * Locks this instance
205 * When set to true, other DD objects in cooperating DDGroups do not receive
206 * notification events when this DD object is dragged over them. Defaults to false.
213 * Unlocks this instace
220 * By default, all instances can be a drop target. This can be disabled by
221 * setting isTarget to false.
228 * The padding configured for this drag and drop object for calculating
229 * the drop zone intersection with this object.
230 * An array containing the 4 padding values: [top, right, bottom, left]
231 * @property {[int]} padding
236 * Cached reference to the linked element
243 * Internal typeof flag
244 * @property __ygDragDrop
250 * Set to true when horizontal contraints are applied
251 * @property constrainX
258 * Set to true when vertical contraints are applied
259 * @property constrainY
266 * The left constraint
274 * The right constraint
290 * The down constraint
298 * Maintain offsets when we resetconstraints. Set to true when you want
299 * the position of the element relative to its parent to stay the same
300 * when the page changes
302 * @property maintainOffset
305 maintainOffset: false,
308 * Array of pixel locations the element will snap to if we specified a
309 * horizontal graduation/interval. This array is generated automatically
310 * when you define a tick interval.
311 * @property {[int]} xTicks
316 * Array of pixel locations the element will snap to if we specified a
317 * vertical graduation/interval. This array is generated automatically
318 * when you define a tick interval.
319 * @property {[int]} yTicks
324 * By default the drag and drop instance will only respond to the primary
325 * button click (left button for a right-handed mouse). Set to true to
326 * allow drag and drop to start with any mouse click that is propogated
328 * @property primaryButtonOnly
331 primaryButtonOnly: true,
334 * The available property is false until the linked dom element is accessible.
335 * @property available
341 * By default, drags can only be initiated if the mousedown occurs in the
342 * region the linked element is. This is done in part to work around a
343 * bug in some browsers that mis-report the mousedown if the previous
344 * mouseup happened outside of the window. This property is set to true
345 * if outer handles are defined. Defaults to false.
347 * @property hasOuterHandles
350 hasOuterHandles: false,
353 * Code that executes immediately before the startDrag event
356 b4StartDrag: function(x, y) { },
359 * Abstract method called after a drag/drop object is clicked
360 * and the drag or mousedown time thresholds have beeen met.
361 * @param {int} X click location
362 * @param {int} Y click location
364 startDrag: function(x, y) { /* override this */ },
367 * Code that executes immediately before the onDrag event
370 b4Drag: function(e) { },
373 * Abstract method called during the onMouseMove event while dragging an
375 * @param {Event} e the mousemove event
377 onDrag: function(e) { /* override this */ },
380 * Abstract method called when this element fist begins hovering over
381 * another DragDrop obj
382 * @param {Event} e the mousemove event
383 * @param {String/[DragDrop]} id In POINT mode, the element
384 * id this is hovering over. In INTERSECT mode, an array of one or more
385 * dragdrop items being hovered over.
387 onDragEnter: function(e, id) { /* override this */ },
390 * Code that executes immediately before the onDragOver event
393 b4DragOver: function(e) { },
396 * Abstract method called when this element is hovering over another
398 * @param {Event} e the mousemove event
399 * @param {String|DragDrop[]} id In POINT mode, the element
400 * id this is hovering over. In INTERSECT mode, an array of dd items
401 * being hovered over.
403 onDragOver: function(e, id) { /* override this */ },
406 * Code that executes immediately before the onDragOut event
409 b4DragOut: function(e) { },
412 * Abstract method called when we are no longer hovering over an element
413 * @param {Event} e the mousemove event
414 * @param {String/[DragDrop]} id In POINT mode, the element
415 * id this was hovering over. In INTERSECT mode, an array of dd items
416 * that the mouse is no longer over.
418 onDragOut: function(e, id) { /* override this */ },
421 * Code that executes immediately before the onDragDrop event
424 b4DragDrop: function(e) { },
427 * Abstract method called when this item is dropped on another DragDrop
429 * @param {Event} e the mouseup event
430 * @param {String/[DragDrop]} id In POINT mode, the element
431 * id this was dropped on. In INTERSECT mode, an array of dd items this
434 onDragDrop: function(e, id) { /* override this */ },
437 * Abstract method called when this item is dropped on an area with no
439 * @param {Event} e the mouseup event
441 onInvalidDrop: function(e) { /* override this */ },
444 * Code that executes immediately before the endDrag event
447 b4EndDrag: function(e) { },
450 * Called when we are done dragging the object
451 * @param {Event} e the mouseup event
453 endDrag: function(e) { /* override this */ },
456 * Code executed immediately before the onMouseDown event
457 * @param {Event} e the mousedown event
460 b4MouseDown: function(e) { },
463 * Called when a drag/drop obj gets a mousedown
464 * @param {Event} e the mousedown event
466 onMouseDown: function(e) { /* override this */ },
469 * Called when a drag/drop obj gets a mouseup
470 * @param {Event} e the mouseup event
472 onMouseUp: function(e) { /* override this */ },
475 * Override the onAvailable method to do what is needed after the initial
476 * position was determined.
478 onAvailable: function () {
482 * Provides default constraint padding to "constrainTo" elements (defaults to `{left:0, right:0, top:0, bottom:0}`).
493 * Initializes the drag drop object's constraints to restrict movement to a certain element.
497 * var dd = new Ext.dd.DDProxy("dragDiv1", "proxytest",
498 * { dragElId: "existingProxyDiv" });
499 * dd.startDrag = function(){
500 * this.constrainTo("parent-id");
503 * Or you can initalize it using the {@link Ext.core.Element} object:
505 * Ext.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
506 * startDrag : function(){
507 * this.constrainTo("parent-id");
511 * @param {Mixed} constrainTo The element to constrain to.
512 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
513 * and can be either a number for symmetrical padding (4 would be equal to `{left:4, right:4, top:4, bottom:4}`) or
514 * an object containing the sides to pad. For example: `{right:10, bottom:10}`
515 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
517 constrainTo : function(constrainTo, pad, inContent){
518 if(Ext.isNumber(pad)){
519 pad = {left: pad, right:pad, top:pad, bottom:pad};
521 pad = pad || this.defaultPadding;
522 var b = Ext.get(this.getEl()).getBox(),
523 ce = Ext.get(constrainTo),
527 if(cd == document.body){
528 c = { x: s.left, y: s.top, width: Ext.core.Element.getViewWidth(), height: Ext.core.Element.getViewHeight()};
531 c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
535 var topSpace = b.y - c.y,
536 leftSpace = b.x - c.x;
538 this.resetConstraints();
539 this.setXConstraint(leftSpace - (pad.left||0), // left
540 c.width - leftSpace - b.width - (pad.right||0), //right
543 this.setYConstraint(topSpace - (pad.top||0), //top
544 c.height - topSpace - b.height - (pad.bottom||0), //bottom
550 * Returns a reference to the linked element
551 * @return {HTMLElement} the html element
555 this._domRef = Ext.getDom(this.id);
562 * Returns a reference to the actual element to drag. By default this is
563 * the same as the html element, but it can be assigned to another
564 * element. An example of this can be found in Ext.dd.DDProxy
565 * @return {HTMLElement} the html element
567 getDragEl: function() {
568 return Ext.getDom(this.dragElId);
572 * Sets up the DragDrop object. Must be called in the constructor of any
573 * Ext.dd.DragDrop subclass
574 * @param {String} id the id of the linked element
575 * @param {String} sGroup the group of related items
576 * @param {Object} config configuration attributes
578 init: function(id, sGroup, config) {
579 this.initTarget(id, sGroup, config);
580 Ext.EventManager.on(this.id, "mousedown", this.handleMouseDown, this);
581 // Ext.EventManager.on(this.id, "selectstart", Event.preventDefault);
585 * Initializes Targeting functionality only... the object does not
586 * get a mousedown handler.
587 * @param {String} id the id of the linked element
588 * @param {String} sGroup the group of related items
589 * @param {Object} config configuration attributes
591 initTarget: function(id, sGroup, config) {
592 // configuration attributes
593 this.config = config || {};
595 // create a local reference to the drag and drop manager
596 this.DDMInstance = Ext.dd.DragDropManager;
597 // initialize the groups array
600 // assume that we have an element reference instead of an id if the
601 // parameter is not a string
602 if (typeof id !== "string") {
609 // add to an interaction group
610 this.addToGroup((sGroup) ? sGroup : "default");
612 // We don't want to register this as the handle with the manager
613 // so we just set the id rather than calling the setter.
614 this.handleElId = id;
616 // the linked element is the element that gets dragged by default
617 this.setDragElId(id);
619 // by default, clicked anchors will not start drag operations.
620 this.invalidHandleTypes = { A: "A" };
621 this.invalidHandleIds = {};
622 this.invalidHandleClasses = [];
626 this.handleOnAvailable();
630 * Applies the configuration parameters that were passed into the constructor.
631 * This is supposed to happen at each level through the inheritance chain. So
632 * a DDProxy implentation will execute apply config on DDProxy, DD, and
633 * DragDrop in order to get all of the parameters that are available in
636 applyConfig: function() {
638 // configurable properties:
639 // padding, isTarget, maintainOffset, primaryButtonOnly
640 this.padding = this.config.padding || [0, 0, 0, 0];
641 this.isTarget = (this.config.isTarget !== false);
642 this.maintainOffset = (this.config.maintainOffset);
643 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
648 * Executed when the linked element is available
651 handleOnAvailable: function() {
652 this.available = true;
653 this.resetConstraints();
658 * Configures the padding for the target zone in px. Effectively expands
659 * (or reduces) the virtual object size for targeting calculations.
660 * Supports css-style shorthand; if only one parameter is passed, all sides
661 * will have that padding, and if only two are passed, the top and bottom
662 * will have the first param, the left and right the second.
663 * @param {int} iTop Top pad
664 * @param {int} iRight Right pad
665 * @param {int} iBot Bot pad
666 * @param {int} iLeft Left pad
668 setPadding: function(iTop, iRight, iBot, iLeft) {
669 // this.padding = [iLeft, iRight, iTop, iBot];
670 if (!iRight && 0 !== iRight) {
671 this.padding = [iTop, iTop, iTop, iTop];
672 } else if (!iBot && 0 !== iBot) {
673 this.padding = [iTop, iRight, iTop, iRight];
675 this.padding = [iTop, iRight, iBot, iLeft];
680 * Stores the initial placement of the linked element.
681 * @param {int} diffX the X offset, default 0
682 * @param {int} diffY the Y offset, default 0
684 setInitPosition: function(diffX, diffY) {
685 var el = this.getEl();
687 if (!this.DDMInstance.verifyEl(el)) {
694 var p = Ext.core.Element.getXY( el );
696 this.initPageX = p[0] - dx;
697 this.initPageY = p[1] - dy;
699 this.lastPageX = p[0];
700 this.lastPageY = p[1];
702 this.setStartPosition(p);
706 * Sets the start position of the element. This is set when the obj
707 * is initialized, the reset when a drag is started.
708 * @param pos current position (from previous lookup)
711 setStartPosition: function(pos) {
712 var p = pos || Ext.core.Element.getXY( this.getEl() );
713 this.deltaSetXY = null;
715 this.startPageX = p[0];
716 this.startPageY = p[1];
720 * Adds this instance to a group of related drag/drop objects. All
721 * instances belong to at least one group, and can belong to as many
723 * @param {String} sGroup the name of the group
725 addToGroup: function(sGroup) {
726 this.groups[sGroup] = true;
727 this.DDMInstance.regDragDrop(this, sGroup);
731 * Removes this instance from the supplied interaction group
732 * @param {String} sGroup The group to drop
734 removeFromGroup: function(sGroup) {
735 if (this.groups[sGroup]) {
736 delete this.groups[sGroup];
739 this.DDMInstance.removeDDFromGroup(this, sGroup);
743 * Allows you to specify that an element other than the linked element
744 * will be moved with the cursor during a drag
745 * @param {String} id the id of the element that will be used to initiate the drag
747 setDragElId: function(id) {
752 * Allows you to specify a child of the linked element that should be
753 * used to initiate the drag operation. An example of this would be if
754 * you have a content div with text and links. Clicking anywhere in the
755 * content area would normally start the drag operation. Use this method
756 * to specify that an element inside of the content div is the element
757 * that starts the drag operation.
758 * @param {String} id the id of the element that will be used to
761 setHandleElId: function(id) {
762 if (typeof id !== "string") {
765 this.handleElId = id;
766 this.DDMInstance.regHandle(this.id, id);
770 * Allows you to set an element outside of the linked element as a drag
772 * @param {String} id the id of the element that will be used to initiate the drag
774 setOuterHandleElId: function(id) {
775 if (typeof id !== "string") {
778 Ext.EventManager.on(id, "mousedown", this.handleMouseDown, this);
779 this.setHandleElId(id);
781 this.hasOuterHandles = true;
785 * Removes all drag and drop hooks for this element
788 Ext.EventManager.un(this.id, "mousedown", this.handleMouseDown, this);
790 this.DDMInstance._remove(this);
793 destroy : function(){
798 * Returns true if this instance is locked, or the drag drop mgr is locked
799 * (meaning that all drag/drop is disabled on the page.)
800 * @return {Boolean} true if this obj or all drag/drop is locked, else
803 isLocked: function() {
804 return (this.DDMInstance.isLocked() || this.locked);
808 * Called when this object is clicked
810 * @param {Ext.dd.DragDrop} oDD the clicked dd object (this dd obj)
813 handleMouseDown: function(e, oDD){
814 if (this.primaryButtonOnly && e.button != 0) {
818 if (this.isLocked()) {
822 this.DDMInstance.refreshCache(this.groups);
824 var pt = e.getPoint();
825 if (!this.hasOuterHandles && !this.DDMInstance.isOverTarget(pt, this) ) {
827 if (this.clickValidator(e)) {
828 // set the initial element position
829 this.setStartPosition();
833 this.DDMInstance.handleMouseDown(e, this);
835 this.DDMInstance.stopEvent(e);
843 clickValidator: function(e) {
844 var target = e.getTarget();
845 return ( this.isValidHandleChild(target) &&
846 (this.id == this.handleElId ||
847 this.DDMInstance.handleWasClicked(target, this.id)) );
851 * Allows you to specify a tag name that should not start a drag operation
852 * when clicked. This is designed to facilitate embedding links within a
853 * drag handle that do something other than start the drag.
854 * @method addInvalidHandleType
855 * @param {String} tagName the type of element to exclude
857 addInvalidHandleType: function(tagName) {
858 var type = tagName.toUpperCase();
859 this.invalidHandleTypes[type] = type;
863 * Lets you to specify an element id for a child of a drag handle
864 * that should not initiate a drag
865 * @method addInvalidHandleId
866 * @param {String} id the element id of the element you wish to ignore
868 addInvalidHandleId: function(id) {
869 if (typeof id !== "string") {
872 this.invalidHandleIds[id] = id;
876 * Lets you specify a css class of elements that will not initiate a drag
877 * @param {String} cssClass the class of the elements you wish to ignore
879 addInvalidHandleClass: function(cssClass) {
880 this.invalidHandleClasses.push(cssClass);
884 * Unsets an excluded tag name set by addInvalidHandleType
885 * @param {String} tagName the type of element to unexclude
887 removeInvalidHandleType: function(tagName) {
888 var type = tagName.toUpperCase();
889 // this.invalidHandleTypes[type] = null;
890 delete this.invalidHandleTypes[type];
894 * Unsets an invalid handle id
895 * @param {String} id the id of the element to re-enable
897 removeInvalidHandleId: function(id) {
898 if (typeof id !== "string") {
901 delete this.invalidHandleIds[id];
905 * Unsets an invalid css class
906 * @param {String} cssClass the class of the element(s) you wish to
909 removeInvalidHandleClass: function(cssClass) {
910 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
911 if (this.invalidHandleClasses[i] == cssClass) {
912 delete this.invalidHandleClasses[i];
918 * Checks the tag exclusion list to see if this click should be ignored
919 * @param {HTMLElement} node the HTMLElement to evaluate
920 * @return {Boolean} true if this is a valid tag type, false if not
922 isValidHandleChild: function(node) {
925 // var n = (node.nodeName == "#text") ? node.parentNode : node;
928 nodeName = node.nodeName.toUpperCase();
930 nodeName = node.nodeName;
932 valid = valid && !this.invalidHandleTypes[nodeName];
933 valid = valid && !this.invalidHandleIds[node.id];
935 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
936 valid = !Ext.fly(node).hasCls(this.invalidHandleClasses[i]);
945 * Creates the array of horizontal tick marks if an interval was specified
946 * in setXConstraint().
949 setXTicks: function(iStartX, iTickSize) {
951 this.xTickSize = iTickSize;
955 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
957 this.xTicks[this.xTicks.length] = i;
962 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
964 this.xTicks[this.xTicks.length] = i;
969 Ext.Array.sort(this.xTicks, this.DDMInstance.numericSort);
973 * Creates the array of vertical tick marks if an interval was specified in
977 setYTicks: function(iStartY, iTickSize) {
979 this.yTickSize = iTickSize;
983 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
985 this.yTicks[this.yTicks.length] = i;
990 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
992 this.yTicks[this.yTicks.length] = i;
997 Ext.Array.sort(this.yTicks, this.DDMInstance.numericSort);
1001 * By default, the element can be dragged any place on the screen. Use
1002 * this method to limit the horizontal travel of the element. Pass in
1003 * 0,0 for the parameters if you want to lock the drag to the y axis.
1004 * @param {int} iLeft the number of pixels the element can move to the left
1005 * @param {int} iRight the number of pixels the element can move to the
1007 * @param {int} iTickSize optional parameter for specifying that the
1008 * element should move iTickSize pixels at a time.
1010 setXConstraint: function(iLeft, iRight, iTickSize) {
1011 this.leftConstraint = iLeft;
1012 this.rightConstraint = iRight;
1014 this.minX = this.initPageX - iLeft;
1015 this.maxX = this.initPageX + iRight;
1016 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
1018 this.constrainX = true;
1022 * Clears any constraints applied to this instance. Also clears ticks
1023 * since they can't exist independent of a constraint at this time.
1025 clearConstraints: function() {
1026 this.constrainX = false;
1027 this.constrainY = false;
1032 * Clears any tick interval defined for this instance
1034 clearTicks: function() {
1042 * By default, the element can be dragged any place on the screen. Set
1043 * this to limit the vertical travel of the element. Pass in 0,0 for the
1044 * parameters if you want to lock the drag to the x axis.
1045 * @param {int} iUp the number of pixels the element can move up
1046 * @param {int} iDown the number of pixels the element can move down
1047 * @param {int} iTickSize optional parameter for specifying that the
1048 * element should move iTickSize pixels at a time.
1050 setYConstraint: function(iUp, iDown, iTickSize) {
1051 this.topConstraint = iUp;
1052 this.bottomConstraint = iDown;
1054 this.minY = this.initPageY - iUp;
1055 this.maxY = this.initPageY + iDown;
1056 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
1058 this.constrainY = true;
1063 * Must be called if you manually reposition a dd element.
1064 * @param {boolean} maintainOffset
1066 resetConstraints: function() {
1067 // Maintain offsets if necessary
1068 if (this.initPageX || this.initPageX === 0) {
1069 // figure out how much this thing has moved
1070 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
1071 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
1073 this.setInitPosition(dx, dy);
1075 // This is the first time we have detected the element's position
1077 this.setInitPosition();
1080 if (this.constrainX) {
1081 this.setXConstraint( this.leftConstraint,
1082 this.rightConstraint,
1086 if (this.constrainY) {
1087 this.setYConstraint( this.topConstraint,
1088 this.bottomConstraint,
1094 * Normally the drag element is moved pixel by pixel, but we can specify
1095 * that it move a number of pixels at a time. This method resolves the
1096 * location when we have it set up like this.
1097 * @param {int} val where we want to place the object
1098 * @param {int[]} tickArray sorted array of valid points
1099 * @return {int} the closest tick
1102 getTick: function(val, tickArray) {
1104 // If tick interval is not defined, it is effectively 1 pixel,
1105 // so we return the value passed to us.
1107 } else if (tickArray[0] >= val) {
1108 // The value is lower than the first tick, so we return the first
1110 return tickArray[0];
1112 for (var i=0, len=tickArray.length; i<len; ++i) {
1114 if (tickArray[next] && tickArray[next] >= val) {
1115 var diff1 = val - tickArray[i];
1116 var diff2 = tickArray[next] - val;
1117 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
1121 // The value is larger than the last tick, so we return the last
1123 return tickArray[tickArray.length - 1];
1129 * @return {string} string representation of the dd obj
1131 toString: function() {
1132 return ("DragDrop " + this.id);