/*
 treeview.js : function to build a javascript treeview

	(c) 2000-2001 TeeTime Scotland
	Written by Sandy Kydd (sandy@teetimescotland.com)

	10-Jan-2001 SK intial version

 This script implements a treeview for use within a treeview/detail
 frames setup. Variables you can customise are at the top of this file.
 It can be used with a separate data url which allows partial tree
 display on initial use and then calls to the data url with the id of
 a parent node whose children should be fetched (by whatever means you
 need, e.g. a db call).
 
 USAGE:
 1) Include this javascript in your main index frameset page.
 2) Set up some initial nodes in the frameset page head.
 3) Add more nodes if necessary from the data frame.
 4) Show the tree in the data and treeview pages.
*/

//----------------------------------------------------------------
// CUSTOMISABLE VALUES
var tree_url = "treeview.html";
var tree_data_url = "treeview.html";
var imagedir="images/";
var img_width=18;
var img_height=18;

//----------------------------------------------------------------
// GLOBAL VARIABLES
var tv;
var targetframe="detailview";
var curnodenum = 0;
var curnode = null;
var allnodes = new Array();

//----------------------------------------------------------------
// FUNCTIONS

// Get nodeid from url parameter
function get_nodeid(loc) {
	return parseInt(loc.search.substr(1,loc.search.length-1));
}

// Set the cgi parameter we're going to use for a nodeid
function set_nodeid_param(id) {
	return "?" + id;
}

// Add a child node to the parent
function add_child(id,name,url,frame,image) {
	var node = new treenode(id,name,url,frame,image,this);

	this.children[this.children.length] = node;
	return node;
}

// Find an existing node from its id
function find_node(nodeid) {
	var i;
	
	for (i = 0; i < allnodes.length; i++) {
		if (allnodes[i].id == nodeid)
			return allnodes[i];
	}
	return null;
}

// Check if this node is the last in a child list
function is_last() {
	if (!this.parent ||
		(this.parent.children[this.parent.children.length-1] == this))
		return true;
	return false;
}

// Print an image for the treeview
function print_image(doc,img,width,height) {
	doc.write("<IMG ALIGN=Left SRC=\"" + imagedir + "/" + img +
		"\" WIDTH=" + width + "HEIGHT=" + height +
		" HSPACE=0 VSPACE=0 BORDER=0>");
}

// Recursively called to draw the treelines for a node
function draw_tree_lines(doc,is_first_parent) {
	var img, url, is_last, is_folder, has_no_children;
	
	// If the node has a parent, recurse
	if (this.parent && this.parent.parent)
		this.parent.draw_tree_lines(doc,false);
		
	// Draw the tree lines (for our level only).
	is_last = this.is_last();
	is_folder = (this.url == null);
	has_no_children = (this.has_all_data && !this.children.length);
	if (is_first_parent) {
		img = (is_last ? "corner" : "tee");
		if (is_folder && !has_no_children) {
			// Start link for folder
			url = (this.has_all_data ? tree_url : tree_data_url) +
				set_nodeid_param(this.id);  
			doc.write("<A HREF=\"" + url + "\">");
			img += (this.show_tree ? "_minus" : "_plus");
		}
	} else {		
		img = (is_last ? "spacer" : "bar");
	}
	print_image(doc,"menu_" + img + ".gif",img_width,img_height);
}

// Print node and its children (recursively)
function print_treenodes(doc) {
	var i, img, is_folder, has_no_children, target;
	
	if (this.id == curnodenum) {
		// We're the currently selected node, so toggle tree
		this.show_tree = !this.show_tree;
		curnode = this;
	}
	
    // Draw the tree lines
	doc.write("<TR VALIGN=Top><TD NOWRAP>");
	if (this.parent)
		this.draw_tree_lines(doc,true);	// TRUE for first
		
	is_folder = (this.url == null);		// no url, so its a folder
	has_no_children = (this.has_all_data && !this.children.length);

	// Set the image to use	
	if (this.image) {
		img = this.image;
	} else {
		img = "menu_";
		if (this.parent == null) {
			img += "root";
		} else if (is_folder) {
			img += "folder_" + (this.show_tree ? "open" : "closed");
		} else {
			img += "link_local";
		}
		img += ".gif";
	}	
	
	if (!is_folder) {
		// Start link for a leaf node
		target = (this.frame ? this.frame : targetframe);
		doc.write("<A TARGET=\"" + target +
			"\" HREF=\"" + this.url + "\">");
	}
	print_image(doc,img,img_width,img_height);
	doc.write("&nbsp;");
	if (this.id == curnodenum)
		doc.write("<SPAN CLASS=\"curnode\">" + this.name + "</SPAN>");
	else
		doc.write(this.name);
	if (!(is_folder && !has_no_children) || this.parent)
		doc.write("</A>");
	doc.write("</TD></TR>\n");

	// Now print the child nodes
	if (this.show_tree) {
		for (i = 0; i < this.children.length; i++)
			this.children[i].print_treenodes(doc);
	}
}

// Print the whole treeview
function print_treeview(doc) {
	doc.write("<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>\n");
	this.print_treenodes(doc);
	doc.write("</TABLE>\n");
}

function show_tree(doc,nodeid) {
	var node;
	
	// Have we added children to the given node?
	if (nodeid) {
		node = parent.find_node(nodeid);
		if (node)
			node.has_all_data = true;
	}
	curnodenum = nodeid;
	tv.print_treeview(doc); 
}

// Make a new tree node
function treenode(id,name,url,frame,image,parent) {
	this.id = id;
	this.name = name;
	this.url = url;
	this.frame = frame;
	this.image = image;
	this.parent = parent;
	this.show_tree = false;
	this.has_all_data = false;
	this.children = new Array();
	
	this.add_child = add_child;
	this.print_treenodes = print_treenodes;
	this.draw_tree_lines = draw_tree_lines;
	this.is_last = is_last;
	allnodes[allnodes.length] = this;
}

// Make a new treeview root node
function treeview(name) {
	this.id = 0;
	this.name = name;
	this.url = null;
	this.frame = null;
	this.image = null;
	this.parent = null;
	this.show_tree = true;
	this.has_all_data = false;
	this.children = new Array();

	this.add_child = add_child;
	this.print_treenodes = print_treenodes;
	this.draw_tree_lines = draw_tree_lines;
	this.is_last = is_last;
	this.print_treeview = print_treeview;
	allnodes[allnodes.length] = this;
}

//----------------------------------------------------------------
