Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / pkgs / ext-dd-debug.js
index 2a08cf1..c0cde04 100644 (file)
@@ -1,6 +1,6 @@
 /*!
 /*!
- * Ext JS Library 3.1.0
- * Copyright(c) 2006-2009 Ext JS, LLC
+ * Ext JS Library 3.2.0
+ * Copyright(c) 2006-2010 Ext JS, Inc.
  * licensing@extjs.com
  * http://www.extjs.com/license
  */
  * licensing@extjs.com
  * http://www.extjs.com/license
  */
@@ -96,7 +96,7 @@ Ext.dd.DragDrop.prototype = {
 
     /**
      * The id of the element that will be dragged.  By default this is same
 
     /**
      * The id of the element that will be dragged.  By default this is same
-     * as the linked element , but could be changed to another element. Ex:
+     * as the linked element, but could be changed to another element. Ex:
      * Ext.dd.DDProxy
      * @property dragElId
      * @type String
      * Ext.dd.DDProxy
      * @property dragElId
      * @type String
@@ -187,7 +187,9 @@ Ext.dd.DragDrop.prototype = {
      * Lock this instance
      * @method lock
      */
      * Lock this instance
      * @method lock
      */
-    lock: function() { this.locked = true; },
+    lock: function() {
+        this.locked = true;
+    },
 
     /**
      * When set to true, other DD objects in cooperating DDGroups do not receive
 
     /**
      * When set to true, other DD objects in cooperating DDGroups do not receive
@@ -201,7 +203,9 @@ Ext.dd.DragDrop.prototype = {
      * Unlock this instace
      * @method unlock
      */
      * Unlock this instace
      * @method unlock
      */
-    unlock: function() { this.locked = false; },
+    unlock: function() {
+        this.locked = false;
+    },
 
     /**
      * By default, all instances can be a drop target.  This can be disabled by
 
     /**
      * By default, all instances can be a drop target.  This can be disabled by
@@ -269,7 +273,6 @@ Ext.dd.DragDrop.prototype = {
      * The up constraint
      * @property minY
      * @type int
      * The up constraint
      * @property minY
      * @type int
-     * @type int
      * @private
      */
     minY: 0,
      * @private
      */
     minY: 0,
@@ -321,7 +324,7 @@ Ext.dd.DragDrop.prototype = {
     primaryButtonOnly: true,
 
     /**
     primaryButtonOnly: true,
 
     /**
-     * The availabe property is false until the linked dom element is accessible.
+     * The available property is false until the linked dom element is accessible.
      * @property available
      * @type boolean
      */
      * @property available
      * @type boolean
      */
@@ -712,7 +715,6 @@ Ext.dd.DragDrop.prototype = {
         this.lastPageX = p[0];
         this.lastPageY = p[1];
 
         this.lastPageX = p[0];
         this.lastPageY = p[1];
 
-
         this.setStartPosition(p);
     },
 
         this.setStartPosition(p);
     },
 
@@ -854,7 +856,6 @@ Ext.dd.DragDrop.prototype = {
                 // set the initial element position
                 this.setStartPosition();
 
                 // set the initial element position
                 this.setStartPosition();
 
-
                 this.b4MouseDown(e);
                 this.onMouseDown(e);
 
                 this.b4MouseDown(e);
                 this.onMouseDown(e);
 
@@ -1105,8 +1106,6 @@ Ext.dd.DragDrop.prototype = {
      * @param {boolean} maintainOffset
      */
     resetConstraints: function() {
      * @param {boolean} maintainOffset
      */
     resetConstraints: function() {
-
-
         // Maintain offsets if necessary
         if (this.initPageX || this.initPageX === 0) {
             // figure out how much this thing has moved
         // Maintain offsets if necessary
         if (this.initPageX || this.initPageX === 0) {
             // figure out how much this thing has moved
@@ -1144,7 +1143,6 @@ Ext.dd.DragDrop.prototype = {
      * @private
      */
     getTick: function(val, tickArray) {
      * @private
      */
     getTick: function(val, tickArray) {
-
         if (!tickArray) {
             // If tick interval is not defined, it is effectively 1 pixel,
             // so we return the value passed to us.
         if (!tickArray) {
             // If tick interval is not defined, it is effectively 1 pixel,
             // so we return the value passed to us.
@@ -1181,7 +1179,7 @@ Ext.dd.DragDrop.prototype = {
 };
 
 })();
 };
 
 })();
-/**
+/*!
  * The drag and drop utility provides a framework for building drag and drop
  * applications.  In addition to enabling drag and drop for specific elements,
  * the drag and drop elements are tracked by the manager class, and the
  * The drag and drop utility provides a framework for building drag and drop
  * applications.  In addition to enabling drag and drop for specific elements,
  * the drag and drop elements are tracked by the manager class, and the
@@ -1212,7 +1210,7 @@ Ext.dd.DragDropMgr = function() {
          * dimension is the DragDrop item group, the second the DragDrop
          * object.
          * @property ids
          * dimension is the DragDrop item group, the second the DragDrop
          * object.
          * @property ids
-         * @type {string: string}
+         * @type String[]
          * @private
          * @static
          */
          * @private
          * @static
          */
@@ -1223,7 +1221,7 @@ Ext.dd.DragDropMgr = function() {
          * if the element that generated the mousedown event is actually the
          * handle and not the html element itself.
          * @property handleIds
          * if the element that generated the mousedown event is actually the
          * handle and not the html element itself.
          * @property handleIds
-         * @type {string: string}
+         * @type String[]
          * @private
          * @static
          */
          * @private
          * @static
          */
@@ -1593,8 +1591,8 @@ Ext.dd.DragDropMgr = function() {
          * Returns true if the specified dd target is a legal target for
          * the specifice drag obj
          * @method isLegalTarget
          * Returns true if the specified dd target is a legal target for
          * the specifice drag obj
          * @method isLegalTarget
-         * @param {DragDrop} the drag obj
-         * @param {DragDrop} the target
+         * @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
          * @return {boolean} true if the target is a legal target for the
          * dd obj
          * @static
@@ -2268,7 +2266,7 @@ Ext.dd.DragDropMgr = function() {
 
         /**
          * Inner class for cached elements
 
         /**
          * Inner class for cached elements
-         * @class DragDropMgr.ElementWrapper
+         * @class Ext.dd.DragDropMgr.ElementWrapper
          * @for DragDropMgr
          * @private
          * @deprecated
          * @for DragDropMgr
          * @private
          * @deprecated
@@ -2381,7 +2379,9 @@ Ext.dd.DragDropMgr = function() {
          * @return {int} the document's scrollTop
          * @static
          */
          * @return {int} the document's scrollTop
          * @static
          */
-        getScrollTop: function () { return this.getScroll().top; },
+        getScrollTop: function () {
+            return this.getScroll().top;
+        },
 
         /**
          * Gets the scrollLeft
 
         /**
          * Gets the scrollLeft
@@ -2389,7 +2389,9 @@ Ext.dd.DragDropMgr = function() {
          * @return {int} the document's scrollTop
          * @static
          */
          * @return {int} the document's scrollTop
          * @static
          */
-        getScrollLeft: function () { return this.getScroll().left; },
+        getScrollLeft: function () {
+            return this.getScroll().left;
+        },
 
         /**
          * Sets the x/y position of an element to the location of the
 
         /**
          * Sets the x/y position of an element to the location of the
@@ -2409,7 +2411,9 @@ Ext.dd.DragDropMgr = function() {
          * @method numericSort
          * @static
          */
          * @method numericSort
          * @static
          */
-        numericSort: function(a, b) { return (a - b); },
+        numericSort: function(a, b) {
+            return (a - b);
+        },
 
         /**
          * Internal counter
 
         /**
          * Internal counter
@@ -2684,8 +2688,6 @@ Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
      * @private
      */
     getTargetCoord: function(iPageX, iPageY) {
      * @private
      */
     getTargetCoord: function(iPageX, iPageY) {
-
-
         var x = iPageX - this.deltaX;
         var y = iPageY - this.deltaY;
 
         var x = iPageX - this.deltaX;
         var y = iPageY - this.deltaY;
 
@@ -3153,1588 +3155,1617 @@ Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
     toString: function() {
         return ("DDTarget " + this.id);
     }
     toString: function() {
         return ("DDTarget " + this.id);
     }
-});/**\r
- * @class Ext.dd.DragTracker\r
- * @extends Ext.util.Observable\r
- */\r
-Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {\r
-    /**\r
-     * @cfg {Boolean} active\r
-        * Defaults to <tt>false</tt>.\r
-        */     \r
-    active: false,\r
-    /**\r
-     * @cfg {Number} tolerance\r
-        * Defaults to <tt>5</tt>.\r
-        */     \r
-    tolerance: 5,\r
-    /**\r
-     * @cfg {Boolean/Number} autoStart\r
-        * Defaults to <tt>false</tt>. Specify <tt>true</tt> to defer trigger start by 1000 ms.\r
-        * Specify a Number for the number of milliseconds to defer trigger start.\r
-        */     \r
-    autoStart: false,\r
-    \r
-    constructor : function(config){\r
-        Ext.apply(this, config);\r
-           this.addEvents(\r
-               /**\r
-                * @event mousedown\r
-                * @param {Object} this\r
-                * @param {Object} e event object\r
-                */\r
-               'mousedown',\r
-               /**\r
-                * @event mouseup\r
-                * @param {Object} this\r
-                * @param {Object} e event object\r
-                */\r
-               'mouseup',\r
-               /**\r
-                * @event mousemove\r
-                * @param {Object} this\r
-                * @param {Object} e event object\r
-                */\r
-               'mousemove',\r
-               /**\r
-                * @event dragstart\r
-                * @param {Object} this\r
-                * @param {Object} startXY the page coordinates of the event\r
-                */\r
-               'dragstart',\r
-               /**\r
-                * @event dragend\r
-                * @param {Object} this\r
-                * @param {Object} e event object\r
-                */\r
-               'dragend',\r
-               /**\r
-                * @event drag\r
-                * @param {Object} this\r
-                * @param {Object} e event object\r
-                */\r
-               'drag'\r
-           );\r
-       \r
-           this.dragRegion = new Ext.lib.Region(0,0,0,0);\r
-       \r
-           if(this.el){\r
-               this.initEl(this.el);\r
-           }\r
-        Ext.dd.DragTracker.superclass.constructor.call(this, config);\r
-    },\r
-\r
-    initEl: function(el){\r
-        this.el = Ext.get(el);\r
-        el.on('mousedown', this.onMouseDown, this,\r
-                this.delegate ? {delegate: this.delegate} : undefined);\r
-    },\r
-\r
-    destroy : function(){\r
-        this.el.un('mousedown', this.onMouseDown, this);\r
-    },\r
-\r
-    onMouseDown: function(e, target){\r
-        if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){\r
-            this.startXY = this.lastXY = e.getXY();\r
-            this.dragTarget = this.delegate ? target : this.el.dom;\r
-            if(this.preventDefault !== false){\r
-                e.preventDefault();\r
-            }\r
-            var doc = Ext.getDoc();\r
-            doc.on('mouseup', this.onMouseUp, this);\r
-            doc.on('mousemove', this.onMouseMove, this);\r
-            doc.on('selectstart', this.stopSelect, this);\r
-            if(this.autoStart){\r
-                this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);\r
-            }\r
-        }\r
-    },\r
-\r
-    onMouseMove: function(e, target){\r
-        // HACK: IE hack to see if button was released outside of window. */\r
-        if(this.active && Ext.isIE && !e.browserEvent.button){\r
-            e.preventDefault();\r
-            this.onMouseUp(e);\r
-            return;\r
-        }\r
-\r
-        e.preventDefault();\r
-        var xy = e.getXY(), s = this.startXY;\r
-        this.lastXY = xy;\r
-        if(!this.active){\r
-            if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){\r
-                this.triggerStart();\r
-            }else{\r
-                return;\r
-            }\r
-        }\r
-        this.fireEvent('mousemove', this, e);\r
-        this.onDrag(e);\r
-        this.fireEvent('drag', this, e);\r
-    },\r
-\r
-    onMouseUp: function(e){\r
-        var doc = Ext.getDoc();\r
-        doc.un('mousemove', this.onMouseMove, this);\r
-        doc.un('mouseup', this.onMouseUp, this);\r
-        doc.un('selectstart', this.stopSelect, this);\r
-        e.preventDefault();\r
-        this.clearStart();\r
-        var wasActive = this.active;\r
-        this.active = false;\r
-        delete this.elRegion;\r
-        this.fireEvent('mouseup', this, e);\r
-        if(wasActive){\r
-            this.onEnd(e);\r
-            this.fireEvent('dragend', this, e);\r
-        }\r
-    },\r
-\r
-    triggerStart: function(isTimer){\r
-        this.clearStart();\r
-        this.active = true;\r
-        this.onStart(this.startXY);\r
-        this.fireEvent('dragstart', this, this.startXY);\r
-    },\r
-\r
-    clearStart : function(){\r
-        if(this.timer){\r
-            clearTimeout(this.timer);\r
-            delete this.timer;\r
-        }\r
-    },\r
-\r
-    stopSelect : function(e){\r
-        e.stopEvent();\r
-        return false;\r
-    },\r
-\r
-    onBeforeStart : function(e){\r
-\r
-    },\r
-\r
-    onStart : function(xy){\r
-\r
-    },\r
-\r
-    onDrag : function(e){\r
-\r
-    },\r
-\r
-    onEnd : function(e){\r
-\r
-    },\r
-\r
-    getDragTarget : function(){\r
-        return this.dragTarget;\r
-    },\r
-\r
-    getDragCt : function(){\r
-        return this.el;\r
-    },\r
-\r
-    getXY : function(constrain){\r
-        return constrain ?\r
-               this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;\r
-    },\r
-\r
-    getOffset : function(constrain){\r
-        var xy = this.getXY(constrain);\r
-        var s = this.startXY;\r
-        return [s[0]-xy[0], s[1]-xy[1]];\r
-    },\r
-\r
-    constrainModes: {\r
-        'point' : function(xy){\r
-\r
-            if(!this.elRegion){\r
-                this.elRegion = this.getDragCt().getRegion();\r
-            }\r
-\r
-            var dr = this.dragRegion;\r
-\r
-            dr.left = xy[0];\r
-            dr.top = xy[1];\r
-            dr.right = xy[0];\r
-            dr.bottom = xy[1];\r
-\r
-            dr.constrainTo(this.elRegion);\r
-\r
-            return [dr.left, dr.top];\r
-        }\r
-    }\r
-});/**\r
- * @class Ext.dd.ScrollManager\r
- * <p>Provides automatic scrolling of overflow regions in the page during drag operations.</p>\r
- * <p>The ScrollManager configs will be used as the defaults for any scroll container registered with it,\r
- * but you can also override most of the configs per scroll container by adding a \r
- * <tt>ddScrollConfig</tt> object to the target element that contains these properties: {@link #hthresh},\r
- * {@link #vthresh}, {@link #increment} and {@link #frequency}.  Example usage:\r
- * <pre><code>\r
-var el = Ext.get('scroll-ct');\r
-el.ddScrollConfig = {\r
-    vthresh: 50,\r
-    hthresh: -1,\r
-    frequency: 100,\r
-    increment: 200\r
-};\r
-Ext.dd.ScrollManager.register(el);\r
-</code></pre>\r
- * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>\r
- * @singleton\r
- */\r
-Ext.dd.ScrollManager = function(){\r
-    var ddm = Ext.dd.DragDropMgr;\r
-    var els = {};\r
-    var dragEl = null;\r
-    var proc = {};\r
-    \r
-    var onStop = function(e){\r
-        dragEl = null;\r
-        clearProc();\r
-    };\r
-    \r
-    var triggerRefresh = function(){\r
-        if(ddm.dragCurrent){\r
-             ddm.refreshCache(ddm.dragCurrent.groups);\r
-        }\r
-    };\r
-    \r
-    var doScroll = function(){\r
-        if(ddm.dragCurrent){\r
-            var dds = Ext.dd.ScrollManager;\r
-            var inc = proc.el.ddScrollConfig ?\r
-                      proc.el.ddScrollConfig.increment : dds.increment;\r
-            if(!dds.animate){\r
-                if(proc.el.scroll(proc.dir, inc)){\r
-                    triggerRefresh();\r
-                }\r
-            }else{\r
-                proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);\r
-            }\r
-        }\r
-    };\r
-    \r
-    var clearProc = function(){\r
-        if(proc.id){\r
-            clearInterval(proc.id);\r
-        }\r
-        proc.id = 0;\r
-        proc.el = null;\r
-        proc.dir = "";\r
-    };\r
-    \r
-    var startProc = function(el, dir){\r
-        clearProc();\r
-        proc.el = el;\r
-        proc.dir = dir;\r
-        var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? \r
-                el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;\r
-        proc.id = setInterval(doScroll, freq);\r
-    };\r
-    \r
-    var onFire = function(e, isDrop){\r
-        if(isDrop || !ddm.dragCurrent){ return; }\r
-        var dds = Ext.dd.ScrollManager;\r
-        if(!dragEl || dragEl != ddm.dragCurrent){\r
-            dragEl = ddm.dragCurrent;\r
-            // refresh regions on drag start\r
-            dds.refreshCache();\r
-        }\r
-        \r
-        var xy = Ext.lib.Event.getXY(e);\r
-        var pt = new Ext.lib.Point(xy[0], xy[1]);\r
-        for(var id in els){\r
-            var el = els[id], r = el._region;\r
-            var c = el.ddScrollConfig ? el.ddScrollConfig : dds;\r
-            if(r && r.contains(pt) && el.isScrollable()){\r
-                if(r.bottom - pt.y <= c.vthresh){\r
-                    if(proc.el != el){\r
-                        startProc(el, "down");\r
-                    }\r
-                    return;\r
-                }else if(r.right - pt.x <= c.hthresh){\r
-                    if(proc.el != el){\r
-                        startProc(el, "left");\r
-                    }\r
-                    return;\r
-                }else if(pt.y - r.top <= c.vthresh){\r
-                    if(proc.el != el){\r
-                        startProc(el, "up");\r
-                    }\r
-                    return;\r
-                }else if(pt.x - r.left <= c.hthresh){\r
-                    if(proc.el != el){\r
-                        startProc(el, "right");\r
-                    }\r
-                    return;\r
-                }\r
-            }\r
-        }\r
-        clearProc();\r
-    };\r
-    \r
-    ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);\r
-    ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);\r
-    \r
-    return {\r
-        /**\r
-         * Registers new overflow element(s) to auto scroll\r
-         * @param {Mixed/Array} el The id of or the element to be scrolled or an array of either\r
-         */\r
-        register : function(el){\r
-            if(Ext.isArray(el)){\r
-                for(var i = 0, len = el.length; i < len; i++) {\r
-                       this.register(el[i]);\r
-                }\r
-            }else{\r
-                el = Ext.get(el);\r
-                els[el.id] = el;\r
-            }\r
-        },\r
-        \r
-        /**\r
-         * Unregisters overflow element(s) so they are no longer scrolled\r
-         * @param {Mixed/Array} el The id of or the element to be removed or an array of either\r
-         */\r
-        unregister : function(el){\r
-            if(Ext.isArray(el)){\r
-                for(var i = 0, len = el.length; i < len; i++) {\r
-                       this.unregister(el[i]);\r
-                }\r
-            }else{\r
-                el = Ext.get(el);\r
-                delete els[el.id];\r
-            }\r
-        },\r
-        \r
-        /**\r
-         * The number of pixels from the top or bottom edge of a container the pointer needs to be to\r
-         * trigger scrolling (defaults to 25)\r
-         * @type Number\r
-         */\r
-        vthresh : 25,\r
-        /**\r
-         * The number of pixels from the right or left edge of a container the pointer needs to be to\r
-         * trigger scrolling (defaults to 25)\r
-         * @type Number\r
-         */\r
-        hthresh : 25,\r
-\r
-        /**\r
-         * The number of pixels to scroll in each scroll increment (defaults to 50)\r
-         * @type Number\r
-         */\r
-        increment : 100,\r
-        \r
-        /**\r
-         * The frequency of scrolls in milliseconds (defaults to 500)\r
-         * @type Number\r
-         */\r
-        frequency : 500,\r
-        \r
-        /**\r
-         * True to animate the scroll (defaults to true)\r
-         * @type Boolean\r
-         */\r
-        animate: true,\r
-        \r
-        /**\r
-         * The animation duration in seconds - \r
-         * MUST BE less than Ext.dd.ScrollManager.frequency! (defaults to .4)\r
-         * @type Number\r
-         */\r
-        animDuration: .4,\r
-        \r
-        /**\r
-         * Manually trigger a cache refresh.\r
-         */\r
-        refreshCache : function(){\r
-            for(var id in els){\r
-                if(typeof els[id] == 'object'){ // for people extending the object prototype\r
-                    els[id]._region = els[id].getRegion();\r
-                }\r
-            }\r
-        }\r
-    };\r
-}();/**\r
- * @class Ext.dd.Registry\r
- * Provides easy access to all drag drop components that are registered on a page.  Items can be retrieved either\r
- * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.\r
- * @singleton\r
- */\r
-Ext.dd.Registry = function(){\r
-    var elements = {}; \r
-    var handles = {}; \r
-    var autoIdSeed = 0;\r
-\r
-    var getId = function(el, autogen){\r
-        if(typeof el == "string"){\r
-            return el;\r
-        }\r
-        var id = el.id;\r
-        if(!id && autogen !== false){\r
-            id = "extdd-" + (++autoIdSeed);\r
-            el.id = id;\r
-        }\r
-        return id;\r
-    };\r
-    \r
-    return {\r
-    /**\r
-     * Resgister a drag drop element\r
-     * @param {String/HTMLElement) element The id or DOM node to register\r
-     * @param {Object} data (optional) An custom data object that will be passed between the elements that are involved\r
-     * in drag drop operations.  You can populate this object with any arbitrary properties that your own code\r
-     * knows how to interpret, plus there are some specific properties known to the Registry that should be\r
-     * populated in the data object (if applicable):\r
-     * <pre>\r
-Value      Description<br />\r
----------  ------------------------------------------<br />\r
-handles    Array of DOM nodes that trigger dragging<br />\r
-           for the element being registered<br />\r
-isHandle   True if the element passed in triggers<br />\r
-           dragging itself, else false\r
-</pre>\r
-     */\r
-        register : function(el, data){\r
-            data = data || {};\r
-            if(typeof el == "string"){\r
-                el = document.getElementById(el);\r
-            }\r
-            data.ddel = el;\r
-            elements[getId(el)] = data;\r
-            if(data.isHandle !== false){\r
-                handles[data.ddel.id] = data;\r
-            }\r
-            if(data.handles){\r
-                var hs = data.handles;\r
-                for(var i = 0, len = hs.length; i < len; i++){\r
-                       handles[getId(hs[i])] = data;\r
-                }\r
-            }\r
-        },\r
-\r
-    /**\r
-     * Unregister a drag drop element\r
-     * @param {String/HTMLElement) element The id or DOM node to unregister\r
-     */\r
-        unregister : function(el){\r
-            var id = getId(el, false);\r
-            var data = elements[id];\r
-            if(data){\r
-                delete elements[id];\r
-                if(data.handles){\r
-                    var hs = data.handles;\r
-                    for(var i = 0, len = hs.length; i < len; i++){\r
-                       delete handles[getId(hs[i], false)];\r
-                    }\r
-                }\r
-            }\r
-        },\r
-\r
-    /**\r
-     * Returns the handle registered for a DOM Node by id\r
-     * @param {String/HTMLElement} id The DOM node or id to look up\r
-     * @return {Object} handle The custom handle data\r
-     */\r
-        getHandle : function(id){\r
-            if(typeof id != "string"){ // must be element?\r
-                id = id.id;\r
-            }\r
-            return handles[id];\r
-        },\r
-\r
-    /**\r
-     * Returns the handle that is registered for the DOM node that is the target of the event\r
-     * @param {Event} e The event\r
-     * @return {Object} handle The custom handle data\r
-     */\r
-        getHandleFromEvent : function(e){\r
-            var t = Ext.lib.Event.getTarget(e);\r
-            return t ? handles[t.id] : null;\r
-        },\r
-\r
-    /**\r
-     * Returns a custom data object that is registered for a DOM node by id\r
-     * @param {String/HTMLElement} id The DOM node or id to look up\r
-     * @return {Object} data The custom data\r
-     */\r
-        getTarget : function(id){\r
-            if(typeof id != "string"){ // must be element?\r
-                id = id.id;\r
-            }\r
-            return elements[id];\r
-        },\r
-\r
-    /**\r
-     * Returns a custom data object that is registered for the DOM node that is the target of the event\r
-     * @param {Event} e The event\r
-     * @return {Object} data The custom data\r
-     */\r
-        getTargetFromEvent : function(e){\r
-            var t = Ext.lib.Event.getTarget(e);\r
-            return t ? elements[t.id] || handles[t.id] : null;\r
-        }\r
-    };\r
-}();/**\r
- * @class Ext.dd.StatusProxy\r
- * A specialized drag proxy that supports a drop status icon, {@link Ext.Layer} styles and auto-repair.  This is the\r
- * default drag proxy used by all Ext.dd components.\r
- * @constructor\r
- * @param {Object} config\r
- */\r
-Ext.dd.StatusProxy = function(config){\r
-    Ext.apply(this, config);\r
-    this.id = this.id || Ext.id();\r
-    this.el = new Ext.Layer({\r
-        dh: {\r
-            id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [\r
-                {tag: "div", cls: "x-dd-drop-icon"},\r
-                {tag: "div", cls: "x-dd-drag-ghost"}\r
-            ]\r
-        }, \r
-        shadow: !config || config.shadow !== false\r
-    });\r
-    this.ghost = Ext.get(this.el.dom.childNodes[1]);\r
-    this.dropStatus = this.dropNotAllowed;\r
-};\r
-\r
-Ext.dd.StatusProxy.prototype = {\r
-    /**\r
-     * @cfg {String} dropAllowed\r
-     * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").\r
-     */\r
-    dropAllowed : "x-dd-drop-ok",\r
-    /**\r
-     * @cfg {String} dropNotAllowed\r
-     * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").\r
-     */\r
-    dropNotAllowed : "x-dd-drop-nodrop",\r
-\r
-    /**\r
-     * Updates the proxy's visual element to indicate the status of whether or not drop is allowed\r
-     * over the current target element.\r
-     * @param {String} cssClass The css class for the new drop status indicator image\r
-     */\r
-    setStatus : function(cssClass){\r
-        cssClass = cssClass || this.dropNotAllowed;\r
-        if(this.dropStatus != cssClass){\r
-            this.el.replaceClass(this.dropStatus, cssClass);\r
-            this.dropStatus = cssClass;\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Resets the status indicator to the default dropNotAllowed value\r
-     * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it\r
-     */\r
-    reset : function(clearGhost){\r
-        this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;\r
-        this.dropStatus = this.dropNotAllowed;\r
-        if(clearGhost){\r
-            this.ghost.update("");\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Updates the contents of the ghost element\r
-     * @param {String/HTMLElement} html The html that will replace the current innerHTML of the ghost element, or a\r
-     * DOM node to append as the child of the ghost element (in which case the innerHTML will be cleared first).\r
-     */\r
-    update : function(html){\r
-        if(typeof html == "string"){\r
-            this.ghost.update(html);\r
-        }else{\r
-            this.ghost.update("");\r
-            html.style.margin = "0";\r
-            this.ghost.dom.appendChild(html);\r
-        }\r
-        var el = this.ghost.dom.firstChild; \r
-        if(el){\r
-            Ext.fly(el).setStyle('float', 'none');\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Returns the underlying proxy {@link Ext.Layer}\r
-     * @return {Ext.Layer} el\r
-    */\r
-    getEl : function(){\r
-        return this.el;\r
-    },\r
-\r
-    /**\r
-     * Returns the ghost element\r
-     * @return {Ext.Element} el\r
-     */\r
-    getGhost : function(){\r
-        return this.ghost;\r
-    },\r
-\r
-    /**\r
-     * Hides the proxy\r
-     * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them\r
-     */\r
-    hide : function(clear){\r
-        this.el.hide();\r
-        if(clear){\r
-            this.reset(true);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Stops the repair animation if it's currently running\r
-     */\r
-    stop : function(){\r
-        if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){\r
-            this.anim.stop();\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Displays this proxy\r
-     */\r
-    show : function(){\r
-        this.el.show();\r
-    },\r
-\r
-    /**\r
-     * Force the Layer to sync its shadow and shim positions to the element\r
-     */\r
-    sync : function(){\r
-        this.el.sync();\r
-    },\r
-\r
-    /**\r
-     * Causes the proxy to return to its position of origin via an animation.  Should be called after an\r
-     * invalid drop operation by the item being dragged.\r
-     * @param {Array} xy The XY position of the element ([x, y])\r
-     * @param {Function} callback The function to call after the repair is complete.\r
-     * @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the browser window.\r
-     */\r
-    repair : function(xy, callback, scope){\r
-        this.callback = callback;\r
-        this.scope = scope;\r
-        if(xy && this.animRepair !== false){\r
-            this.el.addClass("x-dd-drag-repair");\r
-            this.el.hideUnders(true);\r
-            this.anim = this.el.shift({\r
-                duration: this.repairDuration || .5,\r
-                easing: 'easeOut',\r
-                xy: xy,\r
-                stopFx: true,\r
-                callback: this.afterRepair,\r
-                scope: this\r
-            });\r
-        }else{\r
-            this.afterRepair();\r
-        }\r
-    },\r
-\r
-    // private\r
-    afterRepair : function(){\r
-        this.hide(true);\r
-        if(typeof this.callback == "function"){\r
-            this.callback.call(this.scope || this);\r
-        }\r
-        this.callback = null;\r
-        this.scope = null;\r
-    },\r
-    \r
-    destroy: function(){\r
-        Ext.destroy(this.ghost, this.el);    \r
-    }\r
-};/**\r
- * @class Ext.dd.DragSource\r
- * @extends Ext.dd.DDProxy\r
- * A simple class that provides the basic implementation needed to make any element draggable.\r
- * @constructor\r
- * @param {Mixed} el The container element\r
- * @param {Object} config\r
- */\r
-Ext.dd.DragSource = function(el, config){\r
-    this.el = Ext.get(el);\r
-    if(!this.dragData){\r
-        this.dragData = {};\r
-    }\r
-    \r
-    Ext.apply(this, config);\r
-    \r
-    if(!this.proxy){\r
-        this.proxy = new Ext.dd.StatusProxy();\r
-    }\r
-    Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, \r
-          {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});\r
-    \r
-    this.dragging = false;\r
-};\r
-\r
-Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {\r
-    /**\r
-     * @cfg {String} ddGroup\r
-     * A named drag drop group to which this object belongs.  If a group is specified, then this object will only\r
-     * interact with other drag drop objects in the same group (defaults to undefined).\r
-     */\r
-    /**\r
-     * @cfg {String} dropAllowed\r
-     * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").\r
-     */\r
-    dropAllowed : "x-dd-drop-ok",\r
-    /**\r
-     * @cfg {String} dropNotAllowed\r
-     * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").\r
-     */\r
-    dropNotAllowed : "x-dd-drop-nodrop",\r
-\r
-    /**\r
-     * Returns the data object associated with this drag source\r
-     * @return {Object} data An object containing arbitrary data\r
-     */\r
-    getDragData : function(e){\r
-        return this.dragData;\r
-    },\r
-\r
-    // private\r
-    onDragEnter : function(e, id){\r
-        var target = Ext.dd.DragDropMgr.getDDById(id);\r
-        this.cachedTarget = target;\r
-        if(this.beforeDragEnter(target, e, id) !== false){\r
-            if(target.isNotifyTarget){\r
-                var status = target.notifyEnter(this, e, this.dragData);\r
-                this.proxy.setStatus(status);\r
-            }else{\r
-                this.proxy.setStatus(this.dropAllowed);\r
-            }\r
-            \r
-            if(this.afterDragEnter){\r
-                /**\r
-                 * An empty function by default, but provided so that you can perform a custom action\r
-                 * when the dragged item enters the drop target by providing an implementation.\r
-                 * @param {Ext.dd.DragDrop} target The drop target\r
-                 * @param {Event} e The event object\r
-                 * @param {String} id The id of the dragged element\r
-                 * @method afterDragEnter\r
-                 */\r
-                this.afterDragEnter(target, e, id);\r
-            }\r
-        }\r
-    },\r
-\r
-    /**\r
-     * An empty function by default, but provided so that you can perform a custom action\r
-     * before the dragged item enters the drop target and optionally cancel the onDragEnter.\r
-     * @param {Ext.dd.DragDrop} target The drop target\r
-     * @param {Event} e The event object\r
-     * @param {String} id The id of the dragged element\r
-     * @return {Boolean} isValid True if the drag event is valid, else false to cancel\r
-     */\r
-    beforeDragEnter : function(target, e, id){\r
-        return true;\r
-    },\r
-\r
-    // private\r
-    alignElWithMouse: function() {\r
-        Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);\r
-        this.proxy.sync();\r
-    },\r
-\r
-    // private\r
-    onDragOver : function(e, id){\r
-        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);\r
-        if(this.beforeDragOver(target, e, id) !== false){\r
-            if(target.isNotifyTarget){\r
-                var status = target.notifyOver(this, e, this.dragData);\r
-                this.proxy.setStatus(status);\r
-            }\r
-\r
-            if(this.afterDragOver){\r
-                /**\r
-                 * An empty function by default, but provided so that you can perform a custom action\r
-                 * while the dragged item is over the drop target by providing an implementation.\r
-                 * @param {Ext.dd.DragDrop} target The drop target\r
-                 * @param {Event} e The event object\r
-                 * @param {String} id The id of the dragged element\r
-                 * @method afterDragOver\r
-                 */\r
-                this.afterDragOver(target, e, id);\r
-            }\r
-        }\r
-    },\r
-\r
-    /**\r
-     * An empty function by default, but provided so that you can perform a custom action\r
-     * while the dragged item is over the drop target and optionally cancel the onDragOver.\r
-     * @param {Ext.dd.DragDrop} target The drop target\r
-     * @param {Event} e The event object\r
-     * @param {String} id The id of the dragged element\r
-     * @return {Boolean} isValid True if the drag event is valid, else false to cancel\r
-     */\r
-    beforeDragOver : function(target, e, id){\r
-        return true;\r
-    },\r
-\r
-    // private\r
-    onDragOut : function(e, id){\r
-        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);\r
-        if(this.beforeDragOut(target, e, id) !== false){\r
-            if(target.isNotifyTarget){\r
-                target.notifyOut(this, e, this.dragData);\r
-            }\r
-            this.proxy.reset();\r
-            if(this.afterDragOut){\r
-                /**\r
-                 * An empty function by default, but provided so that you can perform a custom action\r
-                 * after the dragged item is dragged out of the target without dropping.\r
-                 * @param {Ext.dd.DragDrop} target The drop target\r
-                 * @param {Event} e The event object\r
-                 * @param {String} id The id of the dragged element\r
-                 * @method afterDragOut\r
-                 */\r
-                this.afterDragOut(target, e, id);\r
-            }\r
-        }\r
-        this.cachedTarget = null;\r
-    },\r
-\r
-    /**\r
-     * An empty function by default, but provided so that you can perform a custom action before the dragged\r
-     * item is dragged out of the target without dropping, and optionally cancel the onDragOut.\r
-     * @param {Ext.dd.DragDrop} target The drop target\r
-     * @param {Event} e The event object\r
-     * @param {String} id The id of the dragged element\r
-     * @return {Boolean} isValid True if the drag event is valid, else false to cancel\r
-     */\r
-    beforeDragOut : function(target, e, id){\r
-        return true;\r
-    },\r
-    \r
-    // private\r
-    onDragDrop : function(e, id){\r
-        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);\r
-        if(this.beforeDragDrop(target, e, id) !== false){\r
-            if(target.isNotifyTarget){\r
-                if(target.notifyDrop(this, e, this.dragData)){ // valid drop?\r
-                    this.onValidDrop(target, e, id);\r
-                }else{\r
-                    this.onInvalidDrop(target, e, id);\r
-                }\r
-            }else{\r
-                this.onValidDrop(target, e, id);\r
-            }\r
-            \r
-            if(this.afterDragDrop){\r
-                /**\r
-                 * An empty function by default, but provided so that you can perform a custom action\r
-                 * after a valid drag drop has occurred by providing an implementation.\r
-                 * @param {Ext.dd.DragDrop} target The drop target\r
-                 * @param {Event} e The event object\r
-                 * @param {String} id The id of the dropped element\r
-                 * @method afterDragDrop\r
-                 */\r
-                this.afterDragDrop(target, e, id);\r
-            }\r
-        }\r
-        delete this.cachedTarget;\r
-    },\r
-\r
-    /**\r
-     * An empty function by default, but provided so that you can perform a custom action before the dragged\r
-     * item is dropped onto the target and optionally cancel the onDragDrop.\r
-     * @param {Ext.dd.DragDrop} target The drop target\r
-     * @param {Event} e The event object\r
-     * @param {String} id The id of the dragged element\r
-     * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel\r
-     */\r
-    beforeDragDrop : function(target, e, id){\r
-        return true;\r
-    },\r
-\r
-    // private\r
-    onValidDrop : function(target, e, id){\r
-        this.hideProxy();\r
-        if(this.afterValidDrop){\r
-            /**\r
-             * An empty function by default, but provided so that you can perform a custom action\r
-             * after a valid drop has occurred by providing an implementation.\r
-             * @param {Object} target The target DD \r
-             * @param {Event} e The event object\r
-             * @param {String} id The id of the dropped element\r
-             * @method afterInvalidDrop\r
-             */\r
-            this.afterValidDrop(target, e, id);\r
-        }\r
-    },\r
-\r
-    // private\r
-    getRepairXY : function(e, data){\r
-        return this.el.getXY();  \r
-    },\r
-\r
-    // private\r
-    onInvalidDrop : function(target, e, id){\r
-        this.beforeInvalidDrop(target, e, id);\r
-        if(this.cachedTarget){\r
-            if(this.cachedTarget.isNotifyTarget){\r
-                this.cachedTarget.notifyOut(this, e, this.dragData);\r
-            }\r
-            this.cacheTarget = null;\r
-        }\r
-        this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);\r
-\r
-        if(this.afterInvalidDrop){\r
-            /**\r
-             * An empty function by default, but provided so that you can perform a custom action\r
-             * after an invalid drop has occurred by providing an implementation.\r
-             * @param {Event} e The event object\r
-             * @param {String} id The id of the dropped element\r
-             * @method afterInvalidDrop\r
-             */\r
-            this.afterInvalidDrop(e, id);\r
-        }\r
-    },\r
-\r
-    // private\r
-    afterRepair : function(){\r
-        if(Ext.enableFx){\r
-            this.el.highlight(this.hlColor || "c3daf9");\r
-        }\r
-        this.dragging = false;\r
-    },\r
-\r
-    /**\r
-     * An empty function by default, but provided so that you can perform a custom action after an invalid\r
-     * drop has occurred.\r
-     * @param {Ext.dd.DragDrop} target The drop target\r
-     * @param {Event} e The event object\r
-     * @param {String} id The id of the dragged element\r
-     * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel\r
-     */\r
-    beforeInvalidDrop : function(target, e, id){\r
-        return true;\r
-    },\r
-\r
-    // private\r
-    handleMouseDown : function(e){\r
-        if(this.dragging) {\r
-            return;\r
-        }\r
-        var data = this.getDragData(e);\r
-        if(data && this.onBeforeDrag(data, e) !== false){\r
-            this.dragData = data;\r
-            this.proxy.stop();\r
-            Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);\r
-        } \r
-    },\r
-\r
-    /**\r
-     * An empty function by default, but provided so that you can perform a custom action before the initial\r
-     * drag event begins and optionally cancel it.\r
-     * @param {Object} data An object containing arbitrary data to be shared with drop targets\r
-     * @param {Event} e The event object\r
-     * @return {Boolean} isValid True if the drag event is valid, else false to cancel\r
-     */\r
-    onBeforeDrag : function(data, e){\r
-        return true;\r
-    },\r
-\r
-    /**\r
-     * An empty function by default, but provided so that you can perform a custom action once the initial\r
-     * drag event has begun.  The drag cannot be canceled from this function.\r
-     * @param {Number} x The x position of the click on the dragged object\r
-     * @param {Number} y The y position of the click on the dragged object\r
-     */\r
-    onStartDrag : Ext.emptyFn,\r
-\r
-    // private override\r
-    startDrag : function(x, y){\r
-        this.proxy.reset();\r
-        this.dragging = true;\r
-        this.proxy.update("");\r
-        this.onInitDrag(x, y);\r
-        this.proxy.show();\r
-    },\r
-\r
-    // private\r
-    onInitDrag : function(x, y){\r
-        var clone = this.el.dom.cloneNode(true);\r
-        clone.id = Ext.id(); // prevent duplicate ids\r
-        this.proxy.update(clone);\r
-        this.onStartDrag(x, y);\r
-        return true;\r
-    },\r
-\r
-    /**\r
-     * Returns the drag source's underlying {@link Ext.dd.StatusProxy}\r
-     * @return {Ext.dd.StatusProxy} proxy The StatusProxy\r
-     */\r
-    getProxy : function(){\r
-        return this.proxy;  \r
-    },\r
-\r
-    /**\r
-     * Hides the drag source's {@link Ext.dd.StatusProxy}\r
-     */\r
-    hideProxy : function(){\r
-        this.proxy.hide();  \r
-        this.proxy.reset(true);\r
-        this.dragging = false;\r
-    },\r
-\r
-    // private\r
-    triggerCacheRefresh : function(){\r
-        Ext.dd.DDM.refreshCache(this.groups);\r
-    },\r
-\r
-    // private - override to prevent hiding\r
-    b4EndDrag: function(e) {\r
-    },\r
-\r
-    // private - override to prevent moving\r
-    endDrag : function(e){\r
-        this.onEndDrag(this.dragData, e);\r
-    },\r
-\r
-    // private\r
-    onEndDrag : function(data, e){\r
-    },\r
-    \r
-    // private - pin to cursor\r
-    autoOffset : function(x, y) {\r
-        this.setDelta(-12, -20);\r
-    },\r
-    \r
-    destroy: function(){\r
-        Ext.dd.DragSource.superclass.destroy.call(this);\r
-        Ext.destroy(this.proxy);\r
-    }\r
-});/**\r
- * @class Ext.dd.DropTarget\r
- * @extends Ext.dd.DDTarget\r
- * A simple class that provides the basic implementation needed to make any element a drop target that can have\r
- * draggable items dropped onto it.  The drop has no effect until an implementation of notifyDrop is provided.\r
- * @constructor\r
- * @param {Mixed} el The container element\r
- * @param {Object} config\r
- */\r
-Ext.dd.DropTarget = function(el, config){\r
-    this.el = Ext.get(el);\r
-    \r
-    Ext.apply(this, config);\r
-    \r
-    if(this.containerScroll){\r
-        Ext.dd.ScrollManager.register(this.el);\r
-    }\r
-    \r
-    Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, \r
-          {isTarget: true});\r
-\r
-};\r
-\r
-Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {\r
-    /**\r
-     * @cfg {String} ddGroup\r
-     * A named drag drop group to which this object belongs.  If a group is specified, then this object will only\r
-     * interact with other drag drop objects in the same group (defaults to undefined).\r
-     */\r
-    /**\r
-     * @cfg {String} overClass\r
-     * The CSS class applied to the drop target element while the drag source is over it (defaults to "").\r
-     */\r
-    /**\r
-     * @cfg {String} dropAllowed\r
-     * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").\r
-     */\r
-    dropAllowed : "x-dd-drop-ok",\r
-    /**\r
-     * @cfg {String} dropNotAllowed\r
-     * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").\r
-     */\r
-    dropNotAllowed : "x-dd-drop-nodrop",\r
-\r
-    // private\r
-    isTarget : true,\r
-\r
-    // private\r
-    isNotifyTarget : true,\r
-\r
-    /**\r
-     * The function a {@link Ext.dd.DragSource} calls once to notify this drop target that the source is now over the\r
-     * target.  This default implementation adds the CSS class specified by overClass (if any) to the drop element\r
-     * and returns the dropAllowed config value.  This method should be overridden if drop validation is required.\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     * @return {String} status The CSS class that communicates the drop status back to the source so that the\r
-     * underlying {@link Ext.dd.StatusProxy} can be updated\r
-     */\r
-    notifyEnter : function(dd, e, data){\r
-        if(this.overClass){\r
-            this.el.addClass(this.overClass);\r
-        }\r
-        return this.dropAllowed;\r
-    },\r
-\r
-    /**\r
-     * The function a {@link Ext.dd.DragSource} calls continuously while it is being dragged over the target.\r
-     * This method will be called on every mouse movement while the drag source is over the drop target.\r
-     * This default implementation simply returns the dropAllowed config value.\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     * @return {String} status The CSS class that communicates the drop status back to the source so that the\r
-     * underlying {@link Ext.dd.StatusProxy} can be updated\r
-     */\r
-    notifyOver : function(dd, e, data){\r
-        return this.dropAllowed;\r
-    },\r
-\r
-    /**\r
-     * The function a {@link Ext.dd.DragSource} calls once to notify this drop target that the source has been dragged\r
-     * out of the target without dropping.  This default implementation simply removes the CSS class specified by\r
-     * overClass (if any) from the drop element.\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     */\r
-    notifyOut : function(dd, e, data){\r
-        if(this.overClass){\r
-            this.el.removeClass(this.overClass);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * The function a {@link Ext.dd.DragSource} calls once to notify this drop target that the dragged item has\r
-     * been dropped on it.  This method has no default implementation and returns false, so you must provide an\r
-     * implementation that does something to process the drop event and returns true so that the drag source's\r
-     * repair action does not run.\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     * @return {Boolean} True if the drop was valid, else false\r
-     */\r
-    notifyDrop : function(dd, e, data){\r
-        return false;\r
-    }\r
-});/**\r
- * @class Ext.dd.DragZone\r
- * @extends Ext.dd.DragSource\r
- * <p>This class provides a container DD instance that allows dragging of multiple child source nodes.</p>\r
- * <p>This class does not move the drag target nodes, but a proxy element which may contain\r
- * any DOM structure you wish. The DOM element to show in the proxy is provided by either a\r
- * provided implementation of {@link #getDragData}, or by registered draggables registered with {@link Ext.dd.Registry}</p>\r
- * <p>If you wish to provide draggability for an arbitrary number of DOM nodes, each of which represent some\r
- * application object (For example nodes in a {@link Ext.DataView DataView}) then use of this class\r
- * is the most efficient way to "activate" those nodes.</p>\r
- * <p>By default, this class requires that draggable child nodes are registered with {@link Ext.dd.Registry}.\r
- * However a simpler way to allow a DragZone to manage any number of draggable elements is to configure\r
- * the DragZone with  an implementation of the {@link #getDragData} method which interrogates the passed\r
- * mouse event to see if it has taken place within an element, or class of elements. This is easily done\r
- * by using the event's {@link Ext.EventObject#getTarget getTarget} method to identify a node based on a\r
- * {@link Ext.DomQuery} selector. For example, to make the nodes of a DataView draggable, use the following\r
- * technique. Knowledge of the use of the DataView is required:</p><pre><code>\r
-myDataView.on('render', function(v) {\r
-    myDataView.dragZone = new Ext.dd.DragZone(v.getEl(), {\r
-\r
-//      On receipt of a mousedown event, see if it is within a DataView node.\r
-//      Return a drag data object if so.\r
-        getDragData: function(e) {\r
-\r
-//          Use the DataView's own itemSelector (a mandatory property) to\r
-//          test if the mousedown is within one of the DataView's nodes.\r
-            var sourceEl = e.getTarget(v.itemSelector, 10);\r
-\r
-//          If the mousedown is within a DataView node, clone the node to produce\r
-//          a ddel element for use by the drag proxy. Also add application data\r
-//          to the returned data object.\r
-            if (sourceEl) {\r
-                d = sourceEl.cloneNode(true);\r
-                d.id = Ext.id();\r
-                return {\r
-                    ddel: d,\r
-                    sourceEl: sourceEl,\r
-                    repairXY: Ext.fly(sourceEl).getXY(),\r
-                    sourceStore: v.store,\r
-                    draggedRecord: v.{@link Ext.DataView#getRecord getRecord}(sourceEl)\r
-                }\r
-            }\r
-        },\r
-\r
-//      Provide coordinates for the proxy to slide back to on failed drag.\r
-//      This is the original XY coordinates of the draggable element captured\r
-//      in the getDragData method.\r
-        getRepairXY: function() {\r
-            return this.dragData.repairXY;\r
-        }\r
-    });\r
-});</code></pre>\r
- * See the {@link Ext.dd.DropZone DropZone} documentation for details about building a DropZone which\r
- * cooperates with this DragZone.\r
- * @constructor\r
- * @param {Mixed} el The container element\r
- * @param {Object} config\r
- */\r
-Ext.dd.DragZone = function(el, config){\r
-    Ext.dd.DragZone.superclass.constructor.call(this, el, config);\r
-    if(this.containerScroll){\r
-        Ext.dd.ScrollManager.register(this.el);\r
-    }\r
-};\r
-\r
-Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {\r
-    /**\r
-     * This property contains the data representing the dragged object. This data is set up by the implementation\r
-     * of the {@link #getDragData} method. It must contain a <tt>ddel</tt> property, but can contain\r
-     * any other data according to the application's needs.\r
-     * @type Object\r
-     * @property dragData\r
-     */\r
-    /**\r
-     * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager\r
-     * for auto scrolling during drag operations.\r
-     */\r
-    /**\r
-     * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair\r
-     * method after a failed drop (defaults to "c3daf9" - light blue)\r
-     */\r
-\r
-    /**\r
-     * Called when a mousedown occurs in this container. Looks in {@link Ext.dd.Registry}\r
-     * for a valid target to drag based on the mouse down. Override this method\r
-     * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned\r
-     * object has a "ddel" attribute (with an HTML Element) for other functions to work.\r
-     * @param {EventObject} e The mouse down event\r
-     * @return {Object} The dragData\r
-     */\r
-    getDragData : function(e){\r
-        return Ext.dd.Registry.getHandleFromEvent(e);\r
-    },\r
-    \r
-    /**\r
-     * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the\r
-     * this.dragData.ddel\r
-     * @param {Number} x The x position of the click on the dragged object\r
-     * @param {Number} y The y position of the click on the dragged object\r
-     * @return {Boolean} true to continue the drag, false to cancel\r
-     */\r
-    onInitDrag : function(x, y){\r
-        this.proxy.update(this.dragData.ddel.cloneNode(true));\r
-        this.onStartDrag(x, y);\r
-        return true;\r
-    },\r
-    \r
-    /**\r
-     * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel \r
-     */\r
-    afterRepair : function(){\r
-        if(Ext.enableFx){\r
-            Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");\r
-        }\r
-        this.dragging = false;\r
-    },\r
-\r
-    /**\r
-     * Called before a repair of an invalid drop to get the XY to animate to. By default returns\r
-     * the XY of this.dragData.ddel\r
-     * @param {EventObject} e The mouse up event\r
-     * @return {Array} The xy location (e.g. [100, 200])\r
-     */\r
-    getRepairXY : function(e){\r
-        return Ext.Element.fly(this.dragData.ddel).getXY();  \r
-    }\r
-});/**\r
- * @class Ext.dd.DropZone\r
- * @extends Ext.dd.DropTarget\r
- * <p>This class provides a container DD instance that allows dropping on multiple child target nodes.</p>\r
- * <p>By default, this class requires that child nodes accepting drop are registered with {@link Ext.dd.Registry}.\r
- * However a simpler way to allow a DropZone to manage any number of target elements is to configure the\r
- * DropZone with an implementation of {@link #getTargetFromEvent} which interrogates the passed\r
- * mouse event to see if it has taken place within an element, or class of elements. This is easily done\r
- * by using the event's {@link Ext.EventObject#getTarget getTarget} method to identify a node based on a\r
- * {@link Ext.DomQuery} selector.</p>\r
- * <p>Once the DropZone has detected through calling getTargetFromEvent, that the mouse is over\r
- * a drop target, that target is passed as the first parameter to {@link #onNodeEnter}, {@link #onNodeOver},\r
- * {@link #onNodeOut}, {@link #onNodeDrop}. You may configure the instance of DropZone with implementations\r
- * of these methods to provide application-specific behaviour for these events to update both\r
- * application state, and UI state.</p>\r
- * <p>For example to make a GridPanel a cooperating target with the example illustrated in\r
- * {@link Ext.dd.DragZone DragZone}, the following technique might be used:</p><pre><code>\r
-myGridPanel.on('render', function() {\r
-    myGridPanel.dropZone = new Ext.dd.DropZone(myGridPanel.getView().scroller, {\r
-\r
-//      If the mouse is over a grid row, return that node. This is\r
-//      provided as the "target" parameter in all "onNodeXXXX" node event handling functions\r
-        getTargetFromEvent: function(e) {\r
-            return e.getTarget(myGridPanel.getView().rowSelector);\r
-        },\r
-\r
-//      On entry into a target node, highlight that node.\r
-        onNodeEnter : function(target, dd, e, data){ \r
-            Ext.fly(target).addClass('my-row-highlight-class');\r
-        },\r
-\r
-//      On exit from a target node, unhighlight that node.\r
-        onNodeOut : function(target, dd, e, data){ \r
-            Ext.fly(target).removeClass('my-row-highlight-class');\r
-        },\r
-\r
-//      While over a target node, return the default drop allowed class which\r
-//      places a "tick" icon into the drag proxy.\r
-        onNodeOver : function(target, dd, e, data){ \r
-            return Ext.dd.DropZone.prototype.dropAllowed;\r
-        },\r
-\r
-//      On node drop we can interrogate the target to find the underlying\r
-//      application object that is the real target of the dragged data.\r
-//      In this case, it is a Record in the GridPanel's Store.\r
-//      We can use the data set up by the DragZone's getDragData method to read\r
-//      any data we decided to attach in the DragZone's getDragData method.\r
-        onNodeDrop : function(target, dd, e, data){\r
-            var rowIndex = myGridPanel.getView().findRowIndex(target);\r
-            var r = myGridPanel.getStore().getAt(rowIndex);\r
-            Ext.Msg.alert('Drop gesture', 'Dropped Record id ' + data.draggedRecord.id +\r
-                ' on Record id ' + r.id);\r
-            return true;\r
-        }\r
-    });\r
-}\r
-</code></pre>\r
- * See the {@link Ext.dd.DragZone DragZone} documentation for details about building a DragZone which\r
- * cooperates with this DropZone.\r
- * @constructor\r
- * @param {Mixed} el The container element\r
- * @param {Object} config\r
- */\r
-Ext.dd.DropZone = function(el, config){\r
-    Ext.dd.DropZone.superclass.constructor.call(this, el, config);\r
-};\r
-\r
-Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {\r
-    /**\r
-     * Returns a custom data object associated with the DOM node that is the target of the event.  By default\r
-     * this looks up the event target in the {@link Ext.dd.Registry}, although you can override this method to\r
-     * provide your own custom lookup.\r
-     * @param {Event} e The event\r
-     * @return {Object} data The custom data\r
-     */\r
-    getTargetFromEvent : function(e){\r
-        return Ext.dd.Registry.getTargetFromEvent(e);\r
-    },\r
-\r
-    /**\r
-     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has entered a drop node\r
-     * that has either been registered or detected by a configured implementation of {@link #getTargetFromEvent}.\r
-     * This method has no default implementation and should be overridden to provide\r
-     * node-specific processing if necessary.\r
-     * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from \r
-     * {@link #getTargetFromEvent} for this node)\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     */\r
-    onNodeEnter : function(n, dd, e, data){\r
-        \r
-    },\r
-\r
-    /**\r
-     * Called while the DropZone determines that a {@link Ext.dd.DragSource} is over a drop node\r
-     * that has either been registered or detected by a configured implementation of {@link #getTargetFromEvent}.\r
-     * The default implementation returns this.dropNotAllowed, so it should be\r
-     * overridden to provide the proper feedback.\r
-     * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from\r
-     * {@link #getTargetFromEvent} for this node)\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     * @return {String} status The CSS class that communicates the drop status back to the source so that the\r
-     * underlying {@link Ext.dd.StatusProxy} can be updated\r
-     */\r
-    onNodeOver : function(n, dd, e, data){\r
-        return this.dropAllowed;\r
-    },\r
-\r
-    /**\r
-     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has been dragged out of\r
-     * the drop node without dropping.  This method has no default implementation and should be overridden to provide\r
-     * node-specific processing if necessary.\r
-     * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from\r
-     * {@link #getTargetFromEvent} for this node)\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     */\r
-    onNodeOut : function(n, dd, e, data){\r
-        \r
-    },\r
-\r
-    /**\r
-     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has been dropped onto\r
-     * the drop node.  The default implementation returns false, so it should be overridden to provide the\r
-     * appropriate processing of the drop event and return true so that the drag source's repair action does not run.\r
-     * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from\r
-     * {@link #getTargetFromEvent} for this node)\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     * @return {Boolean} True if the drop was valid, else false\r
-     */\r
-    onNodeDrop : function(n, dd, e, data){\r
-        return false;\r
-    },\r
-\r
-    /**\r
-     * Called while the DropZone determines that a {@link Ext.dd.DragSource} is being dragged over it,\r
-     * but not over any of its registered drop nodes.  The default implementation returns this.dropNotAllowed, so\r
-     * it should be overridden to provide the proper feedback if necessary.\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     * @return {String} status The CSS class that communicates the drop status back to the source so that the\r
-     * underlying {@link Ext.dd.StatusProxy} can be updated\r
-     */\r
-    onContainerOver : function(dd, e, data){\r
-        return this.dropNotAllowed;\r
-    },\r
-\r
-    /**\r
-     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has been dropped on it,\r
-     * but not on any of its registered drop nodes.  The default implementation returns false, so it should be\r
-     * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to\r
-     * be able to accept drops.  It should return true when valid so that the drag source's repair action does not run.\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     * @return {Boolean} True if the drop was valid, else false\r
-     */\r
-    onContainerDrop : function(dd, e, data){\r
-        return false;\r
-    },\r
-\r
-    /**\r
-     * The function a {@link Ext.dd.DragSource} calls once to notify this drop zone that the source is now over\r
-     * the zone.  The default implementation returns this.dropNotAllowed and expects that only registered drop\r
-     * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops\r
-     * you should override this method and provide a custom implementation.\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     * @return {String} status The CSS class that communicates the drop status back to the source so that the\r
-     * underlying {@link Ext.dd.StatusProxy} can be updated\r
-     */\r
-    notifyEnter : function(dd, e, data){\r
-        return this.dropNotAllowed;\r
-    },\r
-\r
-    /**\r
-     * The function a {@link Ext.dd.DragSource} calls continuously while it is being dragged over the drop zone.\r
-     * This method will be called on every mouse movement while the drag source is over the drop zone.\r
-     * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically\r
-     * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits\r
-     * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a\r
-     * registered node, it will call {@link #onContainerOver}.\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     * @return {String} status The CSS class that communicates the drop status back to the source so that the\r
-     * underlying {@link Ext.dd.StatusProxy} can be updated\r
-     */\r
-    notifyOver : function(dd, e, data){\r
-        var n = this.getTargetFromEvent(e);\r
-        if(!n){ // not over valid drop target\r
-            if(this.lastOverNode){\r
-                this.onNodeOut(this.lastOverNode, dd, e, data);\r
-                this.lastOverNode = null;\r
-            }\r
-            return this.onContainerOver(dd, e, data);\r
-        }\r
-        if(this.lastOverNode != n){\r
-            if(this.lastOverNode){\r
-                this.onNodeOut(this.lastOverNode, dd, e, data);\r
-            }\r
-            this.onNodeEnter(n, dd, e, data);\r
-            this.lastOverNode = n;\r
-        }\r
-        return this.onNodeOver(n, dd, e, data);\r
-    },\r
-\r
-    /**\r
-     * The function a {@link Ext.dd.DragSource} calls once to notify this drop zone that the source has been dragged\r
-     * out of the zone without dropping.  If the drag source is currently over a registered node, the notification\r
-     * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag zone\r
-     */\r
-    notifyOut : function(dd, e, data){\r
-        if(this.lastOverNode){\r
-            this.onNodeOut(this.lastOverNode, dd, e, data);\r
-            this.lastOverNode = null;\r
-        }\r
-    },\r
-\r
-    /**\r
-     * The function a {@link Ext.dd.DragSource} calls once to notify this drop zone that the dragged item has\r
-     * been dropped on it.  The drag zone will look up the target node based on the event passed in, and if there\r
-     * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,\r
-     * otherwise it will call {@link #onContainerDrop}.\r
-     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone\r
-     * @param {Event} e The event\r
-     * @param {Object} data An object containing arbitrary data supplied by the drag source\r
-     * @return {Boolean} True if the drop was valid, else false\r
-     */\r
-    notifyDrop : function(dd, e, data){\r
-        if(this.lastOverNode){\r
-            this.onNodeOut(this.lastOverNode, dd, e, data);\r
-            this.lastOverNode = null;\r
-        }\r
-        var n = this.getTargetFromEvent(e);\r
-        return n ?\r
-            this.onNodeDrop(n, dd, e, data) :\r
-            this.onContainerDrop(dd, e, data);\r
-    },\r
-\r
-    // private\r
-    triggerCacheRefresh : function(){\r
-        Ext.dd.DDM.refreshCache(this.groups);\r
-    }  \r
-});/**\r
- * @class Ext.Element\r
- */\r
-Ext.Element.addMethods({\r
-    /**\r
-     * Initializes a {@link Ext.dd.DD} drag drop object for this element.\r
-     * @param {String} group The group the DD object is member of\r
-     * @param {Object} config The DD config object\r
-     * @param {Object} overrides An object containing methods to override/implement on the DD object\r
-     * @return {Ext.dd.DD} The DD object\r
-     */\r
-    initDD : function(group, config, overrides){\r
-        var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);\r
-        return Ext.apply(dd, overrides);\r
-    },\r
-\r
-    /**\r
-     * Initializes a {@link Ext.dd.DDProxy} object for this element.\r
-     * @param {String} group The group the DDProxy object is member of\r
-     * @param {Object} config The DDProxy config object\r
-     * @param {Object} overrides An object containing methods to override/implement on the DDProxy object\r
-     * @return {Ext.dd.DDProxy} The DDProxy object\r
-     */\r
-    initDDProxy : function(group, config, overrides){\r
-        var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);\r
-        return Ext.apply(dd, overrides);\r
-    },\r
-\r
-    /**\r
-     * Initializes a {@link Ext.dd.DDTarget} object for this element.\r
-     * @param {String} group The group the DDTarget object is member of\r
-     * @param {Object} config The DDTarget config object\r
-     * @param {Object} overrides An object containing methods to override/implement on the DDTarget object\r
-     * @return {Ext.dd.DDTarget} The DDTarget object\r
-     */\r
-    initDDTarget : function(group, config, overrides){\r
-        var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);\r
-        return Ext.apply(dd, overrides);\r
-    }\r
+});/**
+ * @class Ext.dd.DragTracker
+ * @extends Ext.util.Observable
+ * A DragTracker listens for drag events on an Element and fires events at the start and end of the drag,
+ * as well as during the drag. This is useful for components such as {@link Ext.Slider}, where there is
+ * an element that can be dragged around to change the Slider's value.
+ * DragTracker provides a series of template methods that should be overridden to provide functionality
+ * in response to detected drag operations. These are onBeforeStart, onStart, onDrag and onEnd.
+ * See {@link Ext.Slider}'s initEvents function for an example implementation.
+ */
+Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {    
+    /**
+     * @cfg {Boolean} active
+        * Defaults to <tt>false</tt>.
+        */     
+    active: false,
+    /**
+     * @cfg {Number} tolerance
+        * Number of pixels the drag target must be moved before dragging is considered to have started. Defaults to <tt>5</tt>.
+        */     
+    tolerance: 5,
+    /**
+     * @cfg {Boolean/Number} autoStart
+        * Defaults to <tt>false</tt>. Specify <tt>true</tt> to defer trigger start by 1000 ms.
+        * Specify a Number for the number of milliseconds to defer trigger start.
+        */     
+    autoStart: false,
+    
+    constructor : function(config){
+        Ext.apply(this, config);
+           this.addEvents(
+               /**
+                * @event mousedown
+                * @param {Object} this
+                * @param {Object} e event object
+                */
+               'mousedown',
+               /**
+                * @event mouseup
+                * @param {Object} this
+                * @param {Object} e event object
+                */
+               'mouseup',
+               /**
+                * @event mousemove
+                * @param {Object} this
+                * @param {Object} e event object
+                */
+               'mousemove',
+               /**
+                * @event dragstart
+                * @param {Object} this
+                * @param {Object} startXY the page coordinates of the event
+                */
+               'dragstart',
+               /**
+                * @event dragend
+                * @param {Object} this
+                * @param {Object} e event object
+                */
+               'dragend',
+               /**
+                * @event drag
+                * @param {Object} this
+                * @param {Object} e event object
+                */
+               'drag'
+           );
+       
+           this.dragRegion = new Ext.lib.Region(0,0,0,0);
+       
+           if(this.el){
+               this.initEl(this.el);
+           }
+        Ext.dd.DragTracker.superclass.constructor.call(this, config);
+    },
+
+    initEl: function(el){
+        this.el = Ext.get(el);
+        el.on('mousedown', this.onMouseDown, this,
+                this.delegate ? {delegate: this.delegate} : undefined);
+    },
+
+    destroy : function(){
+        this.el.un('mousedown', this.onMouseDown, this);
+    },
+
+    onMouseDown: function(e, target){
+        if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
+            this.startXY = this.lastXY = e.getXY();
+            this.dragTarget = this.delegate ? target : this.el.dom;
+            if(this.preventDefault !== false){
+                e.preventDefault();
+            }
+            var doc = Ext.getDoc();
+            doc.on('mouseup', this.onMouseUp, this);
+            doc.on('mousemove', this.onMouseMove, this);
+            doc.on('selectstart', this.stopSelect, this);
+            if(this.autoStart){
+                this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);
+            }
+        }
+    },
+
+    onMouseMove: function(e, target){
+        // HACK: IE hack to see if button was released outside of window. */
+        if(this.active && Ext.isIE && !e.browserEvent.button){
+            e.preventDefault();
+            this.onMouseUp(e);
+            return;
+        }
+
+        e.preventDefault();
+        var xy = e.getXY(), s = this.startXY;
+        this.lastXY = xy;
+        if(!this.active){
+            if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
+                this.triggerStart();
+            }else{
+                return;
+            }
+        }
+        this.fireEvent('mousemove', this, e);
+        this.onDrag(e);
+        this.fireEvent('drag', this, e);
+    },
+
+    onMouseUp: function(e) {
+        var doc = Ext.getDoc();
+        doc.un('mousemove', this.onMouseMove, this);
+        doc.un('mouseup', this.onMouseUp, this);
+        doc.un('selectstart', this.stopSelect, this);
+        e.preventDefault();
+        this.clearStart();
+        var wasActive = this.active;
+        this.active = false;
+        delete this.elRegion;
+        this.fireEvent('mouseup', this, e);
+        if(wasActive){
+            this.onEnd(e);
+            this.fireEvent('dragend', this, e);
+        }
+    },
+
+    triggerStart: function(isTimer) {
+        this.clearStart();
+        this.active = true;
+        this.onStart(this.startXY);
+        this.fireEvent('dragstart', this, this.startXY);
+    },
+
+    clearStart : function() {
+        if(this.timer){
+            clearTimeout(this.timer);
+            delete this.timer;
+        }
+    },
+
+    stopSelect : function(e) {
+        e.stopEvent();
+        return false;
+    },
+    
+    /**
+     * Template method which should be overridden by each DragTracker instance. Called when the user first clicks and
+     * holds the mouse button down. Return false to disallow the drag
+     * @param {Ext.EventObject} e The event object
+     */
+    onBeforeStart : function(e) {
+
+    },
+
+    /**
+     * Template method which should be overridden by each DragTracker instance. Called when a drag operation starts
+     * (e.g. the user has moved the tracked element beyond the specified tolerance)
+     * @param {Array} xy x and y co-ordinates of the original location of the tracked element
+     */
+    onStart : function(xy) {
+
+    },
+
+    /**
+     * Template method which should be overridden by each DragTracker instance. Called whenever a drag has been detected.
+     * @param {Ext.EventObject} e The event object
+     */
+    onDrag : function(e) {
+
+    },
+
+    /**
+     * Template method which should be overridden by each DragTracker instance. Called when a drag operation has been completed
+     * (e.g. the user clicked and held the mouse down, dragged the element and then released the mouse button)
+     * @param {Ext.EventObject} e The event object
+     */
+    onEnd : function(e) {
+
+    },
+
+    /**
+     * Returns the drag target
+     * @return {Ext.Element} The element currently being tracked
+     */
+    getDragTarget : function(){
+        return this.dragTarget;
+    },
+
+    getDragCt : function(){
+        return this.el;
+    },
+
+    getXY : function(constrain){
+        return constrain ?
+               this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
+    },
+
+    getOffset : function(constrain){
+        var xy = this.getXY(constrain);
+        var s = this.startXY;
+        return [s[0]-xy[0], s[1]-xy[1]];
+    },
+
+    constrainModes: {
+        'point' : function(xy){
+
+            if(!this.elRegion){
+                this.elRegion = this.getDragCt().getRegion();
+            }
+
+            var dr = this.dragRegion;
+
+            dr.left = xy[0];
+            dr.top = xy[1];
+            dr.right = xy[0];
+            dr.bottom = xy[1];
+
+            dr.constrainTo(this.elRegion);
+
+            return [dr.left, dr.top];
+        }
+    }
+});/**
+ * @class Ext.dd.ScrollManager
+ * <p>Provides automatic scrolling of overflow regions in the page during drag operations.</p>
+ * <p>The ScrollManager configs will be used as the defaults for any scroll container registered with it,
+ * but you can also override most of the configs per scroll container by adding a 
+ * <tt>ddScrollConfig</tt> object to the target element that contains these properties: {@link #hthresh},
+ * {@link #vthresh}, {@link #increment} and {@link #frequency}.  Example usage:
+ * <pre><code>
+var el = Ext.get('scroll-ct');
+el.ddScrollConfig = {
+    vthresh: 50,
+    hthresh: -1,
+    frequency: 100,
+    increment: 200
+};
+Ext.dd.ScrollManager.register(el);
+</code></pre>
+ * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
+ * @singleton
+ */
+Ext.dd.ScrollManager = function(){
+    var ddm = Ext.dd.DragDropMgr;
+    var els = {};
+    var dragEl = null;
+    var proc = {};
+    
+    var onStop = function(e){
+        dragEl = null;
+        clearProc();
+    };
+    
+    var triggerRefresh = function(){
+        if(ddm.dragCurrent){
+             ddm.refreshCache(ddm.dragCurrent.groups);
+        }
+    };
+    
+    var doScroll = function(){
+        if(ddm.dragCurrent){
+            var dds = Ext.dd.ScrollManager;
+            var inc = proc.el.ddScrollConfig ?
+                      proc.el.ddScrollConfig.increment : dds.increment;
+            if(!dds.animate){
+                if(proc.el.scroll(proc.dir, inc)){
+                    triggerRefresh();
+                }
+            }else{
+                proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
+            }
+        }
+    };
+    
+    var clearProc = function(){
+        if(proc.id){
+            clearInterval(proc.id);
+        }
+        proc.id = 0;
+        proc.el = null;
+        proc.dir = "";
+    };
+    
+    var startProc = function(el, dir){
+        clearProc();
+        proc.el = el;
+        proc.dir = dir;
+        var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? 
+                el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;
+        proc.id = setInterval(doScroll, freq);
+    };
+    
+    var onFire = function(e, isDrop){
+        if(isDrop || !ddm.dragCurrent){ return; }
+        var dds = Ext.dd.ScrollManager;
+        if(!dragEl || dragEl != ddm.dragCurrent){
+            dragEl = ddm.dragCurrent;
+            // refresh regions on drag start
+            dds.refreshCache();
+        }
+        
+        var xy = Ext.lib.Event.getXY(e);
+        var pt = new Ext.lib.Point(xy[0], xy[1]);
+        for(var id in els){
+            var el = els[id], r = el._region;
+            var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
+            if(r && r.contains(pt) && el.isScrollable()){
+                if(r.bottom - pt.y <= c.vthresh){
+                    if(proc.el != el){
+                        startProc(el, "down");
+                    }
+                    return;
+                }else if(r.right - pt.x <= c.hthresh){
+                    if(proc.el != el){
+                        startProc(el, "left");
+                    }
+                    return;
+                }else if(pt.y - r.top <= c.vthresh){
+                    if(proc.el != el){
+                        startProc(el, "up");
+                    }
+                    return;
+                }else if(pt.x - r.left <= c.hthresh){
+                    if(proc.el != el){
+                        startProc(el, "right");
+                    }
+                    return;
+                }
+            }
+        }
+        clearProc();
+    };
+    
+    ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
+    ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
+    
+    return {
+        /**
+         * Registers new overflow element(s) to auto scroll
+         * @param {Mixed/Array} el The id of or the element to be scrolled or an array of either
+         */
+        register : function(el){
+            if(Ext.isArray(el)){
+                for(var i = 0, len = el.length; i < len; i++) {
+                       this.register(el[i]);
+                }
+            }else{
+                el = Ext.get(el);
+                els[el.id] = el;
+            }
+        },
+        
+        /**
+         * Unregisters overflow element(s) so they are no longer scrolled
+         * @param {Mixed/Array} el The id of or the element to be removed or an array of either
+         */
+        unregister : function(el){
+            if(Ext.isArray(el)){
+                for(var i = 0, len = el.length; i < len; i++) {
+                       this.unregister(el[i]);
+                }
+            }else{
+                el = Ext.get(el);
+                delete els[el.id];
+            }
+        },
+        
+        /**
+         * The number of pixels from the top or bottom edge of a container the pointer needs to be to
+         * trigger scrolling (defaults to 25)
+         * @type Number
+         */
+        vthresh : 25,
+        /**
+         * The number of pixels from the right or left edge of a container the pointer needs to be to
+         * trigger scrolling (defaults to 25)
+         * @type Number
+         */
+        hthresh : 25,
+
+        /**
+         * The number of pixels to scroll in each scroll increment (defaults to 50)
+         * @type Number
+         */
+        increment : 100,
+        
+        /**
+         * The frequency of scrolls in milliseconds (defaults to 500)
+         * @type Number
+         */
+        frequency : 500,
+        
+        /**
+         * True to animate the scroll (defaults to true)
+         * @type Boolean
+         */
+        animate: true,
+        
+        /**
+         * The animation duration in seconds - 
+         * MUST BE less than Ext.dd.ScrollManager.frequency! (defaults to .4)
+         * @type Number
+         */
+        animDuration: .4,
+        
+        /**
+         * Manually trigger a cache refresh.
+         */
+        refreshCache : function(){
+            for(var id in els){
+                if(typeof els[id] == 'object'){ // for people extending the object prototype
+                    els[id]._region = els[id].getRegion();
+                }
+            }
+        }
+    };
+}();/**
+ * @class Ext.dd.Registry
+ * Provides easy access to all drag drop components that are registered on a page.  Items can be retrieved either
+ * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.
+ * @singleton
+ */
+Ext.dd.Registry = function(){
+    var elements = {}; 
+    var handles = {}; 
+    var autoIdSeed = 0;
+
+    var getId = function(el, autogen){
+        if(typeof el == "string"){
+            return el;
+        }
+        var id = el.id;
+        if(!id && autogen !== false){
+            id = "extdd-" + (++autoIdSeed);
+            el.id = id;
+        }
+        return id;
+    };
+    
+    return {
+    /**
+     * Resgister a drag drop element
+     * @param {String/HTMLElement} element The id or DOM node to register
+     * @param {Object} data (optional) An custom data object that will be passed between the elements that are involved
+     * in drag drop operations.  You can populate this object with any arbitrary properties that your own code
+     * knows how to interpret, plus there are some specific properties known to the Registry that should be
+     * populated in the data object (if applicable):
+     * <pre>
+Value      Description<br />
+---------  ------------------------------------------<br />
+handles    Array of DOM nodes that trigger dragging<br />
+           for the element being registered<br />
+isHandle   True if the element passed in triggers<br />
+           dragging itself, else false
+</pre>
+     */
+        register : function(el, data){
+            data = data || {};
+            if(typeof el == "string"){
+                el = document.getElementById(el);
+            }
+            data.ddel = el;
+            elements[getId(el)] = data;
+            if(data.isHandle !== false){
+                handles[data.ddel.id] = data;
+            }
+            if(data.handles){
+                var hs = data.handles;
+                for(var i = 0, len = hs.length; i < len; i++){
+                       handles[getId(hs[i])] = data;
+                }
+            }
+        },
+
+    /**
+     * Unregister a drag drop element
+     * @param {String/HTMLElement} element The id or DOM node to unregister
+     */
+        unregister : function(el){
+            var id = getId(el, false);
+            var data = elements[id];
+            if(data){
+                delete elements[id];
+                if(data.handles){
+                    var hs = data.handles;
+                    for(var i = 0, len = hs.length; i < len; i++){
+                       delete handles[getId(hs[i], false)];
+                    }
+                }
+            }
+        },
+
+    /**
+     * Returns the handle registered for a DOM Node by id
+     * @param {String/HTMLElement} id The DOM node or id to look up
+     * @return {Object} handle The custom handle data
+     */
+        getHandle : function(id){
+            if(typeof id != "string"){ // must be element?
+                id = id.id;
+            }
+            return handles[id];
+        },
+
+    /**
+     * Returns the handle that is registered for the DOM node that is the target of the event
+     * @param {Event} e The event
+     * @return {Object} handle The custom handle data
+     */
+        getHandleFromEvent : function(e){
+            var t = Ext.lib.Event.getTarget(e);
+            return t ? handles[t.id] : null;
+        },
+
+    /**
+     * Returns a custom data object that is registered for a DOM node by id
+     * @param {String/HTMLElement} id The DOM node or id to look up
+     * @return {Object} data The custom data
+     */
+        getTarget : function(id){
+            if(typeof id != "string"){ // must be element?
+                id = id.id;
+            }
+            return elements[id];
+        },
+
+    /**
+     * Returns a custom data object that is registered for the DOM node that is the target of the event
+     * @param {Event} e The event
+     * @return {Object} data The custom data
+     */
+        getTargetFromEvent : function(e){
+            var t = Ext.lib.Event.getTarget(e);
+            return t ? elements[t.id] || handles[t.id] : null;
+        }
+    };
+}();/**
+ * @class Ext.dd.StatusProxy
+ * A specialized drag proxy that supports a drop status icon, {@link Ext.Layer} styles and auto-repair.  This is the
+ * default drag proxy used by all Ext.dd components.
+ * @constructor
+ * @param {Object} config
+ */
+Ext.dd.StatusProxy = function(config){
+    Ext.apply(this, config);
+    this.id = this.id || Ext.id();
+    this.el = new Ext.Layer({
+        dh: {
+            id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
+                {tag: "div", cls: "x-dd-drop-icon"},
+                {tag: "div", cls: "x-dd-drag-ghost"}
+            ]
+        }, 
+        shadow: !config || config.shadow !== false
+    });
+    this.ghost = Ext.get(this.el.dom.childNodes[1]);
+    this.dropStatus = this.dropNotAllowed;
+};
+
+Ext.dd.StatusProxy.prototype = {
+    /**
+     * @cfg {String} dropAllowed
+     * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
+     */
+    dropAllowed : "x-dd-drop-ok",
+    /**
+     * @cfg {String} dropNotAllowed
+     * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
+     */
+    dropNotAllowed : "x-dd-drop-nodrop",
+
+    /**
+     * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
+     * over the current target element.
+     * @param {String} cssClass The css class for the new drop status indicator image
+     */
+    setStatus : function(cssClass){
+        cssClass = cssClass || this.dropNotAllowed;
+        if(this.dropStatus != cssClass){
+            this.el.replaceClass(this.dropStatus, cssClass);
+            this.dropStatus = cssClass;
+        }
+    },
+
+    /**
+     * Resets the status indicator to the default dropNotAllowed value
+     * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
+     */
+    reset : function(clearGhost){
+        this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
+        this.dropStatus = this.dropNotAllowed;
+        if(clearGhost){
+            this.ghost.update("");
+        }
+    },
+
+    /**
+     * Updates the contents of the ghost element
+     * @param {String/HTMLElement} html The html that will replace the current innerHTML of the ghost element, or a
+     * DOM node to append as the child of the ghost element (in which case the innerHTML will be cleared first).
+     */
+    update : function(html){
+        if(typeof html == "string"){
+            this.ghost.update(html);
+        }else{
+            this.ghost.update("");
+            html.style.margin = "0";
+            this.ghost.dom.appendChild(html);
+        }
+        var el = this.ghost.dom.firstChild; 
+        if(el){
+            Ext.fly(el).setStyle('float', 'none');
+        }
+    },
+
+    /**
+     * Returns the underlying proxy {@link Ext.Layer}
+     * @return {Ext.Layer} el
+    */
+    getEl : function(){
+        return this.el;
+    },
+
+    /**
+     * Returns the ghost element
+     * @return {Ext.Element} el
+     */
+    getGhost : function(){
+        return this.ghost;
+    },
+
+    /**
+     * Hides the proxy
+     * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
+     */
+    hide : function(clear){
+        this.el.hide();
+        if(clear){
+            this.reset(true);
+        }
+    },
+
+    /**
+     * Stops the repair animation if it's currently running
+     */
+    stop : function(){
+        if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
+            this.anim.stop();
+        }
+    },
+
+    /**
+     * Displays this proxy
+     */
+    show : function(){
+        this.el.show();
+    },
+
+    /**
+     * Force the Layer to sync its shadow and shim positions to the element
+     */
+    sync : function(){
+        this.el.sync();
+    },
+
+    /**
+     * Causes the proxy to return to its position of origin via an animation.  Should be called after an
+     * invalid drop operation by the item being dragged.
+     * @param {Array} xy The XY position of the element ([x, y])
+     * @param {Function} callback The function to call after the repair is complete.
+     * @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the browser window.
+     */
+    repair : function(xy, callback, scope){
+        this.callback = callback;
+        this.scope = scope;
+        if(xy && this.animRepair !== false){
+            this.el.addClass("x-dd-drag-repair");
+            this.el.hideUnders(true);
+            this.anim = this.el.shift({
+                duration: this.repairDuration || .5,
+                easing: 'easeOut',
+                xy: xy,
+                stopFx: true,
+                callback: this.afterRepair,
+                scope: this
+            });
+        }else{
+            this.afterRepair();
+        }
+    },
+
+    // private
+    afterRepair : function(){
+        this.hide(true);
+        if(typeof this.callback == "function"){
+            this.callback.call(this.scope || this);
+        }
+        this.callback = null;
+        this.scope = null;
+    },
+    
+    destroy: function(){
+        Ext.destroy(this.ghost, this.el);    
+    }
+};/**
+ * @class Ext.dd.DragSource
+ * @extends Ext.dd.DDProxy
+ * A simple class that provides the basic implementation needed to make any element draggable.
+ * @constructor
+ * @param {Mixed} el The container element
+ * @param {Object} config
+ */
+Ext.dd.DragSource = function(el, config){
+    this.el = Ext.get(el);
+    if(!this.dragData){
+        this.dragData = {};
+    }
+    
+    Ext.apply(this, config);
+    
+    if(!this.proxy){
+        this.proxy = new Ext.dd.StatusProxy();
+    }
+    Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
+          {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
+    
+    this.dragging = false;
+};
+
+Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
+    /**
+     * @cfg {String} ddGroup
+     * A named drag drop group to which this object belongs.  If a group is specified, then this object will only
+     * interact with other drag drop objects in the same group (defaults to undefined).
+     */
+    /**
+     * @cfg {String} dropAllowed
+     * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
+     */
+    dropAllowed : "x-dd-drop-ok",
+    /**
+     * @cfg {String} dropNotAllowed
+     * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
+     */
+    dropNotAllowed : "x-dd-drop-nodrop",
+
+    /**
+     * Returns the data object associated with this drag source
+     * @return {Object} data An object containing arbitrary data
+     */
+    getDragData : function(e){
+        return this.dragData;
+    },
+
+    // private
+    onDragEnter : function(e, id){
+        var target = Ext.dd.DragDropMgr.getDDById(id);
+        this.cachedTarget = target;
+        if(this.beforeDragEnter(target, e, id) !== false){
+            if(target.isNotifyTarget){
+                var status = target.notifyEnter(this, e, this.dragData);
+                this.proxy.setStatus(status);
+            }else{
+                this.proxy.setStatus(this.dropAllowed);
+            }
+            
+            if(this.afterDragEnter){
+                /**
+                 * An empty function by default, but provided so that you can perform a custom action
+                 * when the dragged item enters the drop target by providing an implementation.
+                 * @param {Ext.dd.DragDrop} target The drop target
+                 * @param {Event} e The event object
+                 * @param {String} id The id of the dragged element
+                 * @method afterDragEnter
+                 */
+                this.afterDragEnter(target, e, id);
+            }
+        }
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action
+     * before the dragged item enters the drop target and optionally cancel the onDragEnter.
+     * @param {Ext.dd.DragDrop} target The drop target
+     * @param {Event} e The event object
+     * @param {String} id The id of the dragged element
+     * @return {Boolean} isValid True if the drag event is valid, else false to cancel
+     */
+    beforeDragEnter : function(target, e, id){
+        return true;
+    },
+
+    // private
+    alignElWithMouse: function() {
+        Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
+        this.proxy.sync();
+    },
+
+    // private
+    onDragOver : function(e, id){
+        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
+        if(this.beforeDragOver(target, e, id) !== false){
+            if(target.isNotifyTarget){
+                var status = target.notifyOver(this, e, this.dragData);
+                this.proxy.setStatus(status);
+            }
+
+            if(this.afterDragOver){
+                /**
+                 * An empty function by default, but provided so that you can perform a custom action
+                 * while the dragged item is over the drop target by providing an implementation.
+                 * @param {Ext.dd.DragDrop} target The drop target
+                 * @param {Event} e The event object
+                 * @param {String} id The id of the dragged element
+                 * @method afterDragOver
+                 */
+                this.afterDragOver(target, e, id);
+            }
+        }
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action
+     * while the dragged item is over the drop target and optionally cancel the onDragOver.
+     * @param {Ext.dd.DragDrop} target The drop target
+     * @param {Event} e The event object
+     * @param {String} id The id of the dragged element
+     * @return {Boolean} isValid True if the drag event is valid, else false to cancel
+     */
+    beforeDragOver : function(target, e, id){
+        return true;
+    },
+
+    // private
+    onDragOut : function(e, id){
+        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
+        if(this.beforeDragOut(target, e, id) !== false){
+            if(target.isNotifyTarget){
+                target.notifyOut(this, e, this.dragData);
+            }
+            this.proxy.reset();
+            if(this.afterDragOut){
+                /**
+                 * An empty function by default, but provided so that you can perform a custom action
+                 * after the dragged item is dragged out of the target without dropping.
+                 * @param {Ext.dd.DragDrop} target The drop target
+                 * @param {Event} e The event object
+                 * @param {String} id The id of the dragged element
+                 * @method afterDragOut
+                 */
+                this.afterDragOut(target, e, id);
+            }
+        }
+        this.cachedTarget = null;
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action before the dragged
+     * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
+     * @param {Ext.dd.DragDrop} target The drop target
+     * @param {Event} e The event object
+     * @param {String} id The id of the dragged element
+     * @return {Boolean} isValid True if the drag event is valid, else false to cancel
+     */
+    beforeDragOut : function(target, e, id){
+        return true;
+    },
+    
+    // private
+    onDragDrop : function(e, id){
+        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
+        if(this.beforeDragDrop(target, e, id) !== false){
+            if(target.isNotifyTarget){
+                if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
+                    this.onValidDrop(target, e, id);
+                }else{
+                    this.onInvalidDrop(target, e, id);
+                }
+            }else{
+                this.onValidDrop(target, e, id);
+            }
+            
+            if(this.afterDragDrop){
+                /**
+                 * An empty function by default, but provided so that you can perform a custom action
+                 * after a valid drag drop has occurred by providing an implementation.
+                 * @param {Ext.dd.DragDrop} target The drop target
+                 * @param {Event} e The event object
+                 * @param {String} id The id of the dropped element
+                 * @method afterDragDrop
+                 */
+                this.afterDragDrop(target, e, id);
+            }
+        }
+        delete this.cachedTarget;
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action before the dragged
+     * item is dropped onto the target and optionally cancel the onDragDrop.
+     * @param {Ext.dd.DragDrop} target The drop target
+     * @param {Event} e The event object
+     * @param {String} id The id of the dragged element
+     * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
+     */
+    beforeDragDrop : function(target, e, id){
+        return true;
+    },
+
+    // private
+    onValidDrop : function(target, e, id){
+        this.hideProxy();
+        if(this.afterValidDrop){
+            /**
+             * An empty function by default, but provided so that you can perform a custom action
+             * after a valid drop has occurred by providing an implementation.
+             * @param {Object} target The target DD 
+             * @param {Event} e The event object
+             * @param {String} id The id of the dropped element
+             * @method afterInvalidDrop
+             */
+            this.afterValidDrop(target, e, id);
+        }
+    },
+
+    // private
+    getRepairXY : function(e, data){
+        return this.el.getXY();  
+    },
+
+    // private
+    onInvalidDrop : function(target, e, id){
+        this.beforeInvalidDrop(target, e, id);
+        if(this.cachedTarget){
+            if(this.cachedTarget.isNotifyTarget){
+                this.cachedTarget.notifyOut(this, e, this.dragData);
+            }
+            this.cacheTarget = null;
+        }
+        this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
+
+        if(this.afterInvalidDrop){
+            /**
+             * An empty function by default, but provided so that you can perform a custom action
+             * after an invalid drop has occurred by providing an implementation.
+             * @param {Event} e The event object
+             * @param {String} id The id of the dropped element
+             * @method afterInvalidDrop
+             */
+            this.afterInvalidDrop(e, id);
+        }
+    },
+
+    // private
+    afterRepair : function(){
+        if(Ext.enableFx){
+            this.el.highlight(this.hlColor || "c3daf9");
+        }
+        this.dragging = false;
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action after an invalid
+     * drop has occurred.
+     * @param {Ext.dd.DragDrop} target The drop target
+     * @param {Event} e The event object
+     * @param {String} id The id of the dragged element
+     * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
+     */
+    beforeInvalidDrop : function(target, e, id){
+        return true;
+    },
+
+    // private
+    handleMouseDown : function(e){
+        if(this.dragging) {
+            return;
+        }
+        var data = this.getDragData(e);
+        if(data && this.onBeforeDrag(data, e) !== false){
+            this.dragData = data;
+            this.proxy.stop();
+            Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
+        } 
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action before the initial
+     * drag event begins and optionally cancel it.
+     * @param {Object} data An object containing arbitrary data to be shared with drop targets
+     * @param {Event} e The event object
+     * @return {Boolean} isValid True if the drag event is valid, else false to cancel
+     */
+    onBeforeDrag : function(data, e){
+        return true;
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action once the initial
+     * drag event has begun.  The drag cannot be canceled from this function.
+     * @param {Number} x The x position of the click on the dragged object
+     * @param {Number} y The y position of the click on the dragged object
+     */
+    onStartDrag : Ext.emptyFn,
+
+    // private override
+    startDrag : function(x, y){
+        this.proxy.reset();
+        this.dragging = true;
+        this.proxy.update("");
+        this.onInitDrag(x, y);
+        this.proxy.show();
+    },
+
+    // private
+    onInitDrag : function(x, y){
+        var clone = this.el.dom.cloneNode(true);
+        clone.id = Ext.id(); // prevent duplicate ids
+        this.proxy.update(clone);
+        this.onStartDrag(x, y);
+        return true;
+    },
+
+    /**
+     * Returns the drag source's underlying {@link Ext.dd.StatusProxy}
+     * @return {Ext.dd.StatusProxy} proxy The StatusProxy
+     */
+    getProxy : function(){
+        return this.proxy;  
+    },
+
+    /**
+     * Hides the drag source's {@link Ext.dd.StatusProxy}
+     */
+    hideProxy : function(){
+        this.proxy.hide();  
+        this.proxy.reset(true);
+        this.dragging = false;
+    },
+
+    // private
+    triggerCacheRefresh : function(){
+        Ext.dd.DDM.refreshCache(this.groups);
+    },
+
+    // private - override to prevent hiding
+    b4EndDrag: function(e) {
+    },
+
+    // private - override to prevent moving
+    endDrag : function(e){
+        this.onEndDrag(this.dragData, e);
+    },
+
+    // private
+    onEndDrag : function(data, e){
+    },
+    
+    // private - pin to cursor
+    autoOffset : function(x, y) {
+        this.setDelta(-12, -20);
+    },
+    
+    destroy: function(){
+        Ext.dd.DragSource.superclass.destroy.call(this);
+        Ext.destroy(this.proxy);
+    }
+});/**
+ * @class Ext.dd.DropTarget
+ * @extends Ext.dd.DDTarget
+ * A simple class that provides the basic implementation needed to make any element a drop target that can have
+ * draggable items dropped onto it.  The drop has no effect until an implementation of notifyDrop is provided.
+ * @constructor
+ * @param {Mixed} el The container element
+ * @param {Object} config
+ */
+Ext.dd.DropTarget = function(el, config){
+    this.el = Ext.get(el);
+    
+    Ext.apply(this, config);
+    
+    if(this.containerScroll){
+        Ext.dd.ScrollManager.register(this.el);
+    }
+    
+    Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
+          {isTarget: true});
+
+};
+
+Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {
+    /**
+     * @cfg {String} ddGroup
+     * A named drag drop group to which this object belongs.  If a group is specified, then this object will only
+     * interact with other drag drop objects in the same group (defaults to undefined).
+     */
+    /**
+     * @cfg {String} overClass
+     * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
+     */
+    /**
+     * @cfg {String} dropAllowed
+     * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
+     */
+    dropAllowed : "x-dd-drop-ok",
+    /**
+     * @cfg {String} dropNotAllowed
+     * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
+     */
+    dropNotAllowed : "x-dd-drop-nodrop",
+
+    // private
+    isTarget : true,
+
+    // private
+    isNotifyTarget : true,
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop target that the source is now over the
+     * target.  This default implementation adds the CSS class specified by overClass (if any) to the drop element
+     * and returns the dropAllowed config value.  This method should be overridden if drop validation is required.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source so that the
+     * underlying {@link Ext.dd.StatusProxy} can be updated
+     */
+    notifyEnter : function(dd, e, data){
+        if(this.overClass){
+            this.el.addClass(this.overClass);
+        }
+        return this.dropAllowed;
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls continuously while it is being dragged over the target.
+     * This method will be called on every mouse movement while the drag source is over the drop target.
+     * This default implementation simply returns the dropAllowed config value.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source so that the
+     * underlying {@link Ext.dd.StatusProxy} can be updated
+     */
+    notifyOver : function(dd, e, data){
+        return this.dropAllowed;
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop target that the source has been dragged
+     * out of the target without dropping.  This default implementation simply removes the CSS class specified by
+     * overClass (if any) from the drop element.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     */
+    notifyOut : function(dd, e, data){
+        if(this.overClass){
+            this.el.removeClass(this.overClass);
+        }
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop target that the dragged item has
+     * been dropped on it.  This method has no default implementation and returns false, so you must provide an
+     * implementation that does something to process the drop event and returns true so that the drag source's
+     * repair action does not run.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {Boolean} True if the drop was valid, else false
+     */
+    notifyDrop : function(dd, e, data){
+        return false;
+    }
+});/**
+ * @class Ext.dd.DragZone
+ * @extends Ext.dd.DragSource
+ * <p>This class provides a container DD instance that allows dragging of multiple child source nodes.</p>
+ * <p>This class does not move the drag target nodes, but a proxy element which may contain
+ * any DOM structure you wish. The DOM element to show in the proxy is provided by either a
+ * provided implementation of {@link #getDragData}, or by registered draggables registered with {@link Ext.dd.Registry}</p>
+ * <p>If you wish to provide draggability for an arbitrary number of DOM nodes, each of which represent some
+ * application object (For example nodes in a {@link Ext.DataView DataView}) then use of this class
+ * is the most efficient way to "activate" those nodes.</p>
+ * <p>By default, this class requires that draggable child nodes are registered with {@link Ext.dd.Registry}.
+ * However a simpler way to allow a DragZone to manage any number of draggable elements is to configure
+ * the DragZone with  an implementation of the {@link #getDragData} method which interrogates the passed
+ * mouse event to see if it has taken place within an element, or class of elements. This is easily done
+ * by using the event's {@link Ext.EventObject#getTarget getTarget} method to identify a node based on a
+ * {@link Ext.DomQuery} selector. For example, to make the nodes of a DataView draggable, use the following
+ * technique. Knowledge of the use of the DataView is required:</p><pre><code>
+myDataView.on('render', function(v) {
+    myDataView.dragZone = new Ext.dd.DragZone(v.getEl(), {
+
+//      On receipt of a mousedown event, see if it is within a DataView node.
+//      Return a drag data object if so.
+        getDragData: function(e) {
+
+//          Use the DataView's own itemSelector (a mandatory property) to
+//          test if the mousedown is within one of the DataView's nodes.
+            var sourceEl = e.getTarget(v.itemSelector, 10);
+
+//          If the mousedown is within a DataView node, clone the node to produce
+//          a ddel element for use by the drag proxy. Also add application data
+//          to the returned data object.
+            if (sourceEl) {
+                d = sourceEl.cloneNode(true);
+                d.id = Ext.id();
+                return {
+                    ddel: d,
+                    sourceEl: sourceEl,
+                    repairXY: Ext.fly(sourceEl).getXY(),
+                    sourceStore: v.store,
+                    draggedRecord: v.{@link Ext.DataView#getRecord getRecord}(sourceEl)
+                }
+            }
+        },
+
+//      Provide coordinates for the proxy to slide back to on failed drag.
+//      This is the original XY coordinates of the draggable element captured
+//      in the getDragData method.
+        getRepairXY: function() {
+            return this.dragData.repairXY;
+        }
+    });
+});</code></pre>
+ * See the {@link Ext.dd.DropZone DropZone} documentation for details about building a DropZone which
+ * cooperates with this DragZone.
+ * @constructor
+ * @param {Mixed} el The container element
+ * @param {Object} config
+ */
+Ext.dd.DragZone = function(el, config){
+    Ext.dd.DragZone.superclass.constructor.call(this, el, config);
+    if(this.containerScroll){
+        Ext.dd.ScrollManager.register(this.el);
+    }
+};
+
+Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {
+    /**
+     * This property contains the data representing the dragged object. This data is set up by the implementation
+     * of the {@link #getDragData} method. It must contain a <tt>ddel</tt> property, but can contain
+     * any other data according to the application's needs.
+     * @type Object
+     * @property dragData
+     */
+    /**
+     * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager
+     * for auto scrolling during drag operations.
+     */
+    /**
+     * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair
+     * method after a failed drop (defaults to "c3daf9" - light blue)
+     */
+
+    /**
+     * Called when a mousedown occurs in this container. Looks in {@link Ext.dd.Registry}
+     * for a valid target to drag based on the mouse down. Override this method
+     * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned
+     * object has a "ddel" attribute (with an HTML Element) for other functions to work.
+     * @param {EventObject} e The mouse down event
+     * @return {Object} The dragData
+     */
+    getDragData : function(e){
+        return Ext.dd.Registry.getHandleFromEvent(e);
+    },
+    
+    /**
+     * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the
+     * this.dragData.ddel
+     * @param {Number} x The x position of the click on the dragged object
+     * @param {Number} y The y position of the click on the dragged object
+     * @return {Boolean} true to continue the drag, false to cancel
+     */
+    onInitDrag : function(x, y){
+        this.proxy.update(this.dragData.ddel.cloneNode(true));
+        this.onStartDrag(x, y);
+        return true;
+    },
+    
+    /**
+     * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel 
+     */
+    afterRepair : function(){
+        if(Ext.enableFx){
+            Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
+        }
+        this.dragging = false;
+    },
+
+    /**
+     * Called before a repair of an invalid drop to get the XY to animate to. By default returns
+     * the XY of this.dragData.ddel
+     * @param {EventObject} e The mouse up event
+     * @return {Array} The xy location (e.g. [100, 200])
+     */
+    getRepairXY : function(e){
+        return Ext.Element.fly(this.dragData.ddel).getXY();  
+    }
+});/**
+ * @class Ext.dd.DropZone
+ * @extends Ext.dd.DropTarget
+ * <p>This class provides a container DD instance that allows dropping on multiple child target nodes.</p>
+ * <p>By default, this class requires that child nodes accepting drop are registered with {@link Ext.dd.Registry}.
+ * However a simpler way to allow a DropZone to manage any number of target elements is to configure the
+ * DropZone with an implementation of {@link #getTargetFromEvent} which interrogates the passed
+ * mouse event to see if it has taken place within an element, or class of elements. This is easily done
+ * by using the event's {@link Ext.EventObject#getTarget getTarget} method to identify a node based on a
+ * {@link Ext.DomQuery} selector.</p>
+ * <p>Once the DropZone has detected through calling getTargetFromEvent, that the mouse is over
+ * a drop target, that target is passed as the first parameter to {@link #onNodeEnter}, {@link #onNodeOver},
+ * {@link #onNodeOut}, {@link #onNodeDrop}. You may configure the instance of DropZone with implementations
+ * of these methods to provide application-specific behaviour for these events to update both
+ * application state, and UI state.</p>
+ * <p>For example to make a GridPanel a cooperating target with the example illustrated in
+ * {@link Ext.dd.DragZone DragZone}, the following technique might be used:</p><pre><code>
+myGridPanel.on('render', function() {
+    myGridPanel.dropZone = new Ext.dd.DropZone(myGridPanel.getView().scroller, {
+
+//      If the mouse is over a grid row, return that node. This is
+//      provided as the "target" parameter in all "onNodeXXXX" node event handling functions
+        getTargetFromEvent: function(e) {
+            return e.getTarget(myGridPanel.getView().rowSelector);
+        },
+
+//      On entry into a target node, highlight that node.
+        onNodeEnter : function(target, dd, e, data){ 
+            Ext.fly(target).addClass('my-row-highlight-class');
+        },
+
+//      On exit from a target node, unhighlight that node.
+        onNodeOut : function(target, dd, e, data){ 
+            Ext.fly(target).removeClass('my-row-highlight-class');
+        },
+
+//      While over a target node, return the default drop allowed class which
+//      places a "tick" icon into the drag proxy.
+        onNodeOver : function(target, dd, e, data){ 
+            return Ext.dd.DropZone.prototype.dropAllowed;
+        },
+
+//      On node drop we can interrogate the target to find the underlying
+//      application object that is the real target of the dragged data.
+//      In this case, it is a Record in the GridPanel's Store.
+//      We can use the data set up by the DragZone's getDragData method to read
+//      any data we decided to attach in the DragZone's getDragData method.
+        onNodeDrop : function(target, dd, e, data){
+            var rowIndex = myGridPanel.getView().findRowIndex(target);
+            var r = myGridPanel.getStore().getAt(rowIndex);
+            Ext.Msg.alert('Drop gesture', 'Dropped Record id ' + data.draggedRecord.id +
+                ' on Record id ' + r.id);
+            return true;
+        }
+    });
+}
+</code></pre>
+ * See the {@link Ext.dd.DragZone DragZone} documentation for details about building a DragZone which
+ * cooperates with this DropZone.
+ * @constructor
+ * @param {Mixed} el The container element
+ * @param {Object} config
+ */
+Ext.dd.DropZone = function(el, config){
+    Ext.dd.DropZone.superclass.constructor.call(this, el, config);
+};
+
+Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
+    /**
+     * Returns a custom data object associated with the DOM node that is the target of the event.  By default
+     * this looks up the event target in the {@link Ext.dd.Registry}, although you can override this method to
+     * provide your own custom lookup.
+     * @param {Event} e The event
+     * @return {Object} data The custom data
+     */
+    getTargetFromEvent : function(e){
+        return Ext.dd.Registry.getTargetFromEvent(e);
+    },
+
+    /**
+     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has entered a drop node
+     * that has either been registered or detected by a configured implementation of {@link #getTargetFromEvent}.
+     * This method has no default implementation and should be overridden to provide
+     * node-specific processing if necessary.
+     * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from 
+     * {@link #getTargetFromEvent} for this node)
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     */
+    onNodeEnter : function(n, dd, e, data){
+        
+    },
+
+    /**
+     * Called while the DropZone determines that a {@link Ext.dd.DragSource} is over a drop node
+     * that has either been registered or detected by a configured implementation of {@link #getTargetFromEvent}.
+     * The default implementation returns this.dropNotAllowed, so it should be
+     * overridden to provide the proper feedback.
+     * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
+     * {@link #getTargetFromEvent} for this node)
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source so that the
+     * underlying {@link Ext.dd.StatusProxy} can be updated
+     */
+    onNodeOver : function(n, dd, e, data){
+        return this.dropAllowed;
+    },
+
+    /**
+     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has been dragged out of
+     * the drop node without dropping.  This method has no default implementation and should be overridden to provide
+     * node-specific processing if necessary.
+     * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
+     * {@link #getTargetFromEvent} for this node)
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     */
+    onNodeOut : function(n, dd, e, data){
+        
+    },
+
+    /**
+     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has been dropped onto
+     * the drop node.  The default implementation returns false, so it should be overridden to provide the
+     * appropriate processing of the drop event and return true so that the drag source's repair action does not run.
+     * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
+     * {@link #getTargetFromEvent} for this node)
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {Boolean} True if the drop was valid, else false
+     */
+    onNodeDrop : function(n, dd, e, data){
+        return false;
+    },
+
+    /**
+     * Called while the DropZone determines that a {@link Ext.dd.DragSource} is being dragged over it,
+     * but not over any of its registered drop nodes.  The default implementation returns this.dropNotAllowed, so
+     * it should be overridden to provide the proper feedback if necessary.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source so that the
+     * underlying {@link Ext.dd.StatusProxy} can be updated
+     */
+    onContainerOver : function(dd, e, data){
+        return this.dropNotAllowed;
+    },
+
+    /**
+     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has been dropped on it,
+     * but not on any of its registered drop nodes.  The default implementation returns false, so it should be
+     * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to
+     * be able to accept drops.  It should return true when valid so that the drag source's repair action does not run.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {Boolean} True if the drop was valid, else false
+     */
+    onContainerDrop : function(dd, e, data){
+        return false;
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop zone that the source is now over
+     * the zone.  The default implementation returns this.dropNotAllowed and expects that only registered drop
+     * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops
+     * you should override this method and provide a custom implementation.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source so that the
+     * underlying {@link Ext.dd.StatusProxy} can be updated
+     */
+    notifyEnter : function(dd, e, data){
+        return this.dropNotAllowed;
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls continuously while it is being dragged over the drop zone.
+     * This method will be called on every mouse movement while the drag source is over the drop zone.
+     * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically
+     * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits
+     * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
+     * registered node, it will call {@link #onContainerOver}.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source so that the
+     * underlying {@link Ext.dd.StatusProxy} can be updated
+     */
+    notifyOver : function(dd, e, data){
+        var n = this.getTargetFromEvent(e);
+        if(!n){ // not over valid drop target
+            if(this.lastOverNode){
+                this.onNodeOut(this.lastOverNode, dd, e, data);
+                this.lastOverNode = null;
+            }
+            return this.onContainerOver(dd, e, data);
+        }
+        if(this.lastOverNode != n){
+            if(this.lastOverNode){
+                this.onNodeOut(this.lastOverNode, dd, e, data);
+            }
+            this.onNodeEnter(n, dd, e, data);
+            this.lastOverNode = n;
+        }
+        return this.onNodeOver(n, dd, e, data);
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop zone that the source has been dragged
+     * out of the zone without dropping.  If the drag source is currently over a registered node, the notification
+     * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag zone
+     */
+    notifyOut : function(dd, e, data){
+        if(this.lastOverNode){
+            this.onNodeOut(this.lastOverNode, dd, e, data);
+            this.lastOverNode = null;
+        }
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop zone that the dragged item has
+     * been dropped on it.  The drag zone will look up the target node based on the event passed in, and if there
+     * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,
+     * otherwise it will call {@link #onContainerDrop}.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {Boolean} True if the drop was valid, else false
+     */
+    notifyDrop : function(dd, e, data){
+        if(this.lastOverNode){
+            this.onNodeOut(this.lastOverNode, dd, e, data);
+            this.lastOverNode = null;
+        }
+        var n = this.getTargetFromEvent(e);
+        return n ?
+            this.onNodeDrop(n, dd, e, data) :
+            this.onContainerDrop(dd, e, data);
+    },
+
+    // private
+    triggerCacheRefresh : function(){
+        Ext.dd.DDM.refreshCache(this.groups);
+    }  
+});/**
+ * @class Ext.Element
+ */
+Ext.Element.addMethods({
+    /**
+     * Initializes a {@link Ext.dd.DD} drag drop object for this element.
+     * @param {String} group The group the DD object is member of
+     * @param {Object} config The DD config object
+     * @param {Object} overrides An object containing methods to override/implement on the DD object
+     * @return {Ext.dd.DD} The DD object
+     */
+    initDD : function(group, config, overrides){
+        var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
+        return Ext.apply(dd, overrides);
+    },
+
+    /**
+     * Initializes a {@link Ext.dd.DDProxy} object for this element.
+     * @param {String} group The group the DDProxy object is member of
+     * @param {Object} config The DDProxy config object
+     * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
+     * @return {Ext.dd.DDProxy} The DDProxy object
+     */
+    initDDProxy : function(group, config, overrides){
+        var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
+        return Ext.apply(dd, overrides);
+    },
+
+    /**
+     * Initializes a {@link Ext.dd.DDTarget} object for this element.
+     * @param {String} group The group the DDTarget object is member of
+     * @param {Object} config The DDTarget config object
+     * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
+     * @return {Ext.dd.DDTarget} The DDTarget object
+     */
+    initDDTarget : function(group, config, overrides){
+        var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
+        return Ext.apply(dd, overrides);
+    }
 });
\ No newline at end of file
 });
\ No newline at end of file