UNPKG

vanillajs-browser-helpers

Version:

Collection of convenience code snippets (helpers) that aims to make it a little easier to work with vanilla JS in the browser

113 lines (89 loc) 3.07 kB
import type { VoidFunction } from './shared/types'; import isEventTarget from './isEventTarget'; import eventOptionsSupported from './eventOptionsSupported'; import on from './on'; import off from './off'; type WhenFunction = (e: Event) => boolean; export interface OnceEventListenerOptions extends AddEventListenerOptions { /** A function that returns a boolean to determine when the event should trigger */ when?: WhenFunction } const manuelOnce = ( elm: EventTarget, handler: EventListenerOrEventListenerObject, when?: WhenFunction ) => { const offHandler = (e: Event) => { if (when && when(e) !== true) { return true; } off(elm as EventTarget, e.type, offHandler); return 'handleEvent' in handler ? handler.handleEvent(e) : (handler as EventListener)(e); }; return offHandler; }; const bind = ( elm: EventTarget, eventNames: string | string[], handler: EventListenerOrEventListenerObject, options?: OnceEventListenerOptions ): VoidFunction => { const noOptions = !eventOptionsSupported(); const { when, ...eventOptions } = options || {}; eventOptions.once = !when; const eventHandler = when || noOptions ? manuelOnce(elm, handler, when) : handler; on(elm, eventNames, eventHandler, eventOptions); return () => off(elm, eventNames, eventHandler, eventOptions); }; /** * Bind a single fire event handler for one or more event names on a DOM element. * (Add `when` to the options to conditional trigger the event) * * @param elm - DOM element to bind the event to * @param eventNames - Event names to bind the handler to * @param handler - Handler to bind to the event * @param options - Options to pass to the 'addEventListener' * @return A function to remove the handler again */ function once( elm: EventTarget, eventNames: string | string[], handler: EventListenerOrEventListenerObject, options?: OnceEventListenerOptions ): VoidFunction; /** * Bind a single fire event handler for one or more event names on `document`. * (Add `when` to the options to conditional trigger the event) * * @param eventNames - Event names to bind the handler to * @param handler - Handler to bind to the event * @param options - Options to pass to the 'addEventListener' * @return A function to remove the handler again */ function once( eventNames: string | string[], handler: EventListenerOrEventListenerObject, options?: OnceEventListenerOptions ): VoidFunction; function once( elm: EventTarget | string | string[], eventNames: string | string[] | EventListenerOrEventListenerObject, handler?: EventListenerOrEventListenerObject | OnceEventListenerOptions, options?: OnceEventListenerOptions ): VoidFunction { if (!isEventTarget(elm)) { options = handler as OnceEventListenerOptions; handler = eventNames as EventListenerOrEventListenerObject; eventNames = elm; elm = document; } return bind( elm, eventNames as string | string[], handler as EventListenerOrEventListenerObject, options ); } export default once;