utils/delegateEvent.js

/**
 * Set up a parent element to watch for events on children.
 * Useful for binding events to elements which may not yet be on the page.
 *
 * @module delegateEvent
 * @param {string} scopeSelector - selector for the parent element that will serve as delegator
 * @param {string} eventType - event type to listen for
 * @param {string} selector - selector for child elements to delegate to
 * @param {function} handler - callback function if event is triggered
 * @param {boolean} bubbling - whether or not the event bubbles up to the parent
 * @param {boolean} multiple - whether or not the selector should return an array of items
 */
const delegateEvent = (
	scopeSelector,
	eventType,
	selector,
	handler,
	bubbling = true,
	multiple = false,
) => {
	const $scopeElem = document.querySelector( scopeSelector );

	if ( $scopeElem ) {
		$scopeElem.addEventListener( eventType, ( e ) => {
			let $target;

			if ( bubbling ) {
				// Event bubbles up to the parent, search for the closest parent element
				$target = e.target.closest( selector );
			} else {
				// Event doesn't bubble up to the parent element, search for the child element
				$target = e.target.querySelectorAll( selector );
				if ( ! multiple ) {
					$target = $target.length > 0 ? $target[0] : false;
				}
			}

			if ( $target ) {
				handler( e, $target );
			}
		});
	}
};

export default delegateEvent;