/**********************************************************************************   
The 3-Level Foo Collapser
*   Copyright (C) 2006 Brian Foo (www.brianfoo.com, www.youaremyjoy.com, bwf2101@columbia.edu)
*   Implementation is fairly simple
*   Read through comments for better understanding
*   If you're going to pull this code, at least give me credit
*********************************************************************************/

//Navigation object declared and initialized first in body of navigation page
//ie. var myNav = new navObject("myNav",150);
function navObject(_name,_width){
	this.name = _name;
	this.w = _width;
	this.buttons = new Array();
	this.size = 0;
	return this;
}
//Holds all elements of button object; added to navObject through addButton function
function button(_name,_id,_type,_lnk) {
	this.id = _id;    //0,1,2,3,...,N
	this.type = _type;  //top, sub, sub2, sub3
	this.h = 0;  //px
	this.x = 0;  //px
	this.y = 0;  //px
	this.imgUp = "";
	this.imgOver = "";
	this.imgDown = "";
	this.children = new Array();
	this.parents = new Array();
	if (_lnk == "#") {this.lnk = "#"+_id;}
	else {this.lnk = _lnk;}
	this.text = _name;
	this.style = "";
	return this;
}
//Adds button to navObject through myNav.addButton("Name",top,"index.htm")
navObject.prototype.addButton = function(_name,_type,_lnk) {
	this.buttons[this.size] = new button(_name,this.size,_type,_lnk);
	this.size++;
}
//Builds navigation and prints code to screen; executed by myNav.buildNavigation(*parameters*)
navObject.prototype.buildNavigation = function( 			
	type,	//either "click" or "mouseover"			  
	img_top,img_sub,img_sub2,  //image prefixes excluding suffix and extension, ie. mytop_up.gif, mytop_over.gif, mytop_down.gif would be just 'mytop'
	top_style,sub_style,sub2_style,  //css style names for top, sub, and sub2
	top_h,sub_h,sub2_h) {	//top, sub, sub2 image heights
	for (i=0;i<this.size;i++) {
		switch(this.buttons[i].type) {
			case "top":
				this.buttons[i].imgUp = img_top+"_up.gif";
				this.buttons[i].imgOver = img_top+"_over.gif";
				this.buttons[i].imgDown = img_top+"_down.gif";
				this.buttons[i].style = top_style;
				this.buttons[i].h = top_h;
				break;
			case "sub":
				this.buttons[i].imgUp = img_sub+"_up.gif";
				this.buttons[i].imgOver = img_sub+"_over.gif";
				this.buttons[i].imgDown = img_sub+"_down.gif";
				this.buttons[i].style = sub_style;
				this.buttons[i].h = sub_h;
				break;
			case "sub2":
				this.buttons[i].imgUp = img_sub2+"_up.gif";
				this.buttons[i].imgOver = img_sub2+"_over.gif";
				this.buttons[i].imgDown = img_sub2+"_down.gif";
				this.buttons[i].style = sub2_style;
				this.buttons[i].h = sub2_h;
				break;
			default: /* we'll be quiet if this happens*/;
		}
	}
	this.makeFamilies();
	path = window.location.pathname;
	currentId = this.findId(path);
	if (type == "mouseover") {	this.executeOver(); }
	else { this.executeClick(currentId); }
}
//creates heiarchical families based on button array (order matters!)
//all buttons have either no, one, or two parents
//buttons can have unlimited children
navObject.prototype.makeFamilies = function() {
	for (i=0;i<this.size;i++) {
		if (this.buttons[i].type == "top") {
			currentTop = i;}
		else if (this.buttons[i].type == "sub") {	
			currentSub = i;
			this.buttons[i].parents.push(currentTop);  //add parent to child			
			this.buttons[currentTop].children.push(currentSub);   //add child to parent
			}
		else {
			currentSub2 = i;
			this.buttons[i].parents.push(currentSub);  //add parent to child
			this.buttons[i].parents.push(currentTop);	//add grandparent to child		
			this.buttons[currentSub].children.push(currentSub2);  //add child to parent
			this.buttons[currentTop].children.push(currentSub2);}  //add grandchild to grandparent
	}	
}
//finally prints buttons to body with divs
navObject.prototype.executeClick = function(_id) {
	var currentParent = null, currentGParent = null;  //keeps track of toggleView blocks
	document.writeln('<div style="width: '+this.w+'px;">');  //defines width of navbar
	for (i=0;i<this.size;i++) {
		var hasChildren = false;
		document.write('<a name="'+i+'" class="'+this.buttons[i].style+'" href="'+this.buttons[i].lnk+'" ');  //defines css style class and link
		if (this.buttons[i].children.length > 0) { 
			hasChildren = true;
			if (currentParent == null){	currentParent = i; }
			else{ currentGParent = currentParent;  currentParent = i; }
			document.write('onClick="toggleDisplay(\'block'+i+'\')" '); }		//prints toggleView option if has children
		document.write('onMouseOver="showBG(\'div_'+i+'\',\''+this.buttons[i].imgOver+'\');" ');  //mouseover bg image
		if (i==_id) { document.write('onMouseOut="showBG(\'div_'+i+'\',\''+this.buttons[i].imgDown+'\');">'); }  //mouseout bg image
		else { document.write('onMouseOut="showBG(\'div_'+i+'\',\''+this.buttons[i].imgUp+'\');">'); }
		document.write('<div id="div_'+i+'" ');  //div id
		document.write('class="'+this.buttons[i].style+'" ');  //div css style class
		if (i==_id) { document.write('style="line-height: '+this.buttons[i].h+'px; background-image:url('+this.buttons[i].imgDown+');">'); }  //if currently on this page, show selected image
		else { document.write('style="line-height: '+this.buttons[i].h+'px; background-image:url('+this.buttons[i].imgUp+');">'); }  //line height and bg image
		document.writeln(this.buttons[i].text+'</div></a>');  //prints name of button (formatting options governed by css style class)
		if (hasChildren) {   //prints an open toggleView block if has children
			var showBlock = false;
			for (j=0;j<this.buttons[i].children.length;j++) {
				if (this.buttons[i].children[j] == _id) { showBlock = true; }
			}
			if ( showBlock ) { document.writeln('<div id="block'+i+'" style="display:block;">'); }  //if currently on this page, show this block
			else { document.writeln('<div id="block'+i+'" style="display:none;">'); }
		}  //the rest figures out where to put the closing divs of toggleView blocks
		else if ( currentParent!=null && currentGParent!=null ) {  //a parent and grandparent exists
			if ( i<(this.size-1) ) {  //if not the last element in array
				if (this.buttons[i+1].parents[0]!=currentParent) {  //if the parent of the current and next aren't the same
					document.writeln('</div>');  //close block
					if (this.buttons[i+1].parents[0]!=currentGParent) {  //if the grandparent of the current and the parent of the next aren't the same
						document.writeln('</div>');   //close block
						currentParent = null;
						currentGParent = null;}
					currentParent = currentGParent;
					currentGParent = null;
				}
			} else { document.writeln('</div>'); document.writeln('</div>'); }  //if last button, close leftover blocks
		}
		else if ( currentParent!=null ) {  //only a parent exists
			if ( i<(this.size-1) ) {  //if not the last element in array
				if (this.buttons[i+1].parents[0] != currentParent ) {  //if the parent of the current and next aren't the same
					document.writeln('</div>');  //close block
					currentParent = null;
					currentGParent = null; } 
			} else { document.writeln('</div>'); }  //if last button, close leftover block
		} else { /* Do nothing */ }
	}	
	document.writeln('</div>');  //close container div
}
//same as above, but uses mouseover navigation (usually used for dropdown, horizontal menus)
navObject.prototype.executeOver = function() {
	
}
//returns a button id, given a particular url path
navObject.prototype.findId = function(path) {
	found = false;	id = 0;
	for (i=0;i<this.size;i++) {
		if (this.buttons[i].lnk == path) { 
			found = true; id = i; break; }
	}
	return id;
}
//toggles visibility of blocks
function toggleDisplay(_block){
	block = document.getElementById(_block);
	if (block.style.display=="block"){
		block.style.display="none";			
	}
	else {
		block.style.display="block";
	}
}
//used for mouseovers of buttons
function showBG(_div,_img){
	div = document.getElementById(_div);
	div.style.backgroundImage='url('+_img+')';
}
//pre-loader of images used in body tag
function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}
