UNPKG

@schukai/monster

Version:

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

118 lines (106 loc) 4.19 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. * * SPDX-License-Identifier: AGPL-3.0 */ import { Pathfinder } from "../../data/pathfinder.mjs"; import { isBoolean, isString, isObject, isArray, isFunction, isInteger, } from "../../types/is.mjs"; import { extractKeys } from "./extract-keys.mjs"; export { initOptionsFromAttributes }; /** * Initializes the given options object based on the attributes of the current DOM element. * The function looks for attributes with the prefix 'data-monster-option-', and maps them to * properties in the options object. It replaces the dashes with dots to form the property path. * For example, the attribute 'data-monster-option-url' maps to the 'url' property in the options object. * * With the mapping parameter, the attribute value can be mapped to a different value. * For example, the attribute 'data-monster-option-foo' maps to the 'bar' property in the options object. * * The mapping object would look like this: * * { * 'foo': (value) => value + 'bar' * // the value of the attribute 'data-monster-option-foo' is appended with 'bar' * // and assigned to the 'bar' property in the options object. * // e.g. <div data-monster-option-foo="foo"></div> * 'bar.baz': (value) => value + 'bar' * // the value of the attribute 'data-monster-option-bar-baz' is appended with 'bar' * // and assigned to the 'bar.baz' property in the options object. * // e.g. <div data-monster-option-bar-baz="foo"></div> * } * * Array values have to be separated by '::'. * * @since 3.38.0 * @param {HTMLElement} element - The DOM element to be used as the source of the attributes. * @param {Object} options - The options object to be initialized. * @param {Object} mapping - A mapping between the attribute value and the property value. * @param {string} prefix - The prefix of the attributes to be considered. * @return {Object} - The initialized options object. * @this HTMLElement - The context of the DOM element. */ function initOptionsFromAttributes( element, options, mapping = {}, prefix = "data-monster-option-", ) { if (!(element instanceof HTMLElement)) return options; if (!element.hasAttributes()) return options; const keyMap = extractKeys(options); const finder = new Pathfinder(options); element.getAttributeNames().forEach((name) => { if (!name.startsWith(prefix)) return; // check if the attribute name is a valid option. // the mapping between the attribute is simple. The dash is replaced by a dot. // e.g. data-monster-url => url const optionName = keyMap.get(name.substring(prefix.length).toLowerCase()); if (!finder.exists(optionName)) return; if (element.hasAttribute(name)) { let value = element.getAttribute(name); if ( mapping.hasOwnProperty(optionName) && isFunction(mapping[optionName]) ) { value = mapping[optionName](value); } let optionValue = finder.getVia(optionName); if (optionValue === null || optionValue === undefined) { optionValue = value; } //const typeOfOptionValue = typeof optionValue; if (optionValue === null || optionValue === undefined) { value = null; } else if (isBoolean(optionValue)) { value = value === "true"; } else if (isInteger(optionValue)) { value = Number(value); } else if (isString(optionValue)) { value = String(value); } else if (isObject(optionValue)) { value = JSON.parse(value); } else if (isArray(optionValue)) { value = value.split("::"); } else { value = optionValue; } finder.setVia(optionName, value); } }); return options; }