Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / src / dd / DragTracker.js
diff --git a/src/dd/DragTracker.js b/src/dd/DragTracker.js
new file mode 100644 (file)
index 0000000..6925682
--- /dev/null
@@ -0,0 +1,217 @@
+/*!
+ * Ext JS Library 3.0.0
+ * Copyright(c) 2006-2009 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+/**\r
+ * @class Ext.dd.DragTracker\r
+ * @extends Ext.util.Observable\r
+ */\r
+Ext.dd.DragTracker = 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
+}\r
+\r
+Ext.extend(Ext.dd.DragTracker, 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
+    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
+});
\ No newline at end of file