Skip to content

Commit 4dbea00

Browse files
authored
[5.1] Rewrite treeselect in vanilla JS (#42776)
* Rewrite treeselect in vanilla JS * Fix checkbox state
1 parent 3f6d646 commit 4dbea00

File tree

5 files changed

+162
-142
lines changed

5 files changed

+162
-142
lines changed

administrator/components/com_modules/tmpl/module/edit_assignment.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@
123123
<?php endif; ?>
124124
<?php endforeach; ?>
125125
</ul>
126-
<joomla-alert id="noresultsfound" type="warning" style="display:none"><?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?></joomla-alert>
126+
<joomla-alert id="noresultsfound" type="warning" class="hidden"><?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?></joomla-alert>
127127
<div class="hidden" id="treeselectmenu">
128128
<div class="nav-hover treeselect-menu">
129129
<div class="dropdown">
@@ -132,14 +132,14 @@
132132
<span class="visually-hidden"><?php echo Text::sprintf('JGLOBAL_TOGGLE_DROPDOWN'); ?></span>
133133
</button>
134134
<div class="dropdown-menu">
135-
<h1 class="dropdown-header"><?php echo Text::_('COM_MODULES_SUBITEMS'); ?></h1>
135+
<div class="dropdown-header"><?php echo Text::_('COM_MODULES_SUBITEMS'); ?></div>
136136
<div class="dropdown-divider"></div>
137-
<a class="dropdown-item checkall" href="javascript://"><span class="icon-check-square" aria-hidden="true"></span> <?php echo Text::_('JSELECT'); ?></a>
138-
<a class="dropdown-item uncheckall" href="javascript://"><span class="icon-square" aria-hidden="true"></span> <?php echo Text::_('COM_MODULES_DESELECT'); ?></a>
137+
<a class="dropdown-item checkall"><span class="icon-check-square" aria-hidden="true"></span> <?php echo Text::_('JSELECT'); ?></a>
138+
<a class="dropdown-item uncheckall"><span class="icon-square" aria-hidden="true"></span> <?php echo Text::_('COM_MODULES_DESELECT'); ?></a>
139139
<div class="treeselect-menu-expand">
140140
<div class="dropdown-divider"></div>
141-
<a class="dropdown-item expandall" href="javascript://"><span class="icon-plus" aria-hidden="true"></span> <?php echo Text::_('COM_MODULES_EXPAND'); ?></a>
142-
<a class="dropdown-item collapseall" href="javascript://"><span class="icon-minus" aria-hidden="true"></span> <?php echo Text::_('COM_MODULES_COLLAPSE'); ?></a>
141+
<a class="dropdown-item expandall"><span class="icon-plus" aria-hidden="true"></span> <?php echo Text::_('COM_MODULES_EXPAND'); ?></a>
142+
<a class="dropdown-item collapseall"><span class="icon-minus" aria-hidden="true"></span> <?php echo Text::_('COM_MODULES_COLLAPSE'); ?></a>
143143
</div>
144144
</div>
145145
</div>

build/media_source/legacy/joomla.asset.json

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,6 @@
1212
"jquery"
1313
],
1414
"uri": "legacy/jquery-noconflict.min.js"
15-
},
16-
{
17-
"name": "joomla.treeselectmenu",
18-
"type": "script",
19-
"dependencies": [
20-
"jquery"
21-
],
22-
"uri": "legacy/treeselectmenu.min.js",
23-
"attributes": {
24-
"defer": true
25-
}
2615
}
2716
]
2817
}

build/media_source/legacy/js/treeselectmenu.es5.js

Lines changed: 0 additions & 125 deletions
This file was deleted.

build/media_source/system/joomla.asset.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,14 @@
670670
"attributes": {
671671
"type": "module"
672672
}
673+
},
674+
{
675+
"name": "joomla.treeselectmenu",
676+
"type": "script",
677+
"uri": "system/treeselectmenu.min.js",
678+
"attributes": {
679+
"type": "module"
680+
}
673681
}
674682
]
675683
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/**
2+
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
3+
* @license GNU General Public License version 2 or later; see LICENSE.txt
4+
*/
5+
6+
const treeselectmenu = document.getElementById('treeselectmenu').innerHTML;
7+
const direction = (document.dir !== undefined) ? document.dir : document.documentElement.dir;
8+
9+
document.querySelectorAll('.treeselect li').forEach((li) => {
10+
// Add icons
11+
const icon = document.createElement('span');
12+
icon.classList.add('icon-');
13+
li.prepend(icon);
14+
15+
if (li.querySelector('ul.treeselect-sub')) {
16+
// Add classes to Expand/Collapse icons
17+
li.querySelector('span.icon-').classList.add('treeselect-toggle', 'icon-chevron-down');
18+
19+
// Append drop down menu in nodes
20+
li.querySelector('div.treeselect-item label').insertAdjacentHTML('afterend', treeselectmenu);
21+
22+
const sub = li.querySelector('ul.treeselect-sub');
23+
if (!sub.querySelector('ul.treeselect-sub')) {
24+
li.querySelector('div.treeselect-menu-expand').remove();
25+
}
26+
}
27+
});
28+
29+
// Takes care of the Expand/Collapse of a node
30+
document.querySelectorAll('span.treeselect-toggle').forEach((toggle) => {
31+
toggle.addEventListener('click', ({ target }) => {
32+
const chevron = direction === 'rtl' ? 'icon-chevron-left' : 'icon-chevron-right';
33+
34+
// Take care of parent UL
35+
const { parentNode } = target;
36+
if (parentNode.querySelector('ul.treeselect-sub').classList.contains('hidden')) {
37+
target.classList.remove(chevron);
38+
target.classList.add('icon-chevron-down');
39+
parentNode.querySelectorAll('ul.treeselect-sub').forEach((item) => item.classList.remove('hidden'));
40+
parentNode.querySelectorAll('ul.treeselect-sub i.treeselect-toggle').forEach((item) => {
41+
item.classList.add('icon-chevron-down');
42+
item.classList.remove(chevron);
43+
});
44+
} else {
45+
target.classList.add(chevron);
46+
target.classList.remove('icon-chevron-down');
47+
48+
parentNode.querySelectorAll('ul.treeselect-sub').forEach((item) => item.classList.add('hidden'));
49+
parentNode.querySelectorAll('ul.treeselect-sub i.treeselect-toggle').forEach((item) => {
50+
item.classList.remove('icon-chevron-down');
51+
item.classList.add(chevron);
52+
});
53+
}
54+
});
55+
});
56+
57+
// Takes care of the filtering
58+
document.getElementById('treeselectfilter').addEventListener('keyup', ({ target }) => {
59+
const noResults = document.getElementById('noresultsfound');
60+
const text = target.value.toLowerCase();
61+
let hidden = 0;
62+
63+
noResults.classList.add('hidden');
64+
65+
const listItems = document.querySelectorAll('.treeselect li');
66+
listItems.forEach((item) => {
67+
if (item.innerText.toLowerCase().includes(text)) {
68+
item.classList.remove('d-none');
69+
} else {
70+
item.classList.add('d-none');
71+
hidden += 1;
72+
}
73+
});
74+
75+
if (hidden === listItems.length) {
76+
noResults.classList.remove('hidden');
77+
}
78+
});
79+
80+
// Checks all checkboxes the tree
81+
document.getElementById('treeCheckAll').addEventListener('click', () => {
82+
document.querySelectorAll('.treeselect input').forEach((input) => {
83+
input.checked = true;
84+
});
85+
});
86+
87+
// Unchecks all checkboxes the tree
88+
document.getElementById('treeUncheckAll').addEventListener('click', () => {
89+
document.querySelectorAll('.treeselect input').forEach((input) => {
90+
input.checked = false;
91+
});
92+
});
93+
94+
// Expands all subtrees
95+
document.getElementById('treeExpandAll').addEventListener('click', () => {
96+
document.querySelectorAll('ul.treeselect ul.treeselect-sub').forEach((input) => input.classList.remove('hidden'));
97+
document.querySelectorAll('ul.treeselect span.treeselect-toggle').forEach((item) => {
98+
item.classList.remove('icon-chevron-right');
99+
item.classList.add('icon-chevron-down');
100+
});
101+
});
102+
103+
// Collapses all subtrees
104+
document.getElementById('treeCollapseAll').addEventListener('click', () => {
105+
document.querySelectorAll('ul.treeselect ul.treeselect-sub').forEach((input) => input.classList.add('hidden'));
106+
document.querySelectorAll('ul.treeselect span.treeselect-toggle').forEach((item) => {
107+
item.classList.remove('icon-chevron-down');
108+
item.classList.add('icon-chevron-right');
109+
});
110+
});
111+
112+
// Take care of children check/uncheck all
113+
document.querySelectorAll('a.checkall').forEach((item) => {
114+
item.addEventListener('click', ({ target }) => {
115+
target.closest('li').querySelectorAll('ul.treeselect-sub input').forEach((input) => {
116+
input.checked = true;
117+
});
118+
});
119+
});
120+
document.querySelectorAll('a.uncheckall').forEach((item) => {
121+
item.addEventListener('click', ({ target }) => {
122+
target.closest('li').querySelectorAll('ul.treeselect-sub input').forEach((input) => {
123+
input.checked = false;
124+
});
125+
});
126+
});
127+
128+
// Take care of children toggle all
129+
document.querySelectorAll('a.expandall').forEach((item) => {
130+
item.addEventListener('click', ({ target }) => {
131+
const parent = target.closest('ul');
132+
parent.querySelectorAll('ul.treeselect-sub').forEach((input) => input.classList.remove('hidden'));
133+
parent.querySelectorAll('ul.treeselect-sub .treeselect-toggle').forEach((toggle) => {
134+
toggle.classList.remove('icon-chevron-right');
135+
toggle.classList.add('icon-chevron-down');
136+
});
137+
});
138+
});
139+
document.querySelectorAll('a.collapseall').forEach((item) => {
140+
item.addEventListener('click', ({ target }) => {
141+
const parent = target.closest('ul');
142+
parent.querySelectorAll('ul.treeselect-sub').forEach((input) => input.classList.add('hidden'));
143+
parent.querySelectorAll('ul.treeselect-sub .treeselect-toggle').forEach((toggle) => {
144+
toggle.classList.remove('icon-chevron-down');
145+
toggle.classList.add('icon-chevron-right');
146+
});
147+
});
148+
});

0 commit comments

Comments
 (0)