]> code.citadel.org Git - citadel.git/blobdiff - webcit/static/nanotree.js
Revert "serv_rssclient.c: style update"
[citadel.git] / webcit / static / nanotree.js
diff --git a/webcit/static/nanotree.js b/webcit/static/nanotree.js
new file mode 100644 (file)
index 0000000..c22b7d5
--- /dev/null
@@ -0,0 +1,910 @@
+/**\r
+* Original Author of this file: Martin Mouritzen. (martin@nano.dk)\r
+*\r
+*\r
+* (Lack of) Documentation:\r
+*\r
+*\r
+* If a finishedLoading method exists, it will be called when the tree is loaded.\r
+* (good to display a div, etc.).\r
+*\r
+*\r
+* You have to set the variable rootNode (as a TreeNode).\r
+*\r
+* You have to set a container element, this is the element in which the tree will be.\r
+*\r
+*\r
+* TODO: \r
+* Save cookies better (only 1 cookie for each tree). Else the page will totally cookieclutter.\r
+*\r
+***********************************************************************\r
+* Configuration variables.\r
+************************************************************************/\r
+\r
+// Should the rootNode be displayed.\r
+var showRootNode = true;\r
+\r
+// Should the dashed lines between nodes be shown.\r
+var showLines = true;\r
+\r
+// Should the nodes be sorted? (You can either specify a number, then it will be sorted by that, else it will\r
+// be sorted alphabetically (by name).\r
+var sortNodes = true;\r
+\r
+// This is IMPORTANT... use an unique id for each document you use the tree in. (else they'll get mixed up).\r
+var documentID = window.location.href;\r
+\r
+// being read from cookie.\r
+var nodesOpen = new Array();\r
+\r
+// RootNode of the tree.\r
+var rootNode;\r
+\r
+// Container to display the Tree in.\r
+var container;\r
+\r
+// Shows/Hides subnodes on startup\r
+var showAllNodesOnStartup = false;\r
+\r
+// Is the roots dragable?\r
+var dragable = false;\r
+\r
+\r
+/************************************************************************\r
+* The following is just instancevariables.\r
+************************************************************************/\r
+var href = '';\r
+\r
+// rootNodeCallBack name (if null, it's not selectable).\r
+var rootNodeCallBack = null;\r
+\r
+// selectedNode\r
+var selectedNode = null;\r
+\r
+var states = '';\r
+var statearray = new Array();\r
+\r
+var treeNodeEdited = null;\r
+\r
+var editaborted = false;\r
+\r
+var floatDragElement = null;\r
+var colouredElement = null;\r
+var draggedNodeID = null;\r
+var lastDraggedOnNodeID = null;\r
+\r
+\r
+/**\r
+* The TreeNode Object\r
+* @param id unique id of this treenode\r
+* @param name The title of this node\r
+* @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)\r
+* @param param A parameter, this can be pretty much anything. (eg. an array with information).\r
+* @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).\r
+*/\r
+function TreeNode(id,name,icon,param,orderNumber) {\r
+       this.id = id;\r
+       this.childs = new Array();\r
+       this.name = (name == null ? 'unset name' : name);\r
+       this.icon = (icon == null ? '' : icon);\r
+       this.parent = null;\r
+       this.handler = null;\r
+       this.param = (param == null ? '' : param);\r
+       this.orderNumber = (orderNumber == null ? -1 : orderNumber);\r
+       \r
+       this.openeventlisteners = new Array();\r
+       this.editeventlisteners = new Array();\r
+       this.moveeventlisteners = new Array();\r
+       this.haschilds = false;\r
+       this.editable = false;\r
+       this.linestring = '';\r
+       \r
+       this.nextSibling = null;\r
+       this.prevSibling = null;\r
+       \r
+       this.childsHasBeenFetched = false;\r
+\r
+       this.getID = function() {\r
+               return this.id;\r
+       }\r
+       this.setName = function(newname) {\r
+               this.name = newname;\r
+       }\r
+       this.getName = function() {\r
+               return this.name;\r
+       }\r
+       this.getParam = function() {\r
+               return this.param;\r
+       }\r
+       this.setIcon = function(icon) {\r
+               this.icon = icon;\r
+       }\r
+       this.getIcon = function() {\r
+               if (typeof(this.icon) == 'object') {\r
+                       return this.icon[0];\r
+               }\r
+               return this.icon;\r
+       }\r
+       this.getOpenIcon = function() {\r
+               if (typeof(this.icon) == 'object') {\r
+                       return this.icon[1];\r
+               }\r
+               return this.icon;\r
+       }\r
+       this.hasIcon = function () {\r
+               return this.icon != '';\r
+       }\r
+       this.getOrderNumber = function() {\r
+               return this.orderNumber;\r
+       }\r
+       this.addOpenEventListener = function(event) {\r
+               this.openeventlisteners[this.openeventlisteners.length] = event;\r
+       }\r
+       this.gotOpenEventListeners = function() {\r
+               return (this.openeventlisteners.length > 0);\r
+       }\r
+       this.addEditEventListener = function(event) {\r
+               this.editeventlisteners[this.editeventlisteners.length] = event;\r
+       }\r
+       this.gotEditEventListeners = function() {\r
+               return (this.editeventlisteners.length > 0);\r
+       }\r
+       this.addMoveEventListener = function(event) {\r
+               this.moveeventlisteners[this.moveeventlisteners.length] = event;\r
+       }\r
+       this.gotMoveEventListeners = function() {\r
+               return (this.moveeventlisteners.length > 0);\r
+       }\r
+       this.addChild = function(childNode) {\r
+               var possiblePrevNode = this.childs[this.childs.length - 1]\r
+               if (possiblePrevNode) {\r
+                       possiblePrevNode.nextSibling = childNode;\r
+                       childNode.prevSibling = possiblePrevNode;\r
+                       // alert(childNode.prevSibling);\r
+               }\r
+\r
+               this.childs[this.childs.length] = childNode;\r
+               childNode.setParent(this);\r
+\r
+               if (sortNodes) {\r
+                       function sortByOrder(a,b) {\r
+                               var order1 = a.getOrderNumber();\r
+                               var order2 = b.getOrderNumber();\r
+                               if (order1 == -1 || order2 == -1) {\r
+                                       return a.getName().toLowerCase() > b.getName().toLowerCase() ? 1 : -1;\r
+                               }\r
+                               else {\r
+                                       if (order1 == order2) {\r
+                                               // If they got the same order number, then we'll sort by their title.\r
+                                               return a.getName().toLowerCase() > b.getName().toLowerCase() ? 1 : -1;\r
+                                       }\r
+                                       else {\r
+                                               return order1 - order2;\r
+                                       }\r
+                               }\r
+                       }\r
+                       this.childs.sort(sortByOrder);\r
+               }\r
+       }\r
+       this.removeChild = function(childNode) {\r
+               var found = false;\r
+               for (var i=0;i<this.childs.length;i++) {\r
+                       if (found) {\r
+                               this.childs[i] = this.childs[i + 1];\r
+                       }\r
+                       if (this.childs[i] == childNode) {\r
+                               if (i == (this.childs.length - 1)) {\r
+                                       this.childs[i] = null;\r
+                               }\r
+                               else {\r
+                                       this.childs[i] = this.childs[i + 1];\r
+                               }\r
+                               found = true;\r
+                       }\r
+               }\r
+               if (found) {\r
+                       this.childs.length = this.childs.length-1;\r
+               }\r
+       }\r
+       this.resetChilds = function() {\r
+               this.childs = new Array();\r
+       }\r
+       this.setHasChilds = function(hasChilds) {\r
+               this.haschilds = hasChilds;\r
+       }\r
+       this.hasChilds = function() {\r
+               if (this.haschilds == true) {\r
+                       return true;\r
+               }\r
+               return (this.childs.length > 0);\r
+       }\r
+       this.getChildCount = function() {\r
+               return this.childs.length;\r
+       }\r
+       this.getFirstChild = function() {\r
+               if (this.hasChilds()) {\r
+                       return this.childs[0];\r
+               }\r
+               return null;\r
+       }\r
+       this.gotHandler = function() {\r
+               return this.handler != null;\r
+       }\r
+       this.setHandler = function(handler) {\r
+               this.handler = handler;\r
+       }\r
+       this.getHandler = function() {\r
+               return this.handler;\r
+       }\r
+       this.setParent = function(parent) {\r
+               this.parent = parent;\r
+       }\r
+       this.getParent = function() {\r
+               return this.parent;\r
+       }\r
+       this.getLineString = function() {\r
+               return this.linestring;\r
+       }\r
+       this.setLineString = function(string) {\r
+               this.linestring = string;\r
+       }\r
+       this.isEditable = function() {\r
+               return this.editable;\r
+       }\r
+       this.setEditable = function(editable) {\r
+               this.editable = editable;\r
+       }\r
+       \r
+}\r
+function getTreeNode(nodeID) {\r
+       return findNodeWithID(rootNode,nodeID);\r
+}\r
+function findNodeWithID(node,nodeID) {\r
+       if (node.getID() == nodeID) {\r
+               return node;\r
+       }\r
+       else {\r
+               if (node.hasChilds()) {\r
+                       for(var i=0;i<node.getChildCount();i++) {\r
+                               var value = findNodeWithID(node.childs[i],nodeID);\r
+                               if (value != false) {\r
+                                       return value;\r
+                               }\r
+                       }\r
+               }\r
+               return false;\r
+       }\r
+}\r
+function readStates() {\r
+       //setCookie('tree' + documentID,'');\r
+       states = getCookie('tree' + documentID);\r
+       if (states != null) {\r
+               var array = states.split(';');\r
+               for(var i=0;i<array.length;i++) {\r
+                       var singlestate = array[i].split('|');\r
+                       statearray[i] = new Array();\r
+                       statearray[i]["key"] = singlestate[0];\r
+                       statearray[i]["state"]  = singlestate[1];\r
+               }\r
+       }\r
+}\r
+function getState(nodeID) {\r
+       for(var i=0;i<statearray.length;i++) {\r
+               if (statearray[i]["key"] == nodeID) {\r
+                       state = statearray[i]["state"];\r
+                       if (state == null || state == '') {\r
+                               state = 'closed';\r
+                       }\r
+                       return state;\r
+               }\r
+       }\r
+       return "closed";\r
+}\r
+function writeStates(nodeID,newstate) {\r
+       //alert(nodeID);\r
+       var str = '';\r
+       var found = false;\r
+       for(var i=0;i<statearray.length;i++) {\r
+               if (statearray[i]["key"] == nodeID) {\r
+                       statearray[i]["state"] = newstate;\r
+                       found = true;\r
+               }\r
+               if (statearray[i]["state"] != null) {\r
+                       str += statearray[i]["key"] + '|' + statearray[i]["state"] + ';';\r
+               }\r
+       }\r
+       if (found == false) {\r
+               statearray[statearray.length] = new Array();\r
+               statearray[statearray.length - 1]["key"] = nodeID;\r
+               statearray[statearray.length - 1]["state"] = newstate;\r
+               if (newstate != null) {\r
+                       str += nodeID + '|' + newstate + ';';\r
+               }\r
+       }\r
+       setCookie('tree' + documentID,str);\r
+}\r
+function showTree(path) {\r
+       readStates();\r
+       \r
+       href = path;\r
+       window.focus();\r
+       window.onblur = blurSelection;\r
+       window.onfocus = focusSelection;\r
+       var str = '';\r
+       str = '<div id="node' + rootNode.getID() + '" class="treetitle" style="display:' + (showRootNode == true ? 'block' : 'none') + '">';\r
+       str += '<nobr>';\r
+       if (rootNode.hasIcon()) {\r
+               str += '<img src="' + rootNode.getIcon() + '" style="vertical-align:middle;">';\r
+       }\r
+       str += '<span style="vertical-align:middle;">&nbsp;' + rootNode.getName() + '</span>';\r
+       str += '</nobr></div>';\r
+       \r
+       if (rootNode.hasChilds()) {\r
+               for(i=0;i<rootNode.childs.length;i++) {\r
+                       nodeContents = showNode(rootNode.childs[i],(i == (rootNode.getChildCount() -1)));\r
+                       str = str + nodeContents;\r
+               }\r
+       }\r
+       container.innerHTML = str;\r
+       if (window.finishedLoading) {\r
+               finishedLoading();\r
+       }\r
+}\r
+/**\r
+* Shows the given node, and subnodes.\r
+*/\r
+function showNode(treeNode,lastNode) {\r
+       linestring = treeNode.getLineString();\r
+       var state = getState(treeNode.getID());\r
+       var str;\r
+       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() + '">';\r
+       str += '<nobr>';\r
+       for(var y=0;y<linestring.length;y++) {\r
+               if (linestring.charAt(y) == 'I') {\r
+                       str += '<img src="' + href + 'static/' + (showLines ? 'line' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';\r
+               }\r
+               else if (linestring.charAt(y) == 'B') {\r
+                       str += '<img src="' + href + 'static/white.gif" style="width:19px;height:20px;vertical-align:middle;">';\r
+               }\r
+       }\r
+       if (treeNode.hasChilds()) {\r
+               // If this is the first child of the rootNode, and showRootNode is false, we want to display a different icon.\r
+               if (!showRootNode && (treeNode.getParent() == rootNode) && (treeNode.getParent().getFirstChild() == treeNode)) {\r
+                       if (!lastNode) {\r
+                               str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'static/' + (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() + ');">';\r
+                       }\r
+                       else {\r
+                               str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'static/' + (state == 'open' ? 'minus_last' : 'plus_last') + '_no_root.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';\r
+                       }\r
+               }\r
+               else {\r
+                       if (!lastNode) {\r
+                               str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'static/' + (state == 'open' ? (showLines ? 'minus' : 'minus_nolines') : (showLines ? 'plus' : 'plus_nolines')) + '.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';\r
+                       }\r
+                       else {\r
+                               str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'static/' + (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() + ');">';\r
+                       }\r
+               }\r
+       }\r
+       else {\r
+               // If this is the first child of the rootNode, and showRootNode is false, we want to display a different icon.\r
+               if (!showRootNode && (treeNode.getParent() == rootNode) && (treeNode.getParent().getFirstChild() == treeNode)) {\r
+                       if (!lastNode) {\r
+                               str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'static/' + (showLines ? 't_no_root' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';\r
+                       }\r
+                       else {\r
+                               str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'static/white.gif" style="width:19px;height:20px;vertical-align:middle;">';\r
+                       }\r
+               }\r
+               else {\r
+                       if (!lastNode) {\r
+                               str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'static/' + (showLines ? 't' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';\r
+                       }\r
+                       else {\r
+                               str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'static/' + (showLines ? 'lastnode' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';\r
+                       }\r
+               }\r
+       }\r
+       iconStartImage = treeNode.getIcon();\r
+       if (state != 'closed') {\r
+               if (treeNode.hasChilds()) {\r
+                       iconStartImage = treeNode.getOpenIcon();\r
+               }\r
+       }\r
+       \r
+       str += '<img id="iconimage' + treeNode.getID() + '" src="' + iconStartImage + '" style="vertical-align:middle;" OnClick="selectNode(' + treeNode.getID() + ')">';\r
+       str += '&nbsp;<span unselectable="ON" style="vertical-align:middle;" class="treetitle" ID="title' + treeNode.getID() + '" OnDblClick="handleNode(' + treeNode.getID() + ')" OnClick="selectNode(' + treeNode.getID() + ')">';\r
+       str += treeNode.getName();\r
+       str += '</span>';\r
+       str += '</nobr>';\r
+       str += '</div>';\r
+\r
+       if (treeNode.hasChilds()) {\r
+               if (state == 'open') {\r
+                       str += '<div id="node' + treeNode.getID() + 'sub" style="display:block;">';\r
+                       fireOpenEvent(treeNode);\r
+                       // alert('openevent: ' + treeNode.getName());\r
+               }\r
+               else {\r
+                       str += '<div id="node' + treeNode.getID() + 'sub" style="display:' + (showAllNodesOnStartup == true ? 'block;' : 'none;') + ';">';\r
+               }\r
+               var subgroupstr = '';\r
+               var newChar = '';\r
+\r
+               if (!lastNode) {\r
+                       newChar = 'I';\r
+               }\r
+               else {\r
+                       newChar = 'B';\r
+               }\r
+               for(var z=0;z<treeNode.getChildCount();z++) {\r
+                       treeNode.childs[z].setLineString(linestring + newChar);\r
+               }\r
+               for(var z=0;z<treeNode.getChildCount();z++) {\r
+                       subgroupstr += showNode(treeNode.childs[z],(z == (treeNode.getChildCount() -1)));\r
+               }\r
+               str += subgroupstr;\r
+               str += '</div>';\r
+       }\r
+       else {\r
+               str += '<div id="node' + treeNode.getID() + 'sub" style="display:none;">';\r
+               str += '</div>';\r
+       }\r
+       return str;\r
+}\r
+/*\r
+function mouseMove() {\r
+       if (dragging) {\r
+               alert('bob');\r
+       }\r
+}\r
+function mouseUp() {\r
+       if (dragging) {\r
+               alert('dropped on something!');\r
+       }\r
+}\r
+*/\r
+function startDrag(nodeID) {\r
+       if (!dragable) {\r
+               return;\r
+       }\r
+       draggedNodeID = nodeID;\r
+       \r
+       var srcObj = window.event.srcElement;\r
+       while(srcObj.tagName != 'DIV') {\r
+               srcObj = srcObj.parentElement;\r
+       }\r
+       floatDragElement = document.createElement('DIV');\r
+\r
+       floatDragElement.innerHTML = srcObj.innerHTML;\r
+       floatDragElement.childNodes[0].removeChild(floatDragElement.childNodes[0].childNodes[0]);\r
+       \r
+       document.body.appendChild(floatDragElement);\r
+       floatDragElement.style.zIndex = 100;\r
+       floatDragElement.style.position = 'absolute';\r
+       floatDragElement.style.filter='progid:DXImageTransform.Microsoft.Alpha(1,opacity=60);';\r
+}\r
+function findSpanChild(element) {\r
+       if (element.tagName == 'SPAN') {\r
+               return element;\r
+       }\r
+       else {\r
+               if (element.childNodes) {\r
+                       for(var i=0;i<element.childNodes.length;i++) {\r
+                               var value = findSpanChild(element.childNodes[i]);\r
+                               if (value != false) {\r
+                                       return value;\r
+                               }\r
+                       }\r
+                       return false;\r
+               }\r
+       }\r
+}\r
+function dragEnter(nodeID) {\r
+       if (!dragable) {\r
+               return;\r
+       }\r
+       lastDraggedOnNodeID = nodeID;\r
+       \r
+       if (colouredElement) {\r
+               findSpanChild(colouredElement).className = 'treetitle';\r
+       }\r
+       colouredElement = window.event.srcElement;\r
+       while(colouredElement.tagName != 'DIV') {\r
+               colouredElement = colouredElement.parentElement;\r
+               if (colouredElement.tagName == 'BODY') {\r
+                       // Something gone seriously wrong.\r
+                       alert('Drag failure, reached <BODY>!');\r
+                       return;\r
+               }\r
+       }       \r
+       findSpanChild(colouredElement).className = 'treetitleselectedfocused';\r
+}\r
+function dragLeave() {\r
+       if (!dragable) {\r
+               return;\r
+       }\r
+}\r
+function endDrag(nodeID) {\r
+       if (!dragable) {\r
+               return;\r
+       }\r
+       if (lastDraggedOnNodeID != null) {\r
+               fireMoveEvent(getTreeNode(lastDraggedOnNodeID),draggedNodeID,lastDraggedOnNodeID);\r
+       }\r
+}\r
+function dragProceed() {\r
+       if (!dragable) {\r
+               return;\r
+       }\r
+       var dragged = getTreeNode(draggedNodeID);\r
+       var newparent = getTreeNode(lastDraggedOnNodeID);\r
+\r
+       var oldparent = dragged.getParent();\r
+       \r
+       oldparent.removeChild(dragged);\r
+       newparent.addChild(dragged);\r
+       \r
+       refreshNode(oldparent);\r
+       refreshNode(newparent);\r
+       \r
+       _dragClean()\r
+}\r
+function dragCancel() {\r
+       if (!dragable) {\r
+               return;\r
+       }\r
+       _dragClean()\r
+}\r
+/**\r
+* Don't call this yourself.\r
+*/\r
+function _dragClean() {\r
+       if (!dragable) {\r
+               return;\r
+       }\r
+       if (colouredElement) {\r
+               findSpanChild(colouredElement).className = 'treetitle';\r
+       }\r
+       \r
+       floatDragElement.parentElement.removeChild(floatDragElement);\r
+       floatDragElement = null;\r
+       colouredElement = null;\r
+       draggedNodeID = null;\r
+       lastDraggedOnNodeID = null;\r
+}\r
+function dragMove() {\r
+       if (!dragable) {\r
+               return;\r
+       }\r
+       floatDragElement.style.top = window.event.clientY;\r
+       floatDragElement.style.left = window.event.clientX;\r
+}\r
+function editEnded() {\r
+       if (treeNodeEdited != null) {\r
+               // treeNodeEdited.getID();\r
+               var editTitle = document.getElementById('title' + treeNodeEdited.getID());\r
+               var input = editTitle.childNodes[0];\r
+       \r
+               var newValue = input.value;\r
+               \r
+               if (newValue == treeNodeEdited.getName()) {\r
+                       editTitle.innerHTML = newValue;\r
+                       treeNodeEdited = null;\r
+                       return;\r
+               }\r
+       \r
+               fireEditEvent(treeNodeEdited,newValue);\r
+               \r
+               if (!editaborted) {\r
+                       treeNodeEdited.setName(newValue);\r
+                       editTitle.innerHTML = newValue;\r
+               }\r
+       \r
+               treeNodeEdited = null;\r
+       }\r
+}\r
+function selectNode(nodeID) {\r
+       var treeNode = getTreeNode(nodeID);\r
+\r
+       if (selectedNode != null) {\r
+               if (selectedNode == nodeID) {\r
+                       if (treeNode.isEditable()) {\r
+                               if (treeNodeEdited == treeNode) {\r
+                                       return;\r
+                               }\r
+                               treeNodeEdited = treeNode;\r
+                               var editTitle = document.getElementById('title' + treeNode.getID());\r
+                               editTitle.className = 'editednode';\r
+                               \r
+\r
+                               editTitle.innerHTML = '<input type="text" onKeypress="if (event.keyCode == 13) { this.onblur = null; editEnded(); }" name="editednode" class="editednodeinput">';\r
+                               var input = editTitle.childNodes[0];\r
+                               input.value = treeNode.getName();\r
+                               input.focus();\r
+                               input.select();\r
+                               input.onblur = editEnded;\r
+                       }\r
+                       return;\r
+               }\r
+               if (treeNodeEdited != null) {\r
+                       editEnded();\r
+               }\r
+               var oldNodeTitle = document.getElementById('title' + selectedNode);\r
+               oldNodeTitle.className = 'treetitle';\r
+       }\r
+       selectedNode = nodeID;\r
+       var nodetitle = document.getElementById('title' + selectedNode);\r
+       nodetitle.className = 'treetitleselectedfocused';\r
+       \r
+       if (treeNode.gotHandler()) {\r
+               eval(treeNode.getHandler() + '(getTreeNode(' + nodeID + '));');\r
+       }\r
+       else {\r
+               standardClick(treeNode);\r
+       }\r
+}\r
+function refreshNode(treeNode) {\r
+       var submenu = document.getElementById('node' + treeNode.getID() + 'sub');\r
+       var str = '';\r
+       for(var i=0;i<treeNode.getChildCount();i++) {\r
+               var parent = treeNode.getParent();\r
+               if (!parent) {\r
+                       treeNode.childs[i].setLineString(treeNode.getLineString() + 'B');\r
+               }\r
+               else {\r
+                       if (parent.childs[parent.childs.length - 1] == treeNode) {\r
+                               treeNode.childs[i].setLineString(treeNode.getLineString() + 'B');\r
+                       }\r
+                       else {\r
+                               treeNode.childs[i].setLineString(treeNode.getLineString() + 'I');\r
+                       }\r
+               }\r
+               str += showNode(treeNode.childs[i],i == (treeNode.getChildCount() - 1));\r
+       }\r
+       var actionimage = document.getElementById('handler' + treeNode.getID());\r
+       if (treeNode.getChildCount() == 0) {\r
+               // TreeNode haven't got any children, make sure the right image is displayed.\r
+               if (actionimage.src.indexOf('last') == -1) {\r
+                       actionimage.src = href + 'static/' + (showLines ? 't' : 'white') + '.gif';\r
+               }\r
+               else {\r
+                       actionimage.src = href + 'static/' + (showLines ? 'lastnode' : 'white') + '.gif';\r
+               }\r
+               actionimage.onclick = null;\r
+               \r
+               // Close the submenu\r
+               if (submenu) {\r
+                       submenu.style.display = 'none';\r
+               }\r
+       }\r
+       else {\r
+               // We have children, make sure to display the + and - icon.\r
+               if (actionimage.src.indexOf('plus') != -1) {\r
+                       // The TreeNode have already got children, and displays them.\r
+               }\r
+               else if (actionimage.src.indexOf('minus') != -1) {\r
+                       // The TreeNode have already got children, and displays them.\r
+               }\r
+               else {\r
+                       if (actionimage.src.indexOf('last') == -1) {\r
+                               actionimage.outerHTML = '<img id="handler' + treeNode.getID() + '" src="' + href + 'static/' + (showLines ? 'plus' : 'plus_nolines') + '.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';\r
+                       }\r
+                       else {\r
+                               actionimage.outerHTML = '<img id="handler' + treeNode.getID() + '" src="' + href + 'static/plus_last.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';\r
+                       }\r
+               }\r
+       }\r
+       submenu.innerHTML = str;\r
+}\r
+function handleNode(nodeID) {\r
+       var treeNode = getTreeNode(nodeID);     \r
+       if (!treeNode.hasChilds()) { // No reason to handle a node without childs.\r
+               return;\r
+       }\r
+       \r
+       var submenu = document.getElementById('node' + nodeID + 'sub');\r
+       \r
+       var iconimageholder = document.getElementById('iconimage' + nodeID);\r
+       var actionimage = document.getElementById('handler' + nodeID);\r
+\r
+       // This will be used if showRootNode is set to false.\r
+       var firstChildOfRoot = false;\r
+       if (actionimage.src.indexOf('_no_root') != -1) {\r
+               firstChildOfRoot = true;\r
+       }\r
+       \r
+       if (submenu.style.display == 'none') {\r
+               writeStates(nodeID,'open');\r
+               fireOpenEvent(treeNode);\r
+               submenu.style.display = 'block';\r
+\r
+               iconimageholder.src = treeNode.getOpenIcon();\r
+       \r
+               if (actionimage.src.indexOf('last') == -1) {\r
+                       actionimage.src = href + 'static/' + ((firstChildOfRoot) ? 'minus_no_root' : (showLines ? 'minus' : 'minus_nolines')) + '.gif';\r
+               }\r
+               else {\r
+                       actionimage.src = href + 'static/' + ((firstChildOfRoot) ? 'minus_last_no_root' : (showLines ? 'minus_last' : 'minus_nolines')) + '.gif';\r
+               }\r
+       }\r
+       else {\r
+               writeStates(nodeID,'closed');\r
+               submenu.style.display = 'none';\r
+               \r
+               iconimageholder.src = treeNode.getIcon();\r
+               \r
+               if (actionimage.src.indexOf('last') == -1) {\r
+                       actionimage.src = href + 'static/' + ((firstChildOfRoot) ? 'plus_no_root' : (showLines ? 'plus' : 'plus_nolines')) + '.gif';\r
+               }\r
+               else {\r
+                       actionimage.src = href + 'static/' + ((firstChildOfRoot) ? 'plus_last_no_root' : (showLines ? 'plus_last' : 'plus_nolines')) + '.gif';\r
+               }\r
+       }\r
+}\r
+function fireOpenEvent(treeNode) {\r
+       if (treeNode.gotOpenEventListeners()) {\r
+               for(var i=0;i<treeNode.openeventlisteners.length;i++) {\r
+                       eval(treeNode.openeventlisteners[i] + '(' + treeNode.getID() + ');');\r
+               }\r
+       }\r
+}\r
+function fireEditEvent(treeNode,newVal) {\r
+       if (treeNode.gotEditEventListeners()) {\r
+               for(var i=0;i<treeNode.editeventlisteners.length;i++) {\r
+                       eval(treeNode.editeventlisteners[i] + '(' + treeNode.getID() + ',\'' + escape(newVal) + '\');');\r
+               }\r
+       }\r
+}\r
+function fireMoveEvent(treeNode,draggedNodeID,droppedOnNodeID) {\r
+       if (treeNode.gotMoveEventListeners()) {\r
+               for(var i=0;i<treeNode.moveeventlisteners.length;i++) {\r
+                       eval(treeNode.moveeventlisteners[i] + '(' + draggedNodeID + ',' + droppedOnNodeID + ');');\r
+               }\r
+       }\r
+}\r
+function blurSelection() {\r
+       if (selectedNode != null) {\r
+               var oldNodeTitle = document.getElementById('title' + selectedNode);\r
+               oldNodeTitle.className = 'treetitleselectedblured';\r
+       }\r
+}\r
+function focusSelection() {\r
+       if (selectedNode != null) {\r
+               var oldNodeTitle = document.getElementById('title' + selectedNode);\r
+               oldNodeTitle.className = 'treetitleselectedfocused';\r
+       }\r
+}\r
+function getCookieVal (offset) {  \r
+       var endstr = document.cookie.indexOf (";",offset);  \r
+       if (endstr == -1) {\r
+               endstr = document.cookie.length;\r
+       }\r
+       return unescape(document.cookie.substring(offset,endstr));\r
+}\r
+function getCookie (name) {  \r
+       var arg = name + "=";\r
+       var alen = arg.length;\r
+       var clen = document.cookie.length;\r
+       var i = 0;\r
+       while (i < clen) {\r
+               var j = i + alen;\r
+               if (document.cookie.substring(i, j) == arg) {\r
+                       return getCookieVal(j);\r
+               }\r
+               i = document.cookie.indexOf(" ", i) + 1;\r
+               if (i == 0) {\r
+                       break;\r
+               }\r
+       }\r
+       return null;\r
+}\r
+function setCookie (name, value) {  \r
+       var argv = setCookie.arguments;  \r
+       var argc = setCookie.arguments.length;  \r
+       var expires = (argc > 2) ? argv[2] : null;  \r
+       var path = (argc > 3) ? argv[3] : null;  \r
+       var domain = (argc > 4) ? argv[4] : null;  \r
+       var secure = (argc > 5) ? argv[5] : false;  \r
+       document.cookie = name + "=" + escape (value) + ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) + ((path == null) ? "" : ("; path=" + path)) + ((domain == null) ? "" : ("; domain=" + domain)) + ((secure == true) ? "; secure" : "");\r
+}\r
+function expandNode() {\r
+       var state = getState(selectedNode);\r
+       if (state == 'open') {\r
+               var currentTreeNode = getTreeNode(selectedNode);\r
+               if (currentTreeNode.hasChilds()) {\r
+                       selectNode(currentTreeNode.childs[0].getID());\r
+               }\r
+       }\r
+       else {\r
+               handleNode(selectedNode);\r
+       }\r
+}\r
+function subtractNode() {\r
+       var state = getState(selectedNode);\r
+       if (state == 'closed') {\r
+               var currentTreeNode = getTreeNode(selectedNode);\r
+               var parent = currentTreeNode.getParent();\r
+               if (parent != null && parent != rootNode) {\r
+                       selectNode(parent.getID());\r
+               }\r
+       }\r
+       else {\r
+               handleNode(selectedNode);\r
+       }\r
+}\r
+function selectPrevNode() {\r
+       var currentTreeNode = getTreeNode(selectedNode);\r
+       if (currentTreeNode.prevSibling != null) {\r
+\r
+               var state = getState(currentTreeNode.prevSibling.getID());\r
+\r
+               if (state == 'open' && currentTreeNode.prevSibling.hasChilds()) {\r
+                       // We have to find the last open child of the previoussiblings childs.\r
+                       var current = currentTreeNode.prevSibling.childs[currentTreeNode.prevSibling.childs.length - 1];\r
+                       var currentstate = 'open';\r
+                       while (current.hasChilds() && (getState(current.getID()) == 'open')) {\r
+                               current = current.childs[current.childs.length - 1];\r
+                       }\r
+                       selectNode(current.getID());\r
+               }\r
+               else {\r
+                       selectNode(currentTreeNode.prevSibling.getID());\r
+               }\r
+       }\r
+       else {\r
+               if (currentTreeNode.getParent() != null && currentTreeNode.getParent() != rootNode) {\r
+                       selectNode(currentTreeNode.getParent().getID());\r
+               }\r
+       }\r
+}\r
+function selectNextNode() {\r
+       var currentTreeNode = getTreeNode(selectedNode);\r
+\r
+       var state = getState(selectedNode);\r
+       if (state == 'open' && currentTreeNode.hasChilds()) {\r
+               selectNode(currentTreeNode.childs[0].getID());\r
+       }       \r
+       else {\r
+               if (currentTreeNode.nextSibling != null) {\r
+                       selectNode(currentTreeNode.nextSibling.getID());\r
+               }\r
+               else {\r
+                       // Continue up the tree until we either hit null, or a parent which have a child.\r
+                       var parent = currentTreeNode;\r
+                       while ((parent = parent.getParent()) != rootNode) {\r
+                               if (parent.nextSibling != null) {\r
+                                       selectNode(parent.nextSibling.getID());\r
+                                       break;\r
+                               }\r
+                       }\r
+                       /*\r
+                       if (currentTreeNode.getParent().nextSibling != null) {\r
+                               selectNode(currentTreeNode.getParent().nextSibling.getID());\r
+                       }\r
+                       */\r
+               }\r
+       }\r
+}\r
+function keyDown(event) {\r
+       if (window.event) {\r
+               event = window.event;\r
+       }\r
+       if (event.keyCode == 38) { // Up\r
+               selectPrevNode();\r
+               return false;\r
+       }\r
+       else if (event.keyCode == 40) { // Down\r
+               selectNextNode();\r
+               return false;\r
+       }\r
+       else if (event.keyCode == 37) { // left\r
+               subtractNode();\r
+               return false;\r
+       }\r
+       else if (event.keyCode == 39) { // right\r
+               expandNode();\r
+               return false;\r
+       }\r
+}\r
+document.onkeydown = keyDown;\r