dom_get-closest.js

/**
 * @module getClosest
 * @description Gets the closest ancestor that matches a selector string starting from
 * the passed HTMLElement.
 *
 * @since 1.0.0
 *
 * @param {HTMLElement} el       The element to search upwards from.
 * @param {string}      selector The selector string to search for.
 *
 * @return {HTMLElement|null} An HTMLElement of null if not matching parent found.
 *
 * @example
 * import { getClosest } from  "@gravityforms/utils";
 *
 * function Example() {
 *  const node = document.getElementById( 'example' );
 *  const ancestor = getClosest( node, '.some-example-ancestor' );
 * }
 *
 */
export default function getClosest( el, selector ) {
	let matchesFn;
	let parent;

	[
		'matches',
		'webkitMatchesSelector',
		'mozMatchesSelector',
		'msMatchesSelector',
		'oMatchesSelector',
	].some( ( fn ) => {
		if ( typeof document.body[ fn ] === 'function' ) {
			matchesFn = fn;
			return true;
		}
		/* istanbul ignore next */
		return false;
	} );

	while ( el ) {
		parent = el.parentElement;
		if ( parent && parent[ matchesFn ]( selector ) ) {
			return parent;
		}

		el = parent; // eslint-disable-line
	}

	return null;
}