Created
March 8, 2014 09:27
-
-
Save 6174/9427815 to your computer and use it in GitHub Desktop.
collapsiblelists.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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 | |
*/ | |
// create the CollapsibleLists object | |
var CollapsibleLists = | |
new function(){ | |
/* Makes all lists with the class 'collapsibleList' collapsible. The | |
* parameter is: | |
* | |
* doNotRecurse - true if sub-lists should not be made collapsible | |
*/ | |
this.apply = function(doNotRecurse){ | |
// loop over the unordered lists | |
var uls = document.getElementsByTagName('ul'); | |
for (var index = 0; index < uls.length; index ++){ | |
// check whether this list should be made collapsible | |
if (uls[index].className.match(/(^| )collapsibleList( |$)/)){ | |
// make this list collapsible | |
this.applyTo(uls[index], true); | |
// check whether sub-lists should also be made collapsible | |
if (!doNotRecurse){ | |
// add the collapsibleList class to the sub-lists | |
var subUls = uls[index].getElementsByTagName('ul'); | |
for (var subIndex = 0; subIndex < subUls.length; subIndex ++){ | |
subUls[subIndex].className += ' collapsibleList'; | |
} | |
} | |
} | |
} | |
}; | |
/* Makes the specified list collapsible. The parameters are: | |
* | |
* node - the list element | |
* doNotRecurse - true if sub-lists should not be made collapsible | |
*/ | |
this.applyTo = function(node, doNotRecurse){ | |
// loop over the list items within this node | |
var lis = node.getElementsByTagName('li'); | |
for (var index = 0; index < lis.length; index ++){ | |
// check whether this list item should be collapsible | |
if (!doNotRecurse || node == lis[index].parentNode){ | |
// prevent text from being selected unintentionally | |
if (lis[index].addEventListener){ | |
lis[index].addEventListener( | |
'mousedown', function (e){ e.preventDefault(); }, false); | |
}else{ | |
lis[index].attachEvent( | |
'onselectstart', function(){ event.returnValue = false; }); | |
} | |
// add the click listener | |
if (lis[index].addEventListener){ | |
lis[index].addEventListener( | |
'click', createClickListener(lis[index]), false); | |
}else{ | |
lis[index].attachEvent( | |
'onclick', createClickListener(lis[index])); | |
} | |
// close the unordered lists within this list item | |
toggle(lis[index]); | |
} | |
} | |
}; | |
/* Returns a function that toggles the display status of any unordered | |
* list elements within the specified node. The parameter is: | |
* | |
* node - the node containing the unordered list elements | |
*/ | |
function createClickListener(node){ | |
// return the function | |
return function(e){ | |
// ensure the event object is defined | |
if (!e) e = window.event; | |
// find the list item containing the target of the event | |
var li = (e.target ? e.target : e.srcElement); | |
while (li.nodeName != 'LI') li = li.parentNode; | |
// toggle the state of the node if it was the target of the event | |
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){ | |
// determine whether to open or close the unordered lists | |
var open = node.className.match(/(^| )collapsibleListClosed( |$)/); | |
// loop over the unordered list elements with the node | |
var uls = node.getElementsByTagName('ul'); | |
for (var index = 0; index < uls.length; index ++){ | |
// find the parent list item of this unordered list | |
var li = uls[index]; | |
while (li.nodeName != 'LI') li = li.parentNode; | |
// style the unordered list if it is directly within this node | |
if (li == node) uls[index].style.display = (open ? 'block' : 'none'); | |
} | |
// remove the current class from the node | |
node.className = | |
node.className.replace( | |
/(^| )collapsibleList(Open|Closed)( |$)/, ''); | |
// if the node contains unordered lists, set its class | |
if (uls.length > 0){ | |
node.className += ' collapsibleList' + (open ? 'Open' : 'Closed'); | |
} | |
} | |
}(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment