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(); + }); }); });