/** * @package Regular Labs Library * @version 25.7.12430 * * @author Peter van Westen <[email protected]> * @link https://regularlabs.com * @copyright Copyright © 2025 Regular Labs All Rights Reserved * @license GNU General Public License version 2 or later */ (function() { 'use strict'; window.RegularLabs = window.RegularLabs || {}; window.RegularLabs.TreeSelect = window.RegularLabs.TreeSelect || { direction: (document.dir !== undefined) ? document.dir : document.getElementsByTagName("html")[0].getAttribute("dir"), init: function(id) { const menu = document.querySelector('div#rl-treeselect-' + id); if ( ! menu) { return; } const list = menu.querySelector('ul'); const top_level_items = list.querySelectorAll(':scope > li'); const items = list.querySelectorAll('li'); const search_field = menu.querySelector('[name="treeselectfilter"]'); const sub_tree_select = menu.querySelector('div.sub-tree-select > *'); const no_results_found = menu.querySelector('joomla-alert'); items.forEach((item) => { // Store the innerText for filtering // because if done later, also the text from added menus and buttons is added item.text = item.innerText; }); items.forEach((item) => { const checkbox = item.querySelector(':scope > .treeselect-item > input'); if ( ! checkbox) { return; } item.classList.toggle('rl-item-checked', checkbox.checked); checkbox.addEventListener('change', () => { item.classList.toggle('rl-item-checked', checkbox.checked); }); const child_list = item.querySelector(':scope > ul.treeselect-sub'); if ( ! child_list) { return; } const label = item.querySelector('label'); const sub_tree_select_el = sub_tree_select.cloneNode(true); const sub_tree_expand = document.createElement('span'); sub_tree_expand.className = 'treeselect-toggle icon-chevron-down'; sub_tree_expand.collapsed = false; sub_tree_expand.addEventListener('click', () => { this.expand(child_list, sub_tree_expand); }); sub_tree_select_el.querySelector('[data-action="checkNested"]').addEventListener('click', () => { this.check(child_list, true); }); sub_tree_select_el.querySelector('[data-action="uncheckNested"]').addEventListener('click', () => { this.check(child_list, false); }); sub_tree_select_el.querySelector('[data-action="toggleNested"]').addEventListener('click', () => { this.check(child_list, 'toggle'); }); if (checkbox.dataset['rlTreeselectCollapseChildren']) { // Collapse children if top level parent is selected if (checkbox.checked) { sub_tree_expand.collapsed = false; this.expand(child_list, sub_tree_expand); this.check(child_list, false); } // Add event when (un)checking top level parent checkbox.addEventListener('click', () => { sub_tree_expand.collapsed = ! checkbox.checked; this.expand(child_list, sub_tree_expand); this.check(child_list, false); }); } item.insertBefore(sub_tree_expand, item.firstChild); label.append(sub_tree_select_el); }); menu.querySelector('[data-action="checkAll"]').addEventListener('click', () => { this.check(menu, true); }); menu.querySelector('[data-action="uncheckAll"]').addEventListener('click', () => { this.check(menu, false); }); menu.querySelector('[data-action="toggleAll"]').addEventListener('click', () => { this.check(menu, 'toggle'); }); menu.querySelector('[data-action="expandAll"]').addEventListener('click', () => { top_level_items.forEach((item) => { const child_list = item.querySelector('ul.treeselect-sub'); const sub_tree_expand = item.querySelector('.treeselect-toggle'); if ( ! child_list || ! sub_tree_expand) { return; } sub_tree_expand.collapsed = true; this.expand(child_list, sub_tree_expand); }); }); menu.querySelector('[data-action="collapseAll"]').addEventListener('click', () => { top_level_items.forEach((item) => { const child_list = item.querySelector('ul.treeselect-sub'); const sub_tree_expand = item.querySelector('.treeselect-toggle'); if ( ! child_list || ! sub_tree_expand) { return; } sub_tree_expand.collapsed = false; this.expand(child_list, sub_tree_expand); }); }); menu.querySelector('[data-action="showAll"]').addEventListener('click', () => { this.resetSearch(items, search_field, no_results_found); }); menu.querySelector('[data-action="showSelected"]').addEventListener('click', (e) => { this.resetSearch(items, search_field, no_results_found, true); }); // Takes care of the filtering search_field.addEventListener('keyup', () => { this.doSearch(items, search_field, no_results_found); }); }, resetSearch: function(items, search_field, no_results_found, has_checked) { search_field.value = ''; this.doSearch(items, search_field, no_results_found, has_checked); }, doSearch: function(items, search_field, no_results_found, has_checked) { const text = search_field.value.toLowerCase(); no_results_found.style.display = 'none'; let results_found = 0; items.forEach((item) => { if (has_checked && ! item.querySelector('input:checked')) { item.style.display = 'none'; return; } if (text !== '') { let item_text = item.text.toLowerCase(); item_text = item_text.replace(/\s+/g, ' ').trim(); if (item_text.indexOf(text) == -1) { item.style.display = 'none'; return; } } results_found++; item.style.display = 'block'; }); if ( ! results_found) { no_results_found.style.display = 'block'; } }, check: function(parent, checked) { const items = parent.querySelectorAll('li'); items.forEach((item) => { if (item.style.display === 'none') { return; } const checkbox = item.querySelector(':scope > .treeselect-item input:enabled'); if ( ! checkbox) { return; } checkbox.checked = checked === 'toggle' ? ! checkbox.checked : checked; item.classList.toggle('rl-item-checked', checked); }); }, expand: function(element, button) { const show = button.collapsed; element.style.display = show ? 'block' : 'none'; button.classList.toggle('icon-chevron-down', show); button.classList.toggle(this.direction === 'rtl' ? 'icon-chevron-left' : 'icon-chevron-right', ! show); button.collapsed = ! button.collapsed; if ( ! show) { return; } const child_lists = element.querySelectorAll(':scope > li > ul.treeselect-sub'); if ( ! child_lists.length) { return; } child_lists.forEach((child_list) => { const child_button = child_list.closest('li').querySelector('.treeselect-toggle'); child_button.collapsed = true; this.expand(child_list, child_button); }); } }; })();