abstraction:
The TreeView control displays a hierarchy of nodes, like the way files and folders are displayed in the
left pane of the Windows Explorer feature in Windows operating systems,
Each node in the tree view might contain other nodes, called child nodes.
You can display parent nodes, or nodes that contain child nodes, as expanded or collapsed.
introduction:
to build the treeView control basing on web meaning css, html and js, is not hard to implement, all one needs to do is to build an active css code, you needn't pay too much attention to the js code it is really easy if you look to the treeview structure it at all depend on recursive way, each node can at the same time be parent and child.
design:
here we see the recursive algorithm for creating the html code for treeview control :
Code
function TreeNode(ULiD,txt)
{
// add the parent node,,
this.changeToParent=function(liID)
{
var li=document.getElementById(liID);
li.className='Collapsed ';
var ul=document.createElement('ul');
ul.id=liID+'P_';
var uls=li.getElementsByTagName('ul');
if(uls.length<1)
{
li.appendChild(ul);
}
return ul.id;
}
var ul=document.getElementById(ULiD);
var li=document.createElement('li');
//
li.innerHTML+=txt;
li.id=ULiD+'C_'+NodeCount+'_';
ul.appendChild(li);
NodeCount++;
// recursive:node::
this.addNode=function(chtxt)
{
var pa=this.changeToParent(li.id);
var child=new TreeNode(pa,chtxt)
return child;
}
}
then continue with the class of the treeView control. to use the code below seems reasonable
Code
function TreeView(pid)
{
var open=true;
createTreeViewHtmlCode(pid);
var obj=document.getElementById(pid);
var treeObj=document.getElementById(pid+'tv');
this.addNode=function(txt)
{
var treeN=new TreeNode(pid+'tv',txt);
return treeN;
}
// the main function for the treeView..
}
Then one needs to add JavaScript to the page to toggle the applied styles. For this, I decided to go with an approach that could handle multiple styles being applied to a single element, so my solution is a little more complex than a simple className replacement approach:
Code
Array.prototype.indexOf = IndexOf;
//Toggles between two classes for an element
function ToggleClass(element, firstClass, secondClass, event)
{
event.cancelBubble = true;
var classes = element.className.split(" ");
var firstClassIndex = classes.indexOf(firstClass);
var secondClassIndex = classes.indexOf(secondClass);
if (firstClassIndex == -1 && secondClassIndex == -1)
{
classes[classes.length] = firstClass;
}
else if (firstClassIndex != -1)
{
classes[firstClassIndex] = secondClass;
}
else
{
classes[secondClassIndex] = firstClass;
}
element.className = classes.join(" ");
}
//Finds the index of an item in an array
function IndexOf(item)
{
for (var i=0; i < this.length; i++)
{
if (this[i] == item)
{
return i;
}
}
return -1;
}
I then wrote a script to setup the treeview based on a nested list container. The main reason according to which I chose not to have all the event wiring in the HTML itself, is that my approach leads to cleaner markup and allows one to easily convert any unordered list into a treeview. Here is the script to hook up the click events (it works in both IE and FireFox):
Code
//The toggle event handler for each expandable/collapsable node
//- Note that this also exists to prevent any IE memory leaks
//(due to circular references caused by this)
function ToggleNodeStateHandler(event)
{
ToggleClass(this, "Collapsed", "Expanded", (event == null) ? window.event : event);
}
//Prevents the onclick event from bubbling up to parent elements
function PreventBubbleHandler(event)
{
if (!event) event = window.event;
event.cancelBubble = true;
}
//Adds the relevant onclick handlers for the nodes in the tree view
function SetupTreeView(elementId)
{
var tree = document.getElementById(elementId);
var treeElements = tree.getElementsByTagName("li");
for (var i=0; i < treeElements.length; i++)
{
if (treeElements[i].getElementsByTagName("ul").length > 0)
{
treeElements[i].onclick = ToggleNodeStateHandler;
}
else
{
treeElements[i].onclick = PreventBubbleHandler;
}
}
}
to make it all more convenient for users there is no need for create the html code,
just we call the function:
function createTreeViewHtmlCode(pid)
{
var ul=document.createElement('ul');
ul.className='TreeView';
ul.id=pid+'tv';
document.getElementById(pid).appendChild(ul);
}
here one can observe the entire js code:
Code
Array.prototype.indexOf = IndexOf;
//Toggles between two classes for an element
function ToggleClass(element, firstClass, secondClass, event)
{
event.cancelBubble = true;
var classes = element.className.split(" ");
var firstClassIndex = classes.indexOf(firstClass);
var secondClassIndex = classes.indexOf(secondClass);
if (firstClassIndex == -1 && secondClassIndex == -1)
{
classes[classes.length] = firstClass;
}
else if (firstClassIndex != -1)
{
classes[firstClassIndex] = secondClass;
}
else
{
classes[secondClassIndex] = firstClass;
}
element.className = classes.join(" ");
}
//Finds the index of an item in an array
function IndexOf(item)
{
for (var i=0; i < this.length; i++)
{
if (this[i] == item)
{
return i;
}
}
return -1;
}
//The toggle event handler for each expandable/collapsable node
//- Note that this also exists to prevent any IE memory leaks
//(due to circular references caused by this)
function ToggleNodeStateHandler(event)
{
ToggleClass(this, "Collapsed", "Expanded", (event == null) ? window.event : event);
}
//Prevents the onclick event from bubbling up to parent elements
function PreventBubbleHandler(event)
{
if (!event) event = window.event;
event.cancelBubble = true;
}
//Adds the relevant onclick handlers for the nodes in the tree view
function SetupTreeView(elementId)
{
var tree = document.getElementById(elementId);
var treeElements = tree.getElementsByTagName("li");
for (var i=0; i < treeElements.length; i++)
{
if (treeElements[i].getElementsByTagName("ul").length > 0)
{
treeElements[i].onclick = ToggleNodeStateHandler;
}
else
{
treeElements[i].onclick = PreventBubbleHandler;
}
}
}
function createTreeViewHtmlCode(pid)
{
var ul=document.createElement('ul');
ul.className='TreeView';
ul.id=pid+'tv';
document.getElementById(pid).appendChild(ul);
}
var NodeCount=0;
// this function to create the sub tree,
//mean create the ul in the li, or nested ul.
// this function to create the li in ul:
function TreeNode(ULiD,txt)
{
// add the parent node,,
this.changeToParent=function(liID)
{
var li=document.getElementById(liID);
li.className='Collapsed ';
var ul=document.createElement('ul');
ul.id=liID+'P_';
var uls=li.getElementsByTagName('ul');
if(uls.length<1)
{
li.appendChild(ul);
}
return ul.id;
}
var ul=document.getElementById(ULiD);
var li=document.createElement('li');
//
li.innerHTML+=txt;
li.id=ULiD+'C_'+NodeCount+'_';
ul.appendChild(li);
NodeCount++;
// recursive:node::
this.addNode=function(chtxt)
{
var pa=this.changeToParent(li.id);
var child=new TreeNode(pa,chtxt)
return child;
}
}
function TreeView(pid)
{
var open=true;
createTreeViewHtmlCode(pid);
var obj=document.getElementById(pid);
var treeObj=document.getElementById(pid+'tv');
this.addNode=function(txt)
{
var treeN=new TreeNode(pid+'tv',txt);
return treeN;
}
// the main function for the treeView..
}
now we need to see the way of creating the object of treeView :
Code
var root=new TreeView('tree');
var rr=root.addNode('根节点');
var dd=rr.addNode('根节点2');
dd.addNode('孩子1');
dd.addNode('孩子1');
var ddd=rr.addNode('根节点2');
ddd.addNode('孩子1');
ddd.addNode('孩子1');
var dddd=rr.addNode('根节点2');
dddd.addNode('孩子1');
dddd.addNode('孩子1');
var chi=rr.addNode('根节点2');
chi.addNode('孩子2');
chi.addNode('海子3');
var shi=rr.addNode('根节点2');
shi.addNode('aaaaao');
var shu=shi.addNode('根节点4');
shu.addNode('crearo,,');
shu.addNode('ammar');
shu.addNode('yemen');
but the step must be implemented after you call the header file:
<SCRIPT type="text/javascript" language="javascript" src="treeview.js"></SCRIPT>
now one can observe the auto-generation code simultaneously created by the js object above:
Code
<!-- Level 1 nodes -->
<DIV id="tree">
<UL id="treetv" class="TreeView">
<LI id="treetvC_0_" class="Expanded ">
根节点
<UL id="treetvC_0_P_">
<LI id="treetvC_0_P_C_1_" class="Collapsed ">
根节点2
<UL id="treetvC_0_P_C_1_P_">
<LI id="treetvC_0_P_C_1_P_C_2_">
孩子1
</LI>
<LI id="treetvC_0_P_C_1_P_C_3_">
孩子1
</LI>
</UL>
</LI>
<LI id="treetvC_0_P_C_4_" class="Collapsed ">
根节点2
<UL id="treetvC_0_P_C_4_P_">
<LI id="treetvC_0_P_C_4_P_C_5_">
孩子1
</LI>
<LI id="treetvC_0_P_C_4_P_C_6_">
孩子1
</LI>
</UL>
</LI>
<LI id="treetvC_0_P_C_7_" class="Collapsed ">
根节点2
<UL id="treetvC_0_P_C_7_P_">
<LI id="treetvC_0_P_C_7_P_C_8_">
孩子1
</LI>
<LI id="treetvC_0_P_C_7_P_C_9_">
孩子1
</LI>
</UL>
</LI>
<LI id="treetvC_0_P_C_10_" class="Collapsed ">
根节点2
<UL id="treetvC_0_P_C_10_P_">
<LI id="treetvC_0_P_C_10_P_C_11_">
孩子2
</LI>
<LI id="treetvC_0_P_C_10_P_C_12_">
海子3
</LI>
</UL>
</LI>
<LI id="treetvC_0_P_C_13_" class="Collapsed ">
根节点2
<UL id="treetvC_0_P_C_13_P_">
<LI id="treetvC_0_P_C_13_P_C_14_">
aaaaao
</LI>
<LI id="treetvC_0_P_C_13_P_C_15_" class="Collapsed ">
根节点4
<UL id="treetvC_0_P_C_13_P_C_15_P_">
<LI id="treetvC_0_P_C_13_P_C_15_P_C_16_">
crearo,,
</LI>
<LI id="treetvC_0_P_C_13_P_C_15_P_C_17_">
ammar
</LI>
<LI id="treetvC_0_P_C_13_P_C_15_P_C_18_">
yemen
</LI>
</UL>
</LI>
</UL>
</LI>
</UL>
</LI>
</UL>
</DIV>
here you see the css style :
Now I want the first level node to be collapsed with a plus image next to it by default to indicate that the node can be expanded. In order to achieve this we can get rid of the li symbols by making the list items float left. This makes them stack up, so then one can set the elements to display at a 100% of the containing element. We then need space to place our treeview expandable image, so we put in a left padding of 37px. To simplify the process you can use a CSS child selector to apply this to all list elements within the treeview, like this:
Code
.TreeView li
{
padding: 9 0 0 37px;
float:left;
width:100%;
height:9px;
position: relative;
list-style: none;
background-image:url('images/d4.png');
background-repeat:no-repeat;
background-position:left;
border-left:1px #979797 dotted;
z-index:1000;
}
The addition of the collapsing and expanding images, and the associated effects to the child nodes is achieved with the help of the following styles:
Code
.TreeView, .TreeView ul
{
margin:0px;
padding:0px;
}
LI.Expanded
{
background: url('images/m.png') no-repeat left top;
border-left:1px dotted transparent ;
}
LI.Expanded ul
{
display: block;
}
LI.Collapsed
{
background: url('images/p.png') no-repeat left top;
border-left:1px transparent dotted;
}
LI.Collapsed ul
{
display: none;
}
Moory !! Marisha!!!