It is assumed you know basic Javascript before reading this and know what the DOM is.
First the source code:
function setUp() {
var myULs = document.getElementById('tree').getElementsByTagName('ul');
for (var i = 1; i < myULs.length; i++) {
var toggleObject = document.createElement('a');
toggleObject.innerHTML = '+ ';
myULs\[i\].parentNode.insertBefore(toggleObject, myULs\[i\].parentNode.firstChild);
toggleObject.onclick = eventCaller(toggleObject, myULs\[i\]);
}
}
function eventCaller(toggleButton, list) {
list.style.display = 'none';
return function() {
if (list.style.display == 'none') {
list.style.display = '';
toggleButton.innerHTML = '- ';
} else {
list.style.display = 'none';
toggleButton.innerHTML = '+ ';
}
}
}
onload = setUp;
First, how function setUp works.
var myULs = document.getElementById('tree').getElementsByTagName('ul');
To use the code you need an element with the id of “tree” surrounding the list you want it to work. This code just gets a collection of ul
tags with in the id="tree"
tag. This collection is looped through using a for
loop.
var toggleObject = document.createElement('a');
toggleObject.innerHTML = '+ ';
This creates a new anchor a
element and sets the text inside to a plus sign. I probably shouldn’t use innerHTML
but it makes things simpler.
myULs[i].parentNode.insertBefore(toggleObject, myULs[i].parentNode.firstChild);
This looks messy but is really simple. _someNode_.insertBefore
adds a node to _someNode_
before some child of _someNode_
. In this case we want our newly created anchor tag to be the first child of the ul
’s parent. (i.e. place the link before the ul
and before any text as well).
toggleObject.onclick = eventCaller(toggleObject, myULs[i]);
The onclick
event is then set to some function. It is important to realise the onclick
is not set to eventCaller
but the function eventCaller
returns.
function eventCaller(toggleButton, list)
The function is called with two arguments: a list and the link before it that will toggle the display of the list.
list.style.display = 'none';
First we just set the list to not display by default.
Then the clever bit, we return a function.
What the function does is simple, it toggles the display
style attribute of the list and changes the “button” between plus and minus signs.
But the function is different for each list. Because the function is declared within another function, this new anonymous function still has the scope of the function that created it. This means each copy of this new function has different list
and toggleButton
variables.