diff --git a/examples/getfeatureinfo.js b/examples/getfeatureinfo.js index fcf32db161..ae7258d6cb 100644 --- a/examples/getfeatureinfo.js +++ b/examples/getfeatureinfo.js @@ -46,7 +46,7 @@ var map = new ol.Map({ }) }); -map.on('click', function(evt) { +map.on('singleclick', function(evt) { map.getFeatureInfo({ pixel: evt.getPixel(), success: function(featureInfoByLayer) { diff --git a/examples/gpx.js b/examples/gpx.js index 899b9cdb31..df2452b176 100644 --- a/examples/gpx.js +++ b/examples/gpx.js @@ -48,7 +48,7 @@ $(map.getViewport()).on('mousemove', function(evt) { displayFeatureInfo(pixel); }); -map.on('click', function(evt) { +map.on('singleclick', function(evt) { var pixel = evt.getPixel(); displayFeatureInfo(pixel); }); diff --git a/examples/icon.js b/examples/icon.js index af0e158b30..07ef45ce88 100644 --- a/examples/icon.js +++ b/examples/icon.js @@ -71,7 +71,7 @@ var popup = new ol.Overlay({ map.addOverlay(popup); -map.on('click', function(evt) { +map.on('singleclick', function(evt) { map.getFeatures({ pixel: evt.getPixel(), layers: [vector], diff --git a/examples/kml-earthquakes.js b/examples/kml-earthquakes.js index fd2405cea9..8ff5de66d1 100644 --- a/examples/kml-earthquakes.js +++ b/examples/kml-earthquakes.js @@ -87,7 +87,7 @@ $(map.getViewport()).on('mousemove', function(evt) { displayFeatureInfo(pixel); }); -map.on('click', function(evt) { +map.on('singleclick', function(evt) { var pixel = evt.getPixel(); displayFeatureInfo(pixel); }); diff --git a/examples/kml-timezones.js b/examples/kml-timezones.js index 6657961593..8b88d27d93 100644 --- a/examples/kml-timezones.js +++ b/examples/kml-timezones.js @@ -109,7 +109,7 @@ $(map.getViewport()).on('mousemove', function(evt) { displayFeatureInfo(pixel); }); -map.on('click', function(evt) { +map.on('singleclick', function(evt) { var pixel = evt.getPixel(); displayFeatureInfo(pixel); }); diff --git a/examples/kml.js b/examples/kml.js index bce5752903..c356c761d8 100644 --- a/examples/kml.js +++ b/examples/kml.js @@ -59,7 +59,7 @@ $(map.getViewport()).on('mousemove', function(evt) { displayFeatureInfo(pixel); }); -map.on('click', function(evt) { +map.on('singleclick', function(evt) { var pixel = evt.getPixel(); displayFeatureInfo(pixel); }); diff --git a/examples/overlay.js b/examples/overlay.js index bc5d12915c..e4e036c099 100644 --- a/examples/overlay.js +++ b/examples/overlay.js @@ -47,7 +47,7 @@ var popup = new ol.Overlay({ }); map.addOverlay(popup); -map.on('click', function(evt) { +map.on('singleclick', function(evt) { var element = popup.getElement(); var coordinate = evt.getCoordinate(); var hdms = ol.coordinate.toStringHDMS(ol.proj.transform( diff --git a/examples/popup.js b/examples/popup.js index 944b5b8b8b..0c6a362153 100644 --- a/examples/popup.js +++ b/examples/popup.js @@ -61,7 +61,7 @@ var map = new ol.Map({ /** * Add a click handler to the map to render the popup. */ -map.on('click', function(evt) { +map.on('singleclick', function(evt) { var coordinate = evt.getCoordinate(); var hdms = ol.coordinate.toStringHDMS(ol.proj.transform( coordinate, 'EPSG:3857', 'EPSG:4326')); diff --git a/examples/vector-layer.js b/examples/vector-layer.js index f1c2df3d7a..2f4214ced2 100644 --- a/examples/vector-layer.js +++ b/examples/vector-layer.js @@ -82,7 +82,7 @@ $(map.getViewport()).on('mousemove', function(evt) { displayFeatureInfo(pixel); }); -map.on('click', function(evt) { +map.on('singleclick', function(evt) { var pixel = evt.getPixel(); displayFeatureInfo(pixel); }); diff --git a/src/ol/events/condition.js b/src/ol/events/condition.js index c69c2db7ec..7171cbde36 100644 --- a/src/ol/events/condition.js +++ b/src/ol/events/condition.js @@ -2,8 +2,8 @@ goog.provide('ol.events.ConditionType'); goog.provide('ol.events.condition'); goog.require('goog.dom.TagName'); -goog.require('goog.events.EventType'); goog.require('goog.functions'); +goog.require('ol.MapBrowserEvent.EventType'); /** @@ -54,9 +54,8 @@ ol.events.condition.always = goog.functions.TRUE; * @return {boolean} True if the event is a click event. * @todo stability experimental */ -ol.events.condition.clickOnly = function(mapBrowserEvent) { - var browserEvent = mapBrowserEvent.browserEvent; - return browserEvent.type == goog.events.EventType.CLICK; +ol.events.condition.singleClick = function(mapBrowserEvent) { + return mapBrowserEvent.type == ol.MapBrowserEvent.EventType.SINGLECLICK; }; diff --git a/src/ol/interaction/doubleclickzoominteraction.js b/src/ol/interaction/doubleclickzoominteraction.js index dc439f8b33..1b106052b1 100644 --- a/src/ol/interaction/doubleclickzoominteraction.js +++ b/src/ol/interaction/doubleclickzoominteraction.js @@ -46,8 +46,7 @@ ol.interaction.DoubleClickZoom.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { var stopEvent = false; var browserEvent = mapBrowserEvent.browserEvent; - if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DBLCLICK && - mapBrowserEvent.isMouseActionButton()) { + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DBLCLICK) { var map = mapBrowserEvent.map; var anchor = mapBrowserEvent.getCoordinate(); var delta = browserEvent.shiftKey ? -this.delta_ : this.delta_; diff --git a/src/ol/interaction/selectinteraction.js b/src/ol/interaction/selectinteraction.js index 553254421e..705e872671 100644 --- a/src/ol/interaction/selectinteraction.js +++ b/src/ol/interaction/selectinteraction.js @@ -27,7 +27,7 @@ ol.interaction.Select = function(opt_options) { * @type {ol.events.ConditionType} */ this.condition_ = goog.isDef(options.condition) ? - options.condition : ol.events.condition.clickOnly; + options.condition : ol.events.condition.singleClick; /** * @private diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index de24ec2085..237ac700c9 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -8,7 +8,6 @@ goog.require('goog.events'); goog.require('goog.events.BrowserEvent'); goog.require('goog.events.EventTarget'); goog.require('goog.events.EventType'); -goog.require('ol.BrowserFeature'); goog.require('ol.Coordinate'); goog.require('ol.FrameState'); goog.require('ol.MapEvent'); @@ -76,16 +75,6 @@ ol.MapBrowserEvent.prototype.getPixel = function() { }; -/** - * @return {boolean} Do we have a left click? - */ -ol.MapBrowserEvent.prototype.isMouseActionButton = function() { - // always assume a left-click on touch devices - return ol.BrowserFeature.HAS_TOUCH || - this.browserEvent.isMouseActionButton(); -}; - - /** * Prevents the default browser action. * @see https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault @@ -143,13 +132,13 @@ ol.MapBrowserEventHandler = function(map) { * @type {Array.} * @private */ - this.listenerKeys_ = null; + this.dragListenerKeys_ = null; /** - * @type {Array.} + * @type {goog.events.Key} * @private */ - this.dragListenerKeys_ = null; + this.mousedownListenerKey_ = null; /** * @type {Array.} @@ -164,14 +153,11 @@ ol.MapBrowserEventHandler = function(map) { this.down_ = null; var element = this.map_.getViewport(); - this.listenerKeys_ = [ - goog.events.listen(element, - [goog.events.EventType.CLICK, goog.events.EventType.DBLCLICK], - this.click_, false, this), - goog.events.listen(element, - goog.events.EventType.MOUSEDOWN, - this.handleMouseDown_, false, this) - ]; + + this.mousedownListenerKey_ = goog.events.listen(element, + goog.events.EventType.MOUSEDOWN, + this.handleMouseDown_, false, this); + // touch events this.touchListenerKeys_ = [ goog.events.listen(element, [ @@ -196,19 +182,22 @@ goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget); * @param {goog.events.BrowserEvent} browserEvent Browser event. * @private */ -ol.MapBrowserEventHandler.prototype.click_ = function(browserEvent) { - if (!this.dragged_) { - var newEvent; - var type = browserEvent.type; - if (type == goog.events.EventType.DBLCLICK) { - newEvent = new ol.MapBrowserEvent( - ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, browserEvent); +ol.MapBrowserEventHandler.prototype.emulateClick_ = function(browserEvent) { + if (this.clickTimeoutId_ !== 0) { + // double-click + goog.global.clearTimeout(this.clickTimeoutId_); + this.clickTimeoutId_ = 0; + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, browserEvent); + this.dispatchEvent(newEvent); + } else { + // click + this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() { + this.clickTimeoutId_ = 0; + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_, browserEvent); this.dispatchEvent(newEvent); - } else { - newEvent = new ol.MapBrowserEvent( - ol.MapBrowserEvent.EventType.CLICK, this.map_, browserEvent); - this.dispatchEvent(newEvent); - } + }, this), 250); } }; @@ -219,13 +208,15 @@ ol.MapBrowserEventHandler.prototype.click_ = function(browserEvent) { */ ol.MapBrowserEventHandler.prototype.handleMouseUp_ = function(browserEvent) { if (this.down_) { - this.down_ = null; goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); this.dragListenerKeys_ = null; if (this.dragged_) { var newEvent = new ol.MapBrowserEvent( ol.MapBrowserEvent.EventType.DRAGEND, this.map_, browserEvent); this.dispatchEvent(newEvent); + this.down_ = null; + } else if (browserEvent.isMouseActionButton()) { + this.emulateClick_(browserEvent); } } }; @@ -239,18 +230,16 @@ ol.MapBrowserEventHandler.prototype.handleMouseDown_ = function(browserEvent) { var newEvent = new ol.MapBrowserEvent( ol.MapBrowserEvent.EventType.DOWN, this.map_, browserEvent); this.dispatchEvent(newEvent); - if (!this.down_) { - this.down_ = browserEvent; - this.dragged_ = false; - this.dragListenerKeys_ = [ - goog.events.listen(goog.global.document, goog.events.EventType.MOUSEMOVE, - this.handleMouseMove_, false, this), - goog.events.listen(goog.global.document, goog.events.EventType.MOUSEUP, - this.handleMouseUp_, false, this) - ]; - // prevent browser image dragging with the dom renderer - browserEvent.preventDefault(); - } + this.down_ = browserEvent; + this.dragged_ = false; + this.dragListenerKeys_ = [ + goog.events.listen(goog.global.document, goog.events.EventType.MOUSEMOVE, + this.handleMouseMove_, false, this), + goog.events.listen(goog.global.document, goog.events.EventType.MOUSEUP, + this.handleMouseUp_, false, this) + ]; + // prevent browser image dragging with the dom renderer + browserEvent.preventDefault(); }; @@ -272,21 +261,15 @@ ol.MapBrowserEventHandler.prototype.handleMouseMove_ = function(browserEvent) { }; -/** - * @param {goog.events.BrowserEvent} browserEvent Browser event. - * @private - */ -ol.MapBrowserEventHandler.prototype.relayEvent_ = function(browserEvent) { - this.dispatchEvent(new ol.MapBrowserEvent( - browserEvent.type, this.map_, browserEvent)); -}; - - /** * @param {goog.events.BrowserEvent} browserEvent Browser event. * @private */ ol.MapBrowserEventHandler.prototype.handleTouchStart_ = function(browserEvent) { + if (!goog.isNull(this.mousedownListenerKey_)) { + goog.events.unlistenByKey(this.mousedownListenerKey_); + this.mousedownListenerKey_ = null; + } // prevent context menu // When the IE pointer events are used, this prevents a // 'mousedown' from being fired after this event for the primary @@ -328,24 +311,7 @@ ol.MapBrowserEventHandler.prototype.handleTouchEnd_ = function(browserEvent) { this.dispatchEvent(newEvent); if (!this.dragged_) { goog.asserts.assert(!goog.isNull(this.down_)); - if (this.clickTimeoutId_ !== 0) { - // double-click - goog.global.clearTimeout(this.clickTimeoutId_); - this.clickTimeoutId_ = 0; - newEvent = new ol.MapBrowserEvent( - ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, this.down_); - this.dispatchEvent(newEvent); - this.down_ = null; - } else { - // click - this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() { - this.clickTimeoutId_ = 0; - newEvent = new ol.MapBrowserEvent( - ol.MapBrowserEvent.EventType.CLICK, this.map_, this.down_); - this.dispatchEvent(newEvent); - this.down_ = null; - }, this), 250); - } + this.emulateClick_(this.down_); } }; @@ -354,9 +320,9 @@ ol.MapBrowserEventHandler.prototype.handleTouchEnd_ = function(browserEvent) { * FIXME empty description for jsdoc */ ol.MapBrowserEventHandler.prototype.disposeInternal = function() { - if (!goog.isNull(this.listenerKeys_)) { - goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey); - this.listenerKeys_ = null; + if (!goog.isNull(this.mousedownListenerKey_)) { + goog.events.unlistenByKey(this.mousedownListenerKey_); + this.mousedownListenerKey_ = null; } if (!goog.isNull(this.dragListenerKeys_)) { goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); @@ -375,12 +341,12 @@ ol.MapBrowserEventHandler.prototype.disposeInternal = function() { * @enum {string} */ ol.MapBrowserEvent.EventType = { - CLICK: goog.events.EventType.CLICK, DBLCLICK: goog.events.EventType.DBLCLICK, DOWN: 'down', DRAGSTART: 'dragstart', DRAG: 'drag', DRAGEND: 'dragend', + SINGLECLICK: 'singleclick', TOUCHSTART: goog.events.EventType.TOUCHSTART, TOUCHMOVE: goog.events.EventType.TOUCHMOVE, TOUCHEND: goog.events.EventType.TOUCHEND diff --git a/test/spec/ol/mapbrowserevent.test.js b/test/spec/ol/mapbrowserevent.test.js new file mode 100644 index 0000000000..cf2b385fc7 --- /dev/null +++ b/test/spec/ol/mapbrowserevent.test.js @@ -0,0 +1,58 @@ +goog.provide('ol.test.MapBrowserEventHandler'); + +describe('ol.MapBrowserEventHandler', function() { + describe('#emulateClick_', function() { + var clock; + var handler; + var singleclickSpy; + var dblclickSpy; + + beforeEach(function() { + clock = sinon.useFakeTimers(); + handler = new ol.MapBrowserEventHandler(new ol.Map({})); + + singleclickSpy = sinon.spy(); + goog.events.listen(handler, 'singleclick', singleclickSpy); + + dblclickSpy = sinon.spy(); + goog.events.listen(handler, 'dblclick', dblclickSpy); + }); + + afterEach(function() { + clock.restore(); + }); + + it('emulates click', function() { + handler.emulateClick_(); + expect(singleclickSpy.called).to.not.be.ok(); + expect(dblclickSpy.called).to.not.be.ok(); + + clock.tick(250); + expect(singleclickSpy.calledOnce).to.be.ok(); + expect(dblclickSpy.called).to.not.be.ok(); + + handler.emulateClick_(); + expect(singleclickSpy.calledOnce).to.be.ok(); + expect(dblclickSpy.called).to.not.be.ok(); + }); + + it('emulates dblclick', function() { + handler.emulateClick_(); + expect(singleclickSpy.called).to.not.be.ok(); + expect(dblclickSpy.called).to.not.be.ok(); + + handler.emulateClick_(); + expect(singleclickSpy.called).to.not.be.ok(); + expect(dblclickSpy.calledOnce).to.be.ok(); + + clock.tick(250); + expect(singleclickSpy.called).to.not.be.ok(); + expect(dblclickSpy.calledOnce).to.be.ok(); + }); + + }); +}); + +goog.require('goog.events'); +goog.require('ol.Map'); +goog.require('ol.MapBrowserEventHandler');