Files
2024-12-17 17:34:10 +01:00

234 lines
8.8 KiB
JavaScript

/**
* @package Regular Labs Library
* @version 24.11.1459
*
* @author Peter van Westen <info@regularlabs.com>
* @link https://regularlabs.com
* @copyright Copyright © 2024 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);
});
}
};
})();