Skip to content
Snippets Groups Projects
Select Git revision
  • 6fbc6057a289b1a66c956ddd45f1e2f8eaa21850
  • master default protected
  • 1.31
  • 4.34.1
  • 4.34.0
  • 4.33.1
  • 4.33.0
  • 4.32.2
  • 4.32.1
  • 4.32.0
  • 4.31.0
  • 4.30.1
  • 4.30.0
  • 4.29.1
  • 4.29.0
  • 4.28.0
  • 4.27.0
  • 4.26.0
  • 4.25.5
  • 4.25.4
  • 4.25.3
  • 4.25.2
  • 4.25.1
23 results

api-button.mjs

Blame
  • context-error.mjs 6.88 KiB
    /**
     * 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.
     *
     * SPDX-License-Identifier: AGPL-3.0
     */
    
    import { instanceSymbol } from "../../constants.mjs";
    import {
    	assembleMethodSymbol,
    	registerCustomElement,
    } from "../../dom/customelement.mjs";
    import { ContextErrorStyleSheet } from "./stylesheet/context-error.mjs";
    import { ThemeStyleSheet } from "../stylesheet/theme.mjs";
    import { Popper } from "../layout/popper.mjs";
    import {
    	ATTRIBUTE_ERRORMESSAGE,
    	ATTRIBUTE_ROLE,
    } from "../../dom/constants.mjs";
    import {addErrorAttribute} from "../../dom/error.mjs";
    
    export { ContextError };
    
    /**
     * @private
     * @type {symbol}
     */
    const controlElementSymbol = Symbol("controlElement");
    
    /**
     * @private
     * @type {symbol}
     */
    const buttonElementSymbol = Symbol("buttonElement");
    
    /**
     * local symbol
     * @private
     * @type {symbol}
     */
    const popperElementSymbol = Symbol("popperElement");
    
    /**
     * local symbol
     * @private
     * @type {symbol}
     */
    const iconElementSymbol = Symbol("iconElement");
    
    /**
     * A context error control.
     *
     * @fragments /fragments/components/form/context-error
     *
     * @example /examples/components/form/context-error-simple
     *
     * @since 3.55.0
     * @copyright schukai GmbH
     * @summary A context error control
     */
    class ContextError extends Popper {
    	/**
    	 * This method is called by the `instanceof` operator.
    	 *
    	 * @return {symbol}
    	 */
    	static get [instanceSymbol]() {
    		return Symbol.for(
    			"@schukai/monster/components/form/context-error@@instance",
    		);
    	}
    
    	/**
    	 *
    	 * @return {void}
    	 */
    	[assembleMethodSymbol]() {
    		super[assembleMethodSymbol]();
    		initControlReferences.call(this);
    
    		setTimeout(() => {
    			if (this.hasErrorMessage()) {
    				this[iconElementSymbol].classList.remove("hidden");
    			}
    		}, 1000);
    	}
    
    	/**
    	 * 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 The templates for the control.
    	 * @property {string} templates.main The main template.
    	 * @property {string} mode The mode of the popper. Possible values are `click`, `enter` and `hover`.
    	 * @property {string} content The content of the popper.
    	 * @property {object} popper The popper options.
    	 * @property {string} popper.placement The placement of the popper. Possible values are `top`, `bottom`, `left`, `right`, `auto`, `auto-start`, `auto-end`, `top-start`, `top-end`, `bottom-start`, `bottom-end`, `right-start`, `right-end`, `left-start`, `left-end`.
    	 */
    	get defaults() {
    		return Object.assign({}, super.defaults, {
    			templates: {
    				main: getTemplate(),
    			},
    			mode: "auto",
    
    			content: "<slot></slot>",
    
    			classes: {
    				button: "monster-theme-error-2",
    			},
    		});
    	}
    
    	/**
    	 *
    	 * @return {ContextError}
    	 */
    	showDialog() {
    		if (!this.hasErrorMessage()) {
    			return this;
    		}
    
    		super.showDialog();
    		return this;
    	}
    
    	/**
    	 *
    	 * @return {ContextError}
    	 */
    	hideDialog() {
    		super.hideDialog();
    		return this;
    	}
    
    	/**
    	 *
    	 * @param message
    	 * @param show {boolean|number|string} - If true the dialog is shown immediately. If false the dialog is hidden by default. If a number is specified the dialog is shown for the specified time in milliseconds.
    	 * @return {ContextError}
    	 */
    	setErrorMessage(message, show = false) {
    		message = message.trim();
    
    		if (message === "") {
    			return this.resetErrorMessage();
    		}
    
    		this.setOption("content", message);
    		this[iconElementSymbol].classList.remove("hidden");
    
    		if (show === true || show === 1 || show === "true") {
    			this.showDialog();
    			return this;
    		}
    
    		if (show === false || show === 0 || show === "false") {
    			return this;
    		}
    
    		try {
    			const interval = parseInt(show);
    			this.showDialog();
    			setTimeout(() => {
    				this.hideDialog();
    			}, interval);
    		} catch (e) {}
    
    		return this;
    	}
    
    	/**
    	 * Reset the error message.
    	 * @return {ContextError}
    	 */
    	resetErrorMessage() {
    		this.hideDialog();
    		this.setOption("content", "");
    		this[iconElementSymbol].classList.add("hidden");
    		return this;
    	}
    
    	/**
    	 * Returns true if an error message is set.
    	 * @return {boolean}
    	 */
    	hasErrorMessage() {
    		const c = this.getOption("content");
    		if (c === "") {
    			return false;
    		}
    
    		if (c === "<slot></slot>") {
    			const sr = this.shadowRoot;
    			if (!sr) {
    				return false;
    			}
    
    			const slot = sr.querySelector("slot");
    			if (!slot) {
    				return false;
    			}
    
    			return this.shadowRoot.querySelector("slot").assignedNodes().length > 0;
    		}
    
    		return true;
    	}
    
    	/**
    	 * Returns the HTML Tag of the control.
    	 *
    	 * @return {string}
    	 */
    	static getTag() {
    		return "monster-context-error";
    	}
    
    	/**
    	 * @return {CSSStyleSheet[]}
    	 */
    	static getCSSStyleSheet() {
    		return [ContextErrorStyleSheet, ThemeStyleSheet];
    	}
    }
    
    /**
     * @private
     * @return {Select}
     */
    function initControlReferences() {
    	this[controlElementSymbol] = this.shadowRoot.querySelector(
    		`[${ATTRIBUTE_ROLE}=control]`,
    	);
    	this[buttonElementSymbol] = this.shadowRoot.querySelector(
    		`[${ATTRIBUTE_ROLE}=button]`,
    	);
    	this[popperElementSymbol] = this.shadowRoot.querySelector(
    		`[${ATTRIBUTE_ROLE}=popper]`,
    	);
    	this[iconElementSymbol] = this.shadowRoot.querySelector(
    		"[data-monster-role=button] svg",
    	);
    }
    
    /**
     * @private
     * @return {string}
     */
    function getTemplate() {
    	// language=HTML
    	return `
            <div data-monster-role="control" part="control">
    
                <div data-monster-role="button"
                     data-monster-attributes="class path:classes.button"
                     part="button">
                    <svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" class="hidden"
                         viewBox="0 0 16 16">
                        <path fill="var(--monster-color-error-2)" d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
                        <path fill="var(--monster-color-error-2)" d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0z"/>
                    </svg>
                </div>
    
                <div data-monster-role="popper" part="popper" tabindex="-1" class="monster-color-primary-1">
                    <div data-monster-role="arrow"></div>
                    <div part="content" class="flex">
                        <div data-monster-replace="path:content"></div>
                    </div>
                </div>
    			
            </div>
        `;
    }
    
    registerCustomElement(ContextError);