]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Handler/Drag.js
initial commit
[syp.git] / openlayers / lib / OpenLayers / Handler / Drag.js
1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2  * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3  * full text of the license. */
4
5 /**
6  * @requires OpenLayers/Handler.js
7  */
8
9 /**
10  * Class: OpenLayers.Handler.Drag
11  * The drag handler is used to deal with sequences of browser events related
12  *     to dragging.  The handler is used by controls that want to know when
13  *     a drag sequence begins, when a drag is happening, and when it has
14  *     finished.
15  *
16  * Controls that use the drag handler typically construct it with callbacks
17  *     for 'down', 'move', and 'done'.  Callbacks for these keys are called
18  *     when the drag begins, with each move, and when the drag is done.  In
19  *     addition, controls can have callbacks keyed to 'up' and 'out' if they
20  *     care to differentiate between the types of events that correspond with
21  *     the end of a drag sequence.  If no drag actually occurs (no mouse move)
22  *     the 'down' and 'up' callbacks will be called, but not the 'done'
23  *     callback.
24  *
25  * Create a new drag handler with the <OpenLayers.Handler.Drag> constructor.
26  *
27  * Inherits from:
28  *  - <OpenLayers.Handler>
29  */
30 OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, {
31   
32     /** 
33      * Property: started
34      * {Boolean} When a mousedown event is received, we want to record it, but
35      *     not set 'dragging' until the mouse moves after starting. 
36      */
37     started: false,
38     
39     /**
40      * Property: stopDown
41      * {Boolean} Stop propagation of mousedown events from getting to listeners
42      *     on the same element.  Default is true.
43      */
44     stopDown: true,
45
46     /** 
47      * Property: dragging 
48      * {Boolean} 
49      */
50     dragging: false,
51
52     /** 
53      * Property: last
54      * {<OpenLayers.Pixel>} The last pixel location of the drag.
55      */
56     last: null,
57
58     /** 
59      * Property: start
60      * {<OpenLayers.Pixel>} The first pixel location of the drag.
61      */
62     start: null,
63
64     /**
65      * Property: oldOnselectstart
66      * {Function}
67      */
68     oldOnselectstart: null,
69     
70     /**
71      * Property: interval
72      * {Integer} In order to increase performance, an interval (in 
73      *     milliseconds) can be set to reduce the number of drag events 
74      *     called. If set, a new drag event will not be set until the 
75      *     interval has passed. 
76      *     Defaults to 0, meaning no interval. 
77      */
78     interval: 0,
79     
80     /**
81      * Property: timeoutId
82      * {String} The id of the timeout used for the mousedown interval.
83      *     This is "private", and should be left alone.
84      */
85     timeoutId: null,
86
87     /**
88      * Constructor: OpenLayers.Handler.Drag
89      * Returns OpenLayers.Handler.Drag
90      * 
91      * Parameters:
92      * control - {<OpenLayers.Control>} The control that is making use of
93      *     this handler.  If a handler is being used without a control, the
94      *     handlers setMap method must be overridden to deal properly with
95      *     the map.
96      * callbacks - {Object} An object containing a single function to be
97      *     called when the drag operation is finished. The callback should
98      *     expect to recieve a single argument, the pixel location of the event.
99      *     Callbacks for 'move' and 'done' are supported. You can also speficy
100      *     callbacks for 'down', 'up', and 'out' to respond to those events.
101      * options - {Object} 
102      */
103     initialize: function(control, callbacks, options) {
104         OpenLayers.Handler.prototype.initialize.apply(this, arguments);
105     },
106     
107     /**
108      * The four methods below (down, move, up, and out) are used by subclasses
109      *     to do their own processing related to these mouse events.
110      */
111     
112     /**
113      * Method: down
114      * This method is called during the handling of the mouse down event.
115      *     Subclasses can do their own processing here.
116      *
117      * Parameters:
118      * evt - {Event} The mouse down event
119      */
120     down: function(evt) {
121     },
122     
123     /**
124      * Method: move
125      * This method is called during the handling of the mouse move event.
126      *     Subclasses can do their own processing here.
127      *
128      * Parameters:
129      * evt - {Event} The mouse move event
130      *
131      */
132     move: function(evt) {
133     },
134
135     /**
136      * Method: up
137      * This method is called during the handling of the mouse up event.
138      *     Subclasses can do their own processing here.
139      *
140      * Parameters:
141      * evt - {Event} The mouse up event
142      */
143     up: function(evt) {
144     },
145
146     /**
147      * Method: out
148      * This method is called during the handling of the mouse out event.
149      *     Subclasses can do their own processing here.
150      *
151      * Parameters:
152      * evt - {Event} The mouse out event
153      */
154     out: function(evt) {
155     },
156
157     /**
158      * The methods below are part of the magic of event handling.  Because
159      *     they are named like browser events, they are registered as listeners
160      *     for the events they represent.
161      */
162
163     /**
164      * Method: mousedown
165      * Handle mousedown events
166      *
167      * Parameters:
168      * evt - {Event} 
169      *
170      * Returns:
171      * {Boolean} Let the event propagate.
172      */
173     mousedown: function (evt) {
174         var propagate = true;
175         this.dragging = false;
176         if (this.checkModifiers(evt) && OpenLayers.Event.isLeftClick(evt)) {
177             this.started = true;
178             this.start = evt.xy;
179             this.last = evt.xy;
180             OpenLayers.Element.addClass(
181                 this.map.viewPortDiv, "olDragDown"
182             );
183             this.down(evt);
184             this.callback("down", [evt.xy]);
185             OpenLayers.Event.stop(evt);
186             
187             if(!this.oldOnselectstart) {
188                 this.oldOnselectstart = (document.onselectstart) ? document.onselectstart : function() { return true; };
189                 document.onselectstart = function() {return false;};
190             }
191             
192             propagate = !this.stopDown;
193         } else {
194             this.started = false;
195             this.start = null;
196             this.last = null;
197         }
198         return propagate;
199     },
200
201     /**
202      * Method: mousemove
203      * Handle mousemove events
204      *
205      * Parameters:
206      * evt - {Event} 
207      *
208      * Returns:
209      * {Boolean} Let the event propagate.
210      */
211     mousemove: function (evt) {
212         if (this.started && !this.timeoutId && (evt.xy.x != this.last.x || evt.xy.y != this.last.y)) {
213             if (this.interval > 0) {
214                 this.timeoutId = setTimeout(OpenLayers.Function.bind(this.removeTimeout, this), this.interval);
215             }
216             this.dragging = true;
217             this.move(evt);
218             this.callback("move", [evt.xy]);
219             if(!this.oldOnselectstart) {
220                 this.oldOnselectstart = document.onselectstart;
221                 document.onselectstart = function() {return false;};
222             }
223             this.last = this.evt.xy;
224         }
225         return true;
226     },
227     
228     /**
229      * Method: removeTimeout
230      * Private. Called by mousemove() to remove the drag timeout.
231      */
232     removeTimeout: function() {
233         this.timeoutId = null;
234     },
235
236     /**
237      * Method: mouseup
238      * Handle mouseup events
239      *
240      * Parameters:
241      * evt - {Event} 
242      *
243      * Returns:
244      * {Boolean} Let the event propagate.
245      */
246     mouseup: function (evt) {
247         if (this.started) {
248             var dragged = (this.start != this.last);
249             this.started = false;
250             this.dragging = false;
251             OpenLayers.Element.removeClass(
252                 this.map.viewPortDiv, "olDragDown"
253             );
254             this.up(evt);
255             this.callback("up", [evt.xy]);
256             if(dragged) {
257                 this.callback("done", [evt.xy]);
258             }
259             document.onselectstart = this.oldOnselectstart;
260         }
261         return true;
262     },
263
264     /**
265      * Method: mouseout
266      * Handle mouseout events
267      *
268      * Parameters:
269      * evt - {Event} 
270      *
271      * Returns:
272      * {Boolean} Let the event propagate.
273      */
274     mouseout: function (evt) {
275         if (this.started && OpenLayers.Util.mouseLeft(evt, this.map.div)) {
276             var dragged = (this.start != this.last);
277             this.started = false; 
278             this.dragging = false;
279             OpenLayers.Element.removeClass(
280                 this.map.viewPortDiv, "olDragDown"
281             );
282             this.out(evt);
283             this.callback("out", []);
284             if(dragged) {
285                 this.callback("done", [evt.xy]);
286             }
287             if(document.onselectstart) {
288                 document.onselectstart = this.oldOnselectstart;
289             }
290         }
291         return true;
292     },
293
294     /**
295      * Method: click
296      * The drag handler captures the click event.  If something else registers
297      *     for clicks on the same element, its listener will not be called 
298      *     after a drag.
299      * 
300      * Parameters: 
301      * evt - {Event} 
302      * 
303      * Returns:
304      * {Boolean} Let the event propagate.
305      */
306     click: function (evt) {
307         // let the click event propagate only if the mouse moved
308         return (this.start == this.last);
309     },
310
311     /**
312      * Method: activate
313      * Activate the handler.
314      * 
315      * Returns:
316      * {Boolean} The handler was successfully activated.
317      */
318     activate: function() {
319         var activated = false;
320         if(OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
321             this.dragging = false;
322             activated = true;
323         }
324         return activated;
325     },
326
327     /**
328      * Method: deactivate 
329      * Deactivate the handler.
330      * 
331      * Returns:
332      * {Boolean} The handler was successfully deactivated.
333      */
334     deactivate: function() {
335         var deactivated = false;
336         if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
337             this.started = false;
338             this.dragging = false;
339             this.start = null;
340             this.last = null;
341             deactivated = true;
342             OpenLayers.Element.removeClass(
343                 this.map.viewPortDiv, "olDragDown"
344             );
345         }
346         return deactivated;
347     },
348
349     CLASS_NAME: "OpenLayers.Handler.Drag"
350 });