Author Topic: [JavaScript] Document Tree Structure  (Read 2668 times)

0 Members and 1 Guest are viewing this topic.

Offline Ender

  • x86
  • Hero Member
  • *****
  • Posts: 2390
    • View Profile
[JavaScript] Document Tree Structure
« on: August 17, 2006, 07:57:02 pm »
Here's an object-oriented package designed to be used as a tool for making document tree structures. It consists of an external javascript file and an external css file. I did this for work and received some advice in the Web Programming and Design forum about how to do this. The advice for using DOM really kicked it off ~_~, and looking at other scripts helped also. I got the OO design from the web and it's worked out very nicely, especially the polymorphism!

At first I was trying to use minimal javascript with css hacks. Although it is possible (custom checkbox images), it is pretty fugly, so I took some tutorials on javascript and actually got to appreciate the language. The way that it can easily manipulate DOM is very powerful. DOM is like "smart html editing," it makes objects out of html tags and lets you dynamically modify them through javascript and other client-side languages.

Oh, and you're going to want some images for open and closed folders and for documents. They're currently expected to be named "open.gif", "closed.gif", and "doc.gif"

The stand-alone package consists of two external scripts, one javascript and one css. The way you use it is pretty intuitive. You create a tree object, add branch objects to the tree, add leaf objects to the branches, and tell the tree to write itself.

doctree.js
Code: [Select]
// if you want to modify the image source, you don't have to painfully search through the whole script
// just change the variable value here
var openImg = new Image();
openImg.src = 'open.gif';
var closedImg = new Image();
closedImg.src = 'closed.gif';
var docImg = new Image();
docImg.src = 'doc.gif';

// constructor for the tree class
function tree() {
this.branches = new Array();
this.add = addBranch;      // I'm using polymorphism
this.write = writeTree;    // so that I don't have to worry about
}                                  // which kind of node I am adding or writing
                                   // and can handle all nodes the same

// constructor for the branch class
function branch(text) {
this.id = ''; // id is updated later
this.leaves = new Array();
this.text = text;
this.add = addLeaf;
this.write = writeBranch;
}

// constructor for the leaf class
function leaf(text, link) {
this.id = ''; // id is updated later
this.text = text;
this.link = link;
this.write = writeLeaf;
}

// implementation of branch.add
function addBranch(branch) {
branch.id = 'branch-' + this.branches.length;
this.branches[this.branches.length] = branch;
}

// implementation of leaf.add
function addLeaf(leaf) {
leaf.id = this.id + '-leaf-' + this.leaves.length;
this.leaves[this.leaves.length] = leaf;

}

// implementation of tree.write
function writeTree() {
var treestr = '';
treestr += '<h3>Documents</h3>';
treestr += '<form name="subscription" method="post" action="#">';
treestr += '<input type="submit" value="subscribe"><input type="button" value="reset" onClick="resetCheckboxes()"><br /><br />';
treestr += '<span class="tree">';
for (i in this.branches) {
treestr += this.branches[i].write();
}
treestr += '</span>';
treestr += '</form>';
document.write(treestr);
}

// implementation of branch.write
function writeBranch() {
var branchstr = '<span class="branch">';
branchstr += '<span name="reveal" onClick="handleBranch(\'' + this.id + '\')">';
branchstr += '<img src="' + closedImg.src + '" id="img-' + this.id + '" >' + this.text;
branchstr += '</span>';
branchstr += '<input type="checkbox" id="mcb-' + this.id + '" onClick="handleCheckboxes(\'' + this.id + '\')">';
branchstr += '</span>';
branchstr += '<span class="leaf" id="' + this.id + '">';
for (i in this.leaves) {
branchstr += this.leaves[i].write() + '<br>';
}
branchstr += '</span>';
return branchstr;
}

// implementation of leaf.write
function writeLeaf() {
var leafstr = '';
leafstr += '<a href="#">';
leafstr += '<img src="' + docImg.src + '" border="0">';
leafstr += this.text;
leafstr += '</a>';
leafstr += '<input type="checkbox" id="cb-' + this.id + '">';
return leafstr;
}

/* I use DOM to dynamically interface with the html in javascript
 * It creates objects out of html elements and allows me to modify them
 * It's sort of like "smart html editing"
 * It's used in all the methods below
 */

// This method collapses and uncollapses a branch
function handleBranch(branchid) {
var brstyle = document.getElementById(branchid).style;
swapFolder('img-' + branchid);
// collapse
if (brstyle.display == "block")
brstyle.display = "none";
// uncollapse
else
brstyle.display = "block";
// brstyle.display = (brstyle.display == "none") ? "block" : "none";
}

// This method checks and unchecks the checkboxes of all the leaves in a
// given branch
function handleCheckboxes(branchid) {
var branch = document.getElementById(branchid);
var checkboxes = new Array(), e, i = 0;
var branchCheckbox = document.getElementById('mcb-' + branchid);
// get an array of all the checkboxes that are children of this branch
while (e = document.getElementById(branchid).getElementsByTagName('INPUT')[i++]) {
if (e.type == 'checkbox') {
checkboxes.push(e);
}
}
// check/uncheck all the checkboxes in that array
for (i in checkboxes) {
checkboxes[i].checked = branchCheckbox.checked;
}
}

// This method clears all the checkboxes
function resetCheckboxes() {
var checkboxes = document.getElementsByTagName('INPUT');
for (i in checkboxes)
if (checkboxes[i].type == 'checkbox')
checkboxes[i].checked = false;
}

// This method swaps the folder image to open to closed or vice versa depending // on its current state
function swapFolder(imgid) {
var img = document.getElementById(imgid);
if(img.src.indexOf('closed.gif')>-1)
img.src = openImg.src;
else
img.src = closedImg.src;
//img.src = (img.src == openImg) ? closedImg : openImg;

}

doctree.css
Code: [Select]
body{
font: 10pt Verdana,sans-serif;
color: navy;
}
.tree {

}
.branch{
cursor: pointer;
cursor: hand;
display: block;
}
.leaf{
display: none;
margin-left: 15px;
}
a{
text-decoration: none;
}
a:hover{
text-decoration: underline;
}

test
Code: [Select]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html>
<head>
<title>draft</title>
</head>

<frameset cols="15%,85%">
<frame src="dcoui.html" />
</frameset>

</html>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<head>
<link href="dcoui.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="dcoui.js"></script>
</head>

<body>
<script type="text/javascript">
t = new tree();
b0 = new branch('branch 0');
b1 = new branch('branch 1');
b0.add(new leaf('leaf 0', '#'));
b0.add(new leaf('leaf 1', '#'));
b1.add(new leaf('leaf 0', '#'));
  b10 = new branch('branch 0');
b1.add(b10);
b10.add(new leaf('leaf 0'));
b10.add(new leaf('leaf 1'));
t.add(b0);
t.add(b1);
t.write();
</script>
</body>
</html>
« Last Edit: August 18, 2006, 01:13:22 am by Ender »

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: [JavaScript] Document Tree Structure
« Reply #1 on: August 17, 2006, 10:37:45 pm »
Somebody at work made something like that, for browsing a book (with chapters and sub-chapters and everything), completely done with AJAX.  It was pretty slick.  AJAX is really cool.

Offline Ender

  • x86
  • Hero Member
  • *****
  • Posts: 2390
    • View Profile
Re: [JavaScript] Document Tree Structure
« Reply #2 on: August 18, 2006, 01:10:28 am »
Yeah, AJAX is something that I would definitely like to start doing. It's incredible how the distinction between web sites and applications has become blurred because of it. meebo.com really opened up my eyes to respecting it.

lol@myself, so much for teletype...  I just noticed that half the post is in italics. I was wondering why. Then I found this:

for (i in this.branches) {
      treestr += this.branches.write();
}

In javascript foreach loops, you get the index (or more generically the key) and not the element value. So I was accessing offset i in the array of branches. lmao

Well, I'll just have to go back to those damn code tags!
« Last Edit: August 18, 2006, 01:12:41 am by Ender »

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: [JavaScript] Document Tree Structure
« Reply #3 on: August 18, 2006, 08:18:22 am »
When I post code, I usually put a pre inside a quote.  That's my favorite way :)

And if you want to learn AJAX, check out AJAX For Dummies.  My friend/coworker read a very small part of that book, and he's pretty good at programming AJAX now.