PHP Classes

File: modules/system/assets/js/snowboard/extras/DataConfig.js

Recommend this page to a friend!
  Packages of Luke Towers   Winter   modules/system/assets/js/snowboard/extras/DataConfig.js   Download  
File: modules/system/assets/js/snowboard/extras/DataConfig.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Winter
Content management system that uses MVC
Author: By
Last change:
Date: 7 months ago
Size: 6,480 bytes
 

Contents

Class file image Download
import PluginBase from '../abstracts/PluginBase'; /** * Data configuration provider. * * Provides a mechanism for passing configuration data through an element's data attributes. This * is generally used for widgets or UI interactions to configure them. * * @copyright 2022 Winter. * @author Ben Thomson <git@alfreido.com> */ export default class DataConfig extends PluginBase { /** * Constructor. * * @param {PluginBase} instance * @param {HTMLElement} element * @param {Object} localConfig */ construct(instance, element, localConfig) { if (instance instanceof PluginBase === false) { throw new Error('You must provide a Snowboard plugin to enable data configuration'); } if (element instanceof HTMLElement === false) { throw new Error('Data configuration can only be extracted from HTML elements'); } this.instance = instance; this.element = element; this.localConfig = localConfig || {}; this.instanceConfig = {}; this.acceptedConfigs = {}; this.refresh(); } /** * Gets the config for this instance. * * If the `config` parameter is unspecified, returns the entire configuration. * * @param {string} config */ get(config) { if (config === undefined) { return this.instanceConfig; } if (this.instanceConfig[config] !== undefined) { return this.instanceConfig[config]; } return undefined; } /** * Sets the config for this instance. * * This allows you to override, at runtime, any configuration value as necessary. * * @param {string} config * @param {any} value * @param {boolean} persist */ set(config, value, persist) { if (config === undefined) { throw new Error('You must provide a configuration key to set'); } this.instanceConfig[config] = value; if (persist === true) { this.element.dataset[config] = value; this.localConfig[config] = value; } } /** * Refreshes the configuration from the element. * * This will allow you to make changes to the data config on a DOM level and re-apply them * to the config on the JavaScript side. */ refresh() { this.acceptedConfigs = this.getAcceptedConfigs(); this.instanceConfig = this.processConfig(); } /** * Determines the available configurations that can be set through the data config. * * If an instance has an `acceptAllDataConfigs` property, set to `true`, then all data * attributes will be available as configuration values. This can be a security concern, so * tread carefully. * * Otherwise, available configurations will be determined by the keys available in an object * returned by a `defaults()` method in the instance. * * @returns {string[]|boolean} */ getAcceptedConfigs() { if ( this.instance.acceptAllDataConfigs !== undefined && this.instance.acceptAllDataConfigs === true ) { return true; } if ( this.instance.defaults !== undefined && typeof this.instance.defaults === 'function' && typeof this.instance.defaults() === 'object' ) { return Object.keys(this.instance.defaults()); } return false; } /** * Returns the default values for the instance. * * This will be an empty object if the instance either does not have a `defaults()` method, or * the method itself does not return an object. * * @returns {object} */ getDefaults() { if ( this.instance.defaults !== undefined && typeof this.instance.defaults === 'function' && typeof this.instance.defaults() === 'object' ) { return this.instance.defaults(); } return {}; } /** * Processes the configuration. * * Loads up the defaults, then populates it with any configuration values provided by the data * attributes, based on the rules of the accepted configurations. * * This configuration object is then cached and available through `config.get()` calls. * * @returns {object} */ processConfig() { const config = this.getDefaults(); if (this.acceptedConfigs === false) { return config; } /* eslint-disable */ for (const key in this.element.dataset) { if (this.acceptedConfigs === true || this.acceptedConfigs.includes(key)) { config[key] = this.coerceValue(this.element.dataset[key]); } } for (const key in this.localConfig) { if (this.acceptedConfigs === true || this.acceptedConfigs.includes(key)) { config[key] = this.localConfig[key]; } } /* eslint-enable */ return config; } /** * Coerces configuration values for JavaScript. * * Takes the string value returned from the data attribute and coerces it into a more suitable * type for JavaScript processing. * * @param {*} value * @returns {*} */ coerceValue(value) { const stringValue = String(value); // Null value if (stringValue === 'null') { return null; } // Undefined value if (stringValue === 'undefined') { return undefined; } // Base64 value if (stringValue.startsWith('base64:')) { const base64str = stringValue.replace(/^base64:/, ''); const decoded = atob(base64str); return this.coerceValue(decoded); } // Boolean value if (['true', 'yes'].includes(stringValue.toLowerCase())) { return true; } if (['false', 'no'].includes(stringValue.toLowerCase())) { return false; } // Numeric value if (/^[-+]?[0-9]+(\.[0-9]+)?$/.test(stringValue)) { return Number(stringValue); } // JSON value try { return this.snowboard.jsonParser().parse(stringValue); } catch (e) { return (stringValue === '') ? true : stringValue; } } }