/* Copyright (c) 2006-2007 MetaCarta, Inc., published under the clear BSD license. * See http://svn.openlayers.org/trunk/openlayers/license.txt * for the full text of the license. */ /** * @requires OpenLayers/Handler.js * * Class: OpenLayers.Handler.Click * A handler for mouse clicks. The intention of this handler is to give * controls more flexibility with handling clicks. Browsers trigger * click events twice for a double-click. In addition, the mousedown, * mousemove, mouseup sequence fires a click event. With this handler, * controls can decide whether to ignore clicks associated with a double * click. By setting a , controls can also ignore clicks * that include a drag. Create a new instance with the * constructor. * * Inherits from: * - */ OpenLayers.Handler.Click = OpenLayers.Class(OpenLayers.Handler, { /** * APIProperty: delay * {Number} Number of milliseconds between clicks before the event is * considered a double-click. */ delay: 300, /** * APIProperty: single * {Boolean} Handle single clicks. Default is true. If false, clicks * will not be reported. If true, single-clicks will be reported. */ single: true, /** * APIProperty: double * {Boolean} Handle double-clicks. Default is false. */ 'double': false, /** * APIProperty: pixelTolerance * {Number} Maximum number of pixels between mouseup and mousedown for an * event to be considered a click. Default is null. If set to an * integer value, clicks with a drag greater than the value will be * ignored. This property can only be set when the handler is * constructed. */ pixelTolerance: null, /** * APIProperty: stopSingle * {Boolean} Stop other listeners from being notified of clicks. Default * is false. If true, any click listeners registered before this one * will not be notified of *any* click event (associated with double * or single clicks). */ stopSingle: false, /** * APIProperty: stopDouble * {Boolean} Stop other listeners from being notified of double-clicks. * Default is false. If true, any click listeners registered before * this one will not be notified of *any* double-click events. * * The one caveat with stopDouble is that given a map with two click * handlers, one with stopDouble true and the other with stopSingle * true, the stopSingle handler should be activated last to get * uniform cross-browser performance. Since IE triggers one click * with a dblclick and FF triggers two, if a stopSingle handler is * activated first, all it gets in IE is a single click when the * second handler stops propagation on the dblclick. */ stopDouble: false, /** * Property: timerId * {Number} The id of the timeout waiting to clear the . */ timerId: null, /** * Property: down * {} The pixel location of the last mousedown. */ down: null, /** * Property: cachedEvent * {Event} Since IE doesn't let us call window.setTimeout with extra * arguments, we cache the last click event here. */ cachedEvent: null, /** * Constructor: OpenLayers.Handler.Click * Create a new click handler. * * Parameters: * control - {} The control that is making use of * this handler. If a handler is being used without a control, the * handler's setMap method must be overridden to deal properly with * the map. * callbacks - {Object} An object with keys corresponding to callbacks * that will be called by the handler. The callbacks should * expect to recieve a single argument, the click event. * Callbacks for 'click' and 'dblclick' are supported. * options - {Object} Optional object whose properties will be set on the * handler. */ initialize: function(control, callbacks, options) { OpenLayers.Handler.prototype.initialize.apply(this, arguments); // optionally register for mouseup and mousedown if(this.pixelTolerance != null) { this.mousedown = function(evt) { this.down = evt.xy; return true; }; } }, /** * Method: mousedown * Handle mousedown. Only registered as a listener if pixelTolerance is * a non-zero value at construction. * * Returns: * {Boolean} Continue propagating this event. */ mousedown: null, /** * Method: dblclick * Handle dblclick. For a dblclick, we get two clicks in some browsers * (FF) and one in others (IE). So we need to always register for * dblclick to properly handle single clicks. * * Returns: * {Boolean} Continue propagating this event. */ dblclick: function(evt) { if(this.passesTolerance(evt)) { if(this["double"]) { this.callback('dblclick', [evt]); } this.clearTimer(); } return !this.stopDouble; }, /** * Method: click * Handle click. * * Returns: * {Boolean} Continue propagating this event. */ click: function(evt) { if(this.passesTolerance(evt)) { if(this.timerId != null) { // already received a click this.clearTimer(); } else { // set the timer, send evt only if single is true var clickEvent = this.single ? evt : null; this.timerId = window.setTimeout( OpenLayers.Function.bind(this.delayedCall, this, clickEvent), this.delay ); } } return !this.stopSingle; }, /** * Method: passesTolerance * Determine whether the event is within the optional pixel tolerance. * * Returns: * {Boolean} The click is within the pixel tolerance (if specified). */ passesTolerance: function(evt) { var passes = true; if(this.pixelTolerance) { var dpx = Math.sqrt( Math.pow(this.down.x - evt.xy.x, 2) + Math.pow(this.down.y - evt.xy.y, 2) ); if(dpx > this.pixelTolerance) { passes = false; } } return passes; }, /** * Method: clearTimer * Clear the timer and set to null. */ clearTimer: function() { if(this.timerId != null) { window.clearTimeout(this.timerId); this.timerId = null; } }, /** * Method: delayedCall * Sets to null. And optionally triggers the click callback if * is set. */ delayedCall: function(evt) { this.timerId = null; if(evt) { this.callback('click', [evt]); } }, /** * APIMethod: deactivate * Deactivate the handler. * * Returns: * {Boolean} The handler was successfully deactivated. */ deactivate: function() { var deactivated = false; if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { this.clearTimer(); this.down = null; deactivated = true; } return deactivated; }, CLASS_NAME: "OpenLayers.Handler.Click" });