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 {String[]} invalidHandleClasses
157 invalidHandleClasses: null,
160 * The linked element's absolute X position at the time the drag was
162 * @property startPageX
169 * The linked element's absolute X position at the time the drag was
171 * @property startPageY
178 * The group defines a logical collection of DragDrop objects that are
179 * related. Instances only get events when interacting with other
180 * DragDrop object in the same group. This lets us define multiple
181 * groups using a single DragDrop subclass if we want.
183 * @type Object An object in the format {'group1':true, 'group2':true}
188 * Individual drag/drop instances can be locked. This will prevent
189 * onmousedown start drag.
197 * Locks this instance
204 * When set to true, other DD objects in cooperating DDGroups do not receive
205 * notification events when this DD object is dragged over them. Defaults to false.
212 * Unlocks this instace
219 * By default, all instances can be a drop target. This can be disabled by
220 * setting isTarget to false.
227 * The padding configured for this drag and drop object for calculating
228 * the drop zone intersection with this object.
229 * An array containing the 4 padding values: [top, right, bottom, left]
230 * @property {Number[]} padding
235 * Cached reference to the linked element
242 * Internal typeof flag
243 * @property __ygDragDrop
249 * Set to true when horizontal contraints are applied
250 * @property constrainX
257 * Set to true when vertical contraints are applied
258 * @property constrainY
265 * The left constraint
273 * The right constraint
289 * The down constraint
297 * Maintain offsets when we resetconstraints. Set to true when you want
298 * the position of the element relative to its parent to stay the same
299 * when the page changes
301 * @property maintainOffset
304 maintainOffset: false,
307 * Array of pixel locations the element will snap to if we specified a
308 * horizontal graduation/interval. This array is generated automatically
309 * when you define a tick interval.
310 * @property {Number[]} xTicks
315 * Array of pixel locations the element will snap to if we specified a
316 * vertical graduation/interval. This array is generated automatically
317 * when you define a tick interval.
318 * @property {Number[]} yTicks
323 * By default the drag and drop instance will only respond to the primary
324 * button click (left button for a right-handed mouse). Set to true to
325 * allow drag and drop to start with any mouse click that is propogated
327 * @property primaryButtonOnly
330 primaryButtonOnly: true,
333 * The available property is false until the linked dom element is accessible.
334 * @property available
340 * By default, drags can only be initiated if the mousedown occurs in the
341 * region the linked element is. This is done in part to work around a
342 * bug in some browsers that mis-report the mousedown if the previous
343 * mouseup happened outside of the window. This property is set to true
344 * if outer handles are defined. Defaults to false.
346 * @property hasOuterHandles
349 hasOuterHandles: false,
352 * Code that executes immediately before the startDrag event
355 b4StartDrag: function(x, y) { },
358 * Abstract method called after a drag/drop object is clicked
359 * and the drag or mousedown time thresholds have beeen met.
360 * @param {Number} X click location
361 * @param {Number} Y click location
363 startDrag: function(x, y) { /* override this */ },
366 * Code that executes immediately before the onDrag event
369 b4Drag: function(e) { },
372 * Abstract method called during the onMouseMove event while dragging an
374 * @param {Event} e the mousemove event
376 onDrag: function(e) { /* override this */ },
379 * Abstract method called when this element fist begins hovering over
380 * another DragDrop obj
381 * @param {Event} e the mousemove event
382 * @param {String/Ext.dd.DragDrop[]} id In POINT mode, the element
383 * id this is hovering over. In INTERSECT mode, an array of one or more
384 * dragdrop items being hovered over.
386 onDragEnter: function(e, id) { /* override this */ },
389 * Code that executes immediately before the onDragOver event
392 b4DragOver: function(e) { },
395 * Abstract method called when this element is hovering over another
397 * @param {Event} e the mousemove event
398 * @param {String/Ext.dd.DragDrop[]} id In POINT mode, the element
399 * id this is hovering over. In INTERSECT mode, an array of dd items
400 * being hovered over.
402 onDragOver: function(e, id) { /* override this */ },
405 * Code that executes immediately before the onDragOut event
408 b4DragOut: function(e) { },
411 * Abstract method called when we are no longer hovering over an element
412 * @param {Event} e the mousemove event
413 * @param {String/Ext.dd.DragDrop[]} id In POINT mode, the element
414 * id this was hovering over. In INTERSECT mode, an array of dd items
415 * that the mouse is no longer over.
417 onDragOut: function(e, id) { /* override this */ },
420 * Code that executes immediately before the onDragDrop event
423 b4DragDrop: function(e) { },
426 * Abstract method called when this item is dropped on another DragDrop
428 * @param {Event} e the mouseup event
429 * @param {String/Ext.dd.DragDrop[]} id In POINT mode, the element
430 * id this was dropped on. In INTERSECT mode, an array of dd items this
433 onDragDrop: function(e, id) { /* override this */ },
436 * Abstract method called when this item is dropped on an area with no
438 * @param {Event} e the mouseup event
440 onInvalidDrop: function(e) { /* override this */ },
443 * Code that executes immediately before the endDrag event
446 b4EndDrag: function(e) { },
449 * Called when we are done dragging the object
450 * @param {Event} e the mouseup event
452 endDrag: function(e) { /* override this */ },
455 * Code executed immediately before the onMouseDown event
456 * @param {Event} e the mousedown event
459 b4MouseDown: function(e) { },
462 * Called when a drag/drop obj gets a mousedown
463 * @param {Event} e the mousedown event
465 onMouseDown: function(e) { /* override this */ },
468 * Called when a drag/drop obj gets a mouseup
469 * @param {Event} e the mouseup event
471 onMouseUp: function(e) { /* override this */ },
474 * Override the onAvailable method to do what is needed after the initial
475 * position was determined.
477 onAvailable: function () {
481 * @property {Object} defaultPadding
482 * Provides default constraint padding to "constrainTo" elements.
492 * Initializes the drag drop object's constraints to restrict movement to a certain element.
496 * var dd = new Ext.dd.DDProxy("dragDiv1", "proxytest",
497 * { dragElId: "existingProxyDiv" });
498 * dd.startDrag = function(){
499 * this.constrainTo("parent-id");
502 * Or you can initalize it using the {@link Ext.Element} object:
504 * Ext.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
505 * startDrag : function(){
506 * this.constrainTo("parent-id");
510 * @param {String/HTMLElement/Ext.Element} constrainTo The element or element ID to constrain to.
511 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
512 * and can be either a number for symmetrical padding (4 would be equal to `{left:4, right:4, top:4, bottom:4}`) or
513 * an object containing the sides to pad. For example: `{right:10, bottom:10}`
514 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
516 constrainTo : function(constrainTo, pad, inContent){
517 if(Ext.isNumber(pad)){
518 pad = {left: pad, right:pad, top:pad, bottom:pad};
520 pad = pad || this.defaultPadding;
521 var b = Ext.get(this.getEl()).getBox(),
522 ce = Ext.get(constrainTo),
526 if(cd == document.body){
527 c = { x: s.left, y: s.top, width: Ext.Element.getViewWidth(), height: Ext.Element.getViewHeight()};
530 c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
534 var topSpace = b.y - c.y,
535 leftSpace = b.x - c.x;
537 this.resetConstraints();
538 this.setXConstraint(leftSpace - (pad.left||0), // left
539 c.width - leftSpace - b.width - (pad.right||0), //right
542 this.setYConstraint(topSpace - (pad.top||0), //top
543 c.height - topSpace - b.height - (pad.bottom||0), //bottom
549 * Returns a reference to the linked element
550 * @return {HTMLElement} the html element
554 this._domRef = Ext.getDom(this.id);
561 * Returns a reference to the actual element to drag. By default this is
562 * the same as the html element, but it can be assigned to another
563 * element. An example of this can be found in Ext.dd.DDProxy
564 * @return {HTMLElement} the html element
566 getDragEl: function() {
567 return Ext.getDom(this.dragElId);
571 * Sets up the DragDrop object. Must be called in the constructor of any
572 * Ext.dd.DragDrop subclass
573 * @param {String} id the id of the linked element
574 * @param {String} sGroup the group of related items
575 * @param {Object} config configuration attributes
577 init: function(id, sGroup, config) {
578 this.initTarget(id, sGroup, config);
579 Ext.EventManager.on(this.id, "mousedown", this.handleMouseDown, this);
580 // Ext.EventManager.on(this.id, "selectstart", Event.preventDefault);
584 * Initializes Targeting functionality only... the object does not
585 * get a mousedown handler.
586 * @param {String} id the id of the linked element
587 * @param {String} sGroup the group of related items
588 * @param {Object} config configuration attributes
590 initTarget: function(id, sGroup, config) {
591 // configuration attributes
592 this.config = config || {};
594 // create a local reference to the drag and drop manager
595 this.DDMInstance = Ext.dd.DragDropManager;
596 // initialize the groups array
599 // assume that we have an element reference instead of an id if the
600 // parameter is not a string
601 if (typeof id !== "string") {
608 // add to an interaction group
609 this.addToGroup((sGroup) ? sGroup : "default");
611 // We don't want to register this as the handle with the manager
612 // so we just set the id rather than calling the setter.
613 this.handleElId = id;
615 // the linked element is the element that gets dragged by default
616 this.setDragElId(id);
618 // by default, clicked anchors will not start drag operations.
619 this.invalidHandleTypes = { A: "A" };
620 this.invalidHandleIds = {};
621 this.invalidHandleClasses = [];
625 this.handleOnAvailable();
629 * Applies the configuration parameters that were passed into the constructor.
630 * This is supposed to happen at each level through the inheritance chain. So
631 * a DDProxy implentation will execute apply config on DDProxy, DD, and
632 * DragDrop in order to get all of the parameters that are available in
635 applyConfig: function() {
637 // configurable properties:
638 // padding, isTarget, maintainOffset, primaryButtonOnly
639 this.padding = this.config.padding || [0, 0, 0, 0];
640 this.isTarget = (this.config.isTarget !== false);
641 this.maintainOffset = (this.config.maintainOffset);
642 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
647 * Executed when the linked element is available
650 handleOnAvailable: function() {
651 this.available = true;
652 this.resetConstraints();
657 * Configures the padding for the target zone in px. Effectively expands
658 * (or reduces) the virtual object size for targeting calculations.
659 * Supports css-style shorthand; if only one parameter is passed, all sides
660 * will have that padding, and if only two are passed, the top and bottom
661 * will have the first param, the left and right the second.
662 * @param {Number} iTop Top pad
663 * @param {Number} iRight Right pad
664 * @param {Number} iBot Bot pad
665 * @param {Number} iLeft Left pad
667 setPadding: function(iTop, iRight, iBot, iLeft) {
668 // this.padding = [iLeft, iRight, iTop, iBot];
669 if (!iRight && 0 !== iRight) {
670 this.padding = [iTop, iTop, iTop, iTop];
671 } else if (!iBot && 0 !== iBot) {
672 this.padding = [iTop, iRight, iTop, iRight];
674 this.padding = [iTop, iRight, iBot, iLeft];
679 * Stores the initial placement of the linked element.
680 * @param {Number} diffX the X offset, default 0
681 * @param {Number} diffY the Y offset, default 0
683 setInitPosition: function(diffX, diffY) {
684 var el = this.getEl();
686 if (!this.DDMInstance.verifyEl(el)) {
693 var p = Ext.Element.getXY( el );
695 this.initPageX = p[0] - dx;
696 this.initPageY = p[1] - dy;
698 this.lastPageX = p[0];
699 this.lastPageY = p[1];
701 this.setStartPosition(p);
705 * Sets the start position of the element. This is set when the obj
706 * is initialized, the reset when a drag is started.
707 * @param pos current position (from previous lookup)
710 setStartPosition: function(pos) {
711 var p = pos || Ext.Element.getXY( this.getEl() );
712 this.deltaSetXY = null;
714 this.startPageX = p[0];
715 this.startPageY = p[1];
719 * Adds this instance to a group of related drag/drop objects. All
720 * instances belong to at least one group, and can belong to as many
722 * @param {String} sGroup the name of the group
724 addToGroup: function(sGroup) {
725 this.groups[sGroup] = true;
726 this.DDMInstance.regDragDrop(this, sGroup);
730 * Removes this instance from the supplied interaction group
731 * @param {String} sGroup The group to drop
733 removeFromGroup: function(sGroup) {
734 if (this.groups[sGroup]) {
735 delete this.groups[sGroup];
738 this.DDMInstance.removeDDFromGroup(this, sGroup);
742 * Allows you to specify that an element other than the linked element
743 * will be moved with the cursor during a drag
744 * @param {String} id the id of the element that will be used to initiate the drag
746 setDragElId: function(id) {
751 * Allows you to specify a child of the linked element that should be
752 * used to initiate the drag operation. An example of this would be if
753 * you have a content div with text and links. Clicking anywhere in the
754 * content area would normally start the drag operation. Use this method
755 * to specify that an element inside of the content div is the element
756 * that starts the drag operation.
757 * @param {String} id the id of the element that will be used to
760 setHandleElId: function(id) {
761 if (typeof id !== "string") {
764 this.handleElId = id;
765 this.DDMInstance.regHandle(this.id, id);
769 * Allows you to set an element outside of the linked element as a drag
771 * @param {String} id the id of the element that will be used to initiate the drag
773 setOuterHandleElId: function(id) {
774 if (typeof id !== "string") {
777 Ext.EventManager.on(id, "mousedown", this.handleMouseDown, this);
778 this.setHandleElId(id);
780 this.hasOuterHandles = true;
784 * Removes all drag and drop hooks for this element
787 Ext.EventManager.un(this.id, "mousedown", this.handleMouseDown, this);
789 this.DDMInstance._remove(this);
792 destroy : function(){
797 * Returns true if this instance is locked, or the drag drop mgr is locked
798 * (meaning that all drag/drop is disabled on the page.)
799 * @return {Boolean} true if this obj or all drag/drop is locked, else
802 isLocked: function() {
803 return (this.DDMInstance.isLocked() || this.locked);
807 * Called when this object is clicked
809 * @param {Ext.dd.DragDrop} oDD the clicked dd object (this dd obj)
812 handleMouseDown: function(e, oDD){
813 if (this.primaryButtonOnly && e.button != 0) {
817 if (this.isLocked()) {
821 this.DDMInstance.refreshCache(this.groups);
823 var pt = e.getPoint();
824 if (!this.hasOuterHandles && !this.DDMInstance.isOverTarget(pt, this) ) {
826 if (this.clickValidator(e)) {
827 // set the initial element position
828 this.setStartPosition();
832 this.DDMInstance.handleMouseDown(e, this);
834 this.DDMInstance.stopEvent(e);
842 clickValidator: function(e) {
843 var target = e.getTarget();
844 return ( this.isValidHandleChild(target) &&
845 (this.id == this.handleElId ||
846 this.DDMInstance.handleWasClicked(target, this.id)) );
850 * Allows you to specify a tag name that should not start a drag operation
851 * when clicked. This is designed to facilitate embedding links within a
852 * drag handle that do something other than start the drag.
853 * @method addInvalidHandleType
854 * @param {String} tagName the type of element to exclude
856 addInvalidHandleType: function(tagName) {
857 var type = tagName.toUpperCase();
858 this.invalidHandleTypes[type] = type;
862 * Lets you to specify an element id for a child of a drag handle
863 * that should not initiate a drag
864 * @method addInvalidHandleId
865 * @param {String} id the element id of the element you wish to ignore
867 addInvalidHandleId: function(id) {
868 if (typeof id !== "string") {
871 this.invalidHandleIds[id] = id;
875 * Lets you specify a css class of elements that will not initiate a drag
876 * @param {String} cssClass the class of the elements you wish to ignore
878 addInvalidHandleClass: function(cssClass) {
879 this.invalidHandleClasses.push(cssClass);
883 * Unsets an excluded tag name set by addInvalidHandleType
884 * @param {String} tagName the type of element to unexclude
886 removeInvalidHandleType: function(tagName) {
887 var type = tagName.toUpperCase();
888 // this.invalidHandleTypes[type] = null;
889 delete this.invalidHandleTypes[type];
893 * Unsets an invalid handle id
894 * @param {String} id the id of the element to re-enable
896 removeInvalidHandleId: function(id) {
897 if (typeof id !== "string") {
900 delete this.invalidHandleIds[id];
904 * Unsets an invalid css class
905 * @param {String} cssClass the class of the element(s) you wish to
908 removeInvalidHandleClass: function(cssClass) {
909 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
910 if (this.invalidHandleClasses[i] == cssClass) {
911 delete this.invalidHandleClasses[i];
917 * Checks the tag exclusion list to see if this click should be ignored
918 * @param {HTMLElement} node the HTMLElement to evaluate
919 * @return {Boolean} true if this is a valid tag type, false if not
921 isValidHandleChild: function(node) {
924 // var n = (node.nodeName == "#text") ? node.parentNode : node;
927 nodeName = node.nodeName.toUpperCase();
929 nodeName = node.nodeName;
931 valid = valid && !this.invalidHandleTypes[nodeName];
932 valid = valid && !this.invalidHandleIds[node.id];
934 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
935 valid = !Ext.fly(node).hasCls(this.invalidHandleClasses[i]);
944 * Creates the array of horizontal tick marks if an interval was specified
945 * in setXConstraint().
948 setXTicks: function(iStartX, iTickSize) {
950 this.xTickSize = iTickSize;
954 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
956 this.xTicks[this.xTicks.length] = i;
961 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
963 this.xTicks[this.xTicks.length] = i;
968 Ext.Array.sort(this.xTicks, this.DDMInstance.numericSort);
972 * Creates the array of vertical tick marks if an interval was specified in
976 setYTicks: function(iStartY, iTickSize) {
978 this.yTickSize = iTickSize;
982 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
984 this.yTicks[this.yTicks.length] = i;
989 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
991 this.yTicks[this.yTicks.length] = i;
996 Ext.Array.sort(this.yTicks, this.DDMInstance.numericSort);
1000 * By default, the element can be dragged any place on the screen. Use
1001 * this method to limit the horizontal travel of the element. Pass in
1002 * 0,0 for the parameters if you want to lock the drag to the y axis.
1003 * @param {Number} iLeft the number of pixels the element can move to the left
1004 * @param {Number} iRight the number of pixels the element can move to the
1006 * @param {Number} iTickSize (optional) parameter for specifying that the
1007 * element should move iTickSize pixels at a time.
1009 setXConstraint: function(iLeft, iRight, iTickSize) {
1010 this.leftConstraint = iLeft;
1011 this.rightConstraint = iRight;
1013 this.minX = this.initPageX - iLeft;
1014 this.maxX = this.initPageX + iRight;
1015 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
1017 this.constrainX = true;
1021 * Clears any constraints applied to this instance. Also clears ticks
1022 * since they can't exist independent of a constraint at this time.
1024 clearConstraints: function() {
1025 this.constrainX = false;
1026 this.constrainY = false;
1031 * Clears any tick interval defined for this instance
1033 clearTicks: function() {
1041 * By default, the element can be dragged any place on the screen. Set
1042 * this to limit the vertical travel of the element. Pass in 0,0 for the
1043 * parameters if you want to lock the drag to the x axis.
1044 * @param {Number} iUp the number of pixels the element can move up
1045 * @param {Number} iDown the number of pixels the element can move down
1046 * @param {Number} iTickSize (optional) parameter for specifying that the
1047 * element should move iTickSize pixels at a time.
1049 setYConstraint: function(iUp, iDown, iTickSize) {
1050 this.topConstraint = iUp;
1051 this.bottomConstraint = iDown;
1053 this.minY = this.initPageY - iUp;
1054 this.maxY = this.initPageY + iDown;
1055 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
1057 this.constrainY = true;
1062 * Must be called if you manually reposition a dd element.
1063 * @param {Boolean} maintainOffset
1065 resetConstraints: function() {
1066 // Maintain offsets if necessary
1067 if (this.initPageX || this.initPageX === 0) {
1068 // figure out how much this thing has moved
1069 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
1070 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
1072 this.setInitPosition(dx, dy);
1074 // This is the first time we have detected the element's position
1076 this.setInitPosition();
1079 if (this.constrainX) {
1080 this.setXConstraint( this.leftConstraint,
1081 this.rightConstraint,
1085 if (this.constrainY) {
1086 this.setYConstraint( this.topConstraint,
1087 this.bottomConstraint,
1093 * Normally the drag element is moved pixel by pixel, but we can specify
1094 * that it move a number of pixels at a time. This method resolves the
1095 * location when we have it set up like this.
1096 * @param {Number} val where we want to place the object
1097 * @param {Number[]} tickArray sorted array of valid points
1098 * @return {Number} the closest tick
1101 getTick: function(val, tickArray) {
1103 // If tick interval is not defined, it is effectively 1 pixel,
1104 // so we return the value passed to us.
1106 } else if (tickArray[0] >= val) {
1107 // The value is lower than the first tick, so we return the first
1109 return tickArray[0];
1111 for (var i=0, len=tickArray.length; i<len; ++i) {
1113 if (tickArray[next] && tickArray[next] >= val) {
1114 var diff1 = val - tickArray[i];
1115 var diff2 = tickArray[next] - val;
1116 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
1120 // The value is larger than the last tick, so we return the last
1122 return tickArray[tickArray.length - 1];
1128 * @return {String} string representation of the dd obj
1130 toString: function() {
1131 return ("DragDrop " + this.id);