Nano Tree : Tree : GUI Components : JavaScript DHTML examples (example source code) Organized by topic

JavaScript DHTML
C++
PHP
JavaScript DHTML Home »  GUI Components   » [  Tree  ]   
 



Nano Tree

Please note that some example is only working under IE or Firefox.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>NanoTree</title>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">

<!-- std_treelook.css -->
<style REL="STYLESHEET" TYPE="text/css">
/* Tree Style */
.treetitle {
  padding:2px;
  cursor:default;
  
  font-family: Tahoma,Verdana,Arial, Helvetica, sans-serif;
  font-size: 11px;
  color: #000000;
}
.editednode {
  padding:2px;
  cursor:default;
  background-color: #FFFFFF;;
  color: #000000;
  
  font-family: Tahoma,Verdana,Arial, Helvetica, sans-serif;
  font-size: 11px;
}
.editednodeinput {
  background-color: #FFFFFF;;
  color: #000000;
  
  width: 150px;
  height: 17px;
  
  border-style: solid;
  border-width: 1px;
  border-color: #000000;
  
  font-family: Tahoma,Verdana,Arial, Helvetica, sans-serif;
  font-size: 11px;
}
.treetitleselectedfocused {
  padding:2px;
  cursor:default;
  background-color: highlight;
  color: highlighttext;
  
  font-family: Tahoma,Verdana,Arial, Helvetica, sans-serif;
  font-size: 11px;
}
.treetitleselectedblured {
  padding:2px;
  cursor:default;
  background-color: menu;
  color: windowtext;
  font-family: Tahoma,Verdana,Arial, Helvetica, sans-serif;
  font-size: 11px;
}
</style>

<!-- nanotree.js -->
<script type="text/javascript" language="JavaScript">
/**
* Original Author of this file: Martin Mouritzen. ([email protected])
*
*
* (Lack of) Documentation:
*
*
* If a finishedLoading method exists, it will be called when the tree is loaded.
* (good to display a div, etc.).
*
*
* You have to set the variable rootNode (as a TreeNode).
*
* You have to set a container element, this is the element in which the tree will be.
*
*
* TODO: 
* Save cookies better (only 1 cookie for each tree). Else the page will totally cookieclutter.
*
***********************************************************************
* Configuration variables.
************************************************************************/

// Should the rootNode be displayed.
var showRootNode = true;

// Should the dashed lines between nodes be shown.
var showLines = true;

// Should the nodes be sorted? (You can either specify a number, then it will be sorted by that, else it will
// be sorted alphabetically (by name).
var sortNodes = true;

// This is IMPORTANT... use an unique id for each document you use the tree in. (else they'll get mixed up).
var documentID = window.location.href;

// being read from cookie.
var nodesOpen = new Array();

// RootNode of the tree.
var rootNode;

// Container to display the Tree in.
var container;

// Shows/Hides subnodes on startup
var showAllNodesOnStartup = false;

// Is the roots dragable?
var dragable = false;


/************************************************************************
* The following is just instancevariables.
************************************************************************/
var href = '';

// rootNodeCallBack name (if null, it's not selectable).
var rootNodeCallBack = null;

// selectedNode
var selectedNode = null;

var states = '';
var statearray = new Array();

var treeNodeEdited = null;

var editaborted = false;

var floatDragElement = null;
var colouredElement = null;
var draggedNodeID = null;
var lastDraggedOnNodeID = null;


/**
* The TreeNode Object
@param id unique id of this treenode
@param name The title of this node
@param icon The icon if this node (Can also be an array with 2 elements, the first one will represent the closed state, and the next one the open state)
@param param A parameter, this can be pretty much anything. (eg. an array with information).
@param orderNumber an orderNumber If one is given the nodes will be sorted by this (else they'll be sorted alphabetically (If sorting is on).
*/
function TreeNode(id,name,icon,param,orderNumber) {
  this.id = id;
  this.childs = new Array();
  this.name = (name == null 'unset name' : name);
  this.icon = (icon == null '' : icon);
  this.parent = null;
  this.handler = null;
  this.param = (param == null '' : param);
  this.orderNumber = (orderNumber == null ? -: orderNumber);
  
  this.openeventlisteners = new Array();
  this.editeventlisteners = new Array();
  this.moveeventlisteners = new Array();
  this.haschilds = false;
  this.editable = false;
  this.linestring = '';
  
  this.nextSibling = null;
  this.prevSibling = null;
  
  this.childsHasBeenFetched = false;

  this.getID = function() {
    return this.id;
  }
  this.setName = function(newname) {
    this.name = newname;
  }
  this.getName = function() {
    return this.name;
  }
  this.getParam = function() {
    return this.param;
  }
  this.setIcon = function(icon) {
    this.icon = icon;
  }
  this.getIcon = function() {
    if (typeof(this.icon== 'object') {
      return this.icon[0];
    }
    return this.icon;
  }
  this.getOpenIcon = function() {
    if (typeof(this.icon== 'object') {
      return this.icon[1];
    }
    return this.icon;
  }
  this.hasIcon = function () {
    return this.icon != '';
  }
  this.getOrderNumber = function() {
    return this.orderNumber;
  }
  this.addOpenEventListener = function(event) {
    this.openeventlisteners[this.openeventlisteners.length= event;
  }
  this.gotOpenEventListeners = function() {
    return (this.openeventlisteners.length > 0);
  }
  this.addEditEventListener = function(event) {
    this.editeventlisteners[this.editeventlisteners.length= event;
  }
  this.gotEditEventListeners = function() {
    return (this.editeventlisteners.length > 0);
  }
  this.addMoveEventListener = function(event) {
    this.moveeventlisteners[this.moveeventlisteners.length= event;
  }
  this.gotMoveEventListeners = function() {
    return (this.moveeventlisteners.length > 0);
  }
  this.addChild = function(childNode) {
    var possiblePrevNode = this.childs[this.childs.length - 1]
    if (possiblePrevNode) {
      possiblePrevNode.nextSibling = childNode;
      childNode.prevSibling = possiblePrevNode;
      // alert(childNode.prevSibling);
    }

    this.childs[this.childs.length= childNode;
    childNode.setParent(this);

    if (sortNodes) {
      function sortByOrder(a,b) {
        var order1 = a.getOrderNumber();
        var order2 = b.getOrderNumber();
        if (order1 == -|| order2 == -1) {
          return a.getName().toLowerCase() > b.getName().toLowerCase() : -1;
        }
        else {
          if (order1 == order2) {
            // If they got the same order number, then we'll sort by their title.
            return a.getName().toLowerCase() > b.getName().toLowerCase() : -1;
          }
          else {
            return order1 - order2;
          }
        }
      }
      this.childs.sort(sortByOrder);
    }
  }
  this.removeChild = function(childNode) {
    var found = false;
    for (var i=0;i<this.childs.length;i++) {
      if (found) {
        this.childs[ithis.childs[i + 1];
      }
      if (this.childs[i== childNode) {
        if (i == (this.childs.length - 1)) {
          this.childs[inull;
        }
        else {
          this.childs[ithis.childs[i + 1];
        }
        found = true;
      }
    }
    if (found) {
      this.childs.length = this.childs.length-1;
    }
  }
  this.resetChilds = function() {
    this.childs = new Array();
  }
  this.setHasChilds = function(hasChilds) {
    this.haschilds = hasChilds;
  }
  this.hasChilds = function() {
    if (this.haschilds == true) {
      return true;
    }
    return (this.childs.length > 0);
  }
  this.getChildCount = function() {
    return this.childs.length;
  }
  this.getFirstChild = function() {
    if (this.hasChilds()) {
      return this.childs[0];
    }
    return null;
  }
  this.gotHandler = function() {
    return this.handler != null;
  }
  this.setHandler = function(handler) {
    this.handler = handler;
  }
  this.getHandler = function() {
    return this.handler;
  }
  this.setParent = function(parent) {
    this.parent = parent;
  }
  this.getParent = function() {
    return this.parent;
  }
  this.getLineString = function() {
    return this.linestring;
  }
  this.setLineString = function(string) {
    this.linestring = string;
  }
  this.isEditable = function() {
    return this.editable;
  }
  this.setEditable = function(editable) {
    this.editable = editable;
  }
  
}
function getTreeNode(nodeID) {
  return findNodeWithID(rootNode,nodeID);
}
function findNodeWithID(node,nodeID) {
  if (node.getID() == nodeID) {
    return node;
  }
  else {
    if (node.hasChilds()) {
      for(var i=0;i<node.getChildCount();i++) {
        var value = findNodeWithID(node.childs[i],nodeID);
        if (value != false) {
          return value;
        }
      }
    }
    return false;
  }
}
function readStates() {
  //setCookie('tree' + documentID,'');
  states = getCookie('tree' + documentID);
  if (states != null) {
    var array = states.split(';');
    for(var i=0;i<array.length;i++) {
      var singlestate = array[i].split('|');
      statearray[inew Array();
      statearray[i]["key"= singlestate[0];
      statearray[i]["state"]  = singlestate[1];
    }
  }
}
function getState(nodeID) {
  for(var i=0;i<statearray.length;i++) {
    if (statearray[i]["key"== nodeID) {
      state = statearray[i]["state"];
      if (state == null || state == '') {
        state = 'closed';
      }
      return state;
    }
  }
  return "closed";
}
function writeStates(nodeID,newstate) {
  //alert(nodeID);
  var str = '';
  var found = false;
  for(var i=0;i<statearray.length;i++) {
    if (statearray[i]["key"== nodeID) {
      statearray[i]["state"= newstate;
      found = true;
    }
    if (statearray[i]["state"!= null) {
      str += statearray[i]["key"'|' + statearray[i]["state"';';
    }
  }
  if (found == false) {
    statearray[statearray.lengthnew Array();
    statearray[statearray.length - 1]["key"= nodeID;
    statearray[statearray.length - 1]["state"= newstate;
    if (newstate != null) {
      str += nodeID + '|' + newstate + ';';
    }
  }
  setCookie('tree' + documentID,str);
}
function showTree(path) {
  readStates();
  
  href = path;
  window.focus();
  window.onblur = blurSelection;
  window.onfocus = focusSelection;
  var str = '';
  str = '<div id="node' + rootNode.getID() + '" class="treetitle" style="display:' + (showRootNode == true ? 'block' : 'none') + '">';
  str += '<nobr>';
  if (rootNode.hasIcon()) {
    str += '<img src="' + rootNode.getIcon() + '" style="vertical-align:middle;">';
  }
  str += '<span style="vertical-align:middle;">&nbsp;' + rootNode.getName() '</span>';
  str += '</nobr></div>';
  
  if (rootNode.hasChilds()) {
    for(i=0;i<rootNode.childs.length;i++) {
      nodeContents = showNode(rootNode.childs[i],(i == (rootNode.getChildCount() -1)));
      str = str + nodeContents;
    }
  }
  container.innerHTML = str;
  if (window.finishedLoading) {
    finishedLoading();
  }
}
/**
* Shows the given node, and subnodes.
*/
function showNode(treeNode,lastNode) {
  linestring = treeNode.getLineString();
  var state = getState(treeNode.getID());
  var str;
  str = '<div style="filter:alpha(opacity=100);" ondragenter="dragEnter(' + treeNode.getID() + ');" ondragleave="dragLeave();" ondragstart="startDrag(' + treeNode.getID() + ');" ondrag="dragMove();" ondragend="endDrag(' + treeNode.getID() + ')" id="node' + treeNode.getID() + '">';
  str += '<nobr>';
  for(var y=0;y<linestring.length;y++) {
    if (linestring.charAt(y== 'I') {
      str += '<img src="' + href + 'nanoImages/' + (showLines ? 'line' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';
    }
    else if (linestring.charAt(y== 'B') {
      str += '<img src="' + href + 'nanoImages/white.gif" style="width:19px;height:20px;vertical-align:middle;">';
    }
  }
  if (treeNode.hasChilds()) {
    // If this is the first child of the rootNode, and showRootNode is false, we want to display a different icon.
    if (!showRootNode && (treeNode.getParent() == rootNode&& (treeNode.getParent().getFirstChild() == treeNode)) {
      if (!lastNode) {
        str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (state == 'open' ? (showLines ? 'minus_no_root' : 'minus_nolines') : (showLines ? 'plus_no_root' : 'plus_nolines')) + '.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';
      }
      else {
        str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (state == 'open' ? 'minus_last' : 'plus_last') + '_no_root.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';
      }
    }
    else {
      if (!lastNode) {
        str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (state == 'open' ? (showLines ? 'minus' : 'minus_nolines') : (showLines ? 'plus' : 'plus_nolines')) + '.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';
      }
      else {
        str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (state == 'open' ? (showLines ? 'minus_last' : 'minus_nolines') : (showLines ? 'plus_last' : 'plus_nolines')) + '.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';
      }
    }
  }
  else {
    // If this is the first child of the rootNode, and showRootNode is false, we want to display a different icon.
    if (!showRootNode && (treeNode.getParent() == rootNode&& (treeNode.getParent().getFirstChild() == treeNode)) {
      if (!lastNode) {
        str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (showLines ? 't_no_root' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';
      }
      else {
        str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/white.gif" style="width:19px;height:20px;vertical-align:middle;">';
      }
    }
    else {
      if (!lastNode) {
        str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (showLines ? 't' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';
      }
      else {
        str += '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (showLines ? 'lastnode' : 'white') + '.gif" style="width:19px;height:20px;vertical-align:middle;">';
      }
    }
  }
  iconStartImage = treeNode.getIcon();
  if (state != 'closed') {
    if (treeNode.hasChilds()) {
      iconStartImage = treeNode.getOpenIcon();
    }
  }
  
  str += '<img id="iconimage' + treeNode.getID() + '" src="' + iconStartImage + '" style="vertical-align:middle;" OnClick="selectNode(' + treeNode.getID() + ')">';
  str += '&nbsp;<span unselectable="ON" style="vertical-align:middle;" class="treetitle" ID="title' + treeNode.getID() + '" OnDblClick="handleNode(' + treeNode.getID() + ')" OnClick="selectNode(' + treeNode.getID() + ')">';
  str += treeNode.getName();
  str += '</span>';
  str += '</nobr>';
  str += '</div>';

  if (treeNode.hasChilds()) {
    if (state == 'open') {
      str += '<div id="node' + treeNode.getID() + 'sub" style="display:block;">';
      fireOpenEvent(treeNode);
      // alert('openevent: ' + treeNode.getName());
    }
    else {
      str += '<div id="node' + treeNode.getID() + 'sub" style="display:' + (showAllNodesOnStartup == true ? 'block;' : 'none;') + ';">';
    }
    var subgroupstr = '';
    var newChar = '';

    if (!lastNode) {
      newChar = 'I';
    }
    else {
      newChar = 'B';
    }
    for(var z=0;z<treeNode.getChildCount();z++) {
      treeNode.childs[z].setLineString(linestring + newChar);
    }
    for(var z=0;z<treeNode.getChildCount();z++) {
      subgroupstr += showNode(treeNode.childs[z],(z == (treeNode.getChildCount() -1)));
    }
    str += subgroupstr;
    str += '</div>';
  }
  else {
    str += '<div id="node' + treeNode.getID() + 'sub" style="display:none;">';
    str += '</div>';
  }
  return str;
}
/*
function mouseMove() {
  if (dragging) {
    alert('bob');
  }
}
function mouseUp() {
  if (dragging) {
    alert('dropped on something!');
  }
}
*/
function startDrag(nodeID) {
  if (!dragable) {
    return;
  }
  draggedNodeID = nodeID;
  
  var srcObj = window.event.srcElement;
  while(srcObj.tagName != 'DIV') {
    srcObj = srcObj.parentElement;
  }
  floatDragElement = document.createElement('DIV');

  floatDragElement.innerHTML = srcObj.innerHTML;
  floatDragElement.childNodes[0].removeChild(floatDragElement.childNodes[0].childNodes[0]);
  
  document.body.appendChild(floatDragElement);
  floatDragElement.style.zIndex = 100;
  floatDragElement.style.position = 'absolute';
  floatDragElement.style.filter='progid:DXImageTransform.Microsoft.Alpha(1,opacity=60);';
}
function findSpanChild(element) {
  if (element.tagName == 'SPAN') {
    return element;
  }
  else {
    if (element.childNodes) {
      for(var i=0;i<element.childNodes.length;i++) {
        var value = findSpanChild(element.childNodes[i]);
        if (value != false) {
          return value;
        }
      }
      return false;
    }
  }
}
function dragEnter(nodeID) {
  if (!dragable) {
    return;
  }
  lastDraggedOnNodeID = nodeID;
  
  if (colouredElement) {
    findSpanChild(colouredElement).className = 'treetitle';
  }
  colouredElement = window.event.srcElement;
  while(colouredElement.tagName != 'DIV') {
    colouredElement = colouredElement.parentElement;
    if (colouredElement.tagName == 'BODY') {
      // Something gone seriously wrong.
      alert('Drag failure, reached <BODY>!');
      return;
    }
  }  
  findSpanChild(colouredElement).className = 'treetitleselectedfocused';
}
function dragLeave() {
  if (!dragable) {
    return;
  }
}
function endDrag(nodeID) {
  if (!dragable) {
    return;
  }
  if (lastDraggedOnNodeID != null) {
    fireMoveEvent(getTreeNode(lastDraggedOnNodeID),draggedNodeID,lastDraggedOnNodeID);
  }
}
function dragProceed() {
  if (!dragable) {
    return;
  }
  var dragged = getTreeNode(draggedNodeID);
  var newparent = getTreeNode(lastDraggedOnNodeID);

  var oldparent = dragged.getParent();
  
  oldparent.removeChild(dragged);
  newparent.addChild(dragged);
  
  refreshNode(oldparent);
  refreshNode(newparent);
  
  _dragClean()
}
function dragCancel() {
  if (!dragable) {
    return;
  }
  _dragClean()
}
/**
* Don't call this yourself.
*/
function _dragClean() {
  if (!dragable) {
    return;
  }
  if (colouredElement) {
    findSpanChild(colouredElement).className = 'treetitle';
  }
  
  floatDragElement.parentElement.removeChild(floatDragElement);
  floatDragElement = null;
  colouredElement = null;
  draggedNodeID = null;
  lastDraggedOnNodeID = null;
}
function dragMove() {
  if (!dragable) {
    return;
  }
  floatDragElement.style.top = window.event.clientY;
  floatDragElement.style.left = window.event.clientX;
}
function editEnded() {
  if (treeNodeEdited != null) {
    // treeNodeEdited.getID();
    var editTitle = document.getElementById('title' + treeNodeEdited.getID());
    var input = editTitle.childNodes[0];
  
    var newValue = input.value;
    
    if (newValue == treeNodeEdited.getName()) {
      editTitle.innerHTML = newValue;
      treeNodeEdited = null;
      return;
    }
  
    fireEditEvent(treeNodeEdited,newValue);
    
    if (!editaborted) {
      treeNodeEdited.setName(newValue);
      editTitle.innerHTML = newValue;
    }
  
    treeNodeEdited = null;
  }
}
function selectNode(nodeID) {
  var treeNode = getTreeNode(nodeID);

  if (selectedNode != null) {
    if (selectedNode == nodeID) {
      if (treeNode.isEditable()) {
        if (treeNodeEdited == treeNode) {
          return;
        }
        treeNodeEdited = treeNode;
        var editTitle = document.getElementById('title' + treeNode.getID());
        editTitle.className = 'editednode';
        

        editTitle.innerHTML = '<input type="text" onKeypress="if (event.keyCode == 13) { this.onblur = null; editEnded(); }" name="editednode" class="editednodeinput">';
        var input = editTitle.childNodes[0];
        input.value = treeNode.getName();
        input.focus();
        input.select();
        input.onblur = editEnded;
      }
      return;
    }
    if (treeNodeEdited != null) {
      editEnded();
    }
    var oldNodeTitle = document.getElementById('title' + selectedNode);
    oldNodeTitle.className = 'treetitle';
  }
  selectedNode = nodeID;
  var nodetitle = document.getElementById('title' + selectedNode);
  nodetitle.className = 'treetitleselectedfocused';
  
  if (treeNode.gotHandler()) {
    eval(treeNode.getHandler() '(getTreeNode(' + nodeID + '));');
  }
  else {
    standardClick(treeNode);
  }
}
function refreshNode(treeNode) {
  var submenu = document.getElementById('node' + treeNode.getID() 'sub');
  var str = '';
  for(var i=0;i<treeNode.getChildCount();i++) {
    var parent = treeNode.getParent();
    if (!parent) {
      treeNode.childs[i].setLineString(treeNode.getLineString() 'B');
    }
    else {
      if (parent.childs[parent.childs.length - 1== treeNode) {
        treeNode.childs[i].setLineString(treeNode.getLineString() 'B');
      }
      else {
        treeNode.childs[i].setLineString(treeNode.getLineString() 'I');
      }
    }
    str += showNode(treeNode.childs[i],i == (treeNode.getChildCount() 1));
  }
  var actionimage = document.getElementById('handler' + treeNode.getID());
  if (treeNode.getChildCount() == 0) {
    // TreeNode haven't got any children, make sure the right image is displayed.
    if (actionimage.src.indexOf('last') == -1) {
      actionimage.src = href + 'nanoImages/' + (showLines ? 't' 'white') '.gif';
    }
    else {
      actionimage.src = href + 'nanoImages/' + (showLines ? 'lastnode' : 'white') '.gif';
    }
    actionimage.onclick = null;
    
    // Close the submenu
    if (submenu) {
      submenu.style.display = 'none';
    }
  }
  else {
    // We have children, make sure to display the + and - icon.
    if (actionimage.src.indexOf('plus') != -1) {
      // The TreeNode have already got children, and displays them.
    }
    else if (actionimage.src.indexOf('minus') != -1) {
      // The TreeNode have already got children, and displays them.
    }
    else {
      if (actionimage.src.indexOf('last') == -1) {
        actionimage.outerHTML = '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/' + (showLines ? 'plus' : 'plus_nolines') + '.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';
      }
      else {
        actionimage.outerHTML = '<img id="handler' + treeNode.getID() + '" src="' + href + 'nanoImages/plus_last.gif" style="width:19px;height:20px;vertical-align:middle;" OnClick="handleNode(' + treeNode.getID() + ');">';
      }
    }
  }
  submenu.innerHTML = str;
}
function handleNode(nodeID) {
  var treeNode = getTreeNode(nodeID);  
  if (!treeNode.hasChilds()) { // No reason to handle a node without childs.
    return;
  }
  
  var submenu = document.getElementById('node' + nodeID + 'sub');
  
  var iconimageholder = document.getElementById('iconimage' + nodeID);
  var actionimage = document.getElementById('handler' + nodeID);

  // This will be used if showRootNode is set to false.
  var firstChildOfRoot = false;
  if (actionimage.src.indexOf('_no_root') != -1) {
    firstChildOfRoot = true;
  }
  
  if (submenu.style.display == 'none') {
    writeStates(nodeID,'open');
    fireOpenEvent(treeNode);
    submenu.style.display = 'block';

    iconimageholder.src = treeNode.getOpenIcon();
  
    if (actionimage.src.indexOf('last') == -1) {
      actionimage.src = href + 'nanoImages/' + ((firstChildOfRoot'minus_no_root' : (showLines ? 'minus' : 'minus_nolines')) '.gif';
    }
    else {
      actionimage.src = href + 'nanoImages/' + ((firstChildOfRoot'minus_last_no_root' : (showLines ? 'minus_last' : 'minus_nolines')) '.gif';
    }
  }
  else {
    writeStates(nodeID,'closed');
    submenu.style.display = 'none';
    
    iconimageholder.src = treeNode.getIcon();
    
    if (actionimage.src.indexOf('last') == -1) {
      actionimage.src = href + 'nanoImages/' + ((firstChildOfRoot'plus_no_root' : (showLines ? 'plus' : 'plus_nolines')) '.gif';
    }
    else {
      actionimage.src = href + 'nanoImages/' + ((firstChildOfRoot'plus_last_no_root' : (showLines ? 'plus_last' : 'plus_nolines')) '.gif';
    }
  }
}
function fireOpenEvent(treeNode) {
  if (treeNode.gotOpenEventListeners()) {
    for(var i=0;i<treeNode.openeventlisteners.length;i++) {
      eval(treeNode.openeventlisteners[i'(' + treeNode.getID() ');');
    }
  }
}
function fireEditEvent(treeNode,newVal) {
  if (treeNode.gotEditEventListeners()) {
    for(var i=0;i<treeNode.editeventlisteners.length;i++) {
      eval(treeNode.editeventlisteners[i'(' + treeNode.getID() ',\'' + escape(newVal+ '\');');
    }
  }
}
function fireMoveEvent(treeNode,draggedNodeID,droppedOnNodeID) {
  if (treeNode.gotMoveEventListeners()) {
    for(var i=0;i<treeNode.moveeventlisteners.length;i++) {
      eval(treeNode.moveeventlisteners[i'(' + draggedNodeID + ',' + droppedOnNodeID + ');');
    }
  }
}
function blurSelection() {
  if (selectedNode != null) {
    var oldNodeTitle = document.getElementById('title' + selectedNode);
    oldNodeTitle.className = 'treetitleselectedblured';
  }
}
function focusSelection() {
  if (selectedNode != null) {
    var oldNodeTitle = document.getElementById('title' + selectedNode);
    oldNodeTitle.className = 'treetitleselectedfocused';
  }
}
function getCookieVal (offset) {  
  var endstr = document.cookie.indexOf (";",offset);  
  if (endstr == -1) {
    endstr = document.cookie.length;
  }
  return unescape(document.cookie.substring(offset,endstr));
}
function getCookie (name) {  
  var arg = name + "=";
  var alen = arg.length;
  var clen = document.cookie.length;
  var i = 0;
  while (i < clen) {
    var j = i + alen;
    if (document.cookie.substring(i, j== arg) {
      return getCookieVal(j);
    }
    i = document.cookie.indexOf(" ", i1;
    if (i == 0) {
      break;
    }
  }
  return null;
}
function setCookie (name, value) {  
  var argv = setCookie.arguments;  
  var argc = setCookie.arguments.length;  
  var expires = (argc > 2? argv[2null;  
  var path = (argc > 3? argv[3null;  
  var domain = (argc > 4? argv[4null;  
  var secure = (argc > 5? argv[5false;  
  document.cookie = name + "=" + escape (value((expires == null"" ("; expires=" + expires.toGMTString())) ((path == null"" ("; path=" + path)) ((domain == null"" ("; domain=" + domain)) ((secure == true"; secure" "");
}
function expandNode() {
  var state = getState(selectedNode);
  if (state == 'open') {
    var currentTreeNode = getTreeNode(selectedNode);
    if (currentTreeNode.hasChilds()) {
      selectNode(currentTreeNode.childs[0].getID());
    }
  }
  else {
    handleNode(selectedNode);
  }
}
function subtractNode() {
  var state = getState(selectedNode);
  if (state == 'closed') {
    var currentTreeNode = getTreeNode(selectedNode);
    var parent = currentTreeNode.getParent();
    if (parent != null && parent != rootNode) {
      selectNode(parent.getID());
    }
  }
  else {
    handleNode(selectedNode);
  }
}
function selectPrevNode() {
  var currentTreeNode = getTreeNode(selectedNode);
  if (currentTreeNode.prevSibling != null) {

    var state = getState(currentTreeNode.prevSibling.getID());

    if (state == 'open' && currentTreeNode.prevSibling.hasChilds()) {
      // We have to find the last open child of the previoussiblings childs.
      var current = currentTreeNode.prevSibling.childs[currentTreeNode.prevSibling.childs.length - 1];
      var currentstate = 'open';
      while (current.hasChilds() && (getState(current.getID()) == 'open')) {
        current = current.childs[current.childs.length - 1];
      }
      selectNode(current.getID());
    }
    else {
      selectNode(currentTreeNode.prevSibling.getID());
    }
  }
  else {
    if (currentTreeNode.getParent() != null && currentTreeNode.getParent() != rootNode) {
      selectNode(currentTreeNode.getParent().getID());
    }
  }
}
function selectNextNode() {
  var currentTreeNode = getTreeNode(selectedNode);

  var state = getState(selectedNode);
  if (state == 'open' && currentTreeNode.hasChilds()) {
    selectNode(currentTreeNode.childs[0].getID());
  }  
  else {
    if (currentTreeNode.nextSibling != null) {
      selectNode(currentTreeNode.nextSibling.getID());
    }
    else {
      // Continue up the tree until we either hit null, or a parent which have a child.
      var parent = currentTreeNode;
      while ((parent = parent.getParent()) != rootNode) {
        if (parent.nextSibling != null) {
          selectNode(parent.nextSibling.getID());
          break;
        }
      }
      /*
      if (currentTreeNode.getParent().nextSibling != null) {
        selectNode(currentTreeNode.getParent().nextSibling.getID());
      }
      */
    }
  }
}
function keyDown(event) {
  if (window.event) {
    event = window.event;
  }
  if (event.keyCode == 38) { // Up
    selectPrevNode();
    return false;
  }
  else if (event.keyCode == 40) { // Down
    selectNextNode();
    return false;
  }
  else if (event.keyCode == 37) { // left
    subtractNode();
    return false;
  }
  else if (event.keyCode == 39) { // right
    expandNode();
    return false;
  }
}
document.onkeydown = keyDown;
</script>
<script type="text/javascript" language="JavaScript">
showRootNode = false;
sortNodes = false;
dragable = false;

/**
* Needed to initialize the tree.
* And to call showTree(imagePath); to actually show the tree.
* Alternatively this can be done in a script block at the bottom of the page.
* Though this method is somewhat cleaner.
*/
function init() {
  container = document.getElementById('examplediv');
  showTree('');
}
/**
* Called when a user clicks on a node.
@param treeNode the TreeNode object which have been clicked.
*/
function standardClick(treeNode) {
  var mytext = document.getElementById('mytext');
  var param = treeNode.getParam();
  
  mytext.innerHTML = (param == '') ? treeNode.getName() : param;
}
function nodeEdited(treeNode) {

}
var closedGif = 'nanoImages/folder_closed.gif';
var openGif = 'nanoImages/folder_open.gif';
var pageIcon = 'nanoImages/page16x16.gif';
var userIcon = 'nanoImages/user_16x16.gif';
var helpIcon = 'nanoImages/help_16x16.gif';

rootNode = new TreeNode(1,'RootNode');

var node1 = new TreeNode(2,'subpage 1',helpIcon,'<P>This treenode can be renamed (Try to click onnce more on the node).<br>(You have to handle the renaming itself in a function though, since this is implementation specific. ie: Go down in a database and change the titel of a page).<br>A good example would be to open a PHP script to do the renaming, this can for example be done by setting location.href on a hidden iframe, or by setting the src attribute on a script element.</P>');
node1.setEditable(true);
node1.addEditEventListener('nodeEdited');

var node2 = new TreeNode(3,'subpage 2',new Array(closedGif,openGif));
  var node2a = new TreeNode(4,'1st subpage to Node 2',new Array(closedGif,openGif));
    var node2aa = new TreeNode(5,'subpage to subpage of Node2',new Array(closedGif,openGif));
      var node2aaa = new TreeNode(6,'Some child',pageIcon);
      var node2aab = new TreeNode(7,'Some child',pageIcon);
      var node2aac = new TreeNode(8,'Some child',pageIcon);
      node2aa.addChild(node2aaa);
      node2aa.addChild(node2aab);
      node2aa.addChild(node2aac);
    node2a.addChild(node2aa);
  var node2b = new TreeNode(9,'2nd subpage to Node 2',pageIcon);
  var node2c = new TreeNode(10,'3rd subpageto Node 2',pageIcon);
  node2.addChild(node2a);
  node2.addChild(node2b);
  node2.addChild(node2c);

var node3 = new TreeNode(11,'subpage 3',new Array(closedGif,openGif));
  var node3a = new TreeNode(12,'Yet another child',pageIcon);
  node3.addChild(node3a);

var node4 = new TreeNode(13,'subpage 4',userIcon);

// rootNode.addChild(node1);
rootNode.addChild(node2);
rootNode.addChild(node3);
// rootNode.addChild(node4);
</script>
<style type="text/css">
div,p,a {
  font-family: Verdana,Arial;
  font-size: 11px;
}
#exampletable {
  width: 100%;
  height: 100%;
}
#examplediv {
  width: 250px;
  height: 100%;
  overflow: auto;
}
.explanation {
  font-weight: bold;
  font-style: italic;
}
</style>
</head>
<body OnLoad="init();">
<table id="exampletable">
  <tr>
    <td valign="top" style="width: 250px;">
      <div id="examplediv"></div>
    </td>
    <td valign="top">
      <div style="background-color:#EEE;border-style:dashed;border-color:#000000;border-width:1px;padding:5px;">
        <div style="font-weight: bold;">NanoTree.</div>
        <div id="mytext">
        <p>NanoTree is a JavaScript tree, published under the <a href="http://www.gnu.org/copyleft/lesser.html">LGPL License</a>, which is developed to work in (at leastInternet Explorer and Mozilla<br>
        <p style="font-style:italic;">CopyRight Martin Mouritzen</p>
        </div>
      </div>
      <br>
    </td>
  </tr>
</table>
</body></html>

           
       
Download: nanotree.zip   ( 15  K )  
Related examples in the same category
1.  Build a tree in JavaScriptHas Download File
2.  Delete, insert items in a treeHas Download File
3.  Tree selection action handlerHas Download File
4.  Expand, Collapse, Close, Open selected Tree item and branch Has Download File
5.  Change Tree Node Color and IconHas Download File
6.  Checkbox tree node: checked, unchecked, get the checked itemsHas Download File
7.  Change tree expand and collapse iconsHas Download File
8.  Drag and Drop between treesHas Download File
9.  Build tree from xmlHas Download File
10.  Tree navigation barHas Download File
11.  Navigation Tree Has Download File
12.  Navigation Tree menu based on XML
13.  XML Tree
14.  Building Collapsible Trees








Home| Contact Us
Copyright 2003 - 04 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.