PLEASE
SUPPORT THIS SITE! Rather than charging money for this site, I rely on
donations from users to help support the site and offset development time. If you find this code useful or if it helped on your project, please consider donating. Any amount is appreciated! Thanks!
/**
* Copyright (c)2005-2007 Matt Kruse (javascripttoolbox.com)
*
* Dual licensed under the MIT and GPL licenses.
* This basically means you can use this code however you want for
* free, but don't claim to have written it yourself!
* Donations always accepted: http://www.JavascriptToolbox.com/donate/
*
* Please do not link to the .js files on javascripttoolbox.com from
* your site. Copy the files locally to your server instead.
*
*/
/*
This code is inspired by and extended from Stuart Langridge's aqlist code:
http://www.kryogenix.org/code/browser/aqlists/
Stuart Langridge, November 2002
sil@kryogenix.org
Inspired by Aaron's labels.js (http://youngpup.net/demos/labels/)
and Dave Lindquist's menuDropDown.js (http://www.gazingus.org/dhtml/?id=109)
*/
// Automatically attach a listener to the window onload, to convert the trees
addEvent(window,"load",convertTrees);
// Utility function to add an event listener
function addEvent(o,e,f){
if (o.addEventListener){ o.addEventListener(e,f,false); return true; }
else if (o.attachEvent){ return o.attachEvent("on"+e,f); }
else { return false; }
}
// utility function to set a global variable if it is not already set
function setDefault(name,val) {
if (typeof(window[name])=="undefined" || window[name]==null) {
window[name]=val;
}
}
// Full expands a tree with a given ID
function expandTree(treeId) {
var ul = document.getElementById(treeId);
if (ul == null) { return false; }
expandCollapseList(ul,nodeOpenClass);
}
// Fully collapses a tree with a given ID
function collapseTree(treeId) {
var ul = document.getElementById(treeId);
if (ul == null) { return false; }
expandCollapseList(ul,nodeClosedClass);
}
// Expands enough nodes to expose an LI with a given ID
function expandToItem(treeId,itemId) {
var ul = document.getElementById(treeId);
if (ul == null) { return false; }
var ret = expandCollapseList(ul,nodeOpenClass,itemId);
if (ret) {
var o = document.getElementById(itemId);
if (o.scrollIntoView) {
o.scrollIntoView(false);
}
}
}
// Performs 3 functions:
// a) Expand all nodes
// b) Collapse all nodes
// c) Expand all nodes to reach a certain ID
function expandCollapseList(ul,cName,itemId) {
if (!ul.childNodes || ul.childNodes.length==0) { return false; }
// Iterate LIs
for (var itemi=0;itemi<ul.childNodes.length;itemi++) {
var item = ul.childNodes[itemi];
if (itemId!=null && item.id==itemId) { return true; }
if (item.nodeName == "LI") {
// Iterate things in this LI
var subLists = false;
for (var sitemi=0;sitemi<item.childNodes.length;sitemi++) {
var sitem = item.childNodes[sitemi];
if (sitem.nodeName=="UL") {
subLists = true;
var ret = expandCollapseList(sitem,cName,itemId);
if (itemId!=null && ret) {
item.className=cName;
return true;
}
}
}
if (subLists && itemId==null) {
item.className = cName;
}
}
}
}
// Search the document for UL elements with the correct CLASS name, then process them
function convertTrees() {
setDefault("treeClass","mktree");
setDefault("nodeClosedClass","liClosed");
setDefault("nodeOpenClass","liOpen");
setDefault("nodeBulletClass","liBullet");
setDefault("nodeLinkClass","bullet");
setDefault("preProcessTrees",true);
if (preProcessTrees) {
if (!document.createElement) { return; } // Without createElement, we can't do anything
var uls = document.getElementsByTagName("ul");
if (uls==null) { return; }
var uls_length = uls.length;
for (var uli=0;uli<uls_length;uli++) {
var ul=uls[uli];
if (ul.nodeName=="UL" && ul.className==treeClass) {
processList(ul);
}
}
}
}
function treeNodeOnclick() {
this.parentNode.className = (this.parentNode.className==nodeOpenClass) ? nodeClosedClass : nodeOpenClass;
return false;
}
function retFalse() {
return false;
}
// Process a UL tag and all its children, to convert to a tree
function processList(ul) {
if (!ul.childNodes || ul.childNodes.length==0) { return; }
// Iterate LIs
var childNodesLength = ul.childNodes.length;
for (var itemi=0;itemi<childNodesLength;itemi++) {
var item = ul.childNodes[itemi];
if (item.nodeName == "LI") {
// Iterate things in this LI
var subLists = false;
var itemChildNodesLength = item.childNodes.length;
for (var sitemi=0;sitemi<itemChildNodesLength;sitemi++) {
var sitem = item.childNodes[sitemi];
if (sitem.nodeName=="UL") {
subLists = true;
processList(sitem);
}
}
var s= document.createElement("SPAN");
var t= '\u00A0'; //
s.className = nodeLinkClass;
if (subLists) {
// This LI has UL's in it, so it's a +/- node
if (item.className==null || item.className=="") {
item.className = nodeClosedClass;
}
// If it's just text, make the text work as the link also
if (item.firstChild.nodeName=="#text") {
t = t+item.firstChild.nodeValue;
item.removeChild(item.firstChild);
}
s.onclick = treeNodeOnclick;
}
else {
// No sublists, so it's just a bullet node
item.className = nodeBulletClass;
s.onclick = retFalse;
}
s.appendChild(document.createTextNode(t));
item.insertBefore(s,item.firstChild);
}
}
}