Elegant simple tree : Tree « GUI Components « JavaScript DHTML






Elegant simple tree

 <html> <head> <!-- Copyright (c) 2004, 2005, 2006 Raphael Derosso Pereira <raphaelpereira@users.sourceforge.net> Vinicius Cubas Brand <viniciuscb@users.sourceforge.net> Frank Alcantara <frankalcantara@users.sourceforge.net> All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of its contributors may NOT be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =================================================================== dFTree Dynamic Javascript Folder Tree =================================================================== DFTree is a javascript+css folder tree with dynamic node insertion/erasing/alteration and other functionalities. It is also very lightweight and easy to use. It is CSS 2.1 compliant, although it was developed to be compatible at least with Internet Explorer version 6+ . It was tested sucessfully on Mozilla Firefox and Internet Explorer. To use it: 1. Place in the HEAD section of your HTML document the following tags: <script type="text/javascript" src="dftree.js"></script> <link rel="stylesheet" type="text/css" href="dftree.css"> The first one is to load the javascript functions that generate the folder tree. The second one loads the css styles which the tree are based. Both two must be included in order to the tree to work. 2. build the tree (inside a javascript section) and draw it. 2.1 To create the tree: tree = new dTree({name: 'tree'}); //The attribute name must be the object name  2.2 Creating nodes: n1 = new dNode({id: '1',caption: 'First Node'}); n2 = new dNode({id: '2',caption: 'Second Node'}); n3 = new dNode({id: '3',caption: 'Third Node'}); n4 = new dNode({id: '4',caption: 'Fourth Node'}); 2.3 Placing nodes in the tree: tree.add(n1,'root'); //Places the root; second argument can be anything.  tree.add(n2,'1'); //Adds n2 as son of the node with id='1'  tree.add(n3,'1'); //Adds n3 as son of the node with id='1'  tree.add(n4,'3'); //Adds n3 as son of the node with id='3'  2.4 Removing nodes from the tree (not implemented yet...) 2.5 Altering noded of the tree tree.getNodeById('1').alter({caption: 'foo',onClick: '123'}); (this alters node with id='1') 2.5 Drawing the tree: tree.draw(); List of methods: dNode() //Constructor, sets properties  dNode.changeState() //If opened, closes. If closed, opens.  dNode.open() //Opens node  dNode.close() //Closes node  dNode.alter() //Alter node properties  dFTree() //Constructor, sets properties  dFTree.draw() //Draws the tree  dFTree.add(node,pid) //adds node under the tree  dFTree.alter() //Alters a node of the tree (helper method)  dFTree.getNodeById(id) //Returns the node with id  Look at the source for tree and node properties, at their constructors. --> <script type="text/javascript"> /* Dynamic Folder Tree * Generates DHTML tree dynamically (on the fly). * License: BSD. * See details at http://www.opensource.org/licenses/bsd-license.php * * Copyright (c) 2004, 2005, 2006 * Vinicius Cubas Brand, Raphael Derosso Pereira, Frank Alcantara * {viniciuscb,raphaelpereira,frankalcantara} at users.sourceforge.net * All rights reserved. */// NODE //Usage: a = new dNode({id:2, caption:'tree root', url:'http://www.w3.org'}); function dNode(arrayProps) { //mandatory fields  this.id; //node id  this.caption; //node caption //optional fields  this.url; //url to open  this.target; //target to open url  this.onClick; //javascript to execute onclick  this.onOpen; //javascript to execute when a node of the tree opens  this.onClose; //javascript to execute when a node of the tree closes  this.onFirstOpen; //javascript to execute only on the first open  this.iconClosed; //img.src of closed icon  this.iconOpen; //img.src of open icon  this.runJS = true; //(bool) if true, runs the on* props defined above  this.plusSign = true; //(bool) if the plus sign will appear or not  this.captionClass = 'l'; //(string) the class for this node's caption //The parameters below are private  this._opened = false; //already opened  this._io = false; //is opened  this._children = []; //references to children  this._parent; //pointer to parent  this._myTree; //pointer to myTree for (i in arrayProps) { if (i.charAt(0) != '_') { eval('this.'+i+' = arrayProps[\''+i+'\'];'); } } } //changes node state from open to closed, and vice-versa dNode.prototype.changeState = function() { if (this._io) { this.close(); } else { this.open(); } //cons = COokie of Node Status //setCookie("cons"+this.id,this._io); } dNode.prototype.open = function () { if (!this._io) { if (!this._opened && this.runJS && this.onFirstOpen != null) { eval(this.onFirstOpen); } elseif (this.runJS && this.onOpen != null) { eval(this.onOpen); } this._opened = true; this._io = true; this._refresh(); } } dNode.prototype.close = function() { if (this._io) { if (this.runJS && this.onClose != null) { eval(this.onClose); } this._io = false; this._refresh(); } } //alter node label and other properties dNode.prototype.alter = function(arrayProps) { for (i in arrayProps) { if (i != 'id' && i.charAt(0) != '_') { eval('this.'+i+' = arrayProps[\''+i+'\'];'); } } } //css and dhtml refresh part dNode.prototype._refresh = function() { var nodeDiv = getObjectById("n"+this.id); var plusSpan = getObjectById("p"+this.id); var captionSpan = getObjectById("l"+this.id); var childrenDiv = getObjectById("ch"+this.id); if (nodeDiv != null) { //Handling open and close: checks this._io and changes class as needed if (!this._io) //just closed  { childrenDiv.className = "closed"; } else//just opened  { //prevents IE undesired behaviour when displaying empty DIVs /* if (this._children.length > 0) {*/ childrenDiv.className = "opened"; // }  } plusSpan.innerHTML = this._properPlus(); captionSpan.innerHTML = this.caption; } //alter onLoad, etc  } //gets the proper plus for this moment dNode.prototype._properPlus = function() { if (!this._io) { if (this._myTree.useIcons) { return (this.plusSign)?imageHTML(this._myTree.icons.plus):""; } else { return (this.plusSign)?"+":""; } } else { if (this._myTree.useIcons) { return (this.plusSign)?imageHTML(this._myTree.icons.minus):""; } else { return (this.plusSign)?"-":""; } } } //changes node to selected style class. Perform further actions. dNode.prototype._select = function() { var captionSpan; if (this._myTree._selected) { this._myTree._selected._unselect(); } this._myTree._selected = this; captionSpan = getObjectById("l"+this.id); //changes class to selected link if (captionSpan) { captionSpan.className = 'sl'; } } //changes node to unselected style class. Perform further actions. dNode.prototype._unselect = function() { var captionSpan = getObjectById("l"+this.id); this._myTree._lastSelected = this._myTree._selected; this._myTree._selected = null; //changes class to selected link if (captionSpan) { captionSpan.className = this.captionClass; } } //state can be open or closed //warning: if drawed node is not child or root, bugs will happen dNode.prototype._draw = function() { var str; var div; var myClass = (this._io)? "opened" : "closed"; var myPlus = this._properPlus(); var append = true; var myPlusOnClick = this._myTree.name+'.getNodeById(\''+this.id+'\').changeState();'; var captionOnClickEvent = ""; // var cook;  var plusEventHandler = function(){ eval(myPlusOnClick); } var captionEventHandler = function(){ eval(captionOnClickEvent); } /* if (this.myTree.followCookies) { this._io = getCookie("cons"+this.id); }*///FIXME put this in a separate function, as this will be necessary in //various parts  captionOnClickEvent = this._myTree.name+'.getNodeById(\''+this.id+'\')._select(); '; if (this.onClick) //FIXME when onclick && url  { captionOnClickEvent += this.onClick; } elseif (this.url && this.target) { captionOnClickEvent += 'window.open(\''+this.url+'\',\''+this.target+'\')'; } elseif (this.url) { captionOnClickEvent += 'window.location=\''+this.url+'\''; } //The div of this node  divN = document.createElement('div'); divN.id = 'n'+this.id; divN.className = 'son'; //The span that holds the plus/minus sign  spanP = document.createElement('span'); spanP.id = 'p'+this.id; spanP.className = 'plus'; // spanP.addEventListener('click',plusEventHandler,false);  spanP.onclick = plusEventHandler; spanP.innerHTML = myPlus; //The span that holds the label/caption  spanL = document.createElement('span'); spanL.id = 'l'+this.id; spanL.className = this.captionClass; // spanL.addEventListener('click',captionEventHandler,false);  spanL.onclick = captionEventHandler; spanL.innerHTML = this.caption; //The div that holds the children  divCH = document.createElement('div'); divCH.id = 'ch'+this.id; divCH.className = myClass; // str = '<div id="n'+this.id+'" class="son">'; // str = '<span id="p'+this.id+'" class="plus" onclick="'+myPlusOnClick+'">'+myPlus+'</span>'; // str += '<span id="l'+this.id+'" class="l"'+captionOnClickEvent+'>'+this.caption+'</span>'; // str += '<div id="ch'+this.id+'" class="'+myClass+'"></div>'; // div.innerHTML = str;  divN.appendChild(spanP); divN.appendChild(spanL); divN.appendChild(divCH); if (this._parent != null) { parentChildrenDiv = getObjectById("ch"+this._parent.id); } else//is root  { parentChildrenDiv = getObjectById("dftree_"+this._myTree.name); // append = false;  } if (parentChildrenDiv) { parentChildrenDiv.appendChild(divN); /* if (append) { parentChildrenDiv.innerHTML += str; } else { parentChildrenDiv.innerHTML = str; }*/ } } // TREE //Usage: t = new dFTree({name:t, caption:'tree root', url:'http://www.w3.org'}); function dFTree(arrayProps) { //mandatory fields  this.name; //the value of this must be the name of the object //optional fields  this.is_dynamic = true; //tree is dynamic, i.e. updated on the fly  this.followCookies = true;//use previous state (o/c) of nodes  this.useIcons = false; //use icons or not //arrayProps[icondir]: Icons Directory  iconPath = (arrayProps['icondir'] != null)? arrayProps['icondir'] : ''; this.icons = { root : iconPath+'/foldertree_base.gif', folder : iconPath+'/foldertree_folder.gif', folderOpen : iconPath+'/foldertree_folderopen.gif', node : iconPath+'/foldertree_folder.gif', empty : iconPath+'/foldertree_empty.gif', line : iconPath+'/foldertree_line.gif', join : iconPath+'/foldertree_join.gif', joinBottom : iconPath+'/foldertree_joinbottom.gif', plus : iconPath+'/foldertree_plus.gif', plusBottom : iconPath+'/foldertree_plusbottom.gif', minus : iconPath+'/foldertree_minus.gif', minusBottom : iconPath+'/foldertree_minusbottom.gif', nlPlus : iconPath+'/foldertree_nolines_plus.gif', nlMinus : iconPath+'/foldertree_nolines_minus.gif' }; //private  this._root; //reference to root node  this._aNodes = []; this._lastSelected; //The last selected node  this._selected; //The actual selected node for (i in arrayProps) { if (i.charAt(0) != '_') { eval('this.'+i+' = arrayProps[\''+i+'\'];'); } } } dFTree.prototype.draw = function() { if (!getObjectById("dftree_"+this.name)) { document.write('<div id="dftree_'+this.name+'"></div>'); } if (this._root != null) { this._root._draw(); this._drawBranch(this._root._children); } } //Transforms tree in HTML code. Do not use it. Use draw() instead. /*dFTree.prototype.toString = function() { var str = ''; if (!getObjectById("dftree_"+this.name)) { str = '<div id="dftree_'+this.name+'"></div>'; } return str; / * if (this.root != false) { this.root._draw(); this._drawBranch(this.root.children); }* / }*///Recursive function, draws children dFTree.prototype._drawBranch = function(childrenArray) { var a=0; for (a;a<childrenArray.length;a++) { childrenArray[a]._draw(); this._drawBranch(childrenArray[a]._children); } } //add into a position dFTree.prototype.add = function(node,pid) { var auxPos; var addNode = false; if (typeof (auxPos = this._searchNode(node.id)) != "number") { // if parent exists, add node as its child if (typeof (auxPos = this._searchNode(pid)) == "number") { node._parent = this._aNodes[auxPos]; this._aNodes[auxPos]._children[this._aNodes[auxPos]._children.length] = node; addNode = true; } else//if parent cannot be found and there is a tree root, ignores node  { if (this._root == null) { this._root = node; addNode = true; } } if (addNode) { this._aNodes[this._aNodes.length] = node; node._myTree = this; if (this.is_dynamic) { node._draw(); } } } } //arrayProps: same properties of Node dFTree.prototype.alter = function(arrayProps) { if (arrayProps['id']) { this.getNodeById(arrayProps['id']).alter(arrayProps); } } dFTree.prototype.getNodeById = function(nodeid) { return this._aNodes[this._searchNode(nodeid)]; } //Searches for a node in the node array, returning the position of the array 4it dFTree.prototype._searchNode = function(id) { var a=0; for (a;a<this._aNodes.length;a++) { if (this._aNodes[a].id == id) { return a; } } return false; } //Auxiliar functions //For multi-browser compatibility function getObjectById(name) { if (document.getElementById) { return document.getElementById(name); } elseif (document.all) { return document.all[name]; } elseif (document.layers) { return document.layers[name]; } return false; } // [Cookie] Clears a cookie function clearCookie(cookieName) { var now = new Date(); var yesterday = new Date(now.getTime() - 1000 * 60 * 60 * 24); this.setCookie(cookieName, 'cookieValue', yesterday); this.setCookie(cookieName, 'cookieValue', yesterday); }; // [Cookie] Sets value in a cookie function setCookie(cookieName, cookieValue, expires, path, domain, secure) { document.cookie = escape(cookieName) + '=' + escape(cookieValue) + (expires ? '; expires=' + expires.toGMTString() : '') + (path ? '; path=' + path : '') + (domain ? '; domain=' + domain : '') + (secure ? '; secure' : ''); }; // [Cookie] Gets a value from a cookie function getCookie(cookieName) { var cookieValue = ''; var posName = document.cookie.indexOf(escape(cookieName) + '='); if (posName != -1) { var posValue = posName + (escape(cookieName) + '=').length; var endPos = document.cookie.indexOf(';', posValue); if (endPos != -1) { cookieValue = unescape(document.cookie.substring(posValue, endPos)); } else { cookieValue = unescape(document.cookie.substring(posValue)); } } return (cookieValue); }; function imageHTML(src,attributes) { if (attributes != null) { attributes = ''; } return"<img "+attributes+" src=\""+src+"\">"; } </script> <style rel="stylesheet" type="text/css"> .son { position: relative; left: 10px; } .plus { font-size: 15px; font-weight: bold; cursor: pointer; cursor: hand; color: #000000; font-family: monospace; } .plus:hover { color: #FF0000; } .opened { display: block; } .closed { display: none; } /* link */ .l { padding: 2px; font-weight: bold; font-size: 12px; color: #666666; text-decoration: none; cursor: pointer; cursor: hand; white-space: nowrap; font-family: sans-serif; } .l:hover { text-decoration: underline; } /* selected link */ .sl { padding: 2px; font-weight: bold; font-size: 12px; color: #0000FF; text-decoration: none; cursor: pointer; cursor: hand; white-space: nowrap; font-family: sans-serif; } .sl:hover { text-decoration: underline; } </style> </head> <body> <script language="javascript"> <!-- tree = new dFTree({name: 'tree'}); tree.add(new dNode({id: '0',caption: 'Java2s.com'}),-1); //root node tree.add(new dNode({id: '1',caption: 'Java'}),0); tree.add(new dNode({id: '2',caption: 'JavaScript'}),0); tree.add(new dNode({id: '3',caption: 'PHP'}),1); tree.add(new dNode({id: '4',caption: 'Perl'}),1); tree.add(new dNode({id: '5',caption: 'Oracle'}),1); tree.add(new dNode({id: '6',caption: 'MySQL'}),2); tree.add(new dNode({id: '7',caption: 'C++'}),2); tree.add(new dNode({id: '8',caption: 'Python'}),7); tree.draw(); --> </script> </body> </html> 








Related examples in the same category

1.Explorer based on tree
2.Yahoo! UI Library - Tree Control
3.Yahoo! UI Library - Tree Control 2
4.Tree Control
5.Dynamic TreeView Example
6.Yahoo! UI Library - Tree Control 3
7.Yahoo! UI Library - Tree Control 4
8.Yahoo! UI Library - Tree Control 5
9.Build a tree in JavaScript
10.Delete, insert items in a tree
11.Tree selection action handler
12.Expand, Collapse, Close, Open selected Tree item and branch
13.Change Tree Node Color and Icon
14.Checkbox tree node: checked, unchecked, get the checked items
15.Change tree expand and collapse icons
16.Drag and Drop between trees
17.Build tree from xml
18.Tree navigation bar
19.Navigation Tree
20.Navigation Tree menu based on XML
21.XML Tree
22.Building Collapsible Trees
23.Nano Tree
24.Tree which accepts drag and drop event in JavaScript (IE)
25.Simple Tree in Javascript
26.folder tree static
close