Upgrade to ExtJS 3.0.3 - Released 10/11/2009
[extjs.git] / src / dd / DragTracker.js
1 /*!
2  * Ext JS Library 3.0.3
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**\r
8  * @class Ext.dd.DragTracker\r
9  * @extends Ext.util.Observable\r
10  */\r
11 Ext.dd.DragTracker = function(config){\r
12     Ext.apply(this, config);\r
13     this.addEvents(\r
14         /**\r
15          * @event mousedown\r
16          * @param {Object} this\r
17          * @param {Object} e event object\r
18          */\r
19         'mousedown',\r
20         /**\r
21          * @event mouseup\r
22          * @param {Object} this\r
23          * @param {Object} e event object\r
24          */\r
25         'mouseup',\r
26         /**\r
27          * @event mousemove\r
28          * @param {Object} this\r
29          * @param {Object} e event object\r
30          */\r
31         'mousemove',\r
32         /**\r
33          * @event dragstart\r
34          * @param {Object} this\r
35          * @param {Object} startXY the page coordinates of the event\r
36          */\r
37         'dragstart',\r
38         /**\r
39          * @event dragend\r
40          * @param {Object} this\r
41          * @param {Object} e event object\r
42          */\r
43         'dragend',\r
44         /**\r
45          * @event drag\r
46          * @param {Object} this\r
47          * @param {Object} e event object\r
48          */\r
49         'drag'\r
50     );\r
51 \r
52     this.dragRegion = new Ext.lib.Region(0,0,0,0);\r
53 \r
54     if(this.el){\r
55         this.initEl(this.el);\r
56     }\r
57 }\r
58 \r
59 Ext.extend(Ext.dd.DragTracker, Ext.util.Observable,  {\r
60     /**\r
61      * @cfg {Boolean} active\r
62          * Defaults to <tt>false</tt>.\r
63          */     \r
64     active: false,\r
65     /**\r
66      * @cfg {Number} tolerance\r
67          * Defaults to <tt>5</tt>.\r
68          */     \r
69     tolerance: 5,\r
70     /**\r
71      * @cfg {Boolean/Number} autoStart\r
72          * Defaults to <tt>false</tt>. Specify <tt>true</tt> to defer trigger start by 1000 ms.\r
73          * Specify a Number for the number of milliseconds to defer trigger start.\r
74          */     \r
75     autoStart: false,\r
76 \r
77     initEl: function(el){\r
78         this.el = Ext.get(el);\r
79         el.on('mousedown', this.onMouseDown, this,\r
80                 this.delegate ? {delegate: this.delegate} : undefined);\r
81     },\r
82 \r
83     destroy : function(){\r
84         this.el.un('mousedown', this.onMouseDown, this);\r
85     },\r
86 \r
87     onMouseDown: function(e, target){\r
88         if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){\r
89             this.startXY = this.lastXY = e.getXY();\r
90             this.dragTarget = this.delegate ? target : this.el.dom;\r
91             if(this.preventDefault !== false){\r
92                 e.preventDefault();\r
93             }\r
94             var doc = Ext.getDoc();\r
95             doc.on('mouseup', this.onMouseUp, this);\r
96             doc.on('mousemove', this.onMouseMove, this);\r
97             doc.on('selectstart', this.stopSelect, this);\r
98             if(this.autoStart){\r
99                 this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);\r
100             }\r
101         }\r
102     },\r
103 \r
104     onMouseMove: function(e, target){\r
105         // HACK: IE hack to see if button was released outside of window. */\r
106         if(this.active && Ext.isIE && !e.browserEvent.button){\r
107             e.preventDefault();\r
108             this.onMouseUp(e);\r
109             return;\r
110         }\r
111 \r
112         e.preventDefault();\r
113         var xy = e.getXY(), s = this.startXY;\r
114         this.lastXY = xy;\r
115         if(!this.active){\r
116             if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){\r
117                 this.triggerStart();\r
118             }else{\r
119                 return;\r
120             }\r
121         }\r
122         this.fireEvent('mousemove', this, e);\r
123         this.onDrag(e);\r
124         this.fireEvent('drag', this, e);\r
125     },\r
126 \r
127     onMouseUp: function(e){\r
128         var doc = Ext.getDoc();\r
129         doc.un('mousemove', this.onMouseMove, this);\r
130         doc.un('mouseup', this.onMouseUp, this);\r
131         doc.un('selectstart', this.stopSelect, this);\r
132         e.preventDefault();\r
133         this.clearStart();\r
134         var wasActive = this.active;\r
135         this.active = false;\r
136         delete this.elRegion;\r
137         this.fireEvent('mouseup', this, e);\r
138         if(wasActive){\r
139             this.onEnd(e);\r
140             this.fireEvent('dragend', this, e);\r
141         }\r
142     },\r
143 \r
144     triggerStart: function(isTimer){\r
145         this.clearStart();\r
146         this.active = true;\r
147         this.onStart(this.startXY);\r
148         this.fireEvent('dragstart', this, this.startXY);\r
149     },\r
150 \r
151     clearStart : function(){\r
152         if(this.timer){\r
153             clearTimeout(this.timer);\r
154             delete this.timer;\r
155         }\r
156     },\r
157 \r
158     stopSelect : function(e){\r
159         e.stopEvent();\r
160         return false;\r
161     },\r
162 \r
163     onBeforeStart : function(e){\r
164 \r
165     },\r
166 \r
167     onStart : function(xy){\r
168 \r
169     },\r
170 \r
171     onDrag : function(e){\r
172 \r
173     },\r
174 \r
175     onEnd : function(e){\r
176 \r
177     },\r
178 \r
179     getDragTarget : function(){\r
180         return this.dragTarget;\r
181     },\r
182 \r
183     getDragCt : function(){\r
184         return this.el;\r
185     },\r
186 \r
187     getXY : function(constrain){\r
188         return constrain ?\r
189                this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;\r
190     },\r
191 \r
192     getOffset : function(constrain){\r
193         var xy = this.getXY(constrain);\r
194         var s = this.startXY;\r
195         return [s[0]-xy[0], s[1]-xy[1]];\r
196     },\r
197 \r
198     constrainModes: {\r
199         'point' : function(xy){\r
200 \r
201             if(!this.elRegion){\r
202                 this.elRegion = this.getDragCt().getRegion();\r
203             }\r
204 \r
205             var dr = this.dragRegion;\r
206 \r
207             dr.left = xy[0];\r
208             dr.top = xy[1];\r
209             dr.right = xy[0];\r
210             dr.bottom = xy[1];\r
211 \r
212             dr.constrainTo(this.elRegion);\r
213 \r
214             return [dr.left, dr.top];\r
215         }\r
216     }\r
217 });