UNPKG

@schukai/monster

Version:

Monster is a simple library for creating fast, robust and lightweight websites.

146 lines (130 loc) 4.22 kB
/** * Copyright © Volker Schukai and all contributing authors, {{copyRightYear}}. All rights reserved. * Node module: @schukai/monster * * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3). * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html * * For those who do not wish to adhere to the AGPLv3, a commercial license is available. * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms. * For more information about purchasing a commercial license, please contact Volker Schukai. * * SPDX-License-Identifier: AGPL-3.0 */ import { isArray, isObject } from "../types/is.mjs"; import { validateInstance, validateString } from "../types/validate.mjs"; import { getDocument } from "./util.mjs"; export { fireEvent, fireCustomEvent, findTargetElementFromEvent }; /** * The function sends an event * * @param {Element | Node | HTMLCollection | NodeList} element * @param {string} type * @return {void} * @license AGPLv3 * @since 1.10.0 * @copyright Volker Schukai * @throws {TypeError} value is not an instance of HTMLElement or HTMLCollection * @summary Construct and send and event */ function fireEvent(element, type) { const document = getDocument(); if (element instanceof HTMLElement) { if (type === "click") { element.click(); return; } // https://developer.mozilla.org/en-US/docs/Web/API/Event/Event const event = new Event(validateString(type), { bubbles: true, cancelable: true, composed: true, }); element.dispatchEvent(event); } else if (element instanceof HTMLCollection || element instanceof NodeList) { for (const e of element) { fireEvent(e, type); } } else { throw new TypeError( "value is not an instance of HTMLElement or HTMLCollection", ); } } /** * You can call the function via the monster namespace `new Monster.DOM.fireCustomEvent()`. * * @param {Element | Node | HTMLCollection | NodeList} element * @param {string} type * @param {object} detail * @return {void} * @license AGPLv3 * @since 1.29.0 * @copyright Volker Schukai * @throws {TypeError} value is not an instance of HTMLElement or HTMLCollection * @summary Construct and send and event */ function fireCustomEvent(element, type, detail) { if ( element instanceof HTMLElement || (element && typeof element === "object" && typeof element.dispatchEvent === "function") ) { if (!isObject(detail)) { detail = { detail }; } const event = new CustomEvent(validateString(type), { bubbles: true, cancelable: true, composed: true, detail, }); element.dispatchEvent(event); } else if (element instanceof HTMLCollection || element instanceof NodeList) { for (const e of element) { fireCustomEvent(e, type, detail); } } else { throw new TypeError( "element is not an instance of HTMLElement or HTMLCollection", ); } } /** * This function gets the path `Event.composedPath()` from an event and tries to find the next element * up the tree `element.closest()` with the attribute and value. If no value, or a value that is undefined or null, * is specified, only the attribute is searched. * * @license AGPLv3 * @since 1.14.0 * @param {Event} event * @param {string} attributeName * @param {string|null|undefined} attributeValue * @throws {Error} unsupported event * @throws {TypeError} value is not a string * @throws {TypeError} value is not an instance of HTMLElement * @summary Help function to find the appropriate control */ function findTargetElementFromEvent(event, attributeName, attributeValue) { validateInstance(event, Event); if (typeof event.composedPath !== "function") { throw new Error("unsupported event"); } const path = event.composedPath(); // closest cannot be used here, because closest is not correct for slotted elements if (isArray(path)) { for (let i = 0; i < path.length; i++) { const o = path[i]; if ( o instanceof HTMLElement && o.hasAttribute(attributeName) && (attributeValue === undefined || o.getAttribute(attributeName) === attributeValue) ) { return o; } } } return undefined; }