Simplify event handling for custom elements

This commit is contained in:
Andreas Hocevar
2021-03-03 15:00:25 +01:00
parent c9ec2083d3
commit 83ee87581f
4 changed files with 38 additions and 26 deletions

View File

@@ -7,7 +7,7 @@ import MapEvent from './MapEvent.js';
* @classdesc * @classdesc
* Events emitted as map browser events are instances of this type. * Events emitted as map browser events are instances of this type.
* See {@link module:ol/PluggableMap~PluggableMap} for which events trigger a map browser event. * See {@link module:ol/PluggableMap~PluggableMap} for which events trigger a map browser event.
* @template {UIEvent} EVENT * @template {UIEvent|import("./MapBrowserEventHandler").PointerEventData} EVENT
*/ */
class MapBrowserEvent extends MapEvent { class MapBrowserEvent extends MapEvent {
/** /**
@@ -88,7 +88,9 @@ class MapBrowserEvent extends MapEvent {
*/ */
preventDefault() { preventDefault() {
super.preventDefault(); super.preventDefault();
this.originalEvent.preventDefault(); if ('preventDefault' in this.originalEvent) {
/** @type {UIEvent} */ (this.originalEvent).preventDefault();
}
} }
/** /**
@@ -98,7 +100,9 @@ class MapBrowserEvent extends MapEvent {
*/ */
stopPropagation() { stopPropagation() {
super.stopPropagation(); super.stopPropagation();
this.originalEvent.stopPropagation(); if ('stopPropagation' in this.originalEvent) {
/** @type {UIEvent} */ (this.originalEvent).stopPropagation();
}
} }
} }

View File

@@ -2,15 +2,23 @@
* @module ol/MapBrowserEventHandler * @module ol/MapBrowserEventHandler
*/ */
import EventTarget from './events/Target.js';
import EventType from './events/EventType.js'; import EventType from './events/EventType.js';
import MapBrowserEvent from './MapBrowserEvent.js'; import MapBrowserEvent from './MapBrowserEvent.js';
import MapBrowserEventType from './MapBrowserEventType.js'; import MapBrowserEventType from './MapBrowserEventType.js';
import PointerEventType from './pointer/EventType.js'; import PointerEventType from './pointer/EventType.js';
import Target from './events/Target.js';
import {DEVICE_PIXEL_RATIO, PASSIVE_EVENT_LISTENERS} from './has.js'; import {DEVICE_PIXEL_RATIO, PASSIVE_EVENT_LISTENERS} from './has.js';
import {listen, unlistenByKey} from './events.js'; import {listen, unlistenByKey} from './events.js';
class MapBrowserEventHandler extends EventTarget { /**
* @typedef {Object} PointerEventData
* @property {string} type
* @property {number} clientX
* @property {number} clientY
* @property {EventTarget} target
*/
class MapBrowserEventHandler extends Target {
/** /**
* @param {import("./PluggableMap.js").default} map The map with the viewport to listen to events on. * @param {import("./PluggableMap.js").default} map The map with the viewport to listen to events on.
* @param {number} [moveTolerance] The minimal distance the pointer must travel to trigger a move. * @param {number} [moveTolerance] The minimal distance the pointer must travel to trigger a move.
@@ -60,7 +68,7 @@ class MapBrowserEventHandler extends EventTarget {
/** /**
* The most recent "down" type event (or null if none have occurred). * The most recent "down" type event (or null if none have occurred).
* Set on pointerdown. * Set on pointerdown.
* @type {PointerEvent} * @type {PointerEventData}
* @private * @private
*/ */
this.down_ = null; this.down_ = null;
@@ -122,7 +130,7 @@ class MapBrowserEventHandler extends EventTarget {
} }
/** /**
* @param {PointerEvent} pointerEvent Pointer * @param {PointerEventData} pointerEvent Pointer
* event. * event.
* @private * @private
*/ */
@@ -244,7 +252,12 @@ class MapBrowserEventHandler extends EventTarget {
); );
this.dispatchEvent(newEvent); this.dispatchEvent(newEvent);
this.down_ = pointerEvent; this.down_ = {
type: pointerEvent.type,
clientX: pointerEvent.clientX,
clientY: pointerEvent.clientY,
target: pointerEvent.target,
};
if (this.dragListenerKeys_.length === 0) { if (this.dragListenerKeys_.length === 0) {
const doc = this.map_.getOwnerDocument(); const doc = this.map_.getOwnerDocument();

View File

@@ -682,7 +682,7 @@ class PluggableMap extends BaseObject {
/** /**
* Returns the map pixel position for a browser event relative to the viewport. * Returns the map pixel position for a browser event relative to the viewport.
* @param {UIEvent} event Event. * @param {UIEvent|import("./MapBrowserEventHandler").PointerEventData} event Event.
* @return {import("./pixel.js").Pixel} Pixel. * @return {import("./pixel.js").Pixel} Pixel.
* @api * @api
*/ */
@@ -944,9 +944,8 @@ class PluggableMap extends BaseObject {
* @return {!Document} The document where the map is displayed. * @return {!Document} The document where the map is displayed.
*/ */
getOwnerDocument() { getOwnerDocument() {
return this.getTargetElement() const targetElement = this.getTargetElement();
? this.getTargetElement().ownerDocument return targetElement ? targetElement.ownerDocument : document;
: document;
} }
/** /**
@@ -992,17 +991,7 @@ class PluggableMap extends BaseObject {
eventType === EventType.WHEEL || eventType === EventType.WHEEL ||
eventType === EventType.KEYDOWN eventType === EventType.KEYDOWN
) { ) {
const doc = this.getOwnerDocument(); const target = /** @type {Node} */ (originalEvent.target);
const rootNode = this.viewport_.getRootNode
? this.viewport_.getRootNode()
: doc;
const target =
'host' in rootNode // ShadowRoot
? /** @type {ShadowRoot} */ (rootNode).elementFromPoint(
originalEvent.clientX,
originalEvent.clientY
)
: /** @type {Node} */ (originalEvent.target);
if ( if (
// Abort if the target is a child of the container for elements whose events are not meant // Abort if the target is a child of the container for elements whose events are not meant
// to be handled by map interactions. // to be handled by map interactions.
@@ -1011,7 +1000,7 @@ class PluggableMap extends BaseObject {
// It's possible for the target to no longer be in the page if it has been removed in an // It's possible for the target to no longer be in the page if it has been removed in an
// event listener, this might happen in a Control that recreates it's content based on // event listener, this might happen in a Control that recreates it's content based on
// user interaction either manually or via a render in something like https://reactjs.org/ // user interaction either manually or via a render in something like https://reactjs.org/
!(rootNode === doc ? doc.documentElement : rootNode).contains(target) !this.getOwnerDocument().contains(target)
) { ) {
return; return;
} }

View File

@@ -94,10 +94,16 @@ describe('ol/MapBrowserEventHandler', function () {
expect(handler.down_).to.be(null); expect(handler.down_).to.be(null);
}); });
it('is an event after handlePointerDown_ has been called', function () { it('is properly set after handlePointerDown_ has been called', function () {
const event = new OlEvent('pointerdown'); const event = new OlEvent('pointerdown');
event.clientX = 42;
event.clientY = 666;
event.target = 'foo';
handler.handlePointerDown_(event); handler.handlePointerDown_(event);
expect(handler.down_).to.be(event); expect(handler.down_.type).to.be('pointerdown');
expect(handler.down_.clientX).to.be(42);
expect(handler.down_.clientY).to.be(666);
expect(handler.down_.target).to.be('foo');
}); });
}); });