UNPKG

2.13 kBPlain TextView Raw
1/**
2 * Copyright (c) 2017, Philip Walton <philip@philipwalton.com>
3 */
4
5import { JS } from '@aws-amplify/core';
6
7const proto =
8 JS.browserOrNode().isBrowser && window['Element']
9 ? window['Element'].prototype
10 : null;
11
12const nativeMatches = proto
13 ? proto.matches ||
14 // @ts-ignore
15 proto.matchesSelector ||
16 // @ts-ignore
17 proto.webkitMatchesSelector ||
18 // @ts-ignore
19 proto.mozMatchesSelector ||
20 // @ts-ignore
21 proto.msMatchesSelector ||
22 // @ts-ignore
23 proto.oMatchesSelector
24 : null;
25
26/**
27 * Tests if a DOM elements matches any of the test DOM elements or selectors.
28 * @param {Element} element The DOM element to test.
29 * @param {Element|string|Array<Element|string>} test A DOM element, a CSS
30 * selector, or an array of DOM elements or CSS selectors to match against.
31 * @return {boolean} True of any part of the test matches.
32 */
33export function matches(element, test) {
34 // Validate input.
35 if (element && element.nodeType === 1 && test) {
36 // if test is a string or DOM element test it.
37 if (typeof test === 'string' || test.nodeType === 1) {
38 return (
39 element === test || matchesSelector(element, /** @type {string} */ test)
40 );
41 } else if ('length' in test) {
42 // if it has a length property iterate over the items
43 // and return true if any match.
44 for (let i = 0, item; (item = test[i]); i++) {
45 if (element === item || matchesSelector(element, item)) return true;
46 }
47 }
48 }
49 // Still here? Return false
50 return false;
51}
52
53/**
54 * Tests whether a DOM element matches a selector. This polyfills the native
55 * Element.prototype.matches method across browsers.
56 * @param {!Element} element The DOM element to test.
57 * @param {string} selector The CSS selector to test element against.
58 * @return {boolean} True if the selector matches.
59 */
60function matchesSelector(element, selector) {
61 if (typeof selector !== 'string') return false;
62 if (nativeMatches) return nativeMatches.call(element, selector);
63 const nodes = element.parentNode.querySelectorAll(selector);
64 for (let i = 0, node; (node = nodes[i]); i++) {
65 if (node === element) return true;
66 }
67 return false;
68}