|
From: FlorinCB <ory...@us...> - 2008-09-18 00:44:08
|
Update of /cvsroot/mxbb/mx_music/phpbb2/mx_mod/mx_shared/mygosumenu/1.5 In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv19367/mx_mod/mx_shared/mygosumenu/1.5 Added Files: DynamicTree.css DynamicTree.js DynamicTree.txt DynamicTreeBuilder.js actions.js example1.html example2.html help.html plugins.js Log Message: upgrade --- NEW FILE: DynamicTree.js --- // +---------------------------------------------------------------+ // | DO NOT REMOVE THIS | // +---------------------------------------------------------------+ // | DynamicTree 1.5.2 | // | Author: Cezary Tomczak [www.gosu.pl] | // | Free for any use as long as all copyright messages are intact | // +---------------------------------------------------------------+ function DynamicTree(id) { this.foldersAsLinks = false; this.path = "images/"; this.img = { "branch": "tree-branch.gif", "doc": "tree-doc.gif", "folder": "tree-folder.gif", "folderOpen": "tree-folder-open.gif", "leaf": "tree-leaf.gif", "leafEnd": "tree-leaf-end.gif", "node": "tree-node.gif", "nodeEnd": "tree-node-end.gif", "nodeOpen": "tree-node-open.gif", "nodeOpenEnd": "tree-node-open-end.gif" }; this.cookiePath = ""; this.cookieDomain = ""; this.init = function() { var p, img; for (p in this.img) { this.img[p] = this.path + this.img[p]; } for (p in this.img) { this.imgObjects.push(new Image()); this.imgObjects.getLast().src = this.img[p]; this.img[p] = this.imgObjects.getLast().src; } this.parse(document.getElementById(this.id).childNodes, this.tree, 1); this.loadState(); if (window.addEventListener) { window.addEventListener("unload", function(e) { self.saveState(); }, false); } else if (window.attachEvent) { window.attachEvent("onunload", function(e) { self.saveState(); }); } this.updateHtml(); }; this.parse = function(nodes, tree) { for (var i = 0; i < nodes.length; i++) { if (nodes[i].nodeType == 1) { if (!nodes[i].className) { continue; } if (!nodes[i].id) { nodes[i].id = this.id + "-" + (++this.count); } var node = new Node(); node.id = nodes[i].id; if (nodes[i].firstChild) { if (nodes[i].firstChild.tagName == "A") { var a = nodes[i].firstChild; if (a.firstChild) { node.text = a.firstChild.nodeValue.trim(); } if (a.href) { node.href = a.href; } if (a.title) { node.title = a.title; } if (a.target) { node.target = a.target; } } else { node.text = nodes[i].firstChild.nodeValue.trim(); } } node.parentNode = tree; node.childNodes = (nodes[i].className == "folder" ? new Array() : null); node.isDoc = (nodes[i].className == "doc"); node.isFolder = (nodes[i].className == "folder"); tree.childNodes.push(node); this.allNodes[node.id] = node; } if (nodes[i].nodeType == 1 && nodes[i].childNodes) { this.parse(nodes[i].childNodes, tree.childNodes.getLast()); } } }; this.nodeClick = function(id) { var el = document.getElementById(id+"-section"); var node = document.getElementById(id+"-node"); var icon = document.getElementById(id+"-icon"); if (el.style.display == "block") { el.style.display = "none"; if (this.allNodes[id].isLast()) { node.src = this.img.nodeEnd; } else { node.src = this.img.node; } icon.src = this.img.folder; this.opened.removeByValue(id); } else { el.style.display = "block"; if (this.allNodes[id].isLast()) { node.src = this.img.nodeOpenEnd; } else { node.src = this.img.nodeOpen; } icon.src = this.img.folderOpen; this.opened.push(id); } /* fix ie bug - images not showing */ if (node.outerHTML) { node.outerHTML = node.outerHTML; } if (icon.outerHTML) { icon.outerHTML = icon.outerHTML; } }; this.toHtml = function() { var s = ""; var nodes = this.tree.childNodes; for (var i = 0; i < nodes.length; i++) { s += nodes[i].toHtml(); } return s; }; this.updateHtml = function() { document.getElementById(this.id).innerHTML = this.toHtml(); }; this.loadState = function() { var opened = this.cookie.get("opened"); if (opened) { this.opened = opened.split("|"); this.opened.filter(function(id) { return self.allNodes[id] && self.allNodes[id].isFolder && self.allNodes[id].childNodes.length; }); } }; this.saveState = function() { if (this.opened.length) { this.cookie.set("opened", this.opened.join("|"), 3600*24*30, this.cookiePath, this.cookieDomain); } else { this.clearState(); } }; this.clearState = function() { this.cookie.del("opened"); }; function Node(id, text, parentNode, childNodes, isDoc, isFolder) { this.id = id; this.text = text; this.parentNode = parentNode; this.childNodes = childNodes; this.isDoc = isDoc; this.isFolder = isFolder; this.href = ""; this.title = ""; this.target = ""; this.isLast = function() { if (this.parentNode) { return this.parentNode.childNodes.getLast().id == this.id; } throw "DynamicTree.Node.isLast() failed, this func cannot be called for the root element"; }; this.toHtml = function() { var s = '<div class="?" id="?">'.format((this.isFolder ? "folder" : "doc"), this.id); if (this.isFolder) { var nodeIcon; if (this.childNodes.length) { nodeIcon = (self.opened.contains(this.id) ? (this.isLast() ? self.img.nodeOpenEnd : self.img.nodeOpen) : (this.isLast() ? self.img.nodeEnd : self.img.node)); } else { nodeIcon = (this.isLast() ? self.img.leafEnd : self.img.leaf); } var icon = ((self.opened.contains(this.id) && this.childNodes.length) ? self.img.folderOpen : self.img.folder); if (this.childNodes.length) { s += '<a href="javascript:void(0)" onclick="?.nodeClick(\'?\')">'.format(self.id, this.id); } s += '<img id="?-node" src="?" width="18" height="18" alt="" />'.format(this.id, nodeIcon); if (this.childNodes.length) { s += '</a>'; } s += '<img id="?-icon" src="?" width="18" height="18" alt="" />'.format(this.id, icon); if (self.foldersAsLinks) { s += '<a href="?"??>?</a>'.format(this.href, (this.title ? ' title="?"'.format(this.title) : ""), (this.target ? ' target="?"'.format(this.target) : ""), this.text); } else { s += this.text; } if (this.childNodes.length) { s += '<div class="section?" id="?-section"'.format((this.isLast() ? " last" : ""), this.id); if (self.opened.contains(this.id)) { s += ' style="display: block;"'; } s += '>'; for (var i = 0; i < this.childNodes.length; i++) { s += this.childNodes[i].toHtml(); } s += '</div>'; } } if (this.isDoc) { s += '<img src="?" width="18" height="18" alt="" /><img src="?" width="18" height="18" alt="" />'.format((this.isLast() ? self.img.leafEnd : self.img.leaf), self.img.doc); s += '<a href="?"??>?</a>'.format(this.href, (this.title ? ' title="?"'.format(this.title) : ""), (this.target ? ' target="?"'.format(this.target) : ""), this.text); } s += '</div>'; return s; }; } function Cookie() { this.get = function(name) { var cookies = document.cookie.split(";"); for (var i = 0; i < cookies.length; ++i) { var a = cookies[i].split("="); if (a.length == 2) { a[0] = a[0].trim(); a[1] = a[1].trim(); if (a[0] == name) { return unescape(a[1]); } } } return ""; }; this.set = function(name, value, seconds, path, domain, secure) { var cookie = (name + "=" + escape(value)); if (seconds) { var date = new Date(new Date().getTime()+seconds*1000); cookie += ("; expires="+date.toGMTString()); } cookie += (path ? "; path="+path : ""); cookie += (domain ? "; domain="+domain : ""); cookie += (secure ? "; secure" : ""); document.cookie = cookie; }; this.del = function(name) { document.cookie = name + "=; expires=Thu, 01-Jan-70 00:00:01 GMT"; }; } var self = this; this.id = id; this.tree = new Node("tree", "", null, new Array(), false, true); this.allNodes = {}; // id => object this.opened = []; // opened folders this.active = ""; // active node, text clicked this.cookie = new Cookie(); this.imgObjects = []; this.count = 0; } /* Check whether array contains given string */ if (!Array.prototype.contains) { Array.prototype.contains = function(s) { for (var i = 0; i < this.length; ++i) { if (this[i] === s) { return true; } } return false; }; } /* Remove elements with such value (mutates) */ if (!Array.prototype.removeByValue) { Array.prototype.removeByValue = function(value) { var i, indexes = []; for (i = 0; i < this.length; ++i) { if (this[i] === value) { indexes.push(i); } } for (i = indexes.length - 1; i >= 0; --i) { this.splice(indexes[i], 1); } }; } /* Remove elements judged 'false' by the passed function (mutates) */ if (!Array.prototype.filter) { Array.prototype.filter = function(func) { var i, indexes = []; for (i = 0; i < this.length; ++i) { if (!func(this[i])) { indexes.push(i); } } for (i = indexes.length - 1; i >= 0; --i) { this.splice(indexes[i], 1); } }; } /* Get the last element from the array */ if (!Array.prototype.getLast) { Array.prototype.getLast = function() { return this[this.length-1]; }; } /* Strip whitespace from the beginning and end of a string */ if (!String.prototype.trim) { String.prototype.trim = function() { return this.replace(/^\s*|\s*$/g, ""); }; } /* Replace ? tokens with variables passed as arguments in a string */ String.prototype.format = function() { if (!arguments.length) { throw "String.format() failed, no arguments passed, this = "+this; } var tokens = this.split("?"); if (arguments.length != (tokens.length - 1)) { throw "String.format() failed, tokens != arguments, this = "+this; } var s = tokens[0]; for (var i = 0; i < arguments.length; ++i) { s += (arguments[i] + tokens[i + 1]); } return s; }; --- NEW FILE: DynamicTreeBuilder.js --- // +---------------------------------------------------------------+ // | DO NOT REMOVE THIS | // +---------------------------------------------------------------+ // | DynamicTree 1.5.0 | // | Author: Cezary Tomczak [www.gosu.pl] | // | Free for any use as long as all copyright messages are intact | // +---------------------------------------------------------------+ function DynamicTreeBuilder(id) { this.path = "images/"; this.img = { "branch": "tree-branch.gif", "doc": "tree-doc.gif", "folder": "tree-folder.gif", "folderOpen": "tree-folder-open.gif", "leaf": "tree-leaf.gif", "leafEnd": "tree-leaf-end.gif", "node": "tree-node.gif", "nodeEnd": "tree-node-end.gif", "nodeOpen": "tree-node-open.gif", "nodeOpenEnd": "tree-node-open-end.gif" }; this.cookiePath = ""; this.cookieDomain = ""; this.init = function() { var p, img; for (p in this.img) { this.img[p] = this.path + this.img[p]; } for (p in this.img) { this.imgObjects.push(new Image()); this.imgObjects.getLast().src = this.img[p]; this.img[p] = this.imgObjects.getLast().src; } this.parse(document.getElementById(this.id).childNodes, this.tree); this.loadState(); if (window.addEventListener) { window.addEventListener("unload", function(e) { self.saveState(); }, false); } else if (window.attachEvent) { window.attachEvent("onunload", function(e) { self.saveState(); }); } this.updateHtml(); }; this.reset = function() { this.clearState(); this.tree = new Node("tree", "", null, new Array(), false, true); this.allNodes = {}; this.opened = []; this.active = ""; this.count = 0; this.parse(document.getElementById(this.id).childNodes, this.tree); this.updateHtml(); }; this.parse = function(nodes, tree) { for (var i = 0; i < nodes.length; i++) { if (nodes[i].nodeType == 1) { if (!nodes[i].className) { continue; } nodes[i].id = this.id + "-" + (++this.count); var node = new Node(); node.id = nodes[i].id; if (nodes[i].firstChild) { if (nodes[i].firstChild.tagName == "A") { var a = nodes[i].firstChild; if (a.firstChild) { node.text = a.firstChild.nodeValue.trim(); } if (a.href) { // dirty hack for ie (automatic conversion to absolute paths problem), see also DynamicTreePlugins.importFromHtml() var s = a.parentNode.innerHTML.match(/href=["'](dynamictree:\/\/dynamictree\/)?([^"']*)["']/i); if (s) { node.href = s[2]; } } if (a.title) { node.title = a.title; } if (a.target) { node.target = a.target; } } else { node.text = nodes[i].firstChild.nodeValue.trim(); } } node.parentNode = tree; node.childNodes = (nodes[i].className == "folder" ? new Array() : null); node.isDoc = (nodes[i].className == "doc"); node.isFolder = (nodes[i].className == "folder"); tree.childNodes.push(node); this.allNodes[node.id] = node; } if (nodes[i].nodeType == 1 && nodes[i].childNodes) { this.parse(nodes[i].childNodes, tree.childNodes.getLast()); } } }; this.nodeClick = function(id) { var el = document.getElementById(id+"-section"); var node = document.getElementById(id+"-node"); var icon = document.getElementById(id+"-icon"); if (el.style.display == "block") { el.style.display = "none"; if (this.allNodes[id].isLast()) { node.src = this.img.nodeEnd; } else { node.src = this.img.node; } icon.src = this.img.folder; this.opened.removeByValue(id); } else { el.style.display = "block"; if (this.allNodes[id].isLast()) { node.src = this.img.nodeOpenEnd; } else { node.src = this.img.nodeOpen; } icon.src = this.img.folderOpen; this.opened.push(id); } /* fix ie bug - images not showing */ if (node.outerHTML) { node.outerHTML = node.outerHTML; } if (icon.outerHTML) { icon.outerHTML = icon.outerHTML; } }; this.textClick = function(id) { if (this.active) { document.getElementById(this.active+"-text").className = "text"; } document.getElementById(id+"-text").className = "text-active"; this.active = id; this.textClickListener.call(); }; this.toHtml = function() { var s = ""; var nodes = this.tree.childNodes; for (var i = 0; i < nodes.length; i++) { s += nodes[i].toHtml(); } return s; }; this.updateHtml = function() { document.getElementById(this.id).innerHTML = this.toHtml(); }; this.loadState = function() { var opened = this.cookie.get("opened"); if (opened) { this.opened = opened.split("|"); this.opened.filter(function(id) { return self.allNodes[id] && self.allNodes[id].isFolder && self.allNodes[id].childNodes.length; }); } }; this.saveState = function() { if (this.opened.length) { this.cookie.set("opened", this.opened.join("|"), 3600*24*30, this.cookiePath, this.cookieDomain); } else { this.clearState(); } }; this.clearState = function() { this.cookie.del("opened"); }; this.getActiveNode = function() { if (!this.active) { throw "DynamicTreeBuilder.getActiveNode() failed, there is no active node"; } return this.allNodes[this.active]; } this.mayMoveUp = function() { return this.active && !this.allNodes[this.active].isFirst(); }; this.mayMoveDown = function() { return this.active && !this.allNodes[this.active].isLast(); }; this.mayMoveLeft = function() { return this.active && (this.allNodes[this.active].getLevel() > 1); }; this.mayMoveRight = function() { if (this.active) { var node = this.allNodes[this.active].getNextSibling(); while (node) { if (node.isFolder) { return true; } node = node.getNextSibling(); } } return false; }; this.mayInsertBefore = function() { return Boolean(this.active); }; this.mayInsertAfter = function() { return Boolean(this.active); }; this.mayInsertInside = function() { return this.active && this.allNodes[this.active].isFolder; }; this.mayRemove = function() { if (this.active) { var node = this.allNodes[this.active]; if (node.isDoc) { return true; } if (node.isFolder && !node.childNodes.length) { return true; } } return false; }; this.moveUp = function() { var node = this.allNodes[this.active]; var index = node.getIndex(); var parent = node.parentNode; parent.removeChild(node); parent.appendChildAtIndex(node, index-1); this.updateHtml(); }; this.moveDown = function() { var node = this.allNodes[this.active]; var index = node.getIndex(); var parent = node.parentNode; parent.removeChild(node); parent.appendChildAtIndex(node, index+1); this.updateHtml(); }; this.moveLeft = function() { var node = this.allNodes[this.active]; var left = node.parentNode; left.removeChild(node); left.parentNode.appendChildAtIndex(node, left.getIndex()); this.updateHtml(); }; this.moveRight = function() { var node = this.allNodes[this.active]; var next = node.getNextSibling(); var rightId = null; while (next) { if (next.isFolder) { rightId = next.id; break; } next = next.getNextSibling(); } var right = this.allNodes[rightId]; node.parentNode.removeChild(node); if (right.childNodes.length) { right.appendChildAtIndex(node, 0); } else { right.appendChild(node); } this.updateHtml(); }; this.createNode = function(id, text, type, object) { if (!id || this.allNodes[id] || !text || (type != "doc" && type != "folder")) { throw this.id+'.createNode("'+id+'", "'+text+'", "'+type+'") failed, illegal action'; } var node; if (type == "doc") { node = new Node(id, text, null, null, true, false); } else { node = new Node(id, text, null, new Array(), false, true); } if (object) { for (var p in object) { node[p] = object[p]; } } this.allNodes[id] = node; return node; }; this.insert = function(id, text, type, object) { var node = this.createNode(id, text, type, object); if (this.tree.childNodes.length) { this.tree.appendChildAtIndex(node, 0); } else { this.tree.appendChild(node); } this.updateHtml(); }; this.insertBefore = function(id, text, type, object) { if (!this.mayInsertBefore()) { throw this.id+'.insertBefore() failed, illegal action'; } var node = this.createNode(id, text, type, object); var active = this.allNodes[this.active]; active.parentNode.appendChildAtIndex(node, active.getIndex()); this.updateHtml(); }; this.insertAfter = function(id, text, type, object) { if (!this.mayInsertAfter()) { throw this.id+'.insertAfter() failed, illegal action'; } var node = this.createNode(id, text, type, object); var active = this.allNodes[this.active]; if (active.parentNode.childNodes[active.getIndex()+1]) { active.parentNode.appendChildAtIndex(node, active.getIndex()+1); } else { active.parentNode.appendChild(node); } this.updateHtml(); }; this.insertInsideAtStart = function(id, text, type, object) { if (!this.mayInsertInside()) { throw this.id+'.insertInsideAtStart() failed, illegal action'; } var node = this.createNode(id, text, type, object); var active = this.allNodes[this.active]; if (active.childNodes.length) { active.appendChildAtIndex(node, 0); } else { active.appendChild(node); } this.updateHtml(); }; this.insertInsideAtEnd = function(id, text, type, object) { if (!this.mayInsertInside()) { throw this.id+'.insertInsideAtEnd() failed, illegal action'; } var node = this.createNode(id, text, type, object); var active = this.allNodes[this.active]; active.appendChild(node); this.updateHtml(); }; this.remove = function() { var node = this.allNodes[this.active]; node.parentNode.removeChild(node); this.allNodes[this.active] = null; this.active = ""; this.updateHtml(); }; function Node(id, text, parentNode, childNodes, isDoc, isFolder) { this.id = id; this.text = text; this.parentNode = parentNode; this.childNodes = childNodes; this.isDoc = isDoc; this.isFolder = isFolder; this.href = ""; this.title = ""; this.target = ""; this.isFirst = function() { if (this.parentNode) { return this.parentNode.childNodes[0].id == this.id; } throw "DynamicTreeBuilder.Node.isFirst() failed, this func cannot be called for the root element"; }; this.isLast = function() { if (this.parentNode) { return this.parentNode.childNodes.getLast().id == this.id; } throw "DynamicTreeBuilder.Node.isLast() failed, this func cannot be called for the root element"; }; this.getLevel = function() { var level = 0; var node = this; while (node.parentNode) { level++; node = node.parentNode; } return level; }; this.getNextSibling = function() { if (this.parentNode) { var nodes = this.parentNode.childNodes; var start = false; for (var i = 0; i < nodes.length; i++) { if (start) { return nodes[i]; } if (!start && this.id != nodes[i].id) { continue; } start = true; } return false; } throw "DynamicTreeBuilder.Node.getNextSibling() failed, this func cannot be called for the root element"; }; this.getPreviousSibling = function() { if (this.parentNode) { var nodes = this.parentNode.childNodes; for (var i = 0; i < nodes.length; i++) { if (nodes[i].id == this.id) { if (i) { return nodes[i-1]; } else { return false; } } } throw "DynamicTreeBuilder.Node.getPreviousSibling() failed, unknown error"; } throw "DynamicTreeBuilder.Node.getPreviousSibling() failed, this func cannot be called for the root element"; }; this.getIndex = function() { if (this.parentNode) { var nodes = this.parentNode.childNodes; for (var i = 0; i < nodes.length; i++) { if (nodes[i].id == this.id) { return i; } } throw "DynamicTreeBuilder.Node.getIndex() failed, unknown error"; } throw "DynamicTreeBuilder.Node.getIndex() failed, this func cannot be called for the root element"; }; this.removeChild = function(node) { this.childNodes.removeByIndex(node.getIndex()); node.parentNode = null; }; this.appendChild = function(node) { this.childNodes.push(node); node.parentNode = this; }; this.appendChildAtIndex = function(node, index) { this.childNodes.pushAtIndex(node, index); node.parentNode = this; }; this.toHtml = function() { var s = '<div class="?" id="?">'.format((this.isFolder ? "folder" : "doc"), this.id); if (this.isFolder) { var nodeIcon; if (this.childNodes.length) { nodeIcon = (self.opened.contains(this.id) ? (this.isLast() ? self.img.nodeOpenEnd : self.img.nodeOpen) : (this.isLast() ? self.img.nodeEnd : self.img.node)); } else { nodeIcon = (this.isLast() ? self.img.leafEnd : self.img.leaf); } var icon = ((self.opened.contains(this.id) && this.childNodes.length) ? self.img.folderOpen : self.img.folder); if (this.childNodes.length) { s += '<a href="javascript:void(0)" onclick="?.nodeClick(\'?\')">'.format(self.id, this.id); } s += '<img id="?-node" src="?" width="18" height="18" alt="" />'.format(this.id, nodeIcon); if (this.childNodes.length) { s += '</a>'; } s += '<img id="?-icon" src="?" width="18" height="18" alt="" />'.format(this.id, icon); s += '<span id="?-text" class="text?" onclick="?.textClick(\'?\')">?</span>'.format(this.id, (self.active == this.id ? '-active' : ''), self.id, this.id, this.text); if (this.childNodes.length) { s += '<div class="section?" id="?-section"'.format((this.isLast() ? " last" : ""), this.id); if (self.opened.contains(this.id)) { s += ' style="display: block;"'; } s += '>'; for (var i = 0; i < this.childNodes.length; i++) { s += this.childNodes[i].toHtml(); } s += '</div>'; } } if (this.isDoc) { s += '<img src="?" width="18" height="18" alt="" /><img src="?" />'.format((this.isLast() ? self.img.leafEnd : self.img.leaf), self.img.doc); s += '<span id="?-text" class="text?" onclick="?.textClick(\'?\')">?</span>'.format(this.id, (self.active == this.id ? '-active' : ''), self.id, this.id, this.text); } s += '</div>'; return s; }; } function Cookie() { this.get = function(name) { var cookies = document.cookie.split(";"); for (var i = 0; i < cookies.length; ++i) { var a = cookies[i].split("="); if (a.length == 2) { a[0] = a[0].trim(); a[1] = a[1].trim(); if (a[0] == name) { return unescape(a[1]); } } } return ""; }; this.set = function(name, value, seconds, path, domain, secure) { var cookie = (name + "=" + escape(value)); if (seconds) { var date = new Date(new Date().getTime()+seconds*1000); cookie += ("; expires="+date.toGMTString()); } cookie += (path ? "; path="+path : ""); cookie += (domain ? "; domain="+domain : ""); cookie += (secure ? "; secure" : ""); document.cookie = cookie; }; this.del = function(name) { document.cookie = name + "=; expires=Thu, 01-Jan-70 00:00:01 GMT"; }; } function Listener() { this.funcs = []; this.add = function(func) { this.funcs.push(func); }; this.call = function() { for (var i = 0; i < this.funcs.length; i++) { this.funcs[i](); } }; } var self = this; this.id = id; this.tree = new Node("tree", "", null, new Array(), false, true); this.allNodes = {}; // id => object this.opened = []; // opened folders this.active = ""; // active node, text clicked this.cookie = new Cookie(); this.imgObjects = []; this.count = 0; this.textClickListener = new Listener(); // other modules also may need to know when user clicks on text } /* Check whether array contains given string */ if (!Array.prototype.contains) { Array.prototype.contains = function(s) { for (var i = 0; i < this.length; ++i) { if (this[i] === s) { return true; } } return false; }; } /* Remove elements with such value (mutates) */ if (!Array.prototype.removeByValue) { Array.prototype.removeByValue = function(value) { var i, indexes = []; for (i = 0; i < this.length; ++i) { if (this[i] === value) { indexes.push(i); } } for (i = indexes.length - 1; i >= 0; --i) { this.splice(indexes[i], 1); } }; } /* Remove elements judged 'false' by the passed function (mutates) */ if (!Array.prototype.filter) { Array.prototype.filter = function(func) { var i, indexes = []; for (i = 0; i < this.length; ++i) { if (!func(this[i])) { indexes.push(i); } } for (i = indexes.length - 1; i >= 0; --i) { this.splice(indexes[i], 1); } }; } /* Get the last element from the array */ if (!Array.prototype.getLast) { Array.prototype.getLast = function() { return this[this.length-1]; }; } /* Strip whitespace from the beginning and end of a string */ if (!String.prototype.trim) { String.prototype.trim = function() { return this.replace(/^\s*|\s*$/g, ""); }; } /* Replace ? tokens with variables passed as arguments in a string */ String.prototype.format = function() { if (!arguments.length) { throw "String.format() failed, no arguments passed, this = "+this; } var tokens = this.split("?"); if (arguments.length != (tokens.length - 1)) { throw "String.format() failed, tokens != arguments, this = "+this; } var s = tokens[0]; for (var i = 0; i < arguments.length; ++i) { s += (arguments[i] + tokens[i + 1]); } return s; }; /* Remove element with given index (mutates) */ if (!Array.prototype.removeByIndex) { Array.prototype.removeByIndex = function(index) { this.splice(index, 1); }; } /* Push an element at specified index */ if (!Array.prototype.pushAtIndex) { Array.prototype.pushAtIndex = function(el, index) { this.splice(index, 0, el); }; } --- NEW FILE: actions.js --- function treeTooltipOn() { document.getElementById("tree-tooltip").innerHTML = treeTooltips[treeElements.indexOf(this.id)]; } function treeTooltipOff() { document.getElementById("tree-tooltip").innerHTML = ""; } var treeElements = ["tree-moveUp", "tree-moveDown", "tree-moveLeft", "tree-moveRight", "tree-insert", "tree-info", "tree-remove"]; var treeTooltips = ["Move Up", "Move Down", "Move Left", "Move Right", "Insert", "Info", "Delete"]; for (var i = 0; i < treeElements.length; i++) { document.getElementById(treeElements[i]).onmouseover = treeTooltipOn; document.getElementById(treeElements[i]).onmouseout = treeTooltipOff; } function treeMoveUp() { if (tree.mayMoveUp()) { tree.moveUp(); } } function treeMoveDown() { if (tree.mayMoveDown()) { tree.moveDown(); } } function treeMoveLeft() { if (tree.mayMoveLeft()) { tree.moveLeft(); } } function treeMoveRight() { if (tree.mayMoveRight()) { tree.moveRight(); } } function treeInsert() { treeHideInfo(); document.getElementById("tree-insert-form").style.display = "block"; document.getElementById("tree-insert-where-div").style.display = (tree.active ? "" : "none"); if (tree.active) { var where = document.getElementById("tree-insert-where"); if (tree.mayInsertInside()) { if (!where.options[2] && !where.options[3]) { where.options[2] = new Option("Inside at start", "inside_start"); where.options[3] = new Option("Inside at end", "inside_end"); } } else if (where.options[2] && where.options[3]) { where.options[2] = null; where.options[3] = null; where.options.length = 2; } } } function treeHideInsert() { var name = document.getElementById("tree-insert-name"); var href = document.getElementById("tree-insert-href"); var title = document.getElementById("tree-insert-title"); var target = document.getElementById("tree-insert-target"); name.value = ""; href.value = ""; title.value = ""; target.value = ""; document.getElementById("tree-insert-form").style.display = "none"; } function treeInfo() { treeHideInsert(); var name = document.getElementById("tree-info-name"); var href = document.getElementById("tree-info-href"); var title = document.getElementById("tree-info-title"); var target = document.getElementById("tree-info-target"); name.value = ""; href.value = ""; title.value = ""; target.value = ""; document.getElementById("tree-info-form").style.display = "block"; if (tree.active) { var node = tree.getActiveNode(); name.value = node.text; href.value = node.href; title.value = node.title; target.value = node.target; } } function treeInfoUpdate() { var name = document.getElementById("tree-info-name"); var href = document.getElementById("tree-info-href"); var title = document.getElementById("tree-info-title"); var target = document.getElementById("tree-info-target"); name.value = name.value.trim(); href.value = href.value.trim(); if (!name.value) { return false; } if (tree.active) { var node = tree.getActiveNode(); node.text = name.value; node.href = href.value; node.title = title.value; node.target = target.value; tree.updateHtml(); } } function treeHideInfo() { var name = document.getElementById("tree-info-name"); var href = document.getElementById("tree-info-href"); var title = document.getElementById("tree-info-title"); var target = document.getElementById("tree-info-target"); name.value = ""; href.value = ""; title.value = ""; target.value = ""; document.getElementById("tree-info-form").style.display = "none"; } /* only event - blur */ function treeInsertExecute() { var where = document.getElementById("tree-insert-where"); var type = document.getElementById("tree-insert-type"); var name = document.getElementById("tree-insert-name"); var href = document.getElementById("tree-insert-href"); var title = document.getElementById("tree-insert-title"); var target = document.getElementById("tree-insert-target"); name.value = name.value.trim(); href.value = href.value.trim(); if (!name.value) { return false; } var o = {"href": href.value, "title": title.value, "target": target.value}; if (tree.active) { switch (where.value) { case "before": tree.insertBefore("tree-"+(++tree.count), name.value, type.value, o); break; case "after": tree.insertAfter("tree-"+(++tree.count), name.value, type.value, o); break; case "inside_start": tree.insertInsideAtStart("tree-"+(++tree.count), name.value, type.value, o); break; case "inside_end": tree.insertInsideAtEnd("tree-"+(++tree.count), name.value, type.value, o); break; } } else { tree.insert("tree-"+(++tree.count), name.value, type.value, o); } name.value = ""; href.value = ""; title.value = ""; target.value = ""; this.blur(); } function treeRemove() { if (tree.mayRemove()) { if (confirm("Delete current node ?")) { tree.remove(); if (document.getElementById("tree-insert-form").style.display == "block") { treeInsert(); } if (document.getElementById("tree-info-form").style.display == "block") { treeInfo(); } } } } document.getElementById("tree-moveUp").onclick = treeMoveUp; document.getElementById("tree-moveDown").onclick = treeMoveDown; document.getElementById("tree-moveLeft").onclick = treeMoveLeft; document.getElementById("tree-moveRight").onclick = treeMoveRight; if (document.all && !/opera/i.test(navigator.userAgent)) { document.getElementById("tree-moveUp").ondblclick = treeMoveUp; document.getElementById("tree-moveDown").ondblclick = treeMoveDown; document.getElementById("tree-moveLeft").ondblclick = treeMoveLeft; document.getElementById("tree-moveRight").ondblclick = treeMoveRight; } document.getElementById("tree-insert").onclick = treeInsert; document.getElementById("tree-info").onclick = treeInfo; document.getElementById("tree-remove").onclick = treeRemove; document.getElementById("tree-insert-button").onclick = treeInsertExecute; document.getElementById("tree-insert-cancel").onclick = treeHideInsert; document.getElementById("tree-info-button").onclick = treeInfoUpdate; document.getElementById("tree-info-cancel").onclick = treeHideInfo; tree.textClickListener.add(function() { if (document.getElementById("tree-insert-form").style.display == "block") { treeInsert(); } }); tree.textClickListener.add(function() { if (document.getElementById("tree-info-form").style.display == "block") { treeInfo(); } }); /* Finds the index of the first occurence of item in the array, or -1 if not found */ if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(item) { for (var i = 0; i < this.length; ++i) { if (this[i] === item) { return i; } } return -1; }; } // --------- // ! PLUGINS // --------- function treePluginImportHtml() { document.getElementById("tree-plugin").style.display = "block"; document.getElementById("tree-plugin-header").innerHTML = "Import from Html"; document.getElementById("tree-plugin-button-import-html").style.display = "block"; } function treePluginImportHtmlExecute() { var html = document.getElementById("tree-plugin-textarea"); tree.importFromHtml(html.value); } function treePluginExportHtml() { var w = window.open("", "exportToHtml", "width=600,height=600,scrollbars=yes,resizable=yes"); w.document.write('<html><body><pre>'+tree.exportToHtml().replace(/</g, "<").replace(/>/g, ">")+'</pre></body></html>'); } function treePluginExportPhp() { var w = window.open("", "exportToPhp", "width=600,height=600,scrollbars=yes,resizable=yes"); w.document.write('<pre>'+tree.exportToPhp().replace(/</g, "<").replace(/>/g, ">")+'</pre>'); } function treePluginExportSql() { var w = window.open("", "exportToSql", "width=600,height=600,scrollbars=yes,resizable=yes"); w.document.write('<pre>'+tree.exportToSql().replace(/</g, "<").replace(/>/g, ">")+'</pre>'); } function treePluginHide() { document.getElementById("tree-plugin").style.display = "none"; document.getElementById("tree-plugin-header").innerHTML = ""; document.getElementById("tree-plugin-textarea").value = ""; document.getElementById("tree-plugin-button-import-html").style.display = "none"; } document.getElementById("tree-plugin-import-html").onclick = function() { this.blur(); treePluginHide(); treePluginImportHtml(); }; document.getElementById("tree-plugin-button-import-html").onclick = treePluginImportHtmlExecute; document.getElementById("tree-plugin-export-html").onclick = function() { this.blur(); treePluginHide(); treePluginExportHtml(); }; document.getElementById("tree-plugin-export-php").onclick = function() { this.blur(); treePluginHide(); treePluginExportPhp(); }; document.getElementById("tree-plugin-export-sql").onclick = function() { this.blur(); treePluginHide(); treePluginExportSql(); } --- NEW FILE: plugins.js --- function DynamicTreePlugins() { this.importFromHtml = function(html) { // dirty hack for ie (automatic conversion to absolute paths problem), see also DynamicTreeBuilder.parse() html = html.replace(/href=["']([^"']*)["']/g, 'href="dynamictree://dynamictree/$1"'); document.getElementById(this.id).innerHTML = html; this.reset(); }; this.exportToHtml = function(node) { var ret = ""; if (node) { if (node.isDoc) { ret += '?<div class="doc"><a href="?"??>?</a></div>\n'.format( " ".repeat(4*(node.getLevel()-1)), node.href, (node.title ? ' title="?"'.format(node.title) : ""), (node.target ? ' target="?"'.format(node.target) : ""), node.text ); } if (node.isFolder) { ret += '?<div class="folder">?\n'.format( " ".repeat(4*(node.getLevel()-1)), node.text ); for (var i = 0; i < node.childNodes.length; ++i) { ret += this.exportToHtml(node.childNodes[i]); } ret += '?</div>\n'.format(" ".repeat(4*(node.getLevel()-1))); } } else { var nodes = this.tree.childNodes; for (var i = 0; i < nodes.length; ++i) { ret += this.exportToHtml(nodes[i]); } } return ret; }; this.exportToPhp = function(node) { var ret = ""; if (node) { if (node.childNodes) { ret += "?'?' => array(\n".format( " ".repeat(4*node.getLevel()), node.id ); for (var i = 0; i < node.childNodes.length; ++i) { ret += this.exportToPhp(node.childNodes[i]); } ret += "?)?\n".format( " ".repeat(4*node.getLevel()), node.isLast() ? "" : "," ); } else { ret += "?'?' => null?\n".format( " ".repeat(4*node.getLevel()), node.id, node.isLast() ? "" : "," ); } } else { var nodes = this.tree.childNodes; ret += "$tree = array(\n"; for (var i = 0; i < nodes.length; ++i) { ret += this.exportToPhp(nodes[i]); } ret += ");\n\n"; ret += "$data = array(\n"; var cnt = 0, current = 0; for (var p in this.allNodes) { if (!this.allNodes[p]) { continue; } cnt++; } for (var p in this.allNodes) { if (!this.allNodes[p]) { continue; } current++; var node = this.allNodes[p]; ret += " '?' => array('parent' => '?', 'type' => '?', 'text' => '?', 'href' => '?', 'title' => '?', 'target' => '?')?\n".format( node.id, node.parentNode.id, node.isDoc ? "doc" : "folder", node.text, node.href, node.title, node.target, cnt != current ? "," : "" ); } ret += ");"; } return ret; }; this.exportToSql = function() { var ret = ""; for (var p in this.allNodes) { if (!this.allNodes[p]) { continue; } var node = this.allNodes[p]; ret += 'INSERT INTO menu (id, parent, type, text, href, title, target) VALUES ("?", "?", "?", "?", "?", "?", "?");\n'.format( node.id, node.parentNode.id, node.isDoc ? "doc" : "folder", node.text, node.href, node.title, node.target ); } return ret; }; } /* Repeat string n times */ if (!String.prototype.repeat) { String.prototype.repeat = function(n) { var ret = ""; for (var i = 0; i < n; ++i) { ret += this; } return ret; }; } --- NEW FILE: DynamicTree.txt --- --------- ! INSTALL --------- .. soon .. Warning: - id of the menu and object variable need to be the same ------ ! TODO ------ - documentation ---------------- ! KNOWN PROBLEMS ---------------- * Opera - seems like there is no way to get the original href attribute from <a> elements, they are converted to absolute paths. This can be a problem in TreeBuilder. IE had the same problem, but a dirty hack helped to solve it. * IE 5.0 - plugins don't work in TreeBuilder, Function.call() method is missing in its implementation. --------- ! CHANGES --------- *** 1.5.2 *** - added /tests/foldersAsLinks.html [minor changes in DynamicTree.js & .css] *** 1.5.1 *** - [DynamicTreeBuilder] tmpTreeId was replaced with tree.count in actions.js, this bug could affect you if you had more than 20 records in a tree when starting editing. --- NEW FILE: help.html --- <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>About</title> <style type="text/css"> body { margin: 1em; padding: 0; background: #F1EFE2; color: #000000; font-family: georgia, tahoma, verdana; font-size: 11px; cursor: default; } h1 { font-size: 13px; font-weight: bold; margin: 0; } h2 { font-size: 12px; font-weight: bold; margin: 1em 0; } .hr { font-size: 0px; border-width: 1px; border-color: #aca899; border-style: solid none none none; margin-top: 2px; margin-bottom: 2px; } p { margin: 1em 0; } b { color: #909090; } a { color: #316ac5; text-decoration: none; } a:hover { color: #316ac5; text-decoration: underline; } #contents div { margin-left: 2em; padding-top: 1px; } dl { margin: 1em 0; } dt { font-size: 11px; color: #666666; font-weight: bold; margin: 1em 0; } dd { margin: 1em 0 1em 2em; } i {} </style> </head> <body> <h1>Help</h1> <div class="hr"></div> <p> <div id="contents">1.0 <a href="#management-1-0">DynamicTree</a> <div>1.1 <a href="#dynamictree-1-1">Tree Builder</a></div> </div> <p> <h2>1.0 DynamicTree<a name="dynamictree-1-0"></a></h2> <dl> <dt>1.1 Tree Builder<a name="dynamictree-1-1"></a></dt> <dd> Click on the "+" or "-" near the folder icon to expand/collapse current node. Click on the node name to select an element. To perform an action using icons below the tree, first you have to select an element. <br /> Actions: <br /><br /> <i>Move Up</i>, <i>Move Down</i> - move the node up or down.<br /> <i>Move Left</i> - move above current node's parent.<br /> <i>Move Right</i> - move inside folder that is below current node.<br /> <i>Insert</i> - insert before, after or inside current node.<br /> <i>Info</i> - view details, update data.<br /> <i>Delete</i> - remove doc or folder (must be empty).<br /> </dd> </dl> </p> </p> </body> </html> --- NEW FILE: DynamicTree.css --- .DynamicTree { font-family: georgia, tahoma; font-size: 11px; white-space: nowrap; cursor: default; } .DynamicTree .doc img, .DynamicTree .folder img { border: 0; vertical-align: -4px; } * html .DynamicTree .doc img, * html .DynamicTree .folder img { border: 0; vertical-align: middle; vertical-align: -4px; } .DynamicTree .section { background: url(images/tree-branch.gif) repeat-y; display: none; } .DynamicTree .last { background: none; } .DynamicTree .folder .folder { margin-left: 18px; } .DynamicTree .doc .doc, .DynamicTree .folder .doc { margin-left: 18px; } .DynamicTree .doc a { color: #000000; text-decoration: none; } .DynamicTree .doc a:hover { color: #000000; text-decoration: underline; } .DynamicTree .folder a { color: #000000; text-decoration: none; } .DynamicTree .folder a:hover { color: #000000; text-decoration: underline; } .DynamicTree .text { padding: 1px; } .DynamicTree .text-active { background: #CEE3FF; padding: 1px; } /* hack for IE to fix a bug (background of .section disappearing when mouse is over a link, for example Node 1.1.1.1) */ * html .DynamicTree .doc { position: relative; } * html .DynamicTree .doc a { position: absolute; top: 3px; } .DynamicTree img { border: 0; } .DynamicTree .actions { position: relative; margin-top: 7px; margin-left: 10px; height: 20px; } .DynamicTree .tooltip { position: absolute; line-height: 22px; left: 185px; } .DynamicTree .moveUp, .DynamicTree .moveDown, .DynamicTree .moveLeft, .DynamicTree .moveRight, .DynamicTree .insert, .DynamicTree .info, .DynamicTree .remove { width: 20px; height: 20px; display: block; position: absolute; border: 1px solid #F1EFE2; z-index: 5; cursor: default; } .DynamicTree .moveUp:hover, .DynamicTree .moveDown:hover, .DynamicTree .moveLeft:hover, .DynamicTree .moveRight:hover, .DynamicTree .insert:hover, .DynamicTree .info:hover, .DynamicTree .remove:hover { background-color: #ffffff; border: 1px solid #ACA899; } .DynamicTree .moveUp { left: 0px; } .DynamicTree .moveDown { left: 25px; } .DynamicTree .moveLeft { left: 50px; } .DynamicTree .moveRight { left: 75px; } .DynamicTree .insert { left: 100px; } .DynamicTree .info { left: 125px; } .DynamicTree .remove { left: 150px; } .DynamicTree .wrap { margin-left: 2px; } .DynamicTree .top { background: url(images/tree.gif) no-repeat; padding-left: 25px; line-height: 20px; color: #333333; } .DynamicTree .wrap1 { background: #ffffff; padding: 10px; border: 1px solid #919B9C; width: 250px; } .DynamicTree .wrap2 { margin-left: 2px; } .DynamicTree #tree-insert-form { display: none; margin-top: 1em; } .DynamicTree #tree-insert-form .label { text-align: right; width: 50px; padding-right: 8px; } .DynamicTree #tree-insert-form .input { margin-bottom: 2px; padding-left: 3px; } .DynamicTree #tree-insert-form select { margin-bottom: 2px; } .DynamicTree #tree-insert-form .button { margin-top: 4px; } .DynamicTree #tree-info-form { display: none; margin-top: 1em; } .DynamicTree #tree-info-form .label { text-align: right; width: 50px; padding-right: 8px; } .DynamicTree #tree-info-form .input { margin-bottom: 2px; padding-left: 3px; } .DynamicTree #tree-info-form select { margin-bottom: 2px; } .DynamicTree #tree-info-form .button { margin-top: 4px; } --- NEW FILE: example1.html --- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>DynamicTree example 1</title> <link rel="stylesheet" type="text/css" href="DynamicTree.css" /> <script type="text/javascript" src="../ie5.js"></script> <script type="text/javascript" src="DynamicTree.js"></script> <style type="text/css"> p { font-family: georgia, sans-serif; font-size: 11px; } </style> </head> <body> <p> <b>Project:</b> <a href="http://gosu.pl/dhtml/mygosumenu.html">mygosuMenu</a> <br /> <b>Menu type:</b> #1.5 DynamicTree example 1 <br /> <b>Features:</b> <br /> - Dynamically editable in browser (see example 2) <br /> - Export the structure of the tree to Html, Php or Sql <br /> - State of the menu is saved in cookie <br /> - Unlimited nesting <br /> - Links are visible to search engines <br /> - Accessible for user agents with javascript disabled (see /tests/test2.html) <br /> - Object Oriented code, so you can create many menus on the same page <br /> - Free for any use (BSD license) <br /> <b>Compatibility:</b> Tested on: IE 5.0/5.5/6.0, Mozilla 1.4/1.7, Opera 7.11/7.23/7.52, Netscape 7.11, Firefox 0.7/0.8/0.9, Safari 1.2 </p> <div class="DynamicTree"> <div class="top">Tree View</div> <div class="wrap" id="tree"> <div class="folder">Node 1 <div class="folder">Node 1.1 <div class="folder">Node 1.1.1 <div class="doc"><a href="example1.html" title="Node 1.1.1.1" target="_self">Node 1.1.1.1</a></div> </div> </div> <div class="doc"><a href="example1.html">Node 1.2</a></div> </div> <div class="doc"><a href="example1.html">Node 2</a></div> <div class="doc"><a href="example1.html">Node 3</a></div> <div class="doc"><a href="example1.html">Node 4</a></div> <div class="folder">Node 5 <div class="doc"><a href="example1.html">Node 5.1</a></div> <div class="doc"><a href="example1.html">Node 5.2</a></div> </div> </div> </div> <script type="text/javascript"> var tree = new DynamicTree("tree"); tree.init(); </script> </body> </html> --- NEW FILE: example2.html --- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>DynamicTree example 2</title> <link rel="stylesheet" type="text/css" href="DynamicTree.css" /> <script type="text/javascript" src="../ie5.js"></script> <script type="text/javascript" src="DynamicTreeBuilder.js"></script> <script type="text/javascript" src="plugins.js"></script> <style type="text/css"> body { background: #F1EFE2; } body, table { font-family: georgia, sans-serif; font-size: 11px; } form { margin: 0; } input,select { font-size: 11px; font-family: georgia, tahoma, verdana; } input[readonly] { border: 1px solid #7F9DB9; background: #ffffff; } a { color: #0000ee; text-decoration: none; } a:hover { color: #0000ee; text-decoration: underline; } p { margin-top: 0; margin-bottom: 1em; } #tree-plugin, #tree-plugin-button-import-html { display: none; } #tree-plugin-textarea { white-space: nowrap; } </style> </head> <body> <div><b>Project:</b> <a href="http://gosu.pl/dhtml/mygosumenu.html">mygosuMenu</a></div> <div><b>Menu type:</b> #1.5 DynamicTree example 2</div> <div><b>Features:</b> <a href="javascript:void(document.getElementById('features').style.display = (document.getElementById('features').style.display == 'block' ? 'none' : 'block'))">View/Hide</a></div> <div id="features" style="display: none;"> - Dynamically editable in browser (see example 2) <br /> - Export the structure of the tree to Html, Php or Sql <br /> - State of the menu is saved in cookie <br /> - Unlimited nesting <br /> - Links are visible to search engines <br /> - Accessible for user agents with javascript disabled (see /tests/test2.html) <br /> - Object Oriented code, so you can create many menus on the same page <br /> - Free for any use (BSD license) </div> <div><b>Compatibility:</b> Tested on: IE 5.0/5.5/6.0, Mozilla 1.4/1.7, Opera 7.11/7.23/7.52 Netscape 7.11, Firefox 0.7/0.8/0.9, Safari 1.2</div> <table cellspacing="0" cellpadding="10" style="margin-top: 1em;"> <tr> <td valign="top"> <div class="DynamicTree"> <div class="wrap1"> <div class="top">Tree Builder</div> <div class="wrap2" id="tree"> <div class="folder">Node 1 <div class="folder">Node 1.1 <div class="folder">Node 1.1.1 <div class="doc"><a href="example1.html" title="Node 1.1.1.1" target="_self">Node 1.1.1.1</a></div> </div> </div> <div class="doc"><a href="example2.html">Node 1.2</a></div> </div> <div class="doc"><a href="example3.html">Node 2</a></div> <div class="doc"><a href="/test/example1.html">Node 3</a></div> <div class="doc"><a href="example1.html">Node 4</a></div> <div class="folder">Node 5 <div class="doc"><a href="example1.html">Node 5.1</a></div> <div class="doc"><a href="example1.html">Node 5.2</a></div> </div> </div> </div> <div class="actions"> <a id="tree-moveUp" class="moveUp" href="javascript:void(0)"><img src="images/moveUp.gif" width="20" height="20" alt="" /></a> <a id="tree-moveDown" class="moveDown" href="javascript:void(0)"><img src="images/moveDown.gif" width="20" height="20" alt="" /></a> <a id="tree-moveLeft" class="moveLeft" href="javascript:void(0)"><img src="images/moveLeft.gif" width="20"... [truncated message content] |