Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / DragDropManager.html
diff --git a/docs/source/DragDropManager.html b/docs/source/DragDropManager.html
new file mode 100644 (file)
index 0000000..23148b1
--- /dev/null
@@ -0,0 +1,1309 @@
+<!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre>/*
+ * This is a derivative of the similarly named class in the YUI Library.
+ * The original license:
+ * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ */
+
+
+<span id='Ext-dd.DragDropManager'>/**
+</span> * @class Ext.dd.DragDropManager
+ * DragDropManager is a singleton that tracks the element interaction for
+ * all DragDrop items in the window.  Generally, you will not call
+ * this class directly, but it does have helper methods that could
+ * be useful in your DragDrop implementations.
+ * @singleton
+ */
+Ext.define('Ext.dd.DragDropManager', {
+    singleton: true,
+
+    requires: ['Ext.util.Region'],
+
+    uses: ['Ext.tip.QuickTipManager'],
+
+    // shorter ClassName, to save bytes and use internally
+    alternateClassName: ['Ext.dd.DragDropMgr', 'Ext.dd.DDM'],
+    
+<span id='Ext-dd.DragDropManager-property-ids'>    /**
+</span>     * Two dimensional Array of registered DragDrop objects.  The first
+     * dimension is the DragDrop item group, the second the DragDrop
+     * object.
+     * @property ids
+     * @type String[]
+     * @private
+     * @static
+     */
+    ids: {},
+
+<span id='Ext-dd.DragDropManager-property-handleIds'>    /**
+</span>     * Array of element ids defined as drag handles.  Used to determine
+     * if the element that generated the mousedown event is actually the
+     * handle and not the html element itself.
+     * @property handleIds
+     * @type String[]
+     * @private
+     * @static
+     */
+    handleIds: {},
+
+<span id='Ext-dd.DragDropManager-property-dragCurrent'>    /**
+</span>     * the DragDrop object that is currently being dragged
+     * @property dragCurrent
+     * @type DragDrop
+     * @private
+     * @static
+     **/
+    dragCurrent: null,
+
+<span id='Ext-dd.DragDropManager-property-dragOvers'>    /**
+</span>     * the DragDrop object(s) that are being hovered over
+     * @property dragOvers
+     * @type Array
+     * @private
+     * @static
+     */
+    dragOvers: {},
+
+<span id='Ext-dd.DragDropManager-property-deltaX'>    /**
+</span>     * the X distance between the cursor and the object being dragged
+     * @property deltaX
+     * @type int
+     * @private
+     * @static
+     */
+    deltaX: 0,
+
+<span id='Ext-dd.DragDropManager-property-deltaY'>    /**
+</span>     * the Y distance between the cursor and the object being dragged
+     * @property deltaY
+     * @type int
+     * @private
+     * @static
+     */
+    deltaY: 0,
+
+<span id='Ext-dd.DragDropManager-property-preventDefault'>    /**
+</span>     * Flag to determine if we should prevent the default behavior of the
+     * events we define. By default this is true, but this can be set to
+     * false if you need the default behavior (not recommended)
+     * @property preventDefault
+     * @type boolean
+     * @static
+     */
+    preventDefault: true,
+
+<span id='Ext-dd.DragDropManager-property-stopPropagation'>    /**
+</span>     * Flag to determine if we should stop the propagation of the events
+     * we generate. This is true by default but you may want to set it to
+     * false if the html element contains other features that require the
+     * mouse click.
+     * @property stopPropagation
+     * @type boolean
+     * @static
+     */
+    stopPropagation: true,
+
+<span id='Ext-dd.DragDropManager-property-initialized'>    /**
+</span>     * Internal flag that is set to true when drag and drop has been
+     * intialized
+     * @property initialized
+     * @private
+     * @static
+     */
+    initialized: false,
+
+<span id='Ext-dd.DragDropManager-property-locked'>    /**
+</span>     * All drag and drop can be disabled.
+     * @property locked
+     * @private
+     * @static
+     */
+    locked: false,
+
+<span id='Ext-dd.DragDropManager-method-init'>    /**
+</span>     * Called the first time an element is registered.
+     * @method init
+     * @private
+     * @static
+     */
+    init: function() {
+        this.initialized = true;
+    },
+
+<span id='Ext-dd.DragDropManager-property-POINT'>    /**
+</span>     * In point mode, drag and drop interaction is defined by the
+     * location of the cursor during the drag/drop
+     * @property POINT
+     * @type int
+     * @static
+     */
+    POINT: 0,
+
+<span id='Ext-dd.DragDropManager-property-INTERSECT'>    /**
+</span>     * In intersect mode, drag and drop interaction is defined by the
+     * overlap of two or more drag and drop objects.
+     * @property INTERSECT
+     * @type int
+     * @static
+     */
+    INTERSECT: 1,
+
+<span id='Ext-dd.DragDropManager-property-mode'>    /**
+</span>     * The current drag and drop mode.  Default: POINT
+     * @property mode
+     * @type int
+     * @static
+     */
+    mode: 0,
+
+<span id='Ext-dd.DragDropManager-method-_execOnAll'>    /**
+</span>     * Runs method on all drag and drop objects
+     * @method _execOnAll
+     * @private
+     * @static
+     */
+    _execOnAll: function(sMethod, args) {
+        for (var i in this.ids) {
+            for (var j in this.ids[i]) {
+                var oDD = this.ids[i][j];
+                if (! this.isTypeOfDD(oDD)) {
+                    continue;
+                }
+                oDD[sMethod].apply(oDD, args);
+            }
+        }
+    },
+
+<span id='Ext-dd.DragDropManager-method-_onLoad'>    /**
+</span>     * Drag and drop initialization.  Sets up the global event handlers
+     * @method _onLoad
+     * @private
+     * @static
+     */
+    _onLoad: function() {
+
+        this.init();
+
+        var Event = Ext.EventManager;
+        Event.on(document, &quot;mouseup&quot;,   this.handleMouseUp, this, true);
+        Event.on(document, &quot;mousemove&quot;, this.handleMouseMove, this, true);
+        Event.on(window,   &quot;unload&quot;,    this._onUnload, this, true);
+        Event.on(window,   &quot;resize&quot;,    this._onResize, this, true);
+        // Event.on(window,   &quot;mouseout&quot;,    this._test);
+
+    },
+
+<span id='Ext-dd.DragDropManager-method-_onResize'>    /**
+</span>     * Reset constraints on all drag and drop objs
+     * @method _onResize
+     * @private
+     * @static
+     */
+    _onResize: function(e) {
+        this._execOnAll(&quot;resetConstraints&quot;, []);
+    },
+
+<span id='Ext-dd.DragDropManager-method-lock'>    /**
+</span>     * Lock all drag and drop functionality
+     * @method lock
+     * @static
+     */
+    lock: function() { this.locked = true; },
+
+<span id='Ext-dd.DragDropManager-method-unlock'>    /**
+</span>     * Unlock all drag and drop functionality
+     * @method unlock
+     * @static
+     */
+    unlock: function() { this.locked = false; },
+
+<span id='Ext-dd.DragDropManager-method-isLocked'>    /**
+</span>     * Is drag and drop locked?
+     * @method isLocked
+     * @return {boolean} True if drag and drop is locked, false otherwise.
+     * @static
+     */
+    isLocked: function() { return this.locked; },
+
+<span id='Ext-dd.DragDropManager-property-locationCache'>    /**
+</span>     * Location cache that is set for all drag drop objects when a drag is
+     * initiated, cleared when the drag is finished.
+     * @property locationCache
+     * @private
+     * @static
+     */
+    locationCache: {},
+
+<span id='Ext-dd.DragDropManager-property-useCache'>    /**
+</span>     * Set useCache to false if you want to force object the lookup of each
+     * drag and drop linked element constantly during a drag.
+     * @property useCache
+     * @type boolean
+     * @static
+     */
+    useCache: true,
+
+<span id='Ext-dd.DragDropManager-property-clickPixelThresh'>    /**
+</span>     * The number of pixels that the mouse needs to move after the
+     * mousedown before the drag is initiated.  Default=3;
+     * @property clickPixelThresh
+     * @type int
+     * @static
+     */
+    clickPixelThresh: 3,
+
+<span id='Ext-dd.DragDropManager-property-clickTimeThresh'>    /**
+</span>     * The number of milliseconds after the mousedown event to initiate the
+     * drag if we don't get a mouseup event. Default=350
+     * @property clickTimeThresh
+     * @type int
+     * @static
+     */
+    clickTimeThresh: 350,
+
+<span id='Ext-dd.DragDropManager-property-dragThreshMet'>    /**
+</span>     * Flag that indicates that either the drag pixel threshold or the
+     * mousdown time threshold has been met
+     * @property dragThreshMet
+     * @type boolean
+     * @private
+     * @static
+     */
+    dragThreshMet: false,
+
+<span id='Ext-dd.DragDropManager-property-clickTimeout'>    /**
+</span>     * Timeout used for the click time threshold
+     * @property clickTimeout
+     * @type Object
+     * @private
+     * @static
+     */
+    clickTimeout: null,
+
+<span id='Ext-dd.DragDropManager-property-startX'>    /**
+</span>     * The X position of the mousedown event stored for later use when a
+     * drag threshold is met.
+     * @property startX
+     * @type int
+     * @private
+     * @static
+     */
+    startX: 0,
+
+<span id='Ext-dd.DragDropManager-property-startY'>    /**
+</span>     * The Y position of the mousedown event stored for later use when a
+     * drag threshold is met.
+     * @property startY
+     * @type int
+     * @private
+     * @static
+     */
+    startY: 0,
+
+<span id='Ext-dd.DragDropManager-method-regDragDrop'>    /**
+</span>     * Each DragDrop instance must be registered with the DragDropManager.
+     * This is executed in DragDrop.init()
+     * @method regDragDrop
+     * @param {DragDrop} oDD the DragDrop object to register
+     * @param {String} sGroup the name of the group this element belongs to
+     * @static
+     */
+    regDragDrop: function(oDD, sGroup) {
+        if (!this.initialized) { this.init(); }
+
+        if (!this.ids[sGroup]) {
+            this.ids[sGroup] = {};
+        }
+        this.ids[sGroup][oDD.id] = oDD;
+    },
+
+<span id='Ext-dd.DragDropManager-method-removeDDFromGroup'>    /**
+</span>     * Removes the supplied dd instance from the supplied group. Executed
+     * by DragDrop.removeFromGroup, so don't call this function directly.
+     * @method removeDDFromGroup
+     * @private
+     * @static
+     */
+    removeDDFromGroup: function(oDD, sGroup) {
+        if (!this.ids[sGroup]) {
+            this.ids[sGroup] = {};
+        }
+
+        var obj = this.ids[sGroup];
+        if (obj &amp;&amp; obj[oDD.id]) {
+            delete obj[oDD.id];
+        }
+    },
+
+<span id='Ext-dd.DragDropManager-method-_remove'>    /**
+</span>     * Unregisters a drag and drop item.  This is executed in
+     * DragDrop.unreg, use that method instead of calling this directly.
+     * @method _remove
+     * @private
+     * @static
+     */
+    _remove: function(oDD) {
+        for (var g in oDD.groups) {
+            if (g &amp;&amp; this.ids[g] &amp;&amp; this.ids[g][oDD.id]) {
+                delete this.ids[g][oDD.id];
+            }
+        }
+        delete this.handleIds[oDD.id];
+    },
+
+<span id='Ext-dd.DragDropManager-method-regHandle'>    /**
+</span>     * Each DragDrop handle element must be registered.  This is done
+     * automatically when executing DragDrop.setHandleElId()
+     * @method regHandle
+     * @param {String} sDDId the DragDrop id this element is a handle for
+     * @param {String} sHandleId the id of the element that is the drag
+     * handle
+     * @static
+     */
+    regHandle: function(sDDId, sHandleId) {
+        if (!this.handleIds[sDDId]) {
+            this.handleIds[sDDId] = {};
+        }
+        this.handleIds[sDDId][sHandleId] = sHandleId;
+    },
+
+<span id='Ext-dd.DragDropManager-method-isDragDrop'>    /**
+</span>     * Utility function to determine if a given element has been
+     * registered as a drag drop item.
+     * @method isDragDrop
+     * @param {String} id the element id to check
+     * @return {boolean} true if this element is a DragDrop item,
+     * false otherwise
+     * @static
+     */
+    isDragDrop: function(id) {
+        return ( this.getDDById(id) ) ? true : false;
+    },
+
+<span id='Ext-dd.DragDropManager-method-getRelated'>    /**
+</span>     * Returns the drag and drop instances that are in all groups the
+     * passed in instance belongs to.
+     * @method getRelated
+     * @param {DragDrop} p_oDD the obj to get related data for
+     * @param {boolean} bTargetsOnly if true, only return targetable objs
+     * @return {DragDrop[]} the related instances
+     * @static
+     */
+    getRelated: function(p_oDD, bTargetsOnly) {
+        var oDDs = [];
+        for (var i in p_oDD.groups) {
+            for (var j in this.ids[i]) {
+                var dd = this.ids[i][j];
+                if (! this.isTypeOfDD(dd)) {
+                    continue;
+                }
+                if (!bTargetsOnly || dd.isTarget) {
+                    oDDs[oDDs.length] = dd;
+                }
+            }
+        }
+
+        return oDDs;
+    },
+
+<span id='Ext-dd.DragDropManager-method-isLegalTarget'>    /**
+</span>     * Returns true if the specified dd target is a legal target for
+     * the specifice drag obj
+     * @method isLegalTarget
+     * @param {DragDrop} oDD the drag obj
+     * @param {DragDrop} oTargetDD the target
+     * @return {boolean} true if the target is a legal target for the
+     * dd obj
+     * @static
+     */
+    isLegalTarget: function (oDD, oTargetDD) {
+        var targets = this.getRelated(oDD, true);
+        for (var i=0, len=targets.length;i&lt;len;++i) {
+            if (targets[i].id == oTargetDD.id) {
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+<span id='Ext-dd.DragDropManager-method-isTypeOfDD'>    /**
+</span>     * My goal is to be able to transparently determine if an object is
+     * typeof DragDrop, and the exact subclass of DragDrop.  typeof
+     * returns &quot;object&quot;, oDD.constructor.toString() always returns
+     * &quot;DragDrop&quot; and not the name of the subclass.  So for now it just
+     * evaluates a well-known variable in DragDrop.
+     * @method isTypeOfDD
+     * @param {Object} the object to evaluate
+     * @return {boolean} true if typeof oDD = DragDrop
+     * @static
+     */
+    isTypeOfDD: function (oDD) {
+        return (oDD &amp;&amp; oDD.__ygDragDrop);
+    },
+
+<span id='Ext-dd.DragDropManager-method-isHandle'>    /**
+</span>     * Utility function to determine if a given element has been
+     * registered as a drag drop handle for the given Drag Drop object.
+     * @method isHandle
+     * @param {String} id the element id to check
+     * @return {boolean} true if this element is a DragDrop handle, false
+     * otherwise
+     * @static
+     */
+    isHandle: function(sDDId, sHandleId) {
+        return ( this.handleIds[sDDId] &amp;&amp;
+                        this.handleIds[sDDId][sHandleId] );
+    },
+
+<span id='Ext-dd.DragDropManager-method-getDDById'>    /**
+</span>     * Returns the DragDrop instance for a given id
+     * @method getDDById
+     * @param {String} id the id of the DragDrop object
+     * @return {DragDrop} the drag drop object, null if it is not found
+     * @static
+     */
+    getDDById: function(id) {
+        for (var i in this.ids) {
+            if (this.ids[i][id]) {
+                return this.ids[i][id];
+            }
+        }
+        return null;
+    },
+
+<span id='Ext-dd.DragDropManager-method-handleMouseDown'>    /**
+</span>     * Fired after a registered DragDrop object gets the mousedown event.
+     * Sets up the events required to track the object being dragged
+     * @method handleMouseDown
+     * @param {Event} e the event
+     * @param oDD the DragDrop object being dragged
+     * @private
+     * @static
+     */
+    handleMouseDown: function(e, oDD) {
+        if(Ext.tip.QuickTipManager){
+            Ext.tip.QuickTipManager.ddDisable();
+        }
+        if(this.dragCurrent){
+            // the original browser mouseup wasn't handled (e.g. outside FF browser window)
+            // so clean up first to avoid breaking the next drag
+            this.handleMouseUp(e);
+        }
+        
+        this.currentTarget = e.getTarget();
+        this.dragCurrent = oDD;
+
+        var el = oDD.getEl();
+
+        // track start position
+        this.startX = e.getPageX();
+        this.startY = e.getPageY();
+
+        this.deltaX = this.startX - el.offsetLeft;
+        this.deltaY = this.startY - el.offsetTop;
+
+        this.dragThreshMet = false;
+
+        this.clickTimeout = setTimeout(
+                function() {
+                    var DDM = Ext.dd.DragDropManager;
+                    DDM.startDrag(DDM.startX, DDM.startY);
+                },
+                this.clickTimeThresh );
+    },
+
+<span id='Ext-dd.DragDropManager-method-startDrag'>    /**
+</span>     * Fired when either the drag pixel threshol or the mousedown hold
+     * time threshold has been met.
+     * @method startDrag
+     * @param x {int} the X position of the original mousedown
+     * @param y {int} the Y position of the original mousedown
+     * @static
+     */
+    startDrag: function(x, y) {
+        clearTimeout(this.clickTimeout);
+        if (this.dragCurrent) {
+            this.dragCurrent.b4StartDrag(x, y);
+            this.dragCurrent.startDrag(x, y);
+        }
+        this.dragThreshMet = true;
+    },
+
+<span id='Ext-dd.DragDropManager-method-handleMouseUp'>    /**
+</span>     * Internal function to handle the mouseup event.  Will be invoked
+     * from the context of the document.
+     * @method handleMouseUp
+     * @param {Event} e the event
+     * @private
+     * @static
+     */
+    handleMouseUp: function(e) {
+
+        if(Ext.tip.QuickTipManager){
+            Ext.tip.QuickTipManager.ddEnable();
+        }
+        if (! this.dragCurrent) {
+            return;
+        }
+
+        clearTimeout(this.clickTimeout);
+
+        if (this.dragThreshMet) {
+            this.fireEvents(e, true);
+        } else {
+        }
+
+        this.stopDrag(e);
+
+        this.stopEvent(e);
+    },
+
+<span id='Ext-dd.DragDropManager-method-stopEvent'>    /**
+</span>     * Utility to stop event propagation and event default, if these
+     * features are turned on.
+     * @method stopEvent
+     * @param {Event} e the event as returned by this.getEvent()
+     * @static
+     */
+    stopEvent: function(e){
+        if(this.stopPropagation) {
+            e.stopPropagation();
+        }
+
+        if (this.preventDefault) {
+            e.preventDefault();
+        }
+    },
+
+<span id='Ext-dd.DragDropManager-method-stopDrag'>    /**
+</span>     * Internal function to clean up event handlers after the drag
+     * operation is complete
+     * @method stopDrag
+     * @param {Event} e the event
+     * @private
+     * @static
+     */
+    stopDrag: function(e) {
+        // Fire the drag end event for the item that was dragged
+        if (this.dragCurrent) {
+            if (this.dragThreshMet) {
+                this.dragCurrent.b4EndDrag(e);
+                this.dragCurrent.endDrag(e);
+            }
+
+            this.dragCurrent.onMouseUp(e);
+        }
+
+        this.dragCurrent = null;
+        this.dragOvers = {};
+    },
+
+<span id='Ext-dd.DragDropManager-method-handleMouseMove'>    /**
+</span>     * Internal function to handle the mousemove event.  Will be invoked
+     * from the context of the html element.
+     *
+     * @TODO figure out what we can do about mouse events lost when the
+     * user drags objects beyond the window boundary.  Currently we can
+     * detect this in internet explorer by verifying that the mouse is
+     * down during the mousemove event.  Firefox doesn't give us the
+     * button state on the mousemove event.
+     * @method handleMouseMove
+     * @param {Event} e the event
+     * @private
+     * @static
+     */
+    handleMouseMove: function(e) {
+        if (! this.dragCurrent) {
+            return true;
+        }
+        // var button = e.which || e.button;
+
+        // check for IE mouseup outside of page boundary
+        if (Ext.isIE &amp;&amp; (e.button !== 0 &amp;&amp; e.button !== 1 &amp;&amp; e.button !== 2)) {
+            this.stopEvent(e);
+            return this.handleMouseUp(e);
+        }
+
+        if (!this.dragThreshMet) {
+            var diffX = Math.abs(this.startX - e.getPageX());
+            var diffY = Math.abs(this.startY - e.getPageY());
+            if (diffX &gt; this.clickPixelThresh ||
+                        diffY &gt; this.clickPixelThresh) {
+                this.startDrag(this.startX, this.startY);
+            }
+        }
+
+        if (this.dragThreshMet) {
+            this.dragCurrent.b4Drag(e);
+            this.dragCurrent.onDrag(e);
+            if(!this.dragCurrent.moveOnly){
+                this.fireEvents(e, false);
+            }
+        }
+
+        this.stopEvent(e);
+
+        return true;
+    },
+
+<span id='Ext-dd.DragDropManager-method-fireEvents'>    /**
+</span>     * Iterates over all of the DragDrop elements to find ones we are
+     * hovering over or dropping on
+     * @method fireEvents
+     * @param {Event} e the event
+     * @param {boolean} isDrop is this a drop op or a mouseover op?
+     * @private
+     * @static
+     */
+    fireEvents: function(e, isDrop) {
+        var dc = this.dragCurrent;
+
+        // If the user did the mouse up outside of the window, we could
+        // get here even though we have ended the drag.
+        if (!dc || dc.isLocked()) {
+            return;
+        }
+
+        var pt = e.getPoint();
+
+        // cache the previous dragOver array
+        var oldOvers = [];
+
+        var outEvts   = [];
+        var overEvts  = [];
+        var dropEvts  = [];
+        var enterEvts = [];
+
+        // Check to see if the object(s) we were hovering over is no longer
+        // being hovered over so we can fire the onDragOut event
+        for (var i in this.dragOvers) {
+
+            var ddo = this.dragOvers[i];
+
+            if (! this.isTypeOfDD(ddo)) {
+                continue;
+            }
+
+            if (! this.isOverTarget(pt, ddo, this.mode)) {
+                outEvts.push( ddo );
+            }
+
+            oldOvers[i] = true;
+            delete this.dragOvers[i];
+        }
+
+        for (var sGroup in dc.groups) {
+
+            if (&quot;string&quot; != typeof sGroup) {
+                continue;
+            }
+
+            for (i in this.ids[sGroup]) {
+                var oDD = this.ids[sGroup][i];
+                if (! this.isTypeOfDD(oDD)) {
+                    continue;
+                }
+
+                if (oDD.isTarget &amp;&amp; !oDD.isLocked() &amp;&amp; ((oDD != dc) || (dc.ignoreSelf === false))) {
+                    if (this.isOverTarget(pt, oDD, this.mode)) {
+                        // look for drop interactions
+                        if (isDrop) {
+                            dropEvts.push( oDD );
+                        // look for drag enter and drag over interactions
+                        } else {
+
+                            // initial drag over: dragEnter fires
+                            if (!oldOvers[oDD.id]) {
+                                enterEvts.push( oDD );
+                            // subsequent drag overs: dragOver fires
+                            } else {
+                                overEvts.push( oDD );
+                            }
+
+                            this.dragOvers[oDD.id] = oDD;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (this.mode) {
+            if (outEvts.length) {
+                dc.b4DragOut(e, outEvts);
+                dc.onDragOut(e, outEvts);
+            }
+
+            if (enterEvts.length) {
+                dc.onDragEnter(e, enterEvts);
+            }
+
+            if (overEvts.length) {
+                dc.b4DragOver(e, overEvts);
+                dc.onDragOver(e, overEvts);
+            }
+
+            if (dropEvts.length) {
+                dc.b4DragDrop(e, dropEvts);
+                dc.onDragDrop(e, dropEvts);
+            }
+
+        } else {
+            // fire dragout events
+            var len = 0;
+            for (i=0, len=outEvts.length; i&lt;len; ++i) {
+                dc.b4DragOut(e, outEvts[i].id);
+                dc.onDragOut(e, outEvts[i].id);
+            }
+
+            // fire enter events
+            for (i=0,len=enterEvts.length; i&lt;len; ++i) {
+                // dc.b4DragEnter(e, oDD.id);
+                dc.onDragEnter(e, enterEvts[i].id);
+            }
+
+            // fire over events
+            for (i=0,len=overEvts.length; i&lt;len; ++i) {
+                dc.b4DragOver(e, overEvts[i].id);
+                dc.onDragOver(e, overEvts[i].id);
+            }
+
+            // fire drop events
+            for (i=0, len=dropEvts.length; i&lt;len; ++i) {
+                dc.b4DragDrop(e, dropEvts[i].id);
+                dc.onDragDrop(e, dropEvts[i].id);
+            }
+
+        }
+
+        // notify about a drop that did not find a target
+        if (isDrop &amp;&amp; !dropEvts.length) {
+            dc.onInvalidDrop(e);
+        }
+
+    },
+
+<span id='Ext-dd.DragDropManager-method-getBestMatch'>    /**
+</span>     * Helper function for getting the best match from the list of drag
+     * and drop objects returned by the drag and drop events when we are
+     * in INTERSECT mode.  It returns either the first object that the
+     * cursor is over, or the object that has the greatest overlap with
+     * the dragged element.
+     * @method getBestMatch
+     * @param  {DragDrop[]} dds The array of drag and drop objects
+     * targeted
+     * @return {DragDrop}       The best single match
+     * @static
+     */
+    getBestMatch: function(dds) {
+        var winner = null;
+        // Return null if the input is not what we expect
+        //if (!dds || !dds.length || dds.length == 0) {
+           // winner = null;
+        // If there is only one item, it wins
+        //} else if (dds.length == 1) {
+
+        var len = dds.length;
+
+        if (len == 1) {
+            winner = dds[0];
+        } else {
+            // Loop through the targeted items
+            for (var i=0; i&lt;len; ++i) {
+                var dd = dds[i];
+                // If the cursor is over the object, it wins.  If the
+                // cursor is over multiple matches, the first one we come
+                // to wins.
+                if (dd.cursorIsOver) {
+                    winner = dd;
+                    break;
+                // Otherwise the object with the most overlap wins
+                } else {
+                    if (!winner ||
+                        winner.overlap.getArea() &lt; dd.overlap.getArea()) {
+                        winner = dd;
+                    }
+                }
+            }
+        }
+
+        return winner;
+    },
+
+<span id='Ext-dd.DragDropManager-method-refreshCache'>    /**
+</span>     * Refreshes the cache of the top-left and bottom-right points of the
+     * drag and drop objects in the specified group(s).  This is in the
+     * format that is stored in the drag and drop instance, so typical
+     * usage is:
+     * &lt;code&gt;
+     * Ext.dd.DragDropManager.refreshCache(ddinstance.groups);
+     * &lt;/code&gt;
+     * Alternatively:
+     * &lt;code&gt;
+     * Ext.dd.DragDropManager.refreshCache({group1:true, group2:true});
+     * &lt;/code&gt;
+     * @TODO this really should be an indexed array.  Alternatively this
+     * method could accept both.
+     * @method refreshCache
+     * @param {Object} groups an associative array of groups to refresh
+     * @static
+     */
+    refreshCache: function(groups) {
+        for (var sGroup in groups) {
+            if (&quot;string&quot; != typeof sGroup) {
+                continue;
+            }
+            for (var i in this.ids[sGroup]) {
+                var oDD = this.ids[sGroup][i];
+
+                if (this.isTypeOfDD(oDD)) {
+                // if (this.isTypeOfDD(oDD) &amp;&amp; oDD.isTarget) {
+                    var loc = this.getLocation(oDD);
+                    if (loc) {
+                        this.locationCache[oDD.id] = loc;
+                    } else {
+                        delete this.locationCache[oDD.id];
+                        // this will unregister the drag and drop object if
+                        // the element is not in a usable state
+                        // oDD.unreg();
+                    }
+                }
+            }
+        }
+    },
+
+<span id='Ext-dd.DragDropManager-method-verifyEl'>    /**
+</span>     * This checks to make sure an element exists and is in the DOM.  The
+     * main purpose is to handle cases where innerHTML is used to remove
+     * drag and drop objects from the DOM.  IE provides an 'unspecified
+     * error' when trying to access the offsetParent of such an element
+     * @method verifyEl
+     * @param {HTMLElement} el the element to check
+     * @return {boolean} true if the element looks usable
+     * @static
+     */
+    verifyEl: function(el) {
+        if (el) {
+            var parent;
+            if(Ext.isIE){
+                try{
+                    parent = el.offsetParent;
+                }catch(e){}
+            }else{
+                parent = el.offsetParent;
+            }
+            if (parent) {
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+<span id='Ext-dd.DragDropManager-method-getLocation'>    /**
+</span>     * Returns a Region object containing the drag and drop element's position
+     * and size, including the padding configured for it
+     * @method getLocation
+     * @param {DragDrop} oDD the drag and drop object to get the
+     *                       location for
+     * @return {Ext.util.Region} a Region object representing the total area
+     *                             the element occupies, including any padding
+     *                             the instance is configured for.
+     * @static
+     */
+    getLocation: function(oDD) {
+        if (! this.isTypeOfDD(oDD)) {
+            return null;
+        }
+
+        //delegate getLocation method to the
+        //drag and drop target.
+        if (oDD.getRegion) {
+            return oDD.getRegion();
+        }
+
+        var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
+
+        try {
+            pos= Ext.core.Element.getXY(el);
+        } catch (e) { }
+
+        if (!pos) {
+            return null;
+        }
+
+        x1 = pos[0];
+        x2 = x1 + el.offsetWidth;
+        y1 = pos[1];
+        y2 = y1 + el.offsetHeight;
+
+        t = y1 - oDD.padding[0];
+        r = x2 + oDD.padding[1];
+        b = y2 + oDD.padding[2];
+        l = x1 - oDD.padding[3];
+
+        return Ext.create('Ext.util.Region', t, r, b, l);
+    },
+
+<span id='Ext-dd.DragDropManager-method-isOverTarget'>    /**
+</span>     * Checks the cursor location to see if it over the target
+     * @method isOverTarget
+     * @param {Ext.util.Point} pt The point to evaluate
+     * @param {DragDrop} oTarget the DragDrop object we are inspecting
+     * @return {boolean} true if the mouse is over the target
+     * @private
+     * @static
+     */
+    isOverTarget: function(pt, oTarget, intersect) {
+        // use cache if available
+        var loc = this.locationCache[oTarget.id];
+        if (!loc || !this.useCache) {
+            loc = this.getLocation(oTarget);
+            this.locationCache[oTarget.id] = loc;
+
+        }
+
+        if (!loc) {
+            return false;
+        }
+
+        oTarget.cursorIsOver = loc.contains( pt );
+
+        // DragDrop is using this as a sanity check for the initial mousedown
+        // in this case we are done.  In POINT mode, if the drag obj has no
+        // contraints, we are also done. Otherwise we need to evaluate the
+        // location of the target as related to the actual location of the
+        // dragged element.
+        var dc = this.dragCurrent;
+        if (!dc || !dc.getTargetCoord ||
+                (!intersect &amp;&amp; !dc.constrainX &amp;&amp; !dc.constrainY)) {
+            return oTarget.cursorIsOver;
+        }
+
+        oTarget.overlap = null;
+
+        // Get the current location of the drag element, this is the
+        // location of the mouse event less the delta that represents
+        // where the original mousedown happened on the element.  We
+        // need to consider constraints and ticks as well.
+        var pos = dc.getTargetCoord(pt.x, pt.y);
+
+        var el = dc.getDragEl();
+        var curRegion = Ext.create('Ext.util.Region', pos.y,
+                                               pos.x + el.offsetWidth,
+                                               pos.y + el.offsetHeight,
+                                               pos.x );
+
+        var overlap = curRegion.intersect(loc);
+
+        if (overlap) {
+            oTarget.overlap = overlap;
+            return (intersect) ? true : oTarget.cursorIsOver;
+        } else {
+            return false;
+        }
+    },
+
+<span id='Ext-dd.DragDropManager-method-_onUnload'>    /**
+</span>     * unload event handler
+     * @method _onUnload
+     * @private
+     * @static
+     */
+    _onUnload: function(e, me) {
+        Ext.dd.DragDropManager.unregAll();
+    },
+
+<span id='Ext-dd.DragDropManager-method-unregAll'>    /**
+</span>     * Cleans up the drag and drop events and objects.
+     * @method unregAll
+     * @private
+     * @static
+     */
+    unregAll: function() {
+
+        if (this.dragCurrent) {
+            this.stopDrag();
+            this.dragCurrent = null;
+        }
+
+        this._execOnAll(&quot;unreg&quot;, []);
+
+        for (var i in this.elementCache) {
+            delete this.elementCache[i];
+        }
+
+        this.elementCache = {};
+        this.ids = {};
+    },
+
+<span id='Ext-dd.DragDropManager-property-elementCache'>    /**
+</span>     * A cache of DOM elements
+     * @property elementCache
+     * @private
+     * @static
+     */
+    elementCache: {},
+
+<span id='Ext-dd.DragDropManager-method-getElWrapper'>    /**
+</span>     * Get the wrapper for the DOM element specified
+     * @method getElWrapper
+     * @param {String} id the id of the element to get
+     * @return {Ext.dd.DDM.ElementWrapper} the wrapped element
+     * @private
+     * @deprecated This wrapper isn't that useful
+     * @static
+     */
+    getElWrapper: function(id) {
+        var oWrapper = this.elementCache[id];
+        if (!oWrapper || !oWrapper.el) {
+            oWrapper = this.elementCache[id] =
+                new this.ElementWrapper(Ext.getDom(id));
+        }
+        return oWrapper;
+    },
+
+<span id='Ext-dd.DragDropManager-method-getElement'>    /**
+</span>     * Returns the actual DOM element
+     * @method getElement
+     * @param {String} id the id of the elment to get
+     * @return {Object} The element
+     * @deprecated use Ext.lib.Ext.getDom instead
+     * @static
+     */
+    getElement: function(id) {
+        return Ext.getDom(id);
+    },
+
+<span id='Ext-dd.DragDropManager-method-getCss'>    /**
+</span>     * Returns the style property for the DOM element (i.e.,
+     * document.getElById(id).style)
+     * @method getCss
+     * @param {String} id the id of the elment to get
+     * @return {Object} The style property of the element
+     * @static
+     */
+    getCss: function(id) {
+        var el = Ext.getDom(id);
+        return (el) ? el.style : null;
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper'>    /**
+</span>     * Inner class for cached elements
+     * @class Ext.dd.DragDropManager.ElementWrapper
+     * @for DragDropManager
+     * @private
+     * @deprecated
+     */
+    ElementWrapper: function(el) {
+<span id='Ext-dd.DragDropManager.ElementWrapper-property-el'>            /**
+</span>             * The element
+             * @property el
+             */
+            this.el = el || null;
+<span id='Ext-dd.DragDropManager.ElementWrapper-property-id'>            /**
+</span>             * The element id
+             * @property id
+             */
+            this.id = this.el &amp;&amp; el.id;
+<span id='Ext-dd.DragDropManager.ElementWrapper-property-css'>            /**
+</span>             * A reference to the style property
+             * @property css
+             */
+            this.css = this.el &amp;&amp; el.style;
+        },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-getPosX'>    /**
+</span>     * Returns the X position of an html element
+     * @method getPosX
+     * @param el the element for which to get the position
+     * @return {int} the X coordinate
+     * @for DragDropManager
+     * @static
+     */
+    getPosX: function(el) {
+        return Ext.core.Element.getX(el);
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-getPosY'>    /**
+</span>     * Returns the Y position of an html element
+     * @method getPosY
+     * @param el the element for which to get the position
+     * @return {int} the Y coordinate
+     * @static
+     */
+    getPosY: function(el) {
+        return Ext.core.Element.getY(el);
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-swapNode'>    /**
+</span>     * Swap two nodes.  In IE, we use the native method, for others we
+     * emulate the IE behavior
+     * @method swapNode
+     * @param n1 the first node to swap
+     * @param n2 the other node to swap
+     * @static
+     */
+    swapNode: function(n1, n2) {
+        if (n1.swapNode) {
+            n1.swapNode(n2);
+        } else {
+            var p = n2.parentNode;
+            var s = n2.nextSibling;
+
+            if (s == n1) {
+                p.insertBefore(n1, n2);
+            } else if (n2 == n1.nextSibling) {
+                p.insertBefore(n2, n1);
+            } else {
+                n1.parentNode.replaceChild(n2, n1);
+                p.insertBefore(n1, s);
+            }
+        }
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-getScroll'>    /**
+</span>     * Returns the current scroll position
+     * @method getScroll
+     * @private
+     * @static
+     */
+    getScroll: function () {
+        var doc   = window.document,
+            docEl = doc.documentElement,
+            body  = doc.body,
+            top   = 0,
+            left  = 0;
+            
+        if (Ext.isGecko4) {
+            top  = window.scrollYOffset;
+            left = window.scrollXOffset;
+        } else {
+            if (docEl &amp;&amp; (docEl.scrollTop || docEl.scrollLeft)) {
+                top  = docEl.scrollTop;
+                left = docEl.scrollLeft;
+            } else if (body) {
+                top  = body.scrollTop;
+                left = body.scrollLeft;
+            } 
+        }
+        return {
+            top: top,
+            left: left
+        };
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-getStyle'>    /**
+</span>     * Returns the specified element style property
+     * @method getStyle
+     * @param {HTMLElement} el          the element
+     * @param {string}      styleProp   the style property
+     * @return {string} The value of the style property
+     * @static
+     */
+    getStyle: function(el, styleProp) {
+        return Ext.fly(el).getStyle(styleProp);
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-getScrollTop'>    /**
+</span>     * Gets the scrollTop
+     * @method getScrollTop
+     * @return {int} the document's scrollTop
+     * @static
+     */
+    getScrollTop: function () {
+        return this.getScroll().top;
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-getScrollLeft'>    /**
+</span>     * Gets the scrollLeft
+     * @method getScrollLeft
+     * @return {int} the document's scrollTop
+     * @static
+     */
+    getScrollLeft: function () {
+        return this.getScroll().left;
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-moveToEl'>    /**
+</span>     * Sets the x/y position of an element to the location of the
+     * target element.
+     * @method moveToEl
+     * @param {HTMLElement} moveEl      The element to move
+     * @param {HTMLElement} targetEl    The position reference element
+     * @static
+     */
+    moveToEl: function (moveEl, targetEl) {
+        var aCoord = Ext.core.Element.getXY(targetEl);
+        Ext.core.Element.setXY(moveEl, aCoord);
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-numericSort'>    /**
+</span>     * Numeric array sort function
+     * @method numericSort
+     * @static
+     */
+    numericSort: function(a, b) {
+        return (a - b);
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-property-_timeoutCount'>    /**
+</span>     * Internal counter
+     * @property _timeoutCount
+     * @private
+     * @static
+     */
+    _timeoutCount: 0,
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-_addListeners'>    /**
+</span>     * Trying to make the load order less important.  Without this we get
+     * an error if this file is loaded before the Event Utility.
+     * @method _addListeners
+     * @private
+     * @static
+     */
+    _addListeners: function() {
+        if ( document ) {
+            this._onLoad();
+        } else {
+            if (this._timeoutCount &gt; 2000) {
+            } else {
+                setTimeout(this._addListeners, 10);
+                if (document &amp;&amp; document.body) {
+                    this._timeoutCount += 1;
+                }
+            }
+        }
+    },
+
+<span id='Ext-dd.DragDropManager.ElementWrapper-method-handleWasClicked'>    /**
+</span>     * Recursively searches the immediate parent and all child nodes for
+     * the handle element in order to determine wheter or not it was
+     * clicked.
+     * @method handleWasClicked
+     * @param node the html element to inspect
+     * @static
+     */
+    handleWasClicked: function(node, id) {
+        if (this.isHandle(id, node.id)) {
+            return true;
+        } else {
+            // check to see if this is a text node child of the one we want
+            var p = node.parentNode;
+
+            while (p) {
+                if (this.isHandle(id, p.id)) {
+                    return true;
+                } else {
+                    p = p.parentNode;
+                }
+            }
+        }
+
+        return false;
+    }
+}, function() {
+    this._addListeners();
+});
+</pre></pre></body></html>
\ No newline at end of file