UNPKG

drupal-attribute

Version:

Emulate Drupal Attribute in JavaScript.

145 lines (142 loc) 4.75 kB
'use strict'; class DrupalAttribute extends Map { getClasses() { let results = null; const classValue = this.get('class'); if (classValue !== undefined) { results = classValue; } return results; } addClass(...values) { let classes = this.getClasses(); if (classes === null) { classes = []; this.set('class', classes); } values.forEach((value) => { if (value !== null && value !== undefined) { // Handle Maps by converting to array of value. if (typeof value === "string") { value = [value]; } if (value instanceof Map) { value = Array.from(value.values()); } value.forEach(function (d) { if (d === null || d === undefined || d === '') { return; } d = String(d); if (classes.indexOf(d) < 0) { classes.push(d); } }); } }); return this; } removeClass(value) { const classes = this.getClasses(); if (classes !== null) { if (!Array.isArray(value)) { value = [value]; } value.forEach(function (v) { let index = classes.indexOf(v); if (index > -1) { classes.splice(index, 1); } }); } return this; } hasClass(value) { let classes = this.getClasses(); return classes !== null ? (classes.indexOf(value) > -1) : false; } setAttribute(key, value) { // Omit attribute for nullish / false values. if (value === null || value === undefined || value === false) { this.delete(key); return this; } // Boolean true, render key="key". if (value === true) { this.set(key, key); return this; } // Reuse addClass method. if (key === 'class') { return this.addClass(value); } this.set(key, value); return this; } removeAttribute(key) { this.delete(key); return this; } toString() { let components = []; for (let key of this.keys()) { let value = this.get(key); // Skip nullish / falsey / empty attributes. if (value === null || value === undefined || value === false || value === '') { continue; } if (Array.isArray(value)) { // Remove nullish / empty values from array, and make sure all values // are converted to strings. const filtered = value .filter(v => v !== null && v !== undefined && v !== '') .map(String); // Skip empty arrays. if (filtered.length === 0) { continue; } value = filtered.join(' '); } components.push(`${key}="${String(value)}"`); } return components.length ? ' ' + components.join(' ') : ''; } /** * Merge another DrupalAttribute instance into this one. */ merge(collection) { // Convert both the current attributes and the input collection's attributes to plain objects. let currentAttributes = Object.fromEntries(this); let newAttributes = Object.fromEntries(collection); // Perform a deep merge. let mergedAttributes = this.mergeDeep(currentAttributes, newAttributes); // Clear the current Map and set the merged attributes. this.clear(); for (let key in mergedAttributes) { this.set(key, mergedAttributes[key]); } return this; } // Helper function for deep merging. mergeDeep(target, source) { for (let key in source) { if (source[key] instanceof Array) { if (!target[key]) { target[key] = []; } target[key] = Array.from(new Set(target[key].concat(source[key]))); } else if (source[key] instanceof Object) { if (!target[key]) { target[key] = {}; } Object.assign(source[key], this.mergeDeep(target[key], source[key])); } else { target[key] = source[key]; } } return target; } } exports.DrupalAttribute = DrupalAttribute;