diff --git a/src/ol/Observable.js b/src/ol/Observable.js index b4d548a43b..347e131c73 100644 --- a/src/ol/Observable.js +++ b/src/ol/Observable.js @@ -51,7 +51,7 @@ class Observable extends EventTarget { /** * Listen for a certain type of event. * @param {string|Array} type The event type or array of event types. - * @param {function(?): ?} listener The listener function. + * @param {import("./events.js").ListenerFunction} listener The listener function. * @return {import("./events.js").EventsKey|Array} Unique key for the listener. If * called with an array of event types as the first argument, the return * will be an array of keys. diff --git a/src/ol/events.js b/src/ol/events.js index 5a64a185ce..f234e82dca 100644 --- a/src/ol/events.js +++ b/src/ol/events.js @@ -13,7 +13,6 @@ import {clear} from './obj.js'; * @api */ - /** * Listener function. This function is called with an event object as argument. * When the function returns `false`, event propagation will stop. @@ -22,6 +21,14 @@ import {clear} from './obj.js'; * @api */ +/** + * @typedef {Object} ListenerObject + * @property {ListenerFunction} handleEvent + */ + +/** + * @typedef {ListenerFunction|ListenerObject} Listener + */ /** * Registers an event listener on an event target. Inspired by diff --git a/src/ol/events/Target.js b/src/ol/events/Target.js index 766a954479..7ea0ccf929 100644 --- a/src/ol/events/Target.js +++ b/src/ol/events/Target.js @@ -56,7 +56,7 @@ class Target extends Disposable { /** * @private - * @type {!Object>} + * @type {!Object>} */ this.listeners_ = {}; @@ -64,7 +64,7 @@ class Target extends Disposable { /** * @param {string} type Type. - * @param {import("../events.js").ListenerFunction} listener Listener. + * @param {import("../events.js").Listener} listener Listener. */ addEventListener(type, listener) { if (!type || !listener) { @@ -85,15 +85,13 @@ class Target extends Disposable { * of this type. The event parameter can either be a string or an * Object with a `type` property. * - * @param {{type: string, - * target: (EventTargetLike|undefined), - * propagationStopped: (boolean|undefined)}| - * import("./Event.js").default|string} event Event object. + * @param {import("./Event.js").default|string} event Event object. * @return {boolean|undefined} `false` if anyone called preventDefault on the * event object or if any of the listeners returned false. * @api */ dispatchEvent(event) { + /** @type {import("./Event.js").default|Event} */ const evt = typeof event === 'string' ? new Event(event) : event; const type = evt.type; if (!evt.target) { @@ -108,7 +106,12 @@ class Target extends Disposable { } ++this.dispatching_[type]; for (let i = 0, ii = listeners.length; i < ii; ++i) { - if (listeners[i].call(this, evt) === false || evt.propagationStopped) { + if ('handleEvent' in listeners[i]) { + propagate = /** @type {import("../events.js").ListenerObject} */ (listeners[i]).handleEvent(evt); + } else { + propagate = /** @type {import("../events.js").ListenerFunction} */ (listeners[i]).call(this, evt); + } + if (propagate === false || evt.propagationStopped) { propagate = false; break; } @@ -138,7 +141,7 @@ class Target extends Disposable { * order that they will be called in. * * @param {string} type Type. - * @return {Array} Listeners. + * @return {Array} Listeners. */ getListeners(type) { return this.listeners_[type]; @@ -157,7 +160,7 @@ class Target extends Disposable { /** * @param {string} type Type. - * @param {import("../events.js").ListenerFunction} listener Listener. + * @param {import("../events.js").Listener} listener Listener. */ removeEventListener(type, listener) { const listeners = this.listeners_[type];