UNPKG

@schukai/monster

Version:

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

241 lines (213 loc) 6.12 kB
/** * Copyright © schukai GmbH 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 schukai GmbH. */ import { instanceSymbol } from "../../constants.mjs"; import { addAttributeToken, hasObjectLink } from "../../dom/attributes.mjs"; import { ATTRIBUTE_ERRORMESSAGE, ATTRIBUTE_ROLE, customElementUpdaterLinkSymbol, } from "../../dom/constants.mjs"; import { CustomControl } from "../../dom/customcontrol.mjs"; import { CustomElement } from "../../dom/customelement.mjs"; import { assembleMethodSymbol, registerCustomElement, } from "../../dom/customelement.mjs"; import { findTargetElementFromEvent } from "../../dom/events.mjs"; import { isFunction } from "../../types/is.mjs"; import { MonitorAttributeErrorsStyleSheet } from "./stylesheet/monitor-attribute-errors.mjs"; import { fireCustomEvent } from "../../dom/events.mjs"; import { getDocument } from "../../dom/util.mjs"; import { clone } from "../../util/clone.mjs"; export { MonitorAttributeErrors }; /** * @private * @type {symbol} */ const mutationObserversSymbol = Symbol("mutationObservers"); /** * A MonitorAttributeErrors * * @fragments /fragments/components/notify/monitor-attribute-errors/ * * @example /examples/components/notify/monitor-attribute-errors-simple * * @since 3.98.0 * @copyright schukai GmbH * @summary A beautiful MonitorAttributeErrors that can make your life easier and also looks good. */ class MonitorAttributeErrors extends CustomElement { /** * This method is called by the `instanceof` operator. * @returns {symbol} */ static get [instanceSymbol]() { return Symbol.for( "@schukai/monster/components/notify/monitor-attribute-errors@@instance", ); } /** * * @return {Components.Notify.MonitorAttributeErrors */ [assembleMethodSymbol]() { super[assembleMethodSymbol](); return this; } /** * @return {void} */ connectedCallback() { super.connectedCallback(); setupMutationObserver.call(this, getDocument()); } /** * @return {void} */ disconnectedCallback() { super.disconnectedCallback(); deactivateAllObservers.call(this); } /** * To set the options via the HTML Tag, the attribute `data-monster-options` must be used. * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control} * * The individual configuration values can be found in the table. * * @property {Object} templates Template definitions * @property {string} templates.main Main template * @property {Object} features Features * @property {boolean} features.notifyUser Notify user (monster-notify control is required) * @property {Object} notifyUser Notify user * @property {string} notifyUser.selector Selector for the notify user control (feature notifyUser must be enabled) */ get defaults() { return Object.assign({}, super.defaults, { templates: { main: getTemplate(), }, features: { notifyUser: false, }, notifyUser: { selector: "monster-notify", }, actions: { click: () => { throw new Error("the click action is not defined"); }, }, }); } /** * @return {string} */ static getTag() { return "monster-monitor-attribute-errors"; } /** * @return {CSSStyleSheet[]} */ static getCSSStyleSheet() { return [MonitorAttributeErrorsStyleSheet]; } } /** * @private * @param root */ function setupMutationObserver(root) { const self = this; if (!this?.[mutationObserversSymbol]) { this[mutationObserversSymbol] = []; } const config = { childList: true, subtree: true, attributes: true, attributeFilter: ["data-monster-error"], }; const callback = (mutationsList, observer) => { for (const mutation of mutationsList) { if (mutation.type === "childList") { mutation.addedNodes.forEach((node) => { checkNodeForErrors(node); observeShadowRoots(node); }); } if ( mutation.type === "attributes" && mutation.attributeName === "data-monster-error" ) { const node = mutation.target; checkNodeForErrors(node); } } }; const observer = new MutationObserver(callback); observer.observe(root, config); this[mutationObserversSymbol].push(observer); // Speichert den Observer root.querySelectorAll("*").forEach((node) => { checkNodeForErrors(node); observeShadowRoots(node); }); function checkNodeForErrors(node) { if (node.nodeType === 1 && node.hasAttribute("data-monster-error")) { const fktOpen = console.groupCollapsed || console.group || console.log || function () {}; const fktLog = console.log || function () {}; const fktClose = console.groupEnd || function () {}; fktOpen("MonitorAttributeErrors " + node.tagName); fktLog(node); const errors = node.getAttribute("data-monster-error").split("::"); errors.forEach((error) => { fktLog(error); }); fktClose(); if (self.getOption("features.notifyUser")) { const notifyUser = getDocument().querySelector( self.getOption("notifyUser.selector"), ); if (notifyUser) { notifyUser.push(node.getAttribute("data-monster-error")); } } } } function observeShadowRoots(node) { if ( node.nodeType === 1 && node.shadowRoot && node.shadowRoot.mode === "open" ) { setupMutationObserver.call(self, node.shadowRoot); } } } function deactivateAllObservers() { this[mutationObserversSymbol].forEach((observer) => { observer.disconnect(); }); this[mutationObserversSymbol] = []; } /** * @private * @return {string} */ function getTemplate() { // language=HTML return `<div></div>`; } registerCustomElement(MonitorAttributeErrors);