/* 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();
;