From e8ac3f1a6b0e896fda2034551fea43921ddc039d Mon Sep 17 00:00:00 2001 From: ahocevar Date: Sun, 8 Jul 2012 11:55:31 +0200 Subject: [PATCH 1/4] preventDefault for mousemove and touchmove. This avoids panning of the browser page when drag-panning the map. --- src/ol/event/Drag.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/ol/event/Drag.js b/src/ol/event/Drag.js index d05c97f396..2ef0bec8db 100644 --- a/src/ol/event/Drag.js +++ b/src/ol/event/Drag.js @@ -30,11 +30,21 @@ ol.event.Drag = function(target) { */ this.dragger_ = dragger; + /** + * @private + * @type {ol.event.Events} + */ + this.target_ = target; + // We want to swallow the click event that gets fired after dragging. var newSequence; function unregisterClickStopper() { target.unregister('click', goog.functions.FALSE, undefined, true); } + + // no default for mousemove and touchmove events to avoid page scrolling. + target.register('mousemove', this.preventDefault); + target.register('touchmove', this.preventDefault); dragger.defaultAction = function(x, y) {}; dragger.addEventListener(goog.fx.Dragger.EventType.START, function(evt) { @@ -73,10 +83,19 @@ ol.event.Drag = function(target) { ); }; +/** + * @private + */ +ol.event.Drag.prototype.preventDefault = function(evt) { + evt.preventDefault(); +}; + /** @inheritDoc */ ol.event.Drag.prototype.destroy = function() { + this.target_.unregister('mousemove', this.preventDefault); + this.target_.unregister('touchmove', this.preventDefault); this.dragger_.dispose(); - delete this.dragger_; + goog.object.clear(this); }; From e67e9049cabfb7f9d33d2773d5434396d6637a03 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Sun, 8 Jul 2012 12:12:19 +0200 Subject: [PATCH 2/4] preventDefault and stopPropagation convenience functions. These functions can directly be used as browser event listeners. --- src/ol/event/Drag.js | 15 ++++----------- src/ol/event/Events.js | 19 ++++++++++++------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/ol/event/Drag.js b/src/ol/event/Drag.js index 2ef0bec8db..af1eee8fe3 100644 --- a/src/ol/event/Drag.js +++ b/src/ol/event/Drag.js @@ -43,8 +43,8 @@ ol.event.Drag = function(target) { } // no default for mousemove and touchmove events to avoid page scrolling. - target.register('mousemove', this.preventDefault); - target.register('touchmove', this.preventDefault); + target.register('mousemove', ol.event.preventDefault); + target.register('touchmove', ol.event.preventDefault); dragger.defaultAction = function(x, y) {}; dragger.addEventListener(goog.fx.Dragger.EventType.START, function(evt) { @@ -83,17 +83,10 @@ ol.event.Drag = function(target) { ); }; -/** - * @private - */ -ol.event.Drag.prototype.preventDefault = function(evt) { - evt.preventDefault(); -}; - /** @inheritDoc */ ol.event.Drag.prototype.destroy = function() { - this.target_.unregister('mousemove', this.preventDefault); - this.target_.unregister('touchmove', this.preventDefault); + this.target_.unregister('mousemove', ol.event.preventDefault); + this.target_.unregister('touchmove', ol.event.preventDefault); this.dragger_.dispose(); goog.object.clear(this); }; diff --git a/src/ol/event/Events.js b/src/ol/event/Events.js index fe65d8b363..9089779aec 100644 --- a/src/ol/event/Events.js +++ b/src/ol/event/Events.js @@ -42,16 +42,21 @@ ol.event.isMultiTouch = function(evt) { }; /** - * Is the event a keyboard event with Enter or Space pressed? + * Call preventDefault on the provided event. * * @param {!Event} evt - * @return {boolean} */ -ol.event.isEnterOrSpace = function(evt) { - return evt.type === "keypress" && - (evt.keyCode === goog.events.KeyCodes.ENTER || - evt.keyCode === goog.events.KeyCodes.SPACE || - evt.keyCode === goog.events.KeyCodes.MAC_ENTER); +ol.event.preventDefault = function(evt) { + evt.preventDefault(); +}; + +/** + * Call stopPropagation on the provided event. + * + * @param {!Event} evt + */ +ol.event.stopPropagation = function(evt) { + evt.stopPropagation(); }; From a38a33108522d95be62425b2b8cbac4d3223523c Mon Sep 17 00:00:00 2001 From: ahocevar Date: Sun, 8 Jul 2012 12:14:26 +0200 Subject: [PATCH 3/4] Allow for events on other elements than the map viewport. Not registering browser events as priority events makes it easy for controls to preventDefault or stopPropagation when events are registered on children of the map viewport element. --- src/ol/event/Events.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ol/event/Events.js b/src/ol/event/Events.js index 9089779aec..3ad7969228 100644 --- a/src/ol/event/Events.js +++ b/src/ol/event/Events.js @@ -160,7 +160,7 @@ ol.event.Events.prototype.setElement = function(element) { if (this.element_) { for (t in types) { goog.events.unlisten( - this.element_, types[t], this.handleBrowserEvent, true, this + this.element_, types[t], this.handleBrowserEvent, false, this ); } this.destroySequences(); @@ -171,7 +171,7 @@ ol.event.Events.prototype.setElement = function(element) { this.createSequences(); for (t in types) { goog.events.listen( - element, types[t], this.handleBrowserEvent, true, this + element, types[t], this.handleBrowserEvent, false, this ); } } From ca2414c9d6cfabd3abff6467a4cceab4c93e7673 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Sun, 8 Jul 2012 12:17:11 +0200 Subject: [PATCH 4/4] Simplify controls by registering click events on own elements. This makes sense for all controls that provide buttons or similar UI elements that don't interfer with map interaction. --- src/ol/control/Attribution.js | 15 +------- src/ol/control/Zoom.js | 69 ++++++++++++++++++----------------- 2 files changed, 37 insertions(+), 47 deletions(-) diff --git a/src/ol/control/Attribution.js b/src/ol/control/Attribution.js index 0c03182366..35875a3de4 100644 --- a/src/ol/control/Attribution.js +++ b/src/ol/control/Attribution.js @@ -43,9 +43,7 @@ ol.control.Attribution.prototype.setMap = function(map) { var staticOverlay = map.getStaticOverlay(); if (goog.isNull(this.container_)) { this.container_ = goog.dom.createDom('div', this.CLS); - // This is not registered as priority listener, so priority listeners - // can still get the click event. - map.getEvents().register('click', this.stopLinkClick, this); + goog.events.listen(this.container_, 'click', ol.event.stopPropagation); } if (!goog.isNull(staticOverlay)) { goog.dom.append(staticOverlay, this.container_); @@ -53,16 +51,6 @@ ol.control.Attribution.prototype.setMap = function(map) { goog.base(this, 'setMap', map); }; -/** - * Prevent clicks on links in the attribution from getting through to - * listeners. - */ -ol.control.Attribution.prototype.stopLinkClick = function(evt) { - var node = evt.target; - return node.nodeName !== 'A' || - !goog.dom.getAncestorByClass(node, this.CLS); -}; - /** @inheritDoc */ ol.control.Attribution.prototype.activate = function() { var active = goog.base(this, 'activate'); @@ -96,6 +84,7 @@ ol.control.Attribution.prototype.update = function() { }; ol.control.Attribution.prototype.destroy = function() { + goog.events.unlisten(this.container_, 'click', ol.event.stopPropagation); goog.dom.removeNode(this.container_); goog.base(this, 'destroy'); }; diff --git a/src/ol/control/Zoom.js b/src/ol/control/Zoom.js index 07010a492a..a25cbac6d7 100644 --- a/src/ol/control/Zoom.js +++ b/src/ol/control/Zoom.js @@ -12,13 +12,23 @@ goog.require('goog.dom'); * @param {boolean|undefined} opt_autoActivate */ ol.control.Zoom = function(opt_autoActivate) { - + goog.base(this, opt_autoActivate); + /** + * @type {Node} + */ + this.inButton_ = null; + + /** + * @type {Node} + */ + this.outButton_ = null; + /** * Activate this control when it is added to a map. Default is true. * - * @type {boolean} autoActivate + * @type {boolean} */ this.autoActivate_ = goog.isDef(opt_autoActivate) ? opt_autoActivate : true; @@ -30,38 +40,38 @@ goog.inherits(ol.control.Zoom, ol.control.Control); * @param {ol.Map} map */ ol.control.Zoom.prototype.setMap = function(map) { - goog.base(this, 'setMap', map); var container = goog.dom.createDom('div', ol.control.Zoom.RES.CLS); - var inButton = goog.dom.createDom( + this.inButton_ = goog.dom.createDom( 'div', ol.control.Zoom.RES.IN_CLS, goog.dom.createDom('a', {'href': '#zoomIn'}) ); goog.dom.setTextContent( - /** @type {Element} */ (inButton.firstChild), + /** @type {Element} */ (this.inButton_.firstChild), ol.control.Zoom.RES.IN_TEXT ); - var outButton = goog.dom.createDom( + this.outButton_ = goog.dom.createDom( 'div', ol.control.Zoom.RES.OUT_CLS, goog.dom.createDom('a', {'href': '#zoomOut'}) ); goog.dom.setTextContent( - /** @type {Element} */ (outButton.firstChild), + /** @type {Element} */ (this.outButton_.firstChild), ol.control.Zoom.RES.OUT_TEXT ); - goog.dom.append(container, inButton, outButton); + goog.dom.append(container, this.inButton_, this.outButton_); var overlay = map.getStaticOverlay(); if (goog.isDefAndNotNull(overlay)) { goog.dom.append(overlay, container); } + goog.base(this, 'setMap', map); }; /** @inheritDoc */ ol.control.Zoom.prototype.activate = function() { var active = goog.base(this, 'activate'); if (active) { - this.map_.getEvents().register('click', this.handle, this); - this.map_.getEvents().register('keypress', this.handle, this); + goog.events.listen(this.inButton_, 'click', this.handleIn, false, this); + goog.events.listen(this.outButton_, 'click', this.handleOut, false, this); } return active; }; @@ -70,37 +80,28 @@ ol.control.Zoom.prototype.activate = function() { ol.control.Zoom.prototype.deactivate = function() { var inactive = goog.base(this, 'deactivate'); if (inactive) { - this.map_.getEvents().unregister('click', this.handle, this); - this.map_.getEvents().unregister('keypress', this.handle, this); + goog.events.unlisten(this.inButton_, 'click', this.handleIn, false, this); + goog.events.unlisten(this.outButton_, 'click', this.handleOut, false, this); } return inactive; }; /** * @param {Event} evt - * @return {boolean} */ -ol.control.Zoom.prototype.handle = function(evt) { - var target = /** @type {Node} */ (evt.target), - handled = false; - if (evt.type === 'click' || ol.event.isEnterOrSpace(evt)) { - if (goog.dom.getAncestorByClass(target, ol.control.Zoom.RES.IN_CLS)) { - this.map_.zoomIn(); - handled = true; - } else - if (goog.dom.getAncestorByClass(target, ol.control.Zoom.RES.OUT_CLS)) { - this.map_.zoomOut(); - handled = true; - } - if (handled) { - // Stop default behavior (i.e. don't follow link to anchor) - evt.preventDefault(); - // On Android 2.3, the above does not prevent the link from being - // followed, but stopPropagation does. - evt.stopPropagation(); - } - } - return !handled; +ol.control.Zoom.prototype.handleIn = function(evt) { + this.map_.zoomIn(); + evt.preventDefault(); + evt.stopPropagation(); +}; + +/** + * @param {Event} evt + */ +ol.control.Zoom.prototype.handleOut = function(evt) { + this.map_.zoomOut(); + evt.preventDefault(); + evt.stopPropagation(); }; ol.control.Zoom.prototype.destroy = function() {