UNPKG

select-dom

Version:

Extra lightweight DOM selector helper

101 lines (100 loc) 4.17 kB
// Type predicate for TypeScript function isQueryable(object) { return typeof object.querySelectorAll === 'function'; } function $(selectors, baseElement) { // Shortcut with specified-but-null baseElement if (arguments.length === 2 && !baseElement) { return; } return (baseElement ?? document).querySelector(String(selectors)) ?? undefined; } export class ElementNotFoundError extends Error { name = 'ElementNotFoundError'; } function expectElement(selectors, baseElement) { // Shortcut with specified-but-null baseElement if (arguments.length === 2 && !baseElement) { throw new ElementNotFoundError('Expected element not found because the base is specified but null'); } const element = (baseElement ?? document).querySelector(String(selectors)); if (element) { return element; } throw new ElementNotFoundError(`Expected element not found: ${String(selectors)}`); } function lastElement(selectors, baseElement) { // Shortcut with specified-but-null baseElement if (arguments.length === 2 && !baseElement) { return undefined; } const all = (baseElement ?? document).querySelectorAll(String(selectors)); // eslint-disable-next-line unicorn/prefer-at -- Not an Array, not worth converting it return all[all.length - 1]; } /** * @param selectors One or more CSS selectors separated by commas * @param [baseElement] The element to look inside of * @return Whether it's been found */ function elementExists(selectors, baseElement) { // Shortcut with specified-but-null baseElement if (arguments.length === 2 && !baseElement) { return false; } return Boolean((baseElement ?? document).querySelector(String(selectors))); } /** * @param selectors One or more CSS selectors separated by commas * @param [baseElement] The element to look inside of * @return The number of elements found */ function countElements(selectors, baseElement) { // Shortcut with specified-but-null baseElement if (arguments.length === 2 && !baseElement) { return 0; } return (baseElement ?? document).querySelectorAll(String(selectors)).length; } function $$(selectors, baseElements) { // Shortcut with specified-but-null baseElements if (arguments.length === 2 && !baseElements) { return []; } // Can be: select.all('selectors') or select.all('selectors', singleElementOrDocument) if (!baseElements || isQueryable(baseElements)) { const elements = (baseElements ?? document).querySelectorAll(String(selectors)); return Array.prototype.slice.call(elements); } const elements = new Set(); for (const baseElement of baseElements) { for (const element of baseElement.querySelectorAll(String(selectors))) { elements.add(element); } } return [...elements]; // Convert to array } function expectElements(selectors, baseElements) { // Shortcut with specified-but-null baseElements if (arguments.length === 2 && !baseElements) { throw new ElementNotFoundError('Expected elements not found because the base is specified but null'); } const elements = arguments.length === 2 ? $$(selectors, baseElements) : $$(selectors); if (elements.length > 0) { return elements; } throw new ElementNotFoundError(`Expected elements not found: ${String(selectors)}`); } function expectLastElement(selectors, baseElement) { // Shortcut with specified-but-null baseElements if (arguments.length === 2 && !baseElement) { throw new ElementNotFoundError('Expected element not found because the base is specified but null'); } const all = (baseElement ?? document).querySelectorAll(String(selectors)); if (all.length > 0) { // eslint-disable-next-line unicorn/prefer-at -- Not an Array, not worth converting it return all[all.length - 1]; } throw new ElementNotFoundError(`Expected element not found: ${String(selectors)}`); } export { $, $$, lastElement, elementExists, countElements, expectElement, expectElements, expectLastElement, };