/* eslint-disable no-undef */ class GetManager { static PUBLISHER_ALIASES = new Map([ ['arnnet', ['arn']], ['channelasia', ['ca']], ['reseller', ['rsl']], ]); static VALID_PUBLISHERS = new Set([ 'nww', 'iw', 'cw', 'arnnet', 'reseller', 'cso', 'cio', 'channelasia', ]); static EDITION_ALIASES = new Map([ ['uk', ['gb']], ['middle-east', ['me']], ['asean', ['as']], ['africa', ['af']], ]); static VALID_EDITIONS = new Set([ 'africa', 'asean', 'au', 'ca', 'es', 'ie', 'in', 'it', 'jp', 'kr', 'middle-east', 'nl', 'nz', 'uk', 'us', 'de', 'fr', 'pl', 'se', ]); constructor() { window.foundry_is_language = GetManager.foundry_is_language; window.foundry_is_publisher = GetManager.foundry_is_publisher; window.foundry_is_edition = GetManager.foundry_is_edition; window.foundry_get_publisher = GetManager.foundry_get_publisher; } static getCanonicalPublisher(name) { if (!name) return null; const lowerName = name.toLowerCase(); const found = Array.from(GetManager.PUBLISHER_ALIASES.entries()).find( ([canonical, aliases]) => canonical === lowerName || aliases.includes(lowerName), ); if (found) return found[0]; return GetManager.VALID_PUBLISHERS.has(lowerName) ? lowerName : null; } static getDocumentLanguage() { const langAttr = document.documentElement.getAttribute('lang') || ''; return langAttr.split('-')[0].toLowerCase(); // Extracts the language without the region (e.g., "en" from "en-US") } static getDocumentEdition() { const editionAttr = document.documentElement.getAttribute('data-edition') || ''; return editionAttr.toLowerCase(); } static getCanonicalEdition(name) { if (!name) return null; const lowerName = name.toLowerCase(); const found = Array.from(GetManager.EDITION_ALIASES.entries()).find( ([canonical, aliases]) => canonical === lowerName || aliases.includes(lowerName), ); if (found) return found[0]; return GetManager.VALID_EDITIONS.has(lowerName) ? lowerName : null; } static foundry_is_publisher(publisherNames) { const brandAttr = document.documentElement.getAttribute('data-brand') || ''; if (!brandAttr) return false; const canonicalBrand = brandAttr.toLowerCase(); if (Array.isArray(publisherNames)) { return publisherNames.some(name => GetManager.getCanonicalPublisher(name) === canonicalBrand); } return GetManager.getCanonicalPublisher(publisherNames) === canonicalBrand; } static foundry_is_language(languages) { const currentLang = GetManager.getDocumentLanguage(); if (!currentLang) return false; const languageList = Array.isArray(languages) ? languages.map(lang => lang.toLowerCase()) : languages.split(',').map(lang => lang.trim().toLowerCase()); return languageList.includes(currentLang); } static foundry_is_edition(editionNames) { const currentEdition = GetManager.getDocumentEdition(); if (!currentEdition) return false; if (Array.isArray(editionNames)) { return editionNames.some(name => GetManager.getCanonicalEdition(name) === currentEdition); } return GetManager.getCanonicalEdition(editionNames) === currentEdition; } static foundry_get_publisher() { const brandAttr = document.documentElement.getAttribute('data-brand') || ''; if (!brandAttr) return null; return brandAttr.trim().toLowerCase(); } } new GetManager(); // eslint-disable-line no-new; function ToggleContentVisibilityParagraph() { const elements = document.querySelectorAll('[data-readmore-length]'); if (elements.length === 0) return; elements.forEach((element, index) => { const uniqueId = `readmore-${index}`; const modifiedElement = element; modifiedElement.id = uniqueId; const readMoreText = element.getAttribute('data-readmore-txt') || 'Read more'; const hasReadLess = element.hasAttribute('data-readless'); const readLessText = hasReadLess ? element.getAttribute('data-readless-txt') || readMoreText : ''; const readMoreButton = document.createElement('button'); readMoreButton.textContent = readMoreText; readMoreButton.classList.add('read-more-toggle', 'reset-button'); readMoreButton.setAttribute('aria-controls', uniqueId); readMoreButton.setAttribute('aria-expanded', 'false'); element.insertAdjacentElement('afterend', readMoreButton); readMoreButton.addEventListener('click', function () { const isExpanded = readMoreButton.getAttribute('aria-expanded') === 'true'; readMoreButton.setAttribute('aria-expanded', !isExpanded); element.setAttribute('data-expanded', !isExpanded); if (!hasReadLess) { readMoreButton.remove(); } if (isExpanded) { readMoreButton.textContent = readMoreText; } else { readMoreButton.textContent = readLessText; } }); }); } document.addEventListener('DOMContentLoaded', ToggleContentVisibilityParagraph); ; /** * A class to handle the toggling of content visibility with options. */ class ToggleContentVisibility { /** * @param {Element} node - The DOM element to apply the toggle behavior. * @param {Object} options - Configuration options for the class. */ constructor(node, options = {}) { if (!(node instanceof Element)) { throw new Error('Input node is not a valid DOM element.'); } this.node = node; this.options = this.setOptions(options); this.elements = node.querySelectorAll( Array.isArray(this.options.targetElements) ? this.options.targetElements.join(', ') : '', ); this.showingMore = false; this.readMoreButton = this.node.querySelector('.read-more'); this.readLessButton = this.node.querySelector('.read-less'); this.toggleContentBound = this.toggleContent.bind(this); // Bind method once this.initialize(); } setOptions(options) { const defaults = { initialIndex: 2, showReadLess: false, targetElements: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'blockquote', 'pre', 'address', 'figcaption', 'details', 'ul', 'ol', 'dl', 'table', 'img', 'video', 'audio', 'canvas', 'iframe', 'figure', 'script', 'noscript', 'style', 'form', 'hr', 'svg', ], position: 'after', readMoreText: 'Read more', readLessText: 'Read less', transitionEffect: null, }; const readMoreAttribute = this.node.getAttribute('data-readmore'); const readLessAttribute = this.node.getAttribute('data-readless'); const readMoreCountAttribute = this.node.getAttribute('data-readmore-count'); const parsedCount = parseInt(readMoreCountAttribute, 10); const initialIndex = Number.isNaN(parsedCount) ? defaults.initialIndex : parsedCount; return { ...defaults, ...options, initialIndex, showReadLess: readLessAttribute !== 'false', readMoreText: readMoreAttribute || defaults.readMoreText, readLessText: readLessAttribute || defaults.readLessText, }; } initialize() { if (this.elements.length === 0) return; // No elements, nothing to toggle if (this.options.initialIndex >= this.elements.length) { this.showingMore = true; return; } if (!this.node.id) { this.node.id = `readmore-${Math.random().toString(36).substr(2, 9)}`; } Array.from(this.elements).forEach((element, i) => { element.classList.toggle('hidden', i >= this.options.initialIndex); element.setAttribute('aria-hidden', i >= this.options.initialIndex); }); this.showingMore = false; if (!this.readMoreButton) { this.readMoreButton = ToggleContentVisibility.createControlButton( this.options.readMoreText, ['read-more'], this.toggleContentBound, ); this.appendControlButton(this.readMoreButton); } if (this.options.showReadLess && !this.readLessButton) { this.readLessButton = ToggleContentVisibility.createControlButton( this.options.readLessText, ['read-less'], this.toggleContentBound, ); this.appendControlButton(this.readLessButton); } this.node.setAttribute('aria-expanded', this.showingMore); this.manageButtonState(); } static initAll() { const nodes = document.querySelectorAll('[data-readmore]'); nodes.forEach(node => { new ToggleContentVisibility(node); // eslint-disable-line no-new }); } refresh() { this.destroy(); this.initialize(); } update(newOptions) { this.options = this.setOptions({ ...this.options, ...newOptions }); this.refresh(); } destroy() { this.showingMore = false; if (this.readMoreButton) { this.readMoreButton.removeEventListener('click', this.toggleContentBound); this.readMoreButton.remove(); this.readMoreButton = null; } if (this.readLessButton) { this.readLessButton.removeEventListener('click', this.toggleContentBound); this.readLessButton.remove(); this.readLessButton = null; } Array.from(this.elements).forEach(element => { element.classList.remove('hidden'); element.removeAttribute('aria-hidden'); }); this.node.removeAttribute('aria-expanded'); } toggleContent() { if (this.node.getAttribute('data-readless') === null) { this.showContent(); this.readMoreButton.remove(); if (this.readLessButton) { this.readLessButton.remove(); this.readLessButton = null; } } else if (this.showingMore) { this.hideContent(); } else { this.showContent(); } } showContent() { this.showingMore = true; this.toggleElementsVisibility(true); this.manageButtonState(); } hideContent() { this.showingMore = false; this.toggleElementsVisibility(false); this.manageButtonState(); } toggleElementsVisibility(isVisible) { Array.from(this.elements) .slice(this.options.initialIndex) .forEach(element => { element.classList.toggle('hidden', !isVisible); element.setAttribute('aria-hidden', !isVisible); }); this.node.setAttribute('aria-expanded', isVisible); } manageButtonState() { if (this.showingMore) { this.configureReadLessButton(); } else { this.configureReadMoreButton(); } } configureReadMoreButton() { if (this.readMoreButton) { this.readMoreButton.classList.remove('hidden'); this.readMoreButton.setAttribute('aria-hidden', 'false'); } if (this.readLessButton) { this.readLessButton.classList.add('hidden'); this.readLessButton.setAttribute('aria-hidden', 'true'); } } configureReadLessButton() { if (this.readMoreButton) { this.readMoreButton.classList.add('hidden'); this.readMoreButton.setAttribute('aria-hidden', 'true'); } if (this.readLessButton) { this.readLessButton.classList.remove('hidden'); this.readLessButton.setAttribute('aria-hidden', 'false'); } } static createControlButton(text, classNames, handler) { const button = document.createElement('button'); button.textContent = text; button.classList.add(...classNames); button.addEventListener('click', handler); return button; } appendControlButton(button) { if (this.node.parentNode) { this.node.appendChild(button); } } } ToggleContentVisibility.initAll(); ;