UNPKG

@exadel/esl

Version:

Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components

73 lines (72 loc) 3.22 kB
import { isElement } from './api'; /** Checks if element matches passed selector or exact predicate function */ export const isMatches = (el, matcher) => { if (typeof matcher === 'string') return !matcher || el.matches(matcher); if (typeof matcher === 'function') return matcher.call(el, el); return typeof matcher === 'undefined'; }; /** Safely checks if the target element is within the container element */ export const isSafeContains = (container, element) => { return isElement(element) && isElement(container) && container.contains(element); }; export function isRelativeNode(nodeA, nodeB) { if (!isElement(nodeA) || !isElement(nodeB)) return false; return nodeA.contains(nodeB) || nodeB.contains(nodeA); } /** Creates function that finds next dom element, that matches selector, in the sequence declared by `next` function */ export const createSequenceFinder = (next, includeSelf = false) => { return function (base, predicate) { if (includeSelf && isMatches(base, predicate)) return base; for (let target = next(base); target && target !== base; target = next(target)) { if (isMatches(target, predicate)) return target; } return null; }; }; /** @returns first matching next sibling or null*/ export const findNext = createSequenceFinder((el) => el.nextElementSibling); /** @returns first matching previous sibling or null*/ export const findPrev = createSequenceFinder((el) => el.previousElementSibling); /** @returns first matching parent or null*/ export const findParent = createSequenceFinder((el) => el.parentElement); /** @returns first matching ancestor starting from passed element or null*/ export const findClosest = createSequenceFinder((el) => el.parentElement, true); /** @returns first matching host element starting from passed element*/ export const findHost = createSequenceFinder((el) => { const root = el.getRootNode(); return (root instanceof ShadowRoot) ? root.host : null; }, true); /** @returns Array of all matching elements in subtree or empty array */ export const findAll = (base, sel) => { return sel ? Array.from(base.querySelectorAll(sel)) : [base]; }; /** @returns Array of all matching children or empty array */ export const findChildren = (base, sel) => { return Array.from(base.children).filter((el) => !sel || el.matches(sel)); }; /** * Finds closest parent node of `node` by `predicate`. * Optional `skipSelf` to skip initial node */ export const findClosestBy = (node, predicate, skipSelf = false) => { let current = skipSelf && node ? node.parentNode : node; while (current) { if (predicate(current)) return current; current = current.parentNode; } return null; }; /** * Finds looped next element within parent circle */ export const findNextLooped = createSequenceFinder((el) => el.nextElementSibling || (el.parentElement && el.parentElement.firstElementChild)); /** * Finds looped previous element within parent circle (looped) */ export const findPrevLooped = createSequenceFinder((el) => el.previousElementSibling || (el.parentElement && el.parentElement.lastElementChild));