|
<!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>
<title>Untitled Page</title>
<style type="text/css">
/* style sheets for the tree. Idealy need to be extracted and moved to the separate file
along with javascript code below. */
/* style sheet for a tree object UL element and any sub-elements */
/* NOTE: this style will be automatically assigned by the javascript */
ul.__tree__, ul.__tree__ ul {
background: url(vline.png) repeat-y; /* vertical line repeated vertically to fill up any gaps */
margin: 0 0 0 10px; /* changes default UL margins and padding */
padding: 0;
}
/* style sheet for the each tree item */
ul.__tree__ li {
background: url(node.png) no-repeat; /* |- image to prefix each node */
list-style: none; /* do not display any default LI markings */
padding: 0 12px; /* offset LI */
}
ul.__tree__ li.__last_child__ { /* |_ image for the last child */
background: #fff url(lastnode.png) no-repeat;
}
ul.__tree__ span.__selected__ { /* show text for the selected node in different color */
background: blue !important;
color: white;
}
</style>
</head>
<body>
<!-- tree contents: the tree and all the subnodes are under UL tag.
Leaf elements ar LI items. If there are subnotes, they go into the sub-UL -->
<ul id="t">
<li>Item1</li>
<li>Item2
<ul>
<li>Item2.1</li>
<li><a onclick="alert('look mom, I\'m here!');">Item2.2</a>
<ul>
<li>Item2.2.1</li>
</ul>
</li>
<li>Item2.3</li>
</ul>
</li>
<li>Item3</li>
<li>Item1</li>
</ul>
<script type="text/javascript">
/* Tree class, pass ID of the UL element to attach itself to, and customization functions
the example of calling with customizations would be:
new Tree('someUl', { getIcon : function(li, tree) { return "some.gif" } });
I guess one of the things to do would be to implement a true inheritance, but then it would be
extra code. If your project utilizes any kind of javascript libraries, then you can do true
inheritance using whatever means they provide. As is this is independent of any OO implementation
*/
function Tree(elId, opt) {
this.elem = document.getElementById(elId); // save main UL element
this.elem.className += " __tree__ "; // force style sheet for the whole tree.
this.selected = null; // currently selected LI element.
this.defOpts = { // default implementation of the config options
icons : [ "list.gif", "fold.gif", "open.gif" ],
getIcon : function(li, tree) { // getIcon - gets called during the initialization or any
if (opt && opt.getIcon) // time image is clicked.
return opt.getIcon(li, tree); // if alternative implementation provided by caller/user - use it.
var uls = li.getElementsByTagName("ul"); // see if there are any child nodes.
var icons = (opt && opt.icons) ? opt.icons : this.icons;
if (uls.length == 0)
return icons[0] // return default icons
return icons[uls[0].style.display == "none" ? 1 : 2];
},
onClickImage : function(li, tree) { // gets called when image is being clicked to
if (opt && opt.onClickImage) // expand / collapse node
return opt.onClickImage(li, tree); // use new implementation if provided.
var uls = li.getElementsByTagName("ul"); // check if there are sub-nodes
if (uls.length == 0)
return; // toggle visibility of the child UL
uls[0].style.display = (uls[0].style.display != "none") ? "none" : "block";
var imgs = li.getElementsByTagName("img"); // our image is the first one.
imgs[0].src = this.getIcon(li);
}
};
this.initItem = function(li) { // initializes LI element - tree leaf
li.tree = this; // save reference to the tree object
if (li.initDone) // if already initialized - get out
return;
li.initDone = true;
var img = document.createElement("img"); // create image element
img.src = this.defOpts.getIcon(li, this); // assign image URL
img.onclick = function(e) { // handle on-expand/collapse clicks on image
e = e || window.event;
var t = e.target || e.srcElement; // find element - image. It's direct parent should be LI
t.parentNode.tree.defOpts.onClickImage(t.parentNode, this); // call handler to process event.
}
var span = document.createElement("span"); // create span - our LI should have up to 3 nodes in
for (var i = li.childNodes.length - 1; i >= 0; i--) // image, span with leaf contents and possible UL - sub-tree
if (li.childNodes[i].nodeName == "UL") // if sub-tree - initialize it too
this.initChildren(li.childNodes[i])
else // move everything else inside the span
span.insertBefore(li.removeChild(li.childNodes[i]), span.firstChild);
li.insertBefore(span, li.firstChild); // insert span/leaf
li.insertBefore(img, li.firstChild); // insert image
span.onclick = function(e) { // handle highligh action.
e = e || window.event;
var li = e.target || e.srcElement; // find LI/leaf that generated the event
while (li && li.nodeName != "LI")
li = li.parentNode;
if (!li)
return;
if (li.tree.selected) // un-select previous selection
li.tree.selected.className = li.tree.selected.className.replace(", __selected__ ,", "");
var span = li.firstChild.nextSibling; // find span within LI
span.className += ", __selected__ ,"; // set style and save selection
li.tree.selected = span;
}
};
this.initChildren = function(ul) { // initialize tree/sub-tree UL elements
var last = true;
for (var li = ul.lastChild; li; li = li.previousSibling)
if (li.nodeName == "LI") {
this.initItem(li);
if (last) {
li.className += ", __last_child__ ,"; // set class name for the last element |_
last = false;
}
}
}
this.initChildren(this.elem);
return this;
}
// do the magic!!!
new Tree("t");
</script>
</body>
</html>
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.