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. */
6 * @requires OpenLayers/Handler.js
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
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'
25 * Create a new drag handler with the <OpenLayers.Handler.Drag> constructor.
28 * - <OpenLayers.Handler>
30 OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, {
34 * {Boolean} When a mousedown event is received, we want to record it, but
35 * not set 'dragging' until the mouse moves after starting.
41 * {Boolean} Stop propagation of mousedown events from getting to listeners
42 * on the same element. Default is true.
54 * {<OpenLayers.Pixel>} The last pixel location of the drag.
60 * {<OpenLayers.Pixel>} The first pixel location of the drag.
65 * Property: oldOnselectstart
68 oldOnselectstart: null,
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.
82 * {String} The id of the timeout used for the mousedown interval.
83 * This is "private", and should be left alone.
88 * Constructor: OpenLayers.Handler.Drag
89 * Returns OpenLayers.Handler.Drag
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
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.
103 initialize: function(control, callbacks, options) {
104 OpenLayers.Handler.prototype.initialize.apply(this, arguments);
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.
114 * This method is called during the handling of the mouse down event.
115 * Subclasses can do their own processing here.
118 * evt - {Event} The mouse down event
120 down: function(evt) {
125 * This method is called during the handling of the mouse move event.
126 * Subclasses can do their own processing here.
129 * evt - {Event} The mouse move event
132 move: function(evt) {
137 * This method is called during the handling of the mouse up event.
138 * Subclasses can do their own processing here.
141 * evt - {Event} The mouse up event
148 * This method is called during the handling of the mouse out event.
149 * Subclasses can do their own processing here.
152 * evt - {Event} The mouse out event
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.
165 * Handle mousedown events
171 * {Boolean} Let the event propagate.
173 mousedown: function (evt) {
174 var propagate = true;
175 this.dragging = false;
176 if (this.checkModifiers(evt) && OpenLayers.Event.isLeftClick(evt)) {
180 OpenLayers.Element.addClass(
181 this.map.viewPortDiv, "olDragDown"
184 this.callback("down", [evt.xy]);
185 OpenLayers.Event.stop(evt);
187 if(!this.oldOnselectstart) {
188 this.oldOnselectstart = (document.onselectstart) ? document.onselectstart : function() { return true; };
189 document.onselectstart = function() {return false;};
192 propagate = !this.stopDown;
194 this.started = false;
203 * Handle mousemove events
209 * {Boolean} Let the event propagate.
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);
216 this.dragging = true;
218 this.callback("move", [evt.xy]);
219 if(!this.oldOnselectstart) {
220 this.oldOnselectstart = document.onselectstart;
221 document.onselectstart = function() {return false;};
223 this.last = this.evt.xy;
229 * Method: removeTimeout
230 * Private. Called by mousemove() to remove the drag timeout.
232 removeTimeout: function() {
233 this.timeoutId = null;
238 * Handle mouseup events
244 * {Boolean} Let the event propagate.
246 mouseup: function (evt) {
248 var dragged = (this.start != this.last);
249 this.started = false;
250 this.dragging = false;
251 OpenLayers.Element.removeClass(
252 this.map.viewPortDiv, "olDragDown"
255 this.callback("up", [evt.xy]);
257 this.callback("done", [evt.xy]);
259 document.onselectstart = this.oldOnselectstart;
266 * Handle mouseout events
272 * {Boolean} Let the event propagate.
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"
283 this.callback("out", []);
285 this.callback("done", [evt.xy]);
287 if(document.onselectstart) {
288 document.onselectstart = this.oldOnselectstart;
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
304 * {Boolean} Let the event propagate.
306 click: function (evt) {
307 // let the click event propagate only if the mouse moved
308 return (this.start == this.last);
313 * Activate the handler.
316 * {Boolean} The handler was successfully activated.
318 activate: function() {
319 var activated = false;
320 if(OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
321 this.dragging = false;
329 * Deactivate the handler.
332 * {Boolean} The handler was successfully deactivated.
334 deactivate: function() {
335 var deactivated = false;
336 if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
337 this.started = false;
338 this.dragging = false;
342 OpenLayers.Element.removeClass(
343 this.map.viewPortDiv, "olDragDown"
349 CLASS_NAME: "OpenLayers.Handler.Drag"