/*
CollapsibleLists.js
An object allowing lists to dynamically expand and collapse
Created by Stephen Morley - http://code.stephenmorley.org/ - and released under
the terms of the CC0 1.0 Universal legal code:
http://creativecommons.org/publicdomain/zero/1.0/legalcode
*/
const CollapsibleLists = (function(){
// Makes all lists with the class 'collapsibleList' collapsible. The
// parameter is:
//
// doNotRecurse - true if sub-lists should not be made collapsible
function apply(doNotRecurse){
[].forEach.call(document.getElementsByTagName('ul'), node => {
if (node.classList.contains('collapsibleList')){
applyTo(node, true);
if (!doNotRecurse){
[].forEach.call(node.getElementsByTagName('ul'), subnode => {
subnode.classList.add('collapsibleList')
});
}
}
})
}
// Makes the specified list collapsible. The parameters are:
//
// node - the list element
// doNotRecurse - true if sub-lists should not be made collapsible
function applyTo(node, doNotRecurse){
[].forEach.call(node.getElementsByTagName('li'), li => {
if (!doNotRecurse || node === li.parentNode){
li.style.userSelect = 'none';
li.style.MozUserSelect = 'none';
li.style.msUserSelect = 'none';
li.style.WebkitUserSelect = 'none';
li.addEventListener('click', handleClick.bind(null, li));
toggle(li);
}
});
}
// Handles a click. The parameter is:
//
// node - the node for which clicks are being handled
function handleClick(node, e){
let li = e.target;
while (li.nodeName !== 'LI'){
li = li.parentNode;
}
if (li === node){
toggle(node);
}
}
// Opens or closes the unordered list elements directly within the
// specified node. The parameter is:
//
// node - the node containing the unordered list elements
function toggle(node){
const open = node.classList.contains('collapsibleListClosed');
const uls = node.getElementsByTagName('ul');
[].forEach.call(uls, ul => {
let li = ul;
while (li.nodeName !== 'LI'){
li = li.parentNode;
}
if (li === node){
ul.style.display = (open ? 'block' : 'none');
}
});
node.classList.remove('collapsibleListOpen');
node.classList.remove('collapsibleListClosed');
if (uls.length > 0){
node.classList.add('collapsibleList' + (open ? 'Open' : 'Closed'));
}
}
return {apply, applyTo};
})();