From 99f23caf038b779044aafeaef7ee1aa7427a0356 Mon Sep 17 00:00:00 2001 From: Greg Gianforcaro Date: Wed, 9 Dec 2020 00:46:56 -0500 Subject: [PATCH 1/3] Initial stopPropagation support for PluggableMap --- src/ol/PluggableMap.js | 2 +- test/spec/ol/interaction/select.test.js | 54 +++++++++++++++++++++++++ test/spec/ol/map.test.js | 19 +++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/ol/PluggableMap.js b/src/ol/PluggableMap.js index 8350efbb6d..a48d7922c8 100644 --- a/src/ol/PluggableMap.js +++ b/src/ol/PluggableMap.js @@ -1029,7 +1029,7 @@ class PluggableMap extends BaseObject { continue; } const cont = interaction.handleEvent(mapBrowserEvent); - if (!cont) { + if (!cont || mapBrowserEvent.propagationStopped) { break; } } diff --git a/test/spec/ol/interaction/select.test.js b/test/spec/ol/interaction/select.test.js index 4beafdc8a8..5e8377f7c4 100644 --- a/test/spec/ol/interaction/select.test.js +++ b/test/spec/ol/interaction/select.test.js @@ -105,6 +105,9 @@ describe('ol.interaction.Select', function () { clientX: position.left + x + width / 2, clientY: position.top + y + height / 2, shiftKey: shiftKey, + stopPropagation: () => { + event.propagationStopped = true; + }, }; map.handleMapBrowserEvent(new MapBrowserEvent(type, map, event)); } @@ -459,4 +462,55 @@ describe('ol.interaction.Select', function () { }); }); }); + + describe('supports stop propagation', function () { + let firstInteraction, secondInteraction; + + beforeEach(function () { + firstInteraction = new Select(); + secondInteraction = new Select(); + + map.addInteraction(firstInteraction); + // note second interaction added to map last + map.addInteraction(secondInteraction); + }); + + afterEach(function () { + map.removeInteraction(firstInteraction); + map.removeInteraction(secondInteraction); + }); + + //base case sanity check + describe('without stop propagation', function () { + it('both interactions dispatch select', function () { + const firstSelectSpy = sinon.spy(); + firstInteraction.on('select', firstSelectSpy); + + const secondSelectSpy = sinon.spy(); + secondInteraction.on('select', secondSelectSpy); + + simulateEvent('singleclick', 10, -20); + + expect(firstSelectSpy.callCount).to.be(1); + expect(secondSelectSpy.callCount).to.be(1); + }); + }); + + describe('calling stop propagation', function () { + it('only "last" added interaction dispatches select', function () { + const firstSelectSpy = sinon.spy(); + firstInteraction.on('select', firstSelectSpy); + + const secondSelectSpy = sinon.spy(function (e) { + e.mapBrowserEvent.stopPropagation(); + }); + secondInteraction.on('select', secondSelectSpy); + + simulateEvent('singleclick', 10, -20); + + expect(firstSelectSpy.callCount).to.be(0); + expect(secondSelectSpy.callCount).to.be(1); + }); + }); + }); }); diff --git a/test/spec/ol/map.test.js b/test/spec/ol/map.test.js index 800e49b70f..0f71bd84f1 100644 --- a/test/spec/ol/map.test.js +++ b/test/spec/ol/map.test.js @@ -12,6 +12,7 @@ import MapEvent from '../../../src/ol/MapEvent.js'; import MouseWheelZoom from '../../../src/ol/interaction/MouseWheelZoom.js'; import Overlay from '../../../src/ol/Overlay.js'; import PinchZoom from '../../../src/ol/interaction/PinchZoom.js'; +import Select from '../../../src/ol/interaction/Select.js'; import TileLayer from '../../../src/ol/layer/Tile.js'; import TileLayerRenderer from '../../../src/ol/renderer/canvas/TileLayer.js'; import VectorLayer from '../../../src/ol/layer/Vector.js'; @@ -1093,5 +1094,23 @@ describe('ol.Map', function () { expect(spy.callCount).to.be(0); spy.restore(); }); + + it('does not call handleEvent on interaction when MapBrowserEvent propagation stopped', function () { + const select = new Select(); + const selectStub = sinon.stub(select, 'handleEvent'); + selectStub.callsFake(function (e) { + e.stopPropagation(); + return true; + }); + map.addInteraction(select); + const spy = sinon.spy(dragpan, 'handleEvent'); + map.handleMapBrowserEvent( + new MapBrowserEvent('pointermove', map, new PointerEvent('pointermove')) + ); + expect(spy.callCount).to.be(0); + expect(selectStub.callCount).to.be(1); + spy.restore(); + selectStub.restore(); + }); }); }); From 92f93e8e94ff9a2628cdf60210218e3faf58640a Mon Sep 17 00:00:00 2001 From: Greg Gianforcaro Date: Wed, 9 Dec 2020 01:17:19 -0500 Subject: [PATCH 2/3] Resolve some test failures --- src/ol/interaction/KeyboardPan.js | 2 +- src/ol/interaction/KeyboardZoom.js | 2 +- src/ol/interaction/Pointer.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ol/interaction/KeyboardPan.js b/src/ol/interaction/KeyboardPan.js index be54b99c78..8c4333ac9e 100644 --- a/src/ol/interaction/KeyboardPan.js +++ b/src/ol/interaction/KeyboardPan.js @@ -112,7 +112,7 @@ class KeyboardPan extends Interaction { const delta = [deltaX, deltaY]; rotateCoordinate(delta, view.getRotation()); pan(view, delta, this.duration_); - mapBrowserEvent.preventDefault(); + mapBrowserEvent.originalEvent.preventDefault(); stopEvent = true; } } diff --git a/src/ol/interaction/KeyboardZoom.js b/src/ol/interaction/KeyboardZoom.js index 37ba540309..32d72b11ca 100644 --- a/src/ol/interaction/KeyboardZoom.js +++ b/src/ol/interaction/KeyboardZoom.js @@ -81,7 +81,7 @@ class KeyboardZoom extends Interaction { charCode == '+'.charCodeAt(0) ? this.delta_ : -this.delta_; const view = map.getView(); zoomByDelta(view, delta, undefined, this.duration_); - mapBrowserEvent.preventDefault(); + mapBrowserEvent.originalEvent.preventDefault(); stopEvent = true; } } diff --git a/src/ol/interaction/Pointer.js b/src/ol/interaction/Pointer.js index 9a488af0f0..1420269088 100644 --- a/src/ol/interaction/Pointer.js +++ b/src/ol/interaction/Pointer.js @@ -139,7 +139,7 @@ class PointerInteraction extends Interaction { if (mapBrowserEvent.type == MapBrowserEventType.POINTERDRAG) { this.handleDragEvent(mapBrowserEvent); // prevent page scrolling during dragging - mapBrowserEvent.preventDefault(); + mapBrowserEvent.originalEvent.preventDefault(); } else if (mapBrowserEvent.type == MapBrowserEventType.POINTERUP) { const handledUp = this.handleUpEvent(mapBrowserEvent); this.handlingDownUpSequence = From 9c2b0677fa251041a0fcdefdc222c8f781aea3a9 Mon Sep 17 00:00:00 2001 From: Greg Gianforcaro Date: Wed, 9 Dec 2020 11:42:53 -0500 Subject: [PATCH 3/3] stopPropagation/preventDefault on originalEvent Move stopPropagation/preventDefault to directly target the originalEvent rather than the mapBrowserEvent. --- src/ol/interaction/DoubleClickZoom.js | 2 +- src/ol/interaction/Draw.js | 6 +++--- src/ol/interaction/KeyboardPan.js | 2 +- src/ol/interaction/KeyboardZoom.js | 2 +- src/ol/interaction/MouseWheelZoom.js | 3 +-- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/ol/interaction/DoubleClickZoom.js b/src/ol/interaction/DoubleClickZoom.js index 271a4e1c02..b73aff9321 100644 --- a/src/ol/interaction/DoubleClickZoom.js +++ b/src/ol/interaction/DoubleClickZoom.js @@ -52,7 +52,7 @@ class DoubleClickZoom extends Interaction { const delta = browserEvent.shiftKey ? -this.delta_ : this.delta_; const view = map.getView(); zoomByDelta(view, delta, anchor, this.duration_); - mapBrowserEvent.preventDefault(); + browserEvent.preventDefault(); stopEvent = true; } return !stopEvent; diff --git a/src/ol/interaction/Draw.js b/src/ol/interaction/Draw.js index 58a550d5af..5693577d1c 100644 --- a/src/ol/interaction/Draw.js +++ b/src/ol/interaction/Draw.js @@ -512,7 +512,7 @@ class Draw extends PointerInteraction { handleEvent(event) { if (event.originalEvent.type === EventType.CONTEXTMENU) { // Avoid context menu for long taps when drawing on mobile - event.preventDefault(); + event.originalEvent.preventDefault(); } this.freehand_ = this.mode_ !== Mode.POINT && this.freehandCondition_(event); @@ -554,7 +554,7 @@ class Draw extends PointerInteraction { this.handlePointerMove_(event); if (this.shouldHandle_) { // Avoid page scrolling when freehand drawing on mobile - event.preventDefault(); + event.originalEvent.preventDefault(); } } else if ( event.originalEvent.pointerType === 'mouse' || @@ -646,7 +646,7 @@ class Draw extends PointerInteraction { } if (!pass && this.stopClick_) { - event.stopPropagation(); + event.originalEvent.stopPropagation(); } this.downPx_ = null; return pass; diff --git a/src/ol/interaction/KeyboardPan.js b/src/ol/interaction/KeyboardPan.js index 8c4333ac9e..d328bb9cee 100644 --- a/src/ol/interaction/KeyboardPan.js +++ b/src/ol/interaction/KeyboardPan.js @@ -112,7 +112,7 @@ class KeyboardPan extends Interaction { const delta = [deltaX, deltaY]; rotateCoordinate(delta, view.getRotation()); pan(view, delta, this.duration_); - mapBrowserEvent.originalEvent.preventDefault(); + keyEvent.preventDefault(); stopEvent = true; } } diff --git a/src/ol/interaction/KeyboardZoom.js b/src/ol/interaction/KeyboardZoom.js index 32d72b11ca..5faf63cb72 100644 --- a/src/ol/interaction/KeyboardZoom.js +++ b/src/ol/interaction/KeyboardZoom.js @@ -81,7 +81,7 @@ class KeyboardZoom extends Interaction { charCode == '+'.charCodeAt(0) ? this.delta_ : -this.delta_; const view = map.getView(); zoomByDelta(view, delta, undefined, this.duration_); - mapBrowserEvent.originalEvent.preventDefault(); + keyEvent.preventDefault(); stopEvent = true; } } diff --git a/src/ol/interaction/MouseWheelZoom.js b/src/ol/interaction/MouseWheelZoom.js index 3b9167674b..8b81933558 100644 --- a/src/ol/interaction/MouseWheelZoom.js +++ b/src/ol/interaction/MouseWheelZoom.js @@ -178,10 +178,9 @@ class MouseWheelZoom extends Interaction { return true; } - mapBrowserEvent.preventDefault(); - const map = mapBrowserEvent.map; const wheelEvent = /** @type {WheelEvent} */ (mapBrowserEvent.originalEvent); + wheelEvent.preventDefault(); if (this.useAnchor_) { this.lastAnchor_ = mapBrowserEvent.coordinate;