Skip to content
Snippets Groups Projects
Select Git revision
  • 76a16f062adbe0635cb5db9acab669d9c3fffb9d
  • master default protected
  • 1.31
  • 4.24.3
  • 4.24.2
  • 4.24.1
  • 4.24.0
  • 4.23.6
  • 4.23.5
  • 4.23.4
  • 4.23.3
  • 4.23.2
  • 4.23.1
  • 4.23.0
  • 4.22.3
  • 4.22.2
  • 4.22.1
  • 4.22.0
  • 4.21.0
  • 4.20.1
  • 4.20.0
  • 4.19.0
  • 4.18.0
23 results

context-help.mjs

Blame
  • field-set.mjs 8.37 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 { addAttributeToken } from "../../dom/attributes.mjs";
    import {
    	ATTRIBUTE_ERRORMESSAGE,
    	ATTRIBUTE_ROLE,
    } from "../../dom/constants.mjs";
    import { CustomControl } from "../../dom/customcontrol.mjs";
    import {
    	assembleMethodSymbol,
    	getSlottedElements,
    	registerCustomElement,
    } from "../../dom/customelement.mjs";
    import { isFunction } from "../../types/is.mjs";
    import { FieldSetStyleSheet } from "./stylesheet/field-set.mjs";
    import "../layout/collapse.mjs";
    import "./toggle-switch.mjs";
    
    export { FieldSet };
    
    /**
     * @private
     * @type {symbol}
     */
    const fieldSetElementSymbol = Symbol("fieldSetElement");
    
    /**
     * @private
     * @type {symbol}
     */
    const collapseElementSymbol = Symbol("collapseElement");
    
    /**
     * @private
     * @type {symbol}
     */
    const extendedSwitchSymbol = Symbol("extendedSwitch");
    
    /**
     * @private
     * @type {symbol}
     */
    const headerElementSymbol = Symbol("headerElement");
    
    /**
     * @private
     * @type {symbol}
     */
    const toggleSwitchElementSymbol = Symbol("toggleSwitchElement");
    
    /**
     * @private
     * @type {symbol}
     */
    const extendedSwitchElementSymbol = Symbol("extendedSwitchElement");
    
    /**
     * A field set control that can be used to group form elements.
     *
     * @fragments /fragments/components/form/field-set/
     *
     * @example /examples/components/form/field-set-simple
     *
     * @since 3.65.0
     * @copyright schukai GmbH
     * @summary A field set control
     */
    class FieldSet extends CustomControl {
    	/**
    	 * This method is called by the `instanceof` operator.
    	 * @returns {symbol}
    	 */
    	static get [instanceSymbol]() {
    		return Symbol.for("@schukai/monster/components/form/fieldset@@instance");
    	}
    
    	/**
    	 * @return {Components.Form.FieldSet
    	 */
    	[assembleMethodSymbol]() {
    		super[assembleMethodSymbol]();
    		initControlReferences.call(this);
    		initEventHandler.call(this);
    		updateExtendedFields.call(this);
    		updateColumns.call(this);
    		return 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} labels Label definitions
    	 * @property {Object} actions Callbacks
    	 * @property {string} actions.click="throw Error" Callback when clicked
    	 * @property {Object} features Features
    	 * @property {boolean} features.multipleColumns=true Multiple columns
    	 * @property {Object} classes CSS classes
    	 * @property {boolean} disabled=false Disabled state
    	 */
    	get defaults() {
    		return Object.assign({}, super.defaults, {
    			templates: {
    				main: getTemplate(),
    			},
    			labels: {
    				toggleSwitchOn: "✔",
    				toggleSwitchOff: "✖",
    				toggleSwitchLabel: "Expand",
    				title: "",
    			},
    			classes: {},
    			disabled: false,
    			features: {
    				multipleColumns: true,
    			},
    			actions: {
    				click: () => {
    					throw new Error("the click action is not defined");
    				},
    			},
    			value: null,
    		});
    	}
    
    	/**
    	 *
    	 * @return {string}
    	 */
    	static getTag() {
    		return "monster-field-set";
    	}
    
    	/**
    	 *
    	 * @return {CSSStyleSheet[]}
    	 */
    	static getCSSStyleSheet() {
    		return [FieldSetStyleSheet];
    	}
    
    	/**
    	 * The FieldSet.click() method simulates a click on the internal element.
    	 *
    	 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click}
    	 */
    	click() {
    		if (this.getOption("disabled") === true) {
    			return;
    		}
    
    		if (
    			this[fieldSetElementSymbol] &&
    			isFunction(this[fieldSetElementSymbol].click)
    		) {
    			this[fieldSetElementSymbol].click();
    		}
    	}
    
    	/**
    	 * The Button.focus() method sets focus on the internal element.
    	 *
    	 * @param {Object} options
    	 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus}
    	 */
    	focus(options) {
    		if (this.getOption("disabled") === true) {
    			return;
    		}
    
    		if (
    			this[fieldSetElementSymbol] &&
    			isFunction(this[fieldSetElementSymbol].focus)
    		) {
    			this[fieldSetElementSymbol].focus(options);
    		}
    	}
    
    	/**
    	 * The Button.blur() method removes focus from the internal element.
    	 */
    	blur() {
    		if (
    			this[fieldSetElementSymbol] &&
    			isFunction(this[fieldSetElementSymbol].blur)
    		) {
    			this[fieldSetElementSymbol].blur();
    		}
    	}
    
    	/**
    	 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals}
    	 * @return {boolean}
    	 */
    	static get formAssociated() {
    		return true;
    	}
    
    	/**
    	 * The current value of the form control.
    	 *
    	 * ```js
    	 * e = document.querySelector('monster-field-set');
    	 * console.log(e.value)
    	 * ```
    	 *
    	 * @property {string}
    	 */
    	get value() {
    		return this.getOption("value");
    	}
    
    	/**
    	 * Set the value of the form control.
    	 *
    	 * ```
    	 * e = document.querySelector('monster-field-set');
    	 * e.value=1
    	 * ```
    	 *
    	 * @property {string} value
    	 * @throws {Error} unsupported type
    	 */
    	set value(value) {
    		this.setOption("value", value);
    		try {
    			this?.setFormValue(this.value);
    		} catch (e) {
    			addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
    		}
    	}
    }
    
    /**
     * @private
     */
    function updateExtendedFields() {
    	const nodes = getSlottedElements.call(this, "", "extended");
    	if (nodes.size > 0) {
    		this[extendedSwitchSymbol].classList.remove("hidden");
    	} else {
    		this[extendedSwitchSymbol].classList.add("hidden");
    	}
    }
    
    /**
     * @private
     */
    function updateColumns() {
    	if (this.getOption("features.multipleColumns") !== true) {
    		this[fieldSetElementSymbol].classList.remove("multiple-columns");
    		return;
    	}
    	
    	this[fieldSetElementSymbol].classList.add("multiple-columns");
    	
    }
    
    /**
     * @private
     * @return {initEventHandler}
     * @fires event:monster-field-set-clicked
     */
    function initEventHandler() {
    	this[toggleSwitchElementSymbol].setOption(
    		"labels.toggleSwitchOn",
    		this.getOption("labels.toggleSwitchOn"),
    	);
    	this[toggleSwitchElementSymbol].setOption(
    		"labels.toggleSwitchOff",
    		this.getOption("labels.toggleSwitchOff"),
    	);
    
    	this[toggleSwitchElementSymbol].setOption("actions.on", () => {
    		this[collapseElementSymbol].open();
    	});
    
    	this[toggleSwitchElementSymbol].setOption("actions.off", () => {
    		this[collapseElementSymbol].close();
    	});
    
    	return this;
    }
    
    /**
     * @private
     */
    function initControlReferences() {
    	this[fieldSetElementSymbol] = this.shadowRoot.querySelector(
    		`[${ATTRIBUTE_ROLE}="control"]`,
    	);
    
    	this[extendedSwitchElementSymbol] = this.shadowRoot.querySelector(
    		`[${ATTRIBUTE_ROLE}="extended-switch"]`,
    	);
    
    	this[collapseElementSymbol] = this.shadowRoot.querySelector(
    		`[${ATTRIBUTE_ROLE}="collapse"]`,
    	);
    
    	this[headerElementSymbol] = this.shadowRoot.querySelector(
    		`[${ATTRIBUTE_ROLE}="header"]`,
    	);
    
    	this[extendedSwitchSymbol] = this.shadowRoot.querySelector(
    		`[${ATTRIBUTE_ROLE}="extended-switch"]`,
    	);
    
    	this[toggleSwitchElementSymbol] = this.shadowRoot.querySelector(
    		`monster-toggle-switch`,
    	);
    }
    
    /**
     * @private
     * @return {string}
     */
    function getTemplate() {
    	// language=HTML
    	return `
            <div data-monster-role="control" part="control">
                <div data-monster-role="header">
                    <div data-monster-replace="path:labels.title" data-monster-role="title"></div>
                    <div data-monster-role="extended-switch">
                        <label data-monster-replace="path:labels.toggle-switch-label"></label>
                        <monster-toggle-switch></monster-toggle-switch>
                    </div>
                </div>
                <div data-monster-role="container">
                    <div class="collapse-alignment">
                        <slot part="content"></slot>
                    </div>
                    <monster-collapse data-monster-role="collapse">
                        <slot name="extended" part="extended"></slot>
                    </monster-collapse>
                </div>
            </div>`;
    }
    
    registerCustomElement(FieldSet);