Simple Tree Menu

This example uses the Simple Tree Menu from Dynamic Drive to display a simple UL list as a dynamic tree.

Try it here as a Google Gadget:

HTML and JavaScript Google Gadget xml

HTML and JavaScript as used on a server. The other needed files are the JavaScript file, css file, open.png, closed.png and list.png.

<html>

<head>

<link rel="stylesheet" type="text/css" href="simpletree.css" />

<script type="text/javascript" src="simpletreemenu.js"></script>

<script type="text/javascript">

function init () {

ddtreemenu.createTree("tree", false)

}

</script>

</head>

<body onload="init()">

<h4>Simple Dynamic Tree</h4>

<a href="javascript:ddtreemenu.flatten('tree', 'expand')">Expand All</a> | <a href="javascript:ddtreemenu.flatten('tree', 'contract')">Contract All</a><br/><br/>

<b>Year 1985</b>

<ul id="tree" class="treeview">

<li>Alabama

<ul>

<li>Address: Tuscaloosa, AL</li>

<li>lat: 33.23</li>

<li>lng: -87.62</li>

<li>region: S</li>

<li>tier: 3</li>

<li>count: 5</li>

<li>size: 2</li>

</ul>

</li>

<li>American

<ul>

<li>Address: Washington, DC</li>

<li>lat: 38.9382</li>

<li>lng: -77.086</li>

<li>region: NE</li>

<li>tier: 4</li>

<li>count: 11</li>

<li>size: 3</li>

</ul>

</li>

<li>Boston University

<ul>

<li>Address: Boston, MA</li>

<li>lat: 42.3498</li>

<li>lng: -71.096</li>

<li>region: NE</li>

<li>tier: 2</li>

<li>count: 10</li>

<li>size: 3</li>

</ul>

</li>

</ul>

</body></html>

Google Gadget xml

XML nodes and CDATA are added at the start and end of the file, as is registerLoadHandler (in bold). The HTML tags html, head, and body are removed, as are meta and title. The remaining html is listed as the first lines in the CDATA section. The style sheet (simpletree.css) and JavaScript (simpletreemenu.js) are included after the HTML.

<?xml version="1.0" encoding="UTF-8" ?>

<Module>

<ModulePrefs title="Simple tree using Dynamic Drive Simple Tree Menu" height="300"

description="Simple tree using Dynamic Drive Simple Tree Menu"

author="Stephanie Smullen" author_email="stephanie.smullen@gmail.com">

<Require feature="sharedmap"/>

</ModulePrefs>

<Content type="html">

<![CDATA[

<h4>Simple Dynamic Tree</h4>

<a href="javascript:ddtreemenu.flatten('tree', 'expand')">Expand All</a> | <a href="javascript:ddtreemenu.flatten('tree', 'contract')">Contract All</a><br/><br/>

<b>Year 1985</b>

<ul id="tree" class="treeview">

<li>Alabama

<ul>

<li>Address: Tuscaloosa, AL</li>

<li>lat: 33.23</li>

<li>lng: -87.62</li>

<li>region: S</li>

<li>tier: 3</li>

<li>count: 5</li>

<li>size: 2</li>

</ul>

</li>

<li>American

<ul>

<li>Address: Washington, DC</li>

<li>lat: 38.9382</li>

<li>lng: -77.086</li>

<li>region: NE</li>

<li>tier: 4</li>

<li>count: 11</li>

<li>size: 3</li>

</ul>

</li>

<li>Boston University

<ul>

<li>Address: Boston, MA</li>

<li>lat: 42.3498</li>

<li>lng: -71.096</li>

<li>region: NE</li>

<li>tier: 2</li>

<li>count: 10</li>

<li>size: 3</li>

</ul>

</li>

</ul>

<style type="text/css">

.treeview ul{ /*CSS for Simple Tree Menu*/

margin-left: -40px;

margin: 0px;

padding: 0;

}

.treeview li{ /*Style for LI elements in general (excludes an LI that contains sub lists)*/

background: white url(http://sites.google.com/site/stephaniesmullen/files/mapexamples/list.png) no-repeat left center;

list-style-type: none;

padding-left: 22px;

margin-bottom: 3px;

}

.treeview li.submenu{ /* Style for LI that contains sub lists (other ULs). */

background: white url(http://sites.google.com/site/stephaniesmullen/files/mapexamples/closed.png) no-repeat left 1px;

cursor: hand !important;

cursor: pointer !important;

}

.treeview li.submenu ul{ /*Style for ULs that are children of LIs (submenu) */

display: none; /*Hide them by default. Don't delete. */

}

</style>

<script type="text/javascript">

//Dynamic Drive -- http://www.dynamicdrive.com/dynamicindex1/navigate1.htm

var persisteduls=new Object()

var ddtreemenu=new Object()

ddtreemenu.closefolder="http://sites.google.com/site/stephaniesmullen/files/mapexamples/closed.png" //set image path to "closed" folder image

ddtreemenu.openfolder="https://sites.google.com/site/stephaniesmullen/files/mapexamples/open.png" //set image path to "open" folder image

//////////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){

ulelement.parentNode.className="submenu"

if (typeof persisteduls[treeid]=="object"){ //if cookie exists (persisteduls[treeid] is an array versus "" string)

if (ddtreemenu.searcharray(persisteduls[treeid], index)){

ulelement.setAttribute("rel", "open")

ulelement.style.display="block"

ulelement.parentNode.style.backgroundImage="url("+ddtreemenu.openfolder+")"

}

else

ulelement.setAttribute("rel", "closed")

} //end cookie persist code

else if (ulelement.getAttribute("rel")==null || ulelement.getAttribute("rel")==false) //if no cookie and UL has NO rel attribute explicted added by user

ulelement.setAttribute("rel", "closed")

else if (ulelement.getAttribute("rel")=="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.getAttribute("rel")=="closed"){

submenu.style.display="block"

submenu.setAttribute("rel", "open")

ulelement.parentNode.style.backgroundImage="url("+ddtreemenu.openfolder+")"

}

else if (submenu.getAttribute("rel")=="open"){

submenu.style.display="none"

submenu.setAttribute("rel", "closed")

ulelement.parentNode.style.backgroundImage="url("+ddtreemenu.closefolder+")"

}

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"

currentnode.parentNode.style.backgroundImage="url("+ddtreemenu.openfolder+")"

while (currentnode!=rootnode){

if (currentnode.tagName=="UL"){ //if parent node is a UL, expand it too

currentnode.style.display="block"

currentnode.setAttribute("rel", "open") //indicate it's open

currentnode.parentNode.style.backgroundImage="url("+ddtreemenu.openfolder+")"

}

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].style.display=(action=="expand")? "block" : "none"

var relvalue=(action=="expand")? "open" : "closed"

ultags[i].setAttribute("rel", relvalue)

ultags[i].parentNode.style.backgroundImage=(action=="expand")? "url("+ddtreemenu.openfolder+")" : "url("+ddtreemenu.closefolder+")"

}

}

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].getAttribute("rel")=="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)

}

</script>

<script type="text/javascript">

function init () {

ddtreemenu.createTree("tree", false)

}

gadgets.util.registerOnLoadHandler(init);

</script>

]]>

</Content>

</Module>