import { queryAll } from '@ecl/dom-utils';/** * @param {HTMLElement} element DOM element for component instantiation and scope * @param {Object} options * @param {String} options.moreItemLabelSelector Selector for more button label attribute * @param {String} options.listsSelector Selector for list element * @param {String} options.visibleItemsSelector Selector to retrieve the number of visible items * @param {Boolean} options.attachClickListener Whether or not to bind click events */export class DescriptionList { /** * @static * Shorthand for instance creation and initialisation. * * @param {HTMLElement} root DOM element for component instantiation and scope * * @return {DescriptionList} An instance of DescriptionList. */ static autoInit(root, { DESCRIPTION_LIST: defaultOptions = {} } = {}) { const descriptionList = new DescriptionList(root, defaultOptions); descriptionList.init(); root.ECLDescriptionList = descriptionList; return descriptionList; } constructor( element, { listsSelector = '[data-ecl-description-list-collapsible]', visibleItemsSelector = 'data-ecl-description-list-visible-items', moreItemLabelSelector = 'data-ecl-description-list-more-label', attachClickListener = true, } = {}, ) { // Check element if (!element || element.nodeType !== Node.ELEMENT_NODE) { throw new TypeError( 'DOM element should be given to initialize this widget.', ); } this.element = element; // Options this.moreItemLabelSelector = moreItemLabelSelector; this.listsSelector = listsSelector; this.attachClickListener = attachClickListener; this.visibleItemsSelector = visibleItemsSelector; // Private variables this.moreItemLabel = null; this.lists = null; this.handleClickOnMore = this.handleClickOnMore.bind(this); } /** * Initialise component. */ init() { if (!ECL) { throw new TypeError('Called init but ECL is not present'); } ECL.components = ECL.components || new Map(); this.moreItemLabel = this.element.getAttribute(this.moreItemLabelSelector); this.visibleItems = this.element.getAttribute(this.visibleItemsSelector); this.lists = queryAll(this.listsSelector, this.element); // Add see more button in each list and bind click event on it if (this.lists[0] && this.visibleItems > 0 && this.moreItemLabel) { this.lists.forEach((list) => { if (list.children && list.children.length > this.visibleItems) { const listItem = document.createElement('li'); listItem.classList.add('ecl-description-list__see_more'); const button = document.createElement('a'); button.classList.add('ecl-link', 'ecl-link--standalone'); button.href = '#'; button.innerHTML = this.moreItemLabel; listItem.appendChild(button); list.appendChild(listItem); this.showHide( queryAll('.ecl-description-list__definition-item', list), ); if (this.attachClickListener) { button.addEventListener('click', this.handleClickOnMore); } } }); // Set ecl initialized attribute this.element.setAttribute('data-ecl-auto-initialized', 'true'); ECL.components.set(this.element, this); } } /** * showHide elements basing on user preference. */ showHide(elements) { if (elements) { const items = Array.from(elements); const baseClass = 'ecl-description-list__definition-item'; const hiddenClass = `${baseClass}--hidden`; const lastVisibleClass = `${baseClass}--last-visible`; for (let i = 0; i < items.length; i += 1) { const el = items[i]; if (i < this.visibleItems) { el.classList.remove(hiddenClass); el.classList.remove(lastVisibleClass); } else if (i >= this.visibleItems) { el.classList.add(hiddenClass); } if (i === this.visibleItems - 1) { el.classList.add(lastVisibleClass); } else { el.classList.remove(lastVisibleClass); } } } } /** * Destroy component. */ destroy() { if (this.attachClickListener && this.visibleItems > 0) { const moreItems = queryAll('.ecl-description-list__see_more'); if (moreItems[0]) { moreItems.forEach((item) => { item.removeEventListener('click', this.handleClickOnMore); }); } } if (this.element) { this.element.removeAttribute('data-ecl-auto-initialized'); ECL.components.delete(this.element); } } /** * Expands the list of items. * @param {Event} e */ handleClickOnMore(e) { e.preventDefault(); const listItem = e.target.parentNode; const list = listItem.parentNode; if (this.element.contains(list)) { const parentChildren = Array.from(list.children); parentChildren.forEach((item) => { item.classList.remove('ecl-description-list__definition-item--hidden'); item.classList.remove( 'ecl-description-list__definition-item--last-visible', ); }); // Remove the button listItem.remove(); } }}export default DescriptionList;