/*************************  Expanding Menu *************************
Thrilling 2-level dynamic menu.
Version 3.0, modified by Jon Ippolito to include "collapseOnParentClick" option to correct accidental collapsing of drop-down menus when used in combination in a horizontal navbar.
The menu toggles superlink display of sublinks, with specialized styles, and passes individualized responses to menu items.ADDING MENUMenu items in <div>s wrapped in a <div id="myMenu">
ADDING CONTENT
Content goes in <div>s with ids. This obviates annoying escaped characters in dynamically written content. Make sure you set display = none in style sheet.
ADDING SCRIPT
Include this script in the body in onload OR immediately after the <divs> in the HTML body.
TRIGGERING FROM OTHER LINKS
Currently you have to use this (clumsy) approach:
    document.getElementById( "menulink-fun-3" ).menuItem.respond( {  menuItemEle: document.getElementById(    "menulink-fun-3"    )  } )
    UPGRADE: Simplify this.
PRINTING REQUIRES
<script type="text/javascript" src="tech/sniff.js"></script>
You must put an empty file in the directory called empty.html to print.
tech/print.css
MORE UTILITIES
can be found in a separate file, customized for each menu.
See end of file for more details.
**************************************/
function MenuItem(argsObj) { // {htmlElement:document.getElementById("myListElement"), responseFunction:myFunction}	this.htmlElement = argsObj.htmlElement;	this.responseFunction = (argsObj.responseFunction)? argsObj.responseFunction : "none" ;	this.htmlElement.style.display = "block";	this.htmlElement.onclick = this.respond ;	this.htmlElement.menuItem = this ;
	this.linkType = "bachelor" ; // Default--to be modified later based on associateChildren calls.
	this.htmlElement.onmouseover = actOnMouseover ;	this.htmlElement.onmouseout = actOnMouseout ;}
function actOnMouseover(e) {
    return eval( this.menuItem.funMouseover ) ;
}
function actOnMouseout(e) {
    return eval( this.menuItem.funMouseout ) ;
}
MenuItem.prototype.setClasses = function(classObj) {
    this.funMouseover = classObj.argMouseover;    this.funMouseout = classObj.argMouseout;	this.classBachelorUnselected = classObj.argBachelorUnselected ;	this.classBachelorSelected = classObj.argBachelorSelected ;
	if (this.htmlElement.menu.isTwoLevelMenu) { // This argument can be omitted for 1-level menus.        this.classParentCollapsedUnselected = classObj.argParentCollapsedUnselected ;        this.classParentCollapsedSelected = classObj.argParentCollapsedSelected ;        this.classParentExpandedUnselected = classObj.argParentExpandedUnselected ;        this.classParentExpandedSelected = classObj.argParentExpandedSelected ;        this.classChildUnselected = classObj.argChildUnselected ;        this.classChildSelected = classObj.argChildSelected ;
    }	/* UPGRADE: DO FOLLOWING LATER...MAYBE.	//You only have to set the selections you want; otherwise they default to the last defined one.
	if (classObj.selected0) {		this.classSelected0 = classObj.selected0;		this.classSelected1 = classObj.selected0;		if (classObj.selected1) {			this.classSelected1 = classObj.selected1;		}	}
	*/}
MenuItem.prototype.associateContent = function(contentEle){
    // "this" is the JS object whose name is the same as the id for the menulink in question.
	this.content = contentEle ; // The content div (htmlElement) associated with that menulink.
	this.content.menuItem = this ; // Allows you to identify link if you know the content.
	// UPGRADE: Is it a problem that it's the same name as the handle to the menuItem object from the menuItem htmlElement?}MenuItem.prototype.associateChildren = function(childrenArr) { //[petMenu.itemManager.itemDante , petMenu.itemManager.itemCritter]
    this.linkType = "parent" ;
	// .children is an array of  JS menuItem objects.	// You cannot simply assign one array to be equal to another--you must write it out in a loop.
	// I'm trying to write this so you can call associateChildren more than once for the same parent.	if (!this.children) this.children = new Array() ;	for (var childNum=0; childNum<childrenArr.length; childNum++) {		this.children.push( childrenArr[childNum] ) ;		this.children[this.children.length-1].dad = this ;
		this.children[this.children.length-1].linkType = "child" ;	}
}
MenuItem.prototype.areChildrenOpen = function() {
    _id = this.htmlElement.id ; debug("_id", 2) ;
    _children = this.children ; debug("_children", 2) ;
    return (this.children[0].htmlElement.style.display != "none")? true : false ;
}MenuItem.prototype.respond = function(argObj) { // argObj can be empty or { menuItemEle: document.getElementById("my-link")}
    debug("'beginning response'")
    // If there's no argument, assume "this" is the menuItem's html element, because you clicked on it.
    if (typeof argObj != "undefined") {
        // Firefox will assume argObj is the mouse event if you don't specify it more precisely:
        var menuItemEle = ( typeof argObj.menuItemEle == "undefined" )? this : argObj.menuItemEle ;
    }
    else {
        // IE won't recognize argObj if it's not specified in the function call.
        var menuItemEle = this ;
    }
	// DESELECT ALL STYLES
	menuItemEle.menu.deselectAllItems(); // menuItemEle does not hide children, just deselects them.	//*********************** SET DISPLAY OF CONTENT *********************** 
	if (menuItemEle.menu.useDefaultContentManagement) {        //Display only the content of menuItemEle item.
        menuItemEle.menu.hideAllContent();        menuItemEle.menuItem.content.style.display = "block";
	}	//*********************** SET DISPLAY AND STYLE OF menuItemEle ITEM'S CHILDREN *********************** 	//If the item is a superlink, reset the style and/or display of all children.
	// __________ YOU CLICKED ON A PARENT _________	if ( menuItemEle.menuItem.linkType == "parent" ) {
        debug("'it is a parent'")
        _kidsOpen = menuItemEle.menuItem.areChildrenOpen(); debug("_kidsOpen", 4)		if ( !menuItemEle.menuItem.areChildrenOpen() ) {		//If the superlink's children are not already open.
            debug("'children are not open'")
            // Display the children and give them unselected style.			for (var itemNum=0; itemNum < menuItemEle.menuItem.children.length; itemNum++) {                debug("'displaying child'")
				menuItemEle.menuItem.children[itemNum].htmlElement.style.display = "block";				menuItemEle.menuItem.children[itemNum].htmlElement.className = menuItemEle.menuItem.children[itemNum].classChildUnselected;			}
			// Set the style of menuItemEle parent link to expanded and selected.
			debug("'setting className'")
			menuItemEle.menuItem.htmlElement.className = menuItemEle.menuItem.classParentExpandedSelected ;		}		else { // If one or more children are already displayed.            // Hide the children only if appropriate for this implementation.
            _collapseOnParentClick = menuItemEle.menu.collapseOnParentClick ; debug("_collapseOnParentClick", 4)
            if (menuItemEle.menu.collapseOnParentClick) {                for (var itemNum=0; itemNum < menuItemEle.menuItem.children.length; itemNum++) {                    menuItemEle.menuItem.children[itemNum].htmlElement.style.display = "none";                }
                //Set the style of menuItemEle parent link to collapsed and selected.                menuItemEle.menuItem.htmlElement.className = menuItemEle.menuItem.classParentCollapsedSelected ;
            }
            // If you're using this as a dropdown menu, then you'll want to show all children.
            else {
                for (var itemNum=0; itemNum < menuItemEle.menuItem.children.length; itemNum++) {                    menuItemEle.menuItem.children[itemNum].htmlElement.style.display = "block";                }                
            }		}	}    // __________ YOU CLICKED ON A CHILD _________	else if (menuItemEle.menuItem.linkType == "child") {
		//If it's a sublink, reset the style of the sibling sublinks and the superlink.
        // Set the superlink to medium selectedness. UPGRADE: I THINK FOLLOWING DESELECTS ARE REDUNDANT.        menuItemEle.menuItem.dad.htmlElement.className = menuItemEle.menuItem.dad.classParentExpandedUnselected;        //Set the siblings to medium selectedness. Display them, just in case the link was not called from the menu.        for (var itemNum=0; itemNum < menuItemEle.menuItem.dad.children.length; itemNum++) {
            menuItemEle.menuItem.dad.children[itemNum].htmlElement.style.display = "block" ;                    menuItemEle.menuItem.dad.children[itemNum].htmlElement.className = menuItemEle.menuItem.dad.children[itemNum].classChildUnselected;        }
        // Set menuItemEle child to selected.
        menuItemEle.menuItem.htmlElement.className = menuItemEle.menuItem.classChildSelected;            }
    // __________ YOU CLICKED ON A BACHELOR _________    
    else {		//If the item is a childless parent.
        menuItemEle.menuItem.htmlElement.className = menuItemEle.menuItem.classBachelorSelected ;		}	//*********************** HANDLE OTHER FUNCTIONS *********************** 
	debug("'handling other functions'")	if (debugIsOn) {
        try {
            if (menuItemEle.menuItem.responseFun) eval(menuItemEle.menuItem.responseFun) ;
        }
        catch(e) {
            _choked_on_responseFun = menuItemEle.menuItem.responseFun; debug("_choked_on_responseFun", 9)
        }
    }
    else {
        if (menuItemEle.menuItem.responseFun) eval(menuItemEle.menuItem.responseFun) ;    
    }
    debug("'ending response'")	return false;}MenuItem.prototype.changeToRolloverStyle = function() {
    this.htmlElement.className = this.classRollover ;
}
MenuItem.prototype.associateResponse = function(responseObj) {	this.responseFun = responseObj.responseFun;}function ExpandingMenu(argsObj) { // Use different names for div id and js obj. Sample: {menuId: "navMenuBlock"}
    // Hide menu until you call setInitialCondition later.
    // You probably want to hide it in the css too.
    // This prevents ugly page load.
    this.htmlElement = document.getElementById(argsObj.menuId) ;
    this.htmlElement.menu = this ;
    this.id = argsObj.menuId + "Obj" ;
    // this.htmlElement.style.display="none";
    // Grab item anchors dynamically.	this.itemArr = document.getElementById(argsObj.menuId).getElementsByTagName("div"); // Was "a".	this.itemManager = new Array();	for (var itemNum=0; itemNum < this.itemArr.length; itemNum++) {		this.itemManager[itemNum] = new MenuItem({ htmlElement:this.itemArr[itemNum] });		this.itemManager[this.itemArr[itemNum].id] = this.itemManager[itemNum];		this.itemManager[itemNum].htmlElement.menu = this; // I'm not sure it's a good idea to make the handle from the html element...?	}
	// Is this a two-level menu?
	this.isTwoLevelMenu = (typeof argsObj.isTwoLevelMenu == "undefined")? true : argsObj.isTwoLevelMenu ;
	// Do you want default content divs, or customized content management?
	this.useDefaultContentManagement = (typeof argsObj.useDefaultContentManagement == "undefined")? true : argsObj.useDefaultContentManagement ; // Boolean.
	// Do you want sublinks to collapse when user clicks on a parent?
	this.collapseOnParentClick = (typeof argsObj.collapseOnParentClick == "undefined")? true : argsObj.collapseOnParentClick ;}ExpandingMenu.prototype.hideAllContent = function() {	for (var itemNum=0; itemNum < this.itemManager.length; itemNum++) {		this.itemManager[itemNum].content.style.display = "none";	}}ExpandingMenu.prototype.setInitialCondition = function(itemObj) { 	// UPGRADE: Keith wants me to change this to hideChild and call repeatedly.	// "this" means the menu.	// Hide all child items.	for (var itemNum=0; itemNum < this.itemManager.length; itemNum++) {		if ( this.itemManager[itemNum].linkType == "parent" ) {
			for (var childNum=0; childNum < this.itemManager[itemNum].children.length; childNum++) {				this.itemManager[itemNum].children[childNum].htmlElement.style.display = "none";			}
		}
    }    //Deselect all items.    this.deselectAllItems() ;
    // Set a selected item if user requests one.
    if (itemObj) {
        if ( itemObj.linkType == "bachelor" ) {
            itemObj.htmlElement.className = itemObj.classBachelorSelected ;
        }
        else if ( itemObj.linkType == "parent" ) {
            itemObj.htmlElement.className = itemObj.classParentCollapsedSelected ;
        }
        else { // Must be a child.
            // Set this item's style.
            itemObj.htmlElement.className = itemObj.classChildSelected ;
            // Show the child's siblings, but leave their style unselected.
			for (var childNum=0; childNum < itemObj.dad.children.length; childNum++) {				itemObj.dad.children[childNum].htmlElement.style.display = "block";			}
			// Change the parent's style.
            itemObj.dad.htmlElement.className = itemObj.dad.classParentExpandedSelected ;			
        }
    }
    // Turn on display of the menu (initially hidden by ExpandingMenu constructor).
    this.htmlElement.style.display="block";
    // Show content div if user chooses the menu's default content management.
    if ( this.useDefaultContentManagement ) {
        itemObj.content.style.display = "block" ;
    }
	return false;}
ExpandingMenu.prototype.deselectAllItems = function() {
    // Deselects styles of all menu items, without affecting whether children are hidden or shown. 	for (var itemNum=0; itemNum < this.itemManager.length; itemNum++) {
        if ( this.itemManager[itemNum].linkType == "bachelor" ) {            this.itemManager[itemNum].htmlElement.className = this.itemManager[itemNum].classBachelorUnselected;
        }        if ( this.itemManager[itemNum].linkType == "parent" ) {
            if ( this.itemManager[itemNum].areChildrenOpen() ) {
                this.itemManager[itemNum].htmlElement.className = this.itemManager[itemNum].classParentExpandedUnselected ;
            }
            else { // No children open for this parent.
                this.itemManager[itemNum].htmlElement.className = this.itemManager[itemNum].classParentCollapsedUnselected ;
            }
        }        if ( this.itemManager[itemNum].linkType == "child" ) {            this.itemManager[itemNum].htmlElement.className = this.itemManager[itemNum].classChildUnselected;
        }	}
}
ExpandingMenu.prototype.generatePrintableText = function() { // UPGRADE: Add to argsObj to customize title, pagebreaks, styles, stylesheet name, etc.
    // UPGRADE: Make the printable version into an object of its own?
    this.printableTextVar = "<h1>" + document.title + "</h1>" ;    // this.printableTextVar += "<div>" + document.getElementById("image-print").innerHTML + "</div>" ;
    this.printableTextVar += "<h4>This is a dynamically generated synopsis of the site '" + document.title + "' in printable form. " ;
    // UPGRADE: INSERT CUSTOM URL OPTION.    this.printableTextVar += "You can find the interactive version at " + document.location.href + ".</h4>" ;	for (var itemNum=0; itemNum < this.itemManager.length; itemNum++) {
            /* UPGRADE: ENABLE PAGEBREAK CODE BELOW:
                // Set any desired pagebreaks manually.
                contentDivs[contentDivs.length-1].extraStyle = "" ;
                var idsWithPageBreaksArr = new Array("desc_var", "desc_ope", "desc_min", "desc_mar")
                for ( var idNum = 0; idNum < idsWithPageBreaksArr.length; idNum++ ) {
                    if ( contentDivs[contentDivs.length-1].id == idsWithPageBreaksArr[idNum] ) {
                        contentDivs[contentDivs.length-1].extraStyle = " style='page-break-before: always;' "
                    }
                }
            */
        // Handle headings.
        // Use this for auto headings: // UPGRADE: ADD TEST FOR PARENT LINKS TO GIVE DIFFERENT h's.
        if (this.itemManager[itemNum].linkType == "child") {
            this.printableTextVar += "<h3>" + this.itemManager[itemNum].htmlElement.innerHTML + "</h3><br /><br />" ;
        }
        else {
            this.printableTextVar += "<h2>" + this.itemManager[itemNum].htmlElement.innerHTML + "</h2><br /><br />" ;
        }
            /* UPGRADE: ENABLE CUSTOM HEADING CODE BELOW?
                // Or set headings manually:                if ( link == menuHeadingsArr[0].getElementsByTagName("a").length ) {
                    printableTextVar += "<div class='emph2'>r e c e n t &nbsp; S t i l l &nbsp; W a t e r &nbsp; p r o j e c t s</div>";
                }                if ( link == menuHeadingsArr[0].getElementsByTagName("a").length + menuHeadingsArr[1].getElementsByTagName("a").length ) {
                    printableTextVar += "<div class='emph2'>o n g o i n g &nbsp; S t i l l &nbsp; W a t e r &nbsp; p r o j e c t s</div>";
                }
                if ( link == menuHeadingsArr[0].getElementsByTagName("a").length + menuHeadingsArr[1].getElementsByTagName("a").length + menuHeadingsArr[2].getElementsByTagName("a").length ) {
                    printableTextVar += "<div class='emph2'>r e s e a r c h &nbsp; i n t e r e s t s</div>";
                }
            */
            // Capture what goes under the headings.
            this.itemManager[itemNum].extraStyle = "" ; // UPGRADE: ENABLE THIS?            this.printableTextVar += "<div " + this.itemManager[itemNum].extraStyle + ">" + this.itemManager[itemNum].content.innerHTML + "</div>" ;        }}ExpandingMenu.prototype.openPrintableWindow = function() {
        if ( (browsers.mac && browsers.ie) || (browsers.ns4) || (browsers.saf) ) {
            alert("We're sorry, your browser does not support this action.\n\nPlease consider upgrading to a standards-compliant browser like Firefox.") ;
            return false;
        }
        // YOU HAVE TO PUT AN IMAGE (POSSIBLY HIDDEN) IN YOUR HTML CALLED image-print.		this.htmlVar = this.printableTextVar ;		this.printableWindowVar = window.open('empty.html','printableWindowName','status=yes,scrollbars=yes,resizable=yes,width=750,height=550,top=0,left=200') ;
        this.htmlHeader = "<html><head>" ;
        this.htmlHeader += "<link rel=stylesheet href='tech/print.css' type='text/css' />" ;
        // UNUSED: htmlHeader+= "<link rel=stylesheet href='tech/print_styles.css' type='text/css' media='print' />" ;        this.htmlHeader += "</head><body>" ;
		this.htmlVar = this.htmlHeader + this.htmlVar + "</body></html>" ;		this.printableWindowVar.document.open() ;		this.printableWindowVar.document.write(this.htmlVar) ;		this.printableWindowVar.document.close() ;}//********************************* DIRECTIONS FOR USE **************************//// Following are some of the steps you may take to implement this.// See demo for more details.//// Instantiate a menu.// You can automate these assignments for each particular application.// Create an artist array to enable a formulaic approach to that material.// Associate all the content using a formulaic approach.// Set all items to style of children first, then add select style to the dads.// Associate superlinks with sublinks.// Create special response functions, associate them with different menu items, and initialize their states.// Initialize the menu and choose an initial item to select.// Hide all content and choose an initial content to display.
