Ok... I went ahead and modified the script significantly so that all styling is in the stylesheet and that a section of the tree is recognised as being open or closed through the class name (as opposed to the rel="" tag).
It still works the same as before, except that a lot of repetitive code has been removed. However, as i am not very well versed in JS, it would be nice if the author could have a look at the new script. If it has mistakes, then please let me know and, if not, then consider modifying the original script to reflect them.
The new script:
Code:
/***********************************************
* Simple Tree Menu- © Dynamic Drive DHTML code library (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code
***********************************************/
var persisteduls=new Object()
var ddtreemenu=new Object()
//////////No need to edit beyond here///////////////////////////
ddtreemenu.createTree=function(treeid, enablepersist, persistdays)
{
var ultags=document.getElementById(treeid).getElementsByTagName("ul")
if(typeof persisteduls[treeid]=="undefined")
{
persisteduls[treeid]=(enablepersist==true && ddtreemenu.getCookie(treeid)!="")? ddtreemenu.getCookie(treeid).split(",") : ""
}
for (var i=0; i<ultags.length; i++)
{
ddtreemenu.buildSubTree(treeid, ultags[i], i)
}
if(enablepersist==true) //if enable persist feature
{
var durationdays=(typeof persistdays=="undefined")? 1 : parseInt(persistdays)
ddtreemenu.dotask(window, function(){ddtreemenu.rememberstate(treeid, durationdays)}, "unload") //save opened UL indexes on body unload
}
}
ddtreemenu.buildSubTree=function(treeid, ulelement, index)
{
if(typeof persisteduls[treeid]=="object")//if cookie exists (persisteduls[treeid] is an array versus "" string)
{
if(ddtreemenu.searcharray(persisteduls[treeid], index))
{
ulelement.parentNode.className="open";
}
else
{
ulelement.parentNode.className="closed";
}
}
else if(ulelement.parentNode.className==null || ulelement.parentNode.className==false) //if no cookie and UL has NO rel attribute explicted added by user
{
ulelement.parentNode.className="closed";
}
else if(ulelement.parentNode.className=="open") //else if no cookie and this UL has an explicit rel value of "open"
{
ddtreemenu.expandSubTree(treeid, ulelement) //expand this UL plus all parent ULs (so the most inner UL is revealed!)
}
ulelement.parentNode.onclick=function(e)
{
var submenu=this.getElementsByTagName("ul")[0];
if(submenu.parentNode.className=="closed")
{
ulelement.parentNode.className="open";
}
else if(submenu.parentNode.className=="open")
{
ulelement.parentNode.className="closed";
}
ddtreemenu.preventpropagate(e)
}
ulelement.onclick=function(e)
{
ddtreemenu.preventpropagate(e);
}
}
ddtreemenu.expandSubTree=function(treeid, ulelement) //expand a UL element and any of its parent ULs
{
var rootnode=document.getElementById(treeid);
var currentnode=ulelement;
currentnode.style.display="block";
while (currentnode!=rootnode)
{
if(currentnode.tagName=="ul"); //if parent node is a UL, expand it too
{
currentnode.parentNode.className="open";
}
currentnode=currentnode.parentNode;
}
}
ddtreemenu.flatten=function(treeid, action)//expand or contract all UL elements
{
var ultags=document.getElementById(treeid).getElementsByTagName("ul")
for (var i=0; i<ultags.length; i++)
{
ultags[i].parentNode.className=(action=="expand")? "open" : "closed";
}
}
ddtreemenu.rememberstate=function(treeid, durationdays)//store index of opened ULs relative to other ULs in Tree into cookie
{
var ultags=document.getElementById(treeid).getElementsByTagName("ul")
var openuls=new Array()
for (var i=0; i<ultags.length; i++)
{
if(ultags[i].parentNode.className=="open") openuls[openuls.length]=i //save the index of the opened UL (relative to the entire list of ULs) as an array element
}
if(openuls.length==0) //if there are no opened ULs to save/persist
{
openuls[0]="none open" //set array value to string to simply indicate all ULs should persist with state being closed
}
ddtreemenu.setCookie(treeid, openuls.join(","), durationdays) //populate cookie with value treeid=1,2,3 etc (where 1,2... are the indexes of the opened ULs)
}
////A few utility functions below//////////////////////
ddtreemenu.getCookie=function(Name) //get cookie value
{
var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair
if(document.cookie.match(re))
{//if cookie found
return document.cookie.match(re)[0].split("=")[1] //return its value
}
return ""
}
ddtreemenu.setCookie=function(name, value, days) //set cookei value
{
var expireDate = new Date()
//set "expstring" to either future or past date, to set or delete cookie, respectively
var expstring=expireDate.setDate(expireDate.getDate()+parseInt(days))
document.cookie = name+"="+value+"; expires="+expireDate.toGMTString()+"; path=/";
}
ddtreemenu.searcharray=function(thearray, value) //searches an array for the entered value. If found, delete value from array
{
var isfound=false
for (var i=0; i<thearray.length; i++)
{
if(thearray[i]==value)
{
isfound=true
thearray.shift() //delete this element from array for efficiency sake
break
}
}
return isfound
}
ddtreemenu.preventpropagate=function(e) //prevent action from bubbling upwards
{
if(typeof e!="undefined")
{
e.stopPropagation()
}
else
{
event.cancelBubble=true
}
}
ddtreemenu.dotask=function(target, functionref, tasktype) //assign a function to execute to an event handler (ie: onunload)
{
var tasktype=(window.addEventListener)? tasktype : "on"+tasktype
if(target.addEventListener)
{
target.addEventListener(tasktype, functionref, false)
}
else if(target.attachEvent)
{
target.attachEvent(tasktype, functionref)
}
}
The CSS
Code:
.treeview
{
width:150px;
}
/*CSS for Simple Tree Menu*/
.treeview ul
{
margin: 0;
padding: 0;
}
/*Style for LI elements in general (excludes an LI that contains sub lists)*/
.treeview li
{
list-style-type: none;
padding-left: 12px;
margin-bottom: 3px;
}
.treeview li a
{
background: white url(arrow.gif) no-repeat left center;
padding-left: 8px;
}
/* Style for LI that contains sub lists (other ULs). */
.treeview li.open, .treeview li.closed
{
cursor: hand !important;
cursor: pointer !important;
}
/*Style for ULs that are children of LIs (submenu) */
.treeview li.closed ul
{
display: none; /*Hide them by default. Don't delete. */
}
/*Style for LIs of ULs that are children of LIs (submenu) */
.treeview .open ul li, .treeview .closed ul li
{
cursor: default;
}
li.closed
{
background: white url(plus_sign.gif) no-repeat left 0.4em;
}
li.closed ul
{
display: none;
}
li.open
{
background: white url(minus_sign.gif) no-repeat left 0.4em;
}
li.open ul
{
display: block;
}
Making siblings close upon the opening of an item is still a feature request though!!!
Bookmarks