@schukai/monster
Version:
Monster is a simple library for creating fast, robust and lightweight websites.
118 lines (106 loc) • 4.19 kB
JavaScript
/**
* 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;
}