Important alert: (current site time 7/15/2013 12:42:23 PM EDT)
 

VB icon

Infinite tree w/XML

Email
Submitted on: 10/16/2002 12:11:46 PM
By: Eric Repec InetSolution  
Level: Advanced
User Rating: By 1 Users
Compatibility: JavaScript
Views: 8290
author picture
(About the author)
 
     This is a JavaScript implementation of a infinite tree structure which can model a simple or complex tree on the client or server. A project I was working on required the ability to add more then two children to a node for an implementation of a select tree. I wanted to create a linked list tree structure as you would in C or C++ and was unable to find an implementation of this sort on any of the existing code sites out there. This code has a number of use cases from complex breadcrumb implementations to custom written tree menus. You can also use this tree to show complex dependences and or inheritance within your data. Within this code, there are some good examples of recursion with JavaScript as well as object creation and assignment. I have also created the ability to import and export with XML. This means that you can utilize the XML islands you have lying around to populate this tree and then use the tree to reference the data. I am not sure it this gains anything over the XML DOM or not but it is interesting to say the least. Have fun Eric Repec
 
code:
Can't Copy and Paste this?
Click here for a copy-and-paste friendly version of this code!
 
Terms of Agreement:   
By using this code, you agree to the following terms...   
  1. You may use this code in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
  2. You MAY NOT redistribute this code (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
  3. You may link to this code from another website, but ONLY if it is not wrapped in a frame. 
  4. You will abide by any additional copyright restrictions which the author may have placed in the code or code's description.
				
'**************************************
' Name: Infinite tree w/XML
' Description:This is a JavaScript implementation of a infinite tree structure which can model a simple or complex tree on the client or server. A project I was working on required the ability to add more then two children to a node for an implementation of a select tree. I wanted to create a linked list tree structure as you would in C or C++ and was unable to find an implementation of this sort on any of the existing code sites out there. 
This code has a number of use cases from complex breadcrumb implementations to custom written tree menus. You can also use this tree to show complex dependences and or inheritance within your data. 
Within this code, there are some good examples of recursion with JavaScript as well as object creation and assignment.
I have also created the ability to import and export with XML. This means that you can utilize the XML islands you have lying around to populate this tree and then use the tree to reference the data. I am not sure it this gains anything over the XML DOM or not but it is interesting to say the least. 
Have fun
Eric Repec
' By: Eric Repec InetSolution
'
'This code is copyrighted and has' limited warranties.Please see http://www.Planet-Source-Code.com/vb/scripts/ShowCode.asp?txtCodeId=3239&lngWId=14'for details.'**************************************

<html>
<head>
<title>infinite tree example</title>
<script type="text/javascript" language="JavaScript">
alert("This works best in IE 6.0. I have not tested it on anything else.");
// create a new infinitetree() object and populate the first(root) node with "n1"
var it = new infinitetree("n1");
// it always points to the root. Adding a child to the root with a value of "n2"
it.addChild("n2");
// you could have implemented the current property as a variable but I have implemented as part of the object
// for the fun of it. Here I am setting it to the first child of the root. "n2"
it.setCurrent(it.getChild(0));
// calling a function made possiable by the object property named current. This is a fast way to add a node to the 
// tree
it.addChildtoCurrent("n3");
// setting current = to the last node which was added to the tree. Another short cut.
it.setCurrent(it.lastAdded);
it.addChildtoCurrent("n4");
it.setCurrent(it.lastAdded);
// moving the current property up a level on the tree. Basically current = current.parent.
it.assend();
it.assend();
it.addChildtoCurrent("n5");
it.setCurrent(it.lastAdded);
it.addChildtoCurrent("n6");
it.setCurrent(it.lastAdded);
it.assend();
it.assend();
it.addChildtoCurrent("n7");
it.setCurrent(it.lastAdded);
it.addChildtoCurrent("n8");
it.setCurrent(it.lastAdded);
it.assend();
it.assend();
it.addChildtoCurrent("n8.1");
it.setCurrent(it.lastAdded);
it.addChildtoCurrent("n9");
it.setCurrent(it.lastAdded);
it.addChildtoCurrent("n10");
it.setCurrent(it.lastAdded);
it.addChildtoCurrent("n10.5");
it.setCurrent(it.lastAdded);
it.assend();
it.addChildtoCurrent("n12");
it.setCurrent(it.lastAdded);
it.assend();
it.assend();
it.current.addChild("n11");
// making a copy of the tree using the export to XML and the import to XML methods
var it2 = new infinitetree();
it2.importxml(it.exportxml());
// printing the two trees to prove that they are equal
alert(it2.root.expandnode(true));
alert(it.root.expandnode(true));
// searching the tree for the value "n12" and printing the value of it's parent.
alert(it.search("n12").parent.value);
// a quick and dirty way to dump all the contents of the tree.
alert(it.unload());
function infinitetree(value)
{
		
	this.parent;				// pointer to the node's parent
	this.child = new Array();	// array of children
	this.value = value;			// value of the node
	this.current = this;		// used only on the root node to point to a object pointer which represents the current node.
	this.root = this;			// points to the root.
	this.lastAdded;				// used only on the root node to point to the last added node.
	this.index;					// holds the child index of the nodes parent 
	
	// pass in a well formed XML stream and it will be inserted into the tree placing
	// the root in the place of the node passed.
	this.importxml = function(strXML)
	{
		var oxmlDocument = new ActiveXObject("MSXML2.DOMDocument");
		oxmlDocument.loadXML(strXML);
		this.value = oxmlDocument.firstChild.nodeName;
		for(var i = 0; i < oxmlDocument.firstChild.childNodes.length; i ++)
		{
			this.addChild(oxmlDocument.firstChild.childNodes[i].nodeName);
			this.root.lastAdded.importxml(oxmlDocument.firstChild.childNodes[i].xml);
		}
	}
	
	// Export a xml stream which represents the entire tree
	this.exportxml = function()
	{
		var oxmlDocumentOut = new ActiveXObject("MSXML2.DOMDocument");
		var oxmlDocumentTemp = new ActiveXObject("MSXML2.DOMDocument");
		oxmlDocumentOut.appendChild(oxmlDocumentOut.createElement(this.value));
		for(var i = 0;i < this.child.length;i++)
		{
			oxmlDocumentTemp.loadXML(this.child[i].exportxml());
			oxmlDocumentOut.firstChild.appendChild(oxmlDocumentTemp.firstChild);
		}
		return oxmlDocumentOut.xml;
	}
	
	// this will return an object which represents the item being searched for. 
	//It will return Null if not found in the tree
	this.search = function(sKey)
	{
		if(this.value == sKey) return this;
		else
		for(var i = 0;i < this.child.length; i++)
		{
			oCurrent = this.child[i].search(sKey);
			if(oCurrent != null) return oCurrent;
		}
		return null;
	}
	
	// Helper function used to insert spaces in the output.
	function space(len)
	{
		var spaces = "";
		
		for(var i = 0;i < len;i++)
			spaces += " ";
		return spaces;
	}
	
	// Will return a text block which represents the tree
	// if the first param is passed in a True it will expand all sub nodes of the node passed.
	// if false it will only print the children of the node passed.
	this.expandnode = function(bAllSibs,iDepth)
	{
		var strOut = "";
		if(isNaN(iDepth)) iDepth = 0;
		strOut = this.value;
		for(var i = 0;i < this.child.length; i++)
		{
			if(i == 0) iDepth += this.value.length;
			if(i > 0) strOut += "\n" + space(iDepth);
			if(bAllSibs)
				strOut += this.child[i].expandnode(bAllSibs,iDepth);
			else
				strOut += this.child[i].value + "\n";
		}
		return strOut;
	}
	
	// add a child to the node passed.
	this.addChild = function(value)
	{
		var index = this.child.length;
		this.child[index] = new infinitetree(value);
		this.child[index].root = this.root;
		this.root.lastAdded = this.child[index];
		this.child[index].parent = this;
		this.child[index].index = index;
		return true;
	}
	
	// add a child to the node pointed to by Current
	this.addChildtoCurrent = function(value)
	{
		this.root.current.addChild(value);
	}
	
	// will get a child of the node passed which is pointed to by the index passed.
	this.getChild = function(index)
	{
		if(index == null) index = 0;
		if(index < this.child.length)
			return this.child[index];
		return null;
	}
	
	// will set the root variable current to the node passed
	this.setCurrent = function(node)
	{
		if(node == null) 
			return false;
		this.current = node;
		return true;
	}
	
	// Will move the current pointer to the parent of the passed node
	this.assend = function()
	{
		if(this.root.current.parent == null)
			return false;
		this.root.current = this.root.current.parent;
		return true;
	}
	
	// will print all node values below the node passed.
	this.unload = function()
	{
		var sString = "";
		for(var i = 0;i < this.child.length;i++)
		{
			sString += " <- " + this.child[i].unload();
		}
		return this.value + sString;
	}
}
</script>
<script language="JavaScript" src="working.js"></script>
</head>
<body>
<xml id="xmlisland">
<n1>
	<n2>
		<n3>
			<n4/>
		</n3>
		<n5>
			<n6/>
		</n5>
		<n7>
			<n8/>
		</n7>
		<n8.1>
			<n9>
				<n10>
					<n10.5/>
					<n12/>
				</n10>
				<n11/>
			</n9>
		</n8.1>
	</n2>
</n1>
</xml>
<script language="JavaScript">
// example of pulling the tree from xml in an xml data island.
// show the contents of the island
alert(window.document.all["xmlisland"].innerHTML);
// create a new infinite tree object to use.
var t2 = new infinitetree("n1");
t2.importxml(window.document.all["xmlisland"].innerHTML);
// set the contents of the body to the tree contents.
window.document.body.innerText+=t2.root.expandnode(true);
</script>
<span onclick="window.document.body.innerText+=t2.root.expandnode(true);">test</span>
</body>
</html>


Other 1 submission(s) by this author

 


Report Bad Submission
Use this form to tell us if this entry should be deleted (i.e contains no code, is a virus, etc.).
This submission should be removed because:

Your Vote

What do you think of this code (in the Advanced category)?
(The code with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor (See voting log ...)
 

Other User Comments

10/20/2002 3:29:06 PM

Can I find an example somewhere?
(If this comment was disrespectful, please report it.)

 
10/20/2002 3:41:41 PMEric Repec InetSolution

Sorry I don't understand your question. This is an example of how to implement a mathematical model which is named infinite tree. There are many uses for this type of model it all depends on what you are trying to do.

The example used here was to map some XML to the infinite tree, and then back again. This could be a good way to save the data in the tree.
(If this comment was disrespectful, please report it.)

 
10/20/2002 3:42:25 PMEric Repec InetSolution

Cont.....
The way I used this in real life was to implement an expandable menu system which helped the user navigate through the site. In my implementation I didn't use XML because it ran on browsers which didn't support it. You can also do some searches in Google on "infinite tree" and see some examples of where it is used. This type of construct is often used in complex systems such as a RDBMS or maybe an advanced information tracking system where dependencies are needed on the data.
(If this comment was disrespectful, please report it.)

 
12/30/2002 9:13:13 PM

There appears to be a small discrepency between the code on this (the main) page, and that in the Cut-and-Paste-Friendly page. In the Cut-and-Paste page, the last statement in the is a element that points to a file named working.js while in the main page, the script element is empty. Is this additional script file needed by your implementation?
(If this comment was disrespectful, please report it.)

 

Add Your Feedback
Your feedback will be posted below and an email sent to the author. Please remember that the author was kind enough to share this with you, so any criticisms must be stated politely, or they will be deleted. (For feedback not related to this particular code, please click here instead.)
 

To post feedback, first please login.