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