Mega Code Archive

 
Categories / JavaScript DHTML / GUI Components
 

Nano Tree

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head><title>NanoTree</title> <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> <!-- std_treelook.css --> <style REL="STYLESHEET" TYPE="text/css"> /* Tree Style */ .treetitle {   padding:2px;   cursor:default;      font-family: Tahoma,Verdana,Arial, Helvetica, sans-serif;   font-size: 11px;   color: #000000; } .editednode {   padding:2px;   cursor:default;   background-color: #FFFFFF;;   color: #000000;      font-family: Tahoma,Verdana,Arial, Helvetica, sans-serif;   font-size: 11px; } .editednodeinput {   background-color: #FFFFFF;;   color: #000000;      width: 150px;   height: 17px;      border-style: solid;   border-width: 1px;   border-color: #000000;      font-family: Tahoma,Verdana,Arial, Helvetica, sans-serif;   font-size: 11px; } .treetitleselectedfocused {   padding:2px;   cursor:default;   background-color: highlight;   color: highlighttext;      font-family: Tahoma,Verdana,Arial, Helvetica, sans-serif;   font-size: 11px; } .treetitleselectedblured {   padding:2px;   cursor:default;   background-color: menu;   color: windowtext;   font-family: Tahoma,Verdana,Arial, Helvetica, sans-serif;   font-size: 11px; } </style> <!-- nanotree.js --> <script type="text/javascript" language="JavaScript"> /** * Original Author of this file: Martin Mouritzen. (martin@nano.dk) * * * (Lack of) Documentation: * * * If a finishedLoading method exists, it will be called when the tree is loaded. * (good to display a div, etc.). * * * You have to set the variable rootNode (as a TreeNode). * * You have to set a container element, this is the element in which the tree will be. * * * TODO:  * Save cookies better (only 1 cookie for each tree). Else the page will totally cookieclutter. * *********************************************************************** * Configuration variables. ************************************************************************/ // Should the rootNode be displayed. var showRootNode = true; // Should the dashed lines between nodes be shown. var showLines = true; // Should the nodes be sorted? (You can either specify a number, then it will be sorted by that, else it will // be sorted alphabetically (by name). var sortNodes = true; // This is IMPORTANT... use an unique id for each document you use the tree in. (else they'll get mixed up). var documentID = window.location.href; // being read from cookie. var nodesOpen = new Array(); // RootNode of the tree. var rootNode; // Container to display the Tree in. var container; // Shows/Hides subnodes on startup var showAllNodesOnStartup = false; // Is the roots dragable? var dragable = false; /************************************************************************ * The following is just instancevariables. ************************************************************************/ var href = ''; // rootNodeCallBack name (if null, it's not selectable). var rootNodeCallBack = null; // selectedNode var selectedNode = null; var states = ''; var statearray = new Array(); var treeNodeEdited = null; var editaborted = false; var floatDragElement = null; var colouredElement = null; var draggedNodeID = null; var lastDraggedOnNodeID = null; /** * The TreeNode Object * @param id unique id of this treenode * @param name The title of this node * @param icon The icon if this node (Can also be an array with 2 elements, the first one will represent the closed state, and the next one the open state) * @param param A parameter, this can be pretty much anything. (eg. an array with information). * @param orderNumber an orderNumber If one is given the nodes will be sorted by this (else they'll be sorted alphabetically (If sorting is on). */ function TreeNode(id,name,icon,param,orderNumber) {   this.id = id;   this.childs = new Array();   this.name = (name == null ? 'unset name' : name);   this.icon = (icon == null ? '' : icon);   this.parent = null;   this.handler = null;   this.param = (param == null ? '' : param);   this.orderNumber = (orderNumber == null ? -1 : orderNumber);      this.openeventlisteners = new Array();   this.editeventlisteners = new Array();   this.moveeventlisteners = new Array();   this.haschilds = false;   this.editable = false;   this.linestring = '';      this.nextSibling = null;   this.prevSibling = null;      this.childsHasBeenFetched = false;   this.getID = function() {     return this.id;   }   this.setName = function(newname) {     this.name = newname;   }   this.getName = function() {     return this.name;   }   this.getParam = function() {     return this.param;   }   this.setIcon = function(icon) {     this.icon = icon;   }   this.getIcon = function() {     if (typeof(this.icon) == 'object') {       return this.icon[0];     }     return this.icon;   }   this.getOpenIcon = function() {     if (typeof(this.icon) == 'object') {       return this.icon[1];     }     return this.icon;   }   this.hasIcon = function () {     return this.icon != '';   }   this.getOrderNumber = function() {     return this.orderNumber;   }   this.addOpenEventListener = function(event) {     this.openeventlisteners[this.openeventlisteners.length] = event;   }   this.gotOpenEventListeners = function() {     return (this.openeventlisteners.length > 0);   }   this.addEditEventListener = function(event) {     this.editeventlisteners[this.editeventlisteners.length] = event;   }   this.gotEditEventListeners = function() {     return (this.editeventlisteners.length > 0);   }   this.addMoveEventListener = function(event) {     this.moveeventlisteners[this.moveeventlisteners.length] = event;   }   this.gotMoveEventListeners = function() {     return (this.moveeventlisteners.length > 0);   }   this.addChild = function(childNode) {     var possiblePrevNode = this.childs[this.childs.length - 1]     if (possiblePrevNode) {       possiblePrevNode.nextSibling = childNode;       childNode.prevSibling = possiblePrevNode;       // alert(childNode.prevSibling);     }     this.childs[this.childs.length] = childNode;     childNode.setParent(this);     if (sortNodes) {       function sortByOrder(a,b) {         var order1 = a.getOrderNumber();         var order2 = b.getOrderNumber();         if (order1 == -1 || order2 == -1) {           return a.getName().toLowerCase() > b.getName().toLowerCase() ? 1 : -1;         }         else {           if (order1 == order2) {             // If they got the same order number, then we'll sort by their title.             return a.getName().toLowerCase() > b.getName().toLowerCase() ? 1 : -1;           }           else {             return order1 - order2;           }         }       }       this.childs.sort(sortByOrder);     }   }   this.removeChild = function(childNode) {     var found = false;     for (var i=0;i<this.childs.length;i++) {       if (found) {         this.childs[i] = this.childs[i + 1];       }       if (this.childs[i] == childNode) {         if (i == (this.childs.length - 1)) {           this.childs[i] = null;         }         else {           this.childs[i] = this.childs[i + 1];         }         found = true;       }     }     if (found) {       this.childs.length = this.childs.length-1;     }   }   this.resetChilds = function() {     this.childs = new Array();   }   this.setHasChilds = function(hasChilds) {     this.haschilds = hasChilds;   }   this.hasChilds = function() {     if (this.haschilds == true) {       return true;     }     return (this.childs.length > 0);   }   this.getChildCount = function() {     return this.childs.length;   }   this.getFirstChild = function() {     if (this.hasChilds()) {       return this.childs[0];     }     return null;   }   this.gotHandler = function() {     return this.handler != null;   }   this.setHandler = function(handler) {     this.handler = handler;   }   this.getHandler = function() {     return this.handler;   }   this.setParent = function(parent) {     this.parent = parent;   }   this.getParent = function() {     return this.parent;   }   this.getLineString = function() {     return this.linestring;   }   this.setLineString = function(string) {     this.linestring = string;   }   this.isEditable = function() {     return this.editable;   }   this.setEditable = function(editable) {     this.editable = editable;   }    } function getTreeNode(nodeID) {   return findNodeWithID(rootNode,nodeID); } function findNodeWithID(node,nodeID) {   if (node.getID() == nodeID) {     return node;   }   else {     if (node.hasChilds()) {       for(var i=0;i<node.getChildCount();i++) {         var value = findNodeWithID(node.childs[i],nodeID);         if (value != false) {           return value;         }       }     }     return false;   } } function readStates() {   //setCookie('tree' + documentID,'');   states = getCookie('tree' + documentID);   if (states != null) {     var array = states.split(';');     for(var i=0;i<array.length;i++) {       var singlestate = array[i].split('|');       statearray[i] = new Array();       statearray[i]["key"] = singlestate[0];       statearray[i]["state"]  = singlestate[1];     }   } } function getState(nodeID) {   for(var i=0;i<statearray.length;i++) {     if (statearray[i]["key"] == nodeID) {       state = statearray[i]["state"];       if (state == null || state == '') {         state = 'closed';       }       return state;     }   }   return "closed"; } function writeStates(nodeID,newstate) {   //alert(nodeID);   var str = '';   var found = false;   for(var i=0;i<statearray.length;i++) {     if (statearray[i]["key"] == nodeID) {       statearray[i]["state"] = newstate;       found = true;     }     if (statearray[i]["state"] != null) {       str += statearray[i]["key"] + '|' + statearray[i]["state"] + ';';     }   }   if (found == false) {     statearray[statearray.length] = new Array();     statearray[statearray.length - 1]["key"] = nodeID;     statearray[statearray.length - 1]["state"] = newstate;     if (newstate != null) {       str += nodeID + '|' + newstate + ';';     }   }   setCookie('tree' + documentID,str); } function showTree(path) {   readStates();      href = path;   window.focus();   window.onblur = blurSelection;   window.onfocus = focusSelection;   var str = '';   str = '<div id="node' + rootNode.getID() + '" class="treetitle" style="display:' + (showRootNode == true ? 'block' : 'none') + '">';   str += '<nobr>';   if (rootNode.hasIcon()) {     str += '<img src="' + rootNode.getIcon() + '" style="vertical-align:middle;">';   }   str += '<span style="vertical-align:middle;">&nbsp;' + rootNode.getName() + '</span>';   str += '</nobr></div>';      if (rootNode.hasChilds()) {     for(i=0;i<rootNode.childs.length;i++) {       nodeContents = showNode(rootNode.childs[i],(i == (rootNode.getChildCount() -1)));       str = str + nodeContents;     }   }   container.innerHTML = str;   if (window.finishedLoading) {     finishedLoading();   } } /** * Shows the given node, and subnodes. */ function showNode(treeNode,lastNode) {   linestring = treeNode.getLineString();   var state = getState(treeNode.getID());   var str;   str = '<div style="filter:alpha(opacity=100);" ondragenter="dragEnter(' + treeNode.getID() + ');" ondragleave="dragLeave();" ondragstart="startDrag(' + treeNode.getID() + ');" ondrag="dragMove();" ondragend="endDrag(' + treeNode.getID() + ')" id="node' + treeNode.getID() + '">';   str += '<nobr>';   for(var y=0;y<linestring.length;y++) {     if (linestring.charAt(y) == 'I') {       str += '<img src="' + href + 'nanoImages/' + (showLines ? 'line' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';     }     else if (linestring.charAt(y) == 'B') {       str += '<img src="' + href + 'nanoImages/white.gif" style="width:19px;height:20px;vertical-align:middle;">';     }   }   if (treeNode.hasChilds()) {     // If this is the first child of the rootNode, and showRootNode is false, we want to display a different icon.     if (!showRootNode && (treeNode.getParent() == rootNode) && (treeNode.getParent().getFirstChild() == treeNode)) {       if (!lastNode) {         str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (state == 'open' ? (showLines ? 'minus_no_root' : 'minus_nolines') : (showLines ? 'plus_no_root' : 'plus_nolines')) + '.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';       }       else {         str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (state == 'open' ? 'minus_last' : 'plus_last') + '_no_root.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';       }     }     else {       if (!lastNode) {         str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (state == 'open' ? (showLines ? 'minus' : 'minus_nolines') : (showLines ? 'plus' : 'plus_nolines')) + '.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';       }       else {         str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (state == 'open' ? (showLines ? 'minus_last' : 'minus_nolines') : (showLines ? 'plus_last' : 'plus_nolines')) + '.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';       }     }   }   else {     // If this is the first child of the rootNode, and showRootNode is false, we want to display a different icon.     if (!showRootNode && (treeNode.getParent() == rootNode) && (treeNode.getParent().getFirstChild() == treeNode)) {       if (!lastNode) {         str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (showLines ? 't_no_root' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';       }       else {         str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/white.gif" style="width:19px;height:20px;vertical-align:middle;">';       }     }     else {       if (!lastNode) {         str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (showLines ? 't' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';       }       else {         str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (showLines ? 'lastnode' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';       }     }   }   iconStartImage = treeNode.getIcon();   if (state != 'closed') {     if (treeNode.hasChilds()) {       iconStartImage = treeNode.getOpenIcon();     }   }      str += '<img id="iconimage' + treeNode.getID() + '" src="' + iconStartImage + '" style="vertical-align:middle;" OnClick="selectNode(' + treeNode.getID() + ')">';   str += '&nbsp;<span unselectable="ON" style="vertical-align:middle;" class="treetitle" ID="title' + treeNode.getID() + '" OnDblClick="handleNode(' + treeNode.getID() + ')" OnClick="selectNode(' + treeNode.getID() + ')">';   str += treeNode.getName();   str += '</span>';   str += '</nobr>';   str += '</div>';   if (treeNode.hasChilds()) {     if (state == 'open') {       str += '<div id="node' + treeNode.getID() + 'sub" style="display:block;">';       fireOpenEvent(treeNode);       // alert('openevent: ' + treeNode.getName());     }     else {       str += '<div id="node' + treeNode.getID() + 'sub" style="display:' + (showAllNodesOnStartup == true ? 'block;' : 'none;') + ';">';     }     var subgroupstr = '';     var newChar = '';     if (!lastNode) {       newChar = 'I';     }     else {       newChar = 'B';     }     for(var z=0;z<treeNode.getChildCount();z++) {       treeNode.childs[z].setLineString(linestring + newChar);     }     for(var z=0;z<treeNode.getChildCount();z++) {       subgroupstr += showNode(treeNode.childs[z],(z == (treeNode.getChildCount() -1)));     }     str += subgroupstr;     str += '</div>';   }   else {     str += '<div id="node' + treeNode.getID() + 'sub" style="display:none;">';     str += '</div>';   }   return str; } /* function mouseMove() {   if (dragging) {     alert('bob');   } } function mouseUp() {   if (dragging) {     alert('dropped on something!');   } } */ function startDrag(nodeID) {   if (!dragable) {     return;   }   draggedNodeID = nodeID;      var srcObj = window.event.srcElement;   while(srcObj.tagName != 'DIV') {     srcObj = srcObj.parentElement;   }   floatDragElement = document.createElement('DIV');   floatDragElement.innerHTML = srcObj.innerHTML;   floatDragElement.childNodes[0].removeChild(floatDragElement.childNodes[0].childNodes[0]);      document.body.appendChild(floatDragElement);   floatDragElement.style.zIndex = 100;   floatDragElement.style.position = 'absolute';   floatDragElement.style.filter='progid:DXImageTransform.Microsoft.Alpha(1,opacity=60);'; } function findSpanChild(element) {   if (element.tagName == 'SPAN') {     return element;   }   else {     if (element.childNodes) {       for(var i=0;i<element.childNodes.length;i++) {         var value = findSpanChild(element.childNodes[i]);         if (value != false) {           return value;         }       }       return false;     }   } } function dragEnter(nodeID) {   if (!dragable) {     return;   }   lastDraggedOnNodeID = nodeID;      if (colouredElement) {     findSpanChild(colouredElement).className = 'treetitle';   }   colouredElement = window.event.srcElement;   while(colouredElement.tagName != 'DIV') {     colouredElement = colouredElement.parentElement;     if (colouredElement.tagName == 'BODY') {       // Something gone seriously wrong.       alert('Drag failure, reached <BODY>!');       return;     }   }     findSpanChild(colouredElement).className = 'treetitleselectedfocused'; } function dragLeave() {   if (!dragable) {     return;   } } function endDrag(nodeID) {   if (!dragable) {     return;   }   if (lastDraggedOnNodeID != null) {     fireMoveEvent(getTreeNode(lastDraggedOnNodeID),draggedNodeID,lastDraggedOnNodeID);   } } function dragProceed() {   if (!dragable) {     return;   }   var dragged = getTreeNode(draggedNodeID);   var newparent = getTreeNode(lastDraggedOnNodeID);   var oldparent = dragged.getParent();      oldparent.removeChild(dragged);   newparent.addChild(dragged);      refreshNode(oldparent);   refreshNode(newparent);      _dragClean() } function dragCancel() {   if (!dragable) {     return;   }   _dragClean() } /** * Don't call this yourself. */ function _dragClean() {   if (!dragable) {     return;   }   if (colouredElement) {     findSpanChild(colouredElement).className = 'treetitle';   }      floatDragElement.parentElement.removeChild(floatDragElement);   floatDragElement = null;   colouredElement = null;   draggedNodeID = null;   lastDraggedOnNodeID = null; } function dragMove() {   if (!dragable) {     return;   }   floatDragElement.style.top = window.event.clientY;   floatDragElement.style.left = window.event.clientX; } function editEnded() {   if (treeNodeEdited != null) {     // treeNodeEdited.getID();     var editTitle = document.getElementById('title' + treeNodeEdited.getID());     var input = editTitle.childNodes[0];        var newValue = input.value;          if (newValue == treeNodeEdited.getName()) {       editTitle.innerHTML = newValue;       treeNodeEdited = null;       return;     }        fireEditEvent(treeNodeEdited,newValue);          if (!editaborted) {       treeNodeEdited.setName(newValue);       editTitle.innerHTML = newValue;     }        treeNodeEdited = null;   } } function selectNode(nodeID) {   var treeNode = getTreeNode(nodeID);   if (selectedNode != null) {     if (selectedNode == nodeID) {       if (treeNode.isEditable()) {         if (treeNodeEdited == treeNode) {           return;         }         treeNodeEdited = treeNode;         var editTitle = document.getElementById('title' + treeNode.getID());         editTitle.className = 'editednode';                  editTitle.innerHTML = '<input type="text" onKeypress="if (event.keyCode == 13) { this.onblur = null; editEnded(); }" name="editednode" class="editednodeinput">';         var input = editTitle.childNodes[0];         input.value = treeNode.getName();         input.focus();         input.select();         input.onblur = editEnded;       }       return;     }     if (treeNodeEdited != null) {       editEnded();     }     var oldNodeTitle = document.getElementById('title' + selectedNode);     oldNodeTitle.className = 'treetitle';   }   selectedNode = nodeID;   var nodetitle = document.getElementById('title' + selectedNode);   nodetitle.className = 'treetitleselectedfocused';      if (treeNode.gotHandler()) {     eval(treeNode.getHandler() + '(getTreeNode(' + nodeID + '));');   }   else {     standardClick(treeNode);   } } function refreshNode(treeNode) {   var submenu = document.getElementById('node' + treeNode.getID() + 'sub');   var str = '';   for(var i=0;i<treeNode.getChildCount();i++) {     var parent = treeNode.getParent();     if (!parent) {       treeNode.childs[i].setLineString(treeNode.getLineString() + 'B');     }     else {       if (parent.childs[parent.childs.length - 1] == treeNode) {         treeNode.childs[i].setLineString(treeNode.getLineString() + 'B');       }       else {         treeNode.childs[i].setLineString(treeNode.getLineString() + 'I');       }     }     str += showNode(treeNode.childs[i],i == (treeNode.getChildCount() - 1));   }   var actionimage = document.getElementById('handler' + treeNode.getID());   if (treeNode.getChildCount() == 0) {     // TreeNode haven't got any children, make sure the right image is displayed.     if (actionimage.src.indexOf('last') == -1) {       actionimage.src = href + 'nanoImages/' + (showLines ? 't' : 'white') + '.gif';     }     else {       actionimage.src = href + 'nanoImages/' + (showLines ? 'lastnode' : 'white') + '.gif';     }     actionimage.onclick = null;          // Close the submenu     if (submenu) {       submenu.style.display = 'none';     }   }   else {     // We have children, make sure to display the + and - icon.     if (actionimage.src.indexOf('plus') != -1) {       // The TreeNode have already got children, and displays them.     }     else if (actionimage.src.indexOf('minus') != -1) {       // The TreeNode have already got children, and displays them.     }     else {       if (actionimage.src.indexOf('last') == -1) {         actionimage.outerHTML = '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (showLines ? 'plus' : 'plus_nolines') + '.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';       }       else {         actionimage.outerHTML = '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/plus_last.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';       }     }   }   submenu.innerHTML = str; } function handleNode(nodeID) {   var treeNode = getTreeNode(nodeID);     if (!treeNode.hasChilds()) { // No reason to handle a node without childs.     return;   }      var submenu = document.getElementById('node' + nodeID + 'sub');      var iconimageholder = document.getElementById('iconimage' + nodeID);   var actionimage = document.getElementById('handler' + nodeID);   // This will be used if showRootNode is set to false.   var firstChildOfRoot = false;   if (actionimage.src.indexOf('_no_root') != -1) {     firstChildOfRoot = true;   }      if (submenu.style.display == 'none') {     writeStates(nodeID,'open');     fireOpenEvent(treeNode);     submenu.style.display = 'block';     iconimageholder.src = treeNode.getOpenIcon();        if (actionimage.src.indexOf('last') == -1) {       actionimage.src = href + 'nanoImages/' + ((firstChildOfRoot) ? 'minus_no_root' : (showLines ? 'minus' : 'minus_nolines')) + '.gif';     }     else {       actionimage.src = href + 'nanoImages/' + ((firstChildOfRoot) ? 'minus_last_no_root' : (showLines ? 'minus_last' : 'minus_nolines')) + '.gif';     }   }   else {     writeStates(nodeID,'closed');     submenu.style.display = 'none';          iconimageholder.src = treeNode.getIcon();          if (actionimage.src.indexOf('last') == -1) {       actionimage.src = href + 'nanoImages/' + ((firstChildOfRoot) ? 'plus_no_root' : (showLines ? 'plus' : 'plus_nolines')) + '.gif';     }     else {       actionimage.src = href + 'nanoImages/' + ((firstChildOfRoot) ? 'plus_last_no_root' : (showLines ? 'plus_last' : 'plus_nolines')) + '.gif';     }   } } function fireOpenEvent(treeNode) {   if (treeNode.gotOpenEventListeners()) {     for(var i=0;i<treeNode.openeventlisteners.length;i++) {       eval(treeNode.openeventlisteners[i] + '(' + treeNode.getID() + ');');     }   } } function fireEditEvent(treeNode,newVal) {   if (treeNode.gotEditEventListeners()) {     for(var i=0;i<treeNode.editeventlisteners.length;i++) {       eval(treeNode.editeventlisteners[i] + '(' + treeNode.getID() + ',\'' + escape(newVal) + '\');');     }   } } function fireMoveEvent(treeNode,draggedNodeID,droppedOnNodeID) {   if (treeNode.gotMoveEventListeners()) {     for(var i=0;i<treeNode.moveeventlisteners.length;i++) {       eval(treeNode.moveeventlisteners[i] + '(' + draggedNodeID + ',' + droppedOnNodeID + ');');     }   } } function blurSelection() {   if (selectedNode != null) {     var oldNodeTitle = document.getElementById('title' + selectedNode);     oldNodeTitle.className = 'treetitleselectedblured';   } } function focusSelection() {   if (selectedNode != null) {     var oldNodeTitle = document.getElementById('title' + selectedNode);     oldNodeTitle.className = 'treetitleselectedfocused';   } } function getCookieVal (offset) {     var endstr = document.cookie.indexOf (";",offset);     if (endstr == -1) {     endstr = document.cookie.length;   }   return unescape(document.cookie.substring(offset,endstr)); } function getCookie (name) {     var arg = name + "=";   var alen = arg.length;   var clen = document.cookie.length;   var i = 0;   while (i < clen) {     var j = i + alen;     if (document.cookie.substring(i, j) == arg) {       return getCookieVal(j);     }     i = document.cookie.indexOf(" ", i) + 1;     if (i == 0) {       break;     }   }   return null; } function setCookie (name, value) {     var argv = setCookie.arguments;     var argc = setCookie.arguments.length;     var expires = (argc > 2) ? argv[2] : null;     var path = (argc > 3) ? argv[3] : null;     var domain = (argc > 4) ? argv[4] : null;     var secure = (argc > 5) ? argv[5] : false;     document.cookie = name + "=" + escape (value) + ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) + ((path == null) ? "" : ("; path=" + path)) + ((domain == null) ? "" : ("; domain=" + domain)) + ((secure == true) ? "; secure" : ""); } function expandNode() {   var state = getState(selectedNode);   if (state == 'open') {     var currentTreeNode = getTreeNode(selectedNode);     if (currentTreeNode.hasChilds()) {       selectNode(currentTreeNode.childs[0].getID());     }   }   else {     handleNode(selectedNode);   } } function subtractNode() {   var state = getState(selectedNode);   if (state == 'closed') {     var currentTreeNode = getTreeNode(selectedNode);     var parent = currentTreeNode.getParent();     if (parent != null && parent != rootNode) {       selectNode(parent.getID());     }   }   else {     handleNode(selectedNode);   } } function selectPrevNode() {   var currentTreeNode = getTreeNode(selectedNode);   if (currentTreeNode.prevSibling != null) {     var state = getState(currentTreeNode.prevSibling.getID());     if (state == 'open' && currentTreeNode.prevSibling.hasChilds()) {       // We have to find the last open child of the previoussiblings childs.       var current = currentTreeNode.prevSibling.childs[currentTreeNode.prevSibling.childs.length - 1];       var currentstate = 'open';       while (current.hasChilds() && (getState(current.getID()) == 'open')) {         current = current.childs[current.childs.length - 1];       }       selectNode(current.getID());     }     else {       selectNode(currentTreeNode.prevSibling.getID());     }   }   else {     if (currentTreeNode.getParent() != null && currentTreeNode.getParent() != rootNode) {       selectNode(currentTreeNode.getParent().getID());     }   } } function selectNextNode() {   var currentTreeNode = getTreeNode(selectedNode);   var state = getState(selectedNode);   if (state == 'open' && currentTreeNode.hasChilds()) {     selectNode(currentTreeNode.childs[0].getID());   }     else {     if (currentTreeNode.nextSibling != null) {       selectNode(currentTreeNode.nextSibling.getID());     }     else {       // Continue up the tree until we either hit null, or a parent which have a child.       var parent = currentTreeNode;       while ((parent = parent.getParent()) != rootNode) {         if (parent.nextSibling != null) {           selectNode(parent.nextSibling.getID());           break;         }       }       /*       if (currentTreeNode.getParent().nextSibling != null) {         selectNode(currentTreeNode.getParent().nextSibling.getID());       }       */     }   } } function keyDown(event) {   if (window.event) {     event = window.event;   }   if (event.keyCode == 38) { // Up     selectPrevNode();     return false;   }   else if (event.keyCode == 40) { // Down     selectNextNode();     return false;   }   else if (event.keyCode == 37) { // left     subtractNode();     return false;   }   else if (event.keyCode == 39) { // right     expandNode();     return false;   } } document.onkeydown = keyDown; </script> <script type="text/javascript" language="JavaScript"> showRootNode = false; sortNodes = false; dragable = false; /** * Needed to initialize the tree. * And to call showTree(imagePath); to actually show the tree. * Alternatively this can be done in a script block at the bottom of the page. * Though this method is somewhat cleaner. */ function init() {   container = document.getElementById('examplediv');   showTree(''); } /** * Called when a user clicks on a node. * @param treeNode the TreeNode object which have been clicked. */ function standardClick(treeNode) {   var mytext = document.getElementById('mytext');   var param = treeNode.getParam();      mytext.innerHTML = (param == '') ? treeNode.getName() : param; } function nodeEdited(treeNode) { } var closedGif = 'nanoImages/folder_closed.gif'; var openGif = 'nanoImages/folder_open.gif'; var pageIcon = 'nanoImages/page16x16.gif'; var userIcon = 'nanoImages/user_16x16.gif'; var helpIcon = 'nanoImages/help_16x16.gif'; rootNode = new TreeNode(1,'RootNode'); var node1 = new TreeNode(2,'subpage 1',helpIcon,'<P>This treenode can be renamed (Try to click onnce more on the node).<br>(You have to handle the renaming itself in a function though, since this is implementation specific. ie: Go down in a database and change the titel of a page).<br>A good example would be to open a PHP script to do the renaming, this can for example be done by setting location.href on a hidden iframe, or by setting the src attribute on a script element.</P>'); node1.setEditable(true); node1.addEditEventListener('nodeEdited'); var node2 = new TreeNode(3,'subpage 2',new Array(closedGif,openGif));   var node2a = new TreeNode(4,'1st subpage to Node 2',new Array(closedGif,openGif));     var node2aa = new TreeNode(5,'subpage to subpage of Node2',new Array(closedGif,openGif));       var node2aaa = new TreeNode(6,'Some child',pageIcon);       var node2aab = new TreeNode(7,'Some child',pageIcon);       var node2aac = new TreeNode(8,'Some child',pageIcon);       node2aa.addChild(node2aaa);       node2aa.addChild(node2aab);       node2aa.addChild(node2aac);     node2a.addChild(node2aa);   var node2b = new TreeNode(9,'2nd subpage to Node 2',pageIcon);   var node2c = new TreeNode(10,'3rd subpageto Node 2',pageIcon);   node2.addChild(node2a);   node2.addChild(node2b);   node2.addChild(node2c); var node3 = new TreeNode(11,'subpage 3',new Array(closedGif,openGif));   var node3a = new TreeNode(12,'Yet another child',pageIcon);   node3.addChild(node3a); var node4 = new TreeNode(13,'subpage 4',userIcon); // rootNode.addChild(node1); rootNode.addChild(node2); rootNode.addChild(node3); // rootNode.addChild(node4); </script> <style type="text/css"> div,p,a {   font-family: Verdana,Arial;   font-size: 11px; } #exampletable {   width: 100%;   height: 100%; } #examplediv {   width: 250px;   height: 100%;   overflow: auto; } .explanation {   font-weight: bold;   font-style: italic; } </style> </head> <body OnLoad="init();"> <table id="exampletable">   <tr>     <td valign="top" style="width: 250px;">       <div id="examplediv"></div>     </td>     <td valign="top">       <div style="background-color:#EEE;border-style:dashed;border-color:#000000;border-width:1px;padding:5px;">         <div style="font-weight: bold;">NanoTree.</div>         <div id="mytext">         <p>NanoTree is a JavaScript tree, published under the <a href="http://www.gnu.org/copyleft/lesser.html">LGPL License</a>, which is developed to work in (at least) Internet Explorer and Mozilla<br>         <p style="font-style:italic;">CopyRight Martin Mouritzen</p>         </div>       </div>       <br>     </td>   </tr> </table> </body></html>                          nanotree.zip( 15 k)