////////////////////////////////////////////////////////////////////////
/// \file JKYMenu.js
///
/// JKYMenu is generates a drop-down menu in the specific DOM element
/// on a web page.
///
/// JKYMenu creates a cross-browser (IE & Firefox tested) drop-down
/// menu.
///
///	The script reads an XML file containing the menu structure
/// and generates the menu using the DOM.  See the example JKYMenu.xml
/// file for proper usage.
///
///	Users can style the menu using CSS.  See the example JKYMenu.css
/// file for supported selectors.
///
///	Please contact jkymenu@joshuakaminetsky.net with bugs,
/// suggestions, and questions.
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
/// \example JKYMenu.xml
///
/// This is an example XML file that is used to build the menu.  The
/// XML file should adhere to all XML specifications.  The
/// structure of the file must be preserved.  There must be a single
///	outer menu tag and it must be the first tag.  Menu tags can contain
/// only cell tags.  Cell tags can contain a single text tag and a
/// single menu tag.  The text tag must be specified before the menu
/// tag and if the menu tag is specified the text tag must be specified
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
/// \example JKYMenu.css
///
/// Styles for the td's in the menu can be set using the .JKYMenu
/// class selector.  It is important that border-collapse
///	not be set to anything except collapse.  Also, do not set
/// display, position, float, left, right, top, bottom, or anything else
/// the may destroy the positioning of the menu cells.  Avoid setting
///	styles globally for table, tbody, tr, or td unless you have tested
/// it to make sure that it does not destroy the menu positioning.
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
/// \example JKYMenu.html
///
///	Include JKYMenu.js in the head of your document using the link tag.
///	You should call the JKYMENU function any time after the parent
/// element that you will be attaching your menu to is rendered.  It is
///	suggested that you call the function from the onLoad event handler
/// of the document's body.  JKYMENY has two required arguments and one
/// optional argument.  The required arguments are the parent element's
/// ID attribute value and the URL of the menu XML file, which must
/// reside on the same domain as the calling page.  The optional
/// argument is a constant specifying whether the main menu is
/// horizontal or vertical.
////////////////////////////////////////////////////////////////////////


var JKYMENU_FF = 0;	/*!< Constant for Firefox.  Used to specify the browser being used .*/
var JKYMENU_IE = 1;	/*!< Constant for IE.  Used to specify the browser being used. */
var JKYMENU_VERTICAL = 0;	/*!< Constant used to specify that the main menu should be drawn vertically. */
var JKYMENU_HORIZONTAL = 1;	/*!< Constant used to specify that the main menu should be drawn horizontally. */

var JKYMENU_xmlHttp;	/*!< The XMLHttpRequest object to communicate */
var JKYMENU_rootEl;		/*!< The element that the menu is appended to */
var JKYMENU_level = 0;	/*!< Keeps track of the level of submenu that is being drawn */
var JKYMENU_id = 0;		/*!< Keeps track of unique ID's assigned to menus and submenus */
var JKYMENU_prefix = "JKYMENU_";	/*!< Prefix attached to element names to make sure they are unique */
var JKYMENU_alignment = JKYMENU_VERTICAL;	/*!< Determines whether or not the main menu is drawn horizontally or vertically.  Default is vertical. */

////////////////////////////////////////////////////////////////////////
/// This function should be called from the web page to generate the
/// menu.
///
/// This function should be called from the page any time after the
/// menu's parent element is rendered on the page.  It is suggested that
/// you call this function in the onLoad event of the body.  The
/// function call specifies the parent element ID to which the menu
/// will be appended, the URL of the XML menu file, and the alignment
/// of the main menu (vertical or horizontal).
///
/// \param elId The ID of the parent element to which the menu will be
/// appended
///
/// \param url The URL of the XML file containing the menu structure.
/// The XML file should be on the same domain as the calling page due to
/// due to browser security restrictions.
///
/// \param alignment Optional.  The alignment of the main menu (vertical or
/// horizontal).  This should be specific using the constants
/// JKYMENU_VERTICAL or JKYMENU_HORIZONTAL.
////////////////////////////////////////////////////////////////////////

function JKYMENU(elId, url, alignment) {
	var parent;	// the element that the menu is being added to
	
	// since the alignment is optional and has a default, we only need
	// to set it if the alignment is specific to be horizontal
	if (alignment == JKYMENU_HORIZONTAL) {
		JKYMENU_alignment = alignment;
	}
	
	// initialize the parent element for the menu
	JKYMENU_rootEl = document.getElementById(elId);
	
	// retrieve the XML file from the server
	JKYMENU_getXml(url);
}

////////////////////////////////////////////////////////////////////////
/// This function creates the XMLHttpRequest object in the browser
////////////////////////////////////////////////////////////////////////

function JKYMENU_createRequest() {
	//if IE then we need to use ActiveX
	if (window.ActiveXObject) {
		JKYMENU_xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
	//all other browsers
	} else {
		JKYMENU_xmlHttp = new XMLHttpRequest();
	}
}

////////////////////////////////////////////////////////////////////////
/// This function initializes the XMLHttpRequest and sends it.
///
/// This function sends a GET request to the server for the file at the
/// specified URL and tells the XMLHttpRequest object what to do when
/// the server responds.
///
/// \param url The URL containing the file to be retrieved.  In this
/// the retrieved file will be the XML menu file.
////////////////////////////////////////////////////////////////////////

function JKYMENU_getXml(url) {
	JKYMENU_createRequest();
	JKYMENU_xmlHttp.open("GET", url, true);
	//defines the function to call when the server responds
	JKYMENU_xmlHttp.onreadystatechange = JKYMENU_menuReady;
	JKYMENU_xmlHttp.send(null);
}

////////////////////////////////////////////////////////////////////////
/// This function is called when the server changes state.
///
/// This function is called when server changes state.  If the response
/// is that the server is done with a 200 code, then the function
/// to build the menu is called.
////////////////////////////////////////////////////////////////////////

function JKYMENU_menuReady() {
	if (JKYMENU_xmlHttp.readyState == 4) {
		if (JKYMENU_xmlHttp.status == 200) {
			JKYMENU_buildMenu();
		}
	}
}

////////////////////////////////////////////////////////////////////////
/// This function builds the menu.
///
/// This function creates the menu instance and attaches it to the root
/// element and sets up the rollovers and submenu positioning.
////////////////////////////////////////////////////////////////////////

function JKYMENU_buildMenu() {
	// local vars
	// get the xml document
	var doc = JKYMENU_xmlHttp.responseXML;
	// get the first menu tag from the page
	var menuXml = doc.getElementsByTagName("menu")[0];
	// create the menu and attach it to the page
	// pass null as this menu's parent
	var menu = new JKYMenuNode(menuXml, null);
	// get the stylesheets for this page
	var stylesheets = document.styleSheets;
	var stylesheet;	//a stylesheet	
	var rules; //css rules collection
	var rule; //css rule
	var selector; //css selector
	var padding; //the padding of menu cells
	var border; //the border width of menu cells
	var pxStrLoc; //the location of "px" in the padding and border strings
	
	JKYMENU_rootEl.appendChild(menu.getElement());
	
	// check the stylesheets on the page to set border-collapse
	// because it can't be set by javascript and it must be set
	// for the menu to display borders and position submenus
	// properly.  also find out what the border and padding were set to
	for (var i = 0; i < stylesheets.length; i++) {
		stylesheet = stylesheets[i];
		// browsers implement the css rules collection differently
		// so the following is needed
		if (stylesheet.cssRules) {
			stylesheet.insertRule(".JKYMenu_menu {border-collapse: collapse;}", 0);
			rules = stylesheet.cssRules;
		} else if (stylesheet.rules) {
			stylesheet.addRule(".JKYMenu_menu", "border-collapse: collapse;");
			rules = stylesheet.rules;
		}
		
		//find the .JKYMenu_cell rule and extract the border and padding
		for (var j = 0; j < rules.length; j++) {
			rule = rules.item(j);
			selector = rule.selectorText;
			if (selector == ".JKYMenu") {
				//use only the left border and padding.  jkymenu assumes that
				//all are set equal to each other and does not support
				//differing padding and borders on different sides of cells
				padding = rule.style.paddingLeft;
				border = rule.style.borderLeftWidth;
		
				//jkymenu also assumes that border and padding are specified
				//in pixels so we need to find the "px" string and remove it
				pxStrLoc = padding.indexOf("px");
				padding = padding.substring(0, pxStrLoc);
				pxStrLoc = border.indexOf("px");
				border = border.substring(0, pxStrLoc);
			}
		}
	}
	
	//adjust the menu's positioning now that all elements are rendered and
	//we know what the border and padding are
	menu.adjust(border, padding);
}

////////////////////////////////////////////////////////////////////////
/// This class represents a menu node in the menu.
///
/// A menu node contains all of the cells and submenus within a node
/// in the menu tree as well as a reference to the actual element drawn
/// on the page.  The node is created using the corresponding XML
/// subtree from the XML menu file.
///
/// \param xml The XML tree node for this menu
///
/// \param parentArg The parent cell if this is a submenu
////////////////////////////////////////////////////////////////////////

function JKYMenuNode(xml, parentArg) {
	//assign instance vars
	//the table element
	var element = document.createElement("table");	//html element
	//the table element requires a tbody in it
	var tbody = document.createElement("tbody");
	var parent = parentArg;	//the parent cell if this is a submenu
					//will be null if it is the root menu
	var cells = new Array(); //holds the cells in this menu node
	var cellsXml = xml.childNodes;	//all cells in this menu
	var cellXml;	//the XML for each cell in this menu
	var cell;	//the JKYCell object for each cell in this menu
	var nodeType;	//the type of node being inspected (should be a cell)
	var appender;	//the element that children of this object get appended to
	var id = JKYMENU_id;	//unique menu id for referencing the element
							//from events
	//increment the global id
	JKYMENU_id++;
	
	//methods
	this.getId = function() {	/*! METHOD getId()
								\return ID of the menu*/
		return JKYMENU_prefix + id;
	}
	
	this.getElement = function() {	/*! METHOD getElement()
									\return element of this menu*/
		return element;
	}
	
	this.getTbody = function() {	/*! METHOD getTbody()
									\return tbody of this menu*/
		return tbody;
	}
	
	this.getParent = function() {	/*! METHOD getParent()
									\return parent of this element*/
		return parent;
	}
	
	this.getCells = function() {	/* METHOD getCells()
									\return array of this menu's cells*/
		return cells;
	}
	
	this.genOnMouseOver = function() {	/*! METHOD genOnMouseOver()
										\return string for this menu's onMouseOver function*/
		var funcStr;	//string for the onmouseover function
	
		//we have to make this string something that the browser can understand
		//when the event fires, so we use id's
		funcStr = "JKYMenu_show('" + this.getId() + "');";
		
		//we only need to generate a mouseover if this is a submenu
		if (this.getParent()) {
			if (this.getParent().getParent().getParent()) {
				//we have to make sure that we cascade to display parent menus when displaying
				//submenus otherwise the parent menu would disappear when its
				//onMouseOut event fires
				funcStr += this.getParent().getParent().genOnMouseOver();
			}
		}
		return funcStr;
	}
	
	this.genOnMouseOut = function() {	/*! METHOD genOnMouseOut()
										\return string for this menu's onMouseOut function*/
		var funcStr;	//string for the onmouseout function
	
		//we only need to generate a mouseover if this is a submenu
		if (this.getParent()) {
			//we have to make this string something that the browser can understand
			//when the event fires, so we use id's
			funcStr = "JKYMenu_hide('" + this.getId() + "');";
			
			//we have to make sure that we cascade to display parent menus when displaying
			//submenus otherwise the parent menu would still be visible after the onMouseOut
			//event fires even if we moved the mouse off of the menu all together
			funcStr += this.getParent().getParent().genOnMouseOut();
		}
		return funcStr;
	}
	
	this.adjust = function(border, padding) {	/*! METHOD adjust()
												Adjusts the positioning and widths of submenus
												\param border The border width of each cell
												in this menu
												\param padding The padding of each cell in this menu*/
		var left;	//the left positioning of the submenu
		var top;	//the top position of the submenu
		var width;	//the minimum width of the submenu if needed
		var parentMenu;	//the parent menu of this menu
		var browser;	//the browser that the user is using
		var parentCell; //the parent cell of a menu
		var parentTbody;	//a menu's tbody element
		var td;		//a cell's td element
		var hasParent = this.getParent();	//boolean for whether or not this menu has a parent
		var cell;	//an individual child cell
		
		//if this menu has a parent then it is a submenu and needs to be adjusted
		if (hasParent) {
			//get the left position for this menu
			left = this.getParent().getOffsetLeft();
			//get the top position for this menu
			top = this.getParent().getOffsetTop();
			
			//we will need to know what browser the user is using
			browser = detectBrowser();
			
			//this is where it gets really convoluted so you will have to either take my
			//word for the following or pull all of your hair out
			//this if statement basically says - if the main menu is horizontally aligned and
			//this submenu is in the first sublevel, meaning that it is supposed to be positioned
			//directly below a cell in the main menu
			if (!this.getParent().getParent().getParent() && JKYMENU_alignment == JKYMENU_HORIZONTAL) {
				browser = detectBrowser();
				//don't know why this is necessary in IE, but it is
				if (browser == JKYMENU_IE) {
					left += 1;
				}
				
				//set the left and top position of this menu
				this.getElement().style.left = left + "px";
				this.getElement().style.top = top + "px";
				
				//set the width so that a submenu at this level will always be at
				//least as wide as its parent cell
				width = this.getParent().getElement().offsetWidth - border - padding * 2;
				
			//else this is either vertical or not the first submenu level
			} else {
				//if using IE then we have to make a lot of odd adjustments
				//i will try to explain as far as i understand, but a lot
				//of this i figured out by trial and error and don't
				//know for sure why some of it's necessary
				if (browser == JKYMENU_IE) {
					//if this is a submenu
					if (this.getParent()) {
						//get the parent menu and cell
						parentMenu = this.getParent().getParent();
						parentCell = parentMenu.getParent();
						
						//this menu's parent menu does not have a parent
						//then this is a first level submenu
						if (!parentCell) {
							//move the menu one to the right for some reason
							left++;
							
							//if this menu is the first submenu
							parentTbody = parentMenu.getTbody();
							td = parentTbody.children[0];
							if (td == this.getParent().getTr()) {
								top++;
							} else {
								//if the cells have no borders
								if (!border) {
									top++;
								} else {
									var adjust = ((border - 2) / 2) - border % 2;
									top -= adjust;
								}
							}
						}
						//IE includes the border in it's left calculation
						//which we don't want to do
						if (border) {
							left -= border;
						}
					}
				}
				
				//set the positioning
				this.getElement().style.left = left + "px";
				this.getElement().style.top = top + "px";
			}
		}
		
		//now we have to iterate through every submenu and adjust it
		for (var i = 0; i < this.getCells().length; i++) {
			cell = this.getCells()[i];
			
			//if this is a submenu of a horizontal menu, then we need to set a
			//minimum width
			if (width) {
				cell.setWidth(width);
			}
			//adjust the cell
			cell.adjust(border, padding);
		}
		
		//this needs to be done last because all of the previous adjusting needs
		//to be done with the elements visible
		//set the submenus invisible to start
		if (hasParent) {
			this.getElement().style.display = "none";
		}
	}	
	
	//setup the table element
	//use two methods to set the class, one for IE and one for FF
	element.setAttribute("id", JKYMENU_prefix + id);
	element.setAttribute("class", "JKYMenu_menu");
	element.className = "JKYMenu_menu";
	element.cellSpacing = "0";

	//add the tbody to the table
	element.appendChild(tbody);

	//if there is a parent, then this is not the top level menu
	if (parent) {
		//this will not be in the normal flow of the page since it is a submenu
		element.style.position = "absolute";
		
		//add the javascript to the events of this menu's
		//parent element for rollovers
		element.onmouseover = new Function(this.genOnMouseOver());
		element.onmouseout = new Function(this.genOnMouseOut());
		
	//else this is the top-level menu
	} else {
		//if this menu is horizontal and it's the main menu then there is only
		//one row and this menu node needs a tr.  otherwise, there is a tr in
		//each cell node
		if (JKYMENU_alignment == JKYMENU_HORIZONTAL) {
			this.tr = document.createElement("tr");
			tbody.appendChild(this.tr);
		}
	}
	
	//now we add all of the cells to this menu, recursively
	//creating the submenus of those cells
	for (var i = 0; i < cellsXml.length; i++) {
		cellXml = cellsXml[i];
		nodeType = (cellXml.nodeName);
		nodeType = nodeType.toLowerCase();
		//if the node is a cell, then create the cell object and add its
		//element to this menu's tbody or tr
		if (nodeType == "cell") {
			cell = new JKYCell(cellXml, this);
			appender = tbody;

			//if this is the main menu and the menu is being drawn horizontal
			//then we need to add cells to the tr instead of the td
			if (JKYMENU_alignment == JKYMENU_HORIZONTAL && !this.getParent()) {
				appender = this.tr;
			}
			
			//add the cell to this table's element (tbody or tr) and also
			//to this menu's array of cells
			appender.appendChild(cell.getElement());
			this.getCells().push(cell);
		}
	}
}

////////////////////////////////////////////////////////////////////////
/// Class representation of a cell in a menu.
///
/// The cell class contains the text and submenus of an individual
/// menu cell
///
/// \param xml The XML tree node for this cell
///
/// \param parentArg The parent menu of this cell
////////////////////////////////////////////////////////////////////////

function JKYCell(xml, parentArg) {
	var cellChildren = xml.childNodes;      //all the nodes in this cell
	var cellChild;  //each individual child element
	var cellChildType;      //the type of child it is (text or menu)
	var text;       //text node of the text element of the cell
	var textNode;   //temp text node
	var link = xml.getAttribute("link");	//the link of this element
	var target = xml.getAttribute("target");	//this element's target
												//for links

	var tr = document.createElement("tr");	//this will be the cell's
											//base element if its parent
											//menu is vertical
	//this will be the cells base element if its submenu is horizontal
	//otherwise it is still used, but not the base element to be
	//attached to parent elements
	var element = document.createElement("td");
	var parent = parentArg;   //the parent menu for this cell
	var menu;      //the submenu of this cell if there is one

	//assign methods
	this.getTr = function() {	/*! METHOD getTr()
								\return The tr of this cell if there is one*/
		return tr;
	}
	
	this.getTd = function() {	/*! METHOD getTd()
								\return the td of this cell*/
		return element;
	}
	
	this.getElement = function() {	/*! METHOD getElement()
									This method determines if this cell's
									menu is horizontal or vertical and returns
									an element accordingly
									\return The base element of this cell*/

		//if this cell's menu is horizontal
		if (!this.getParent().getParent() && JKYMENU_alignment == JKYMENU_HORIZONTAL) {
			//then return the td as the base element
			return this.getTd();
		} else {
			//else return the tr as the base element
			return this.getTr();
		}
	}
	
	this.getParent = function() {	/*! METHOD getParent()
									\return The parent menu of this cell*/
		return parent;
	}

	this.getOffsetLeft = function() {	/*! METHOD getOffsetLeft()
										Note that this method actually
										calculates the position of any
										parent menus, not this cell's
										element's offsetLeft
										\return The top position in pixels
										of this element's submenu if
										there is one*/


		//get the parent menu's parent cell to determine if there is one
		var parentMenu = this.getParent().getParent();
		
		//get the offset of this cell's td
		var offset = getOffsetLeft(this.getTd());
		
		//if this cell's parent menu is a submenu and this menu is
		//horizontally aligned, then there is no need to account for
		//the width of this cell
		if (!parentMenu & JKYMENU_alignment == JKYMENU_HORIZONTAL) {
			return offset;
		}
		//otherwise we need to append the width
		offset += this.getTd().offsetWidth;
		return offset;
	}
	
	this.getOffsetTop = function() {	/*! METHOD getOffsetLeft()
										Note that this method actually
										calculates the position of any
										parent menus, not this cell's
										element's offsetTop
										\return The top position in pixels
										of this element's submenu if
										there is one*/

		//determine if the menu one level above this cell's menu exists
		//and if it does and the menu is also horizontal, then the top
		//position of any children needs to be adjusted for this cell's width
		var parentMenu = this.getParent().getParent();
		var offset = getOffsetTop(this.getTd());
		if (!parentMenu & JKYMENU_alignment == JKYMENU_HORIZONTAL) {
			offset += this.getTd().offsetHeight;
		}
		return offset;
	}

	this.adjust = function(border, padding) {	/*! METHOD adjust()
									This method adjusts the cell's submenu's
									position and width accordingly
									\param border The border width of the cells
									in this menu
									\param padding The padding width of the cells
									in this menu*/
									
		//we need to keep track of the level of menu this is for positioning
		if (this.getMenu()) {
			JKYMENU_level++;
			//adjust the submenu
			this.getMenu().adjust(border, padding);
			JKYMENU_level--;
		}
	}

	this.getMenu = function() {	/*! METHOD getMenu()
								\return The submenu of this cell if there is one*/
		return menu;
	}



	this.genOnMouseOver = function() {	/*! METHOD genOnMouseOver
										\return A function to be assignment to the
										onMouseOver event of this cell's td*/
		var funcStr;	//function string
		var func;		//the actual function
	
		//this needs to be from the perspective of the actual element on the page
		funcStr = "JKYMenu_show('" + this.getMenu().getId() + "');";
		func = new Function(funcStr);
		return func;
	}
	
	this.genOnMouseOut = function() {	/*! METHOD genOnMouseOut
										\return A function to be assignment to the
										onMouseOver event of this cell's td*/
		var funcStr;
		var func;
	
		//this needs to be from the perspective of the actual element on the page
		funcStr = "JKYMenu_hide('" + this.getMenu().getId() + "');";
		func = new Function(funcStr);
		return func;
	}
	
	this.setWidth = function(width) {	/*! METHOD setWidth()
										Sets the width of this element
										\param width The width to set*/
		this.getTd().style.width = width + "px";
	}

	//initialize the td
	element.setAttribute("class", "JKYMenu_cell");
	element.className = "JKYMenu";
	element.style.whiteSpace = "nowrap";
	element.style.textAlign = "left";
	element.style.cursor = "default";

	//if this cell is not in a horizontal menu, then we need to add this cell's
	//td to its tr
	if (JKYMENU_alignment == JKYMENU_VERTICAL || this.getParent().getParent()) {
		this.getTr().appendChild(element);
	}
	
	//if a link was specified, set the onclick and cursoer
	if (link) {
		element.onclick = genOnClick(link, target);
		element.style.cursor = "pointer";
	}

	//iterate through each child in the xml and respond appropriately
	for (var i = 0; i < cellChildren.length; i++) {
	        //get all of the children of this cell one at a time and check
	        //the node type (text or menu)
                cellChild = cellChildren[i];
                cellChildType = cellChild.nodeName;
                cellChildType = cellChildType.toLowerCase();

		//if the type is text, then append the text to his cell's element
		if (cellChildType == "text") {
			text = cellChild.childNodes[0].nodeValue;
			textNode = document.createTextNode(text);
			element.appendChild(textNode);

		//otherwise if the type is a menu, create and add the menu to the page and
		//set onMouseOver and onMouseOut events
		} else if (cellChildType == "menu") {
            menu = new JKYMenuNode(cellChild, this);
			document.body.appendChild(menu.getElement());
			element.onmouseover = this.genOnMouseOver();
			element.onmouseout = this.genOnMouseOut();
        }
	}
}

////////////////////////////////////////////////////////////////////////
/// Detects the browser being used by the user
///
///	This function reads the navigator.userAgent field and parses it to
/// to determine what browser the user has.  This is not the best way
/// to differentiate different methods and should only be used when
/// object detection will not work.  Note that browsers often
/// misidentify themselves.  This only supports IE and FF.  It assumes
/// Firefox if not IE because FF tends to be closer to specification.
///
/// \return The constant for the browser
////////////////////////////////////////////////////////////////////////

function detectBrowser() {
	//get the userAgent string
	var agent = navigator.userAgent;

	//search for IE and assume FF if IE not detected
	if (agentFind(agent, "msie")) {
		return JKYMENU_IE;
	} else {
		return JKYMENU_FF;
	}
}

////////////////////////////////////////////////////////////////////////
///	Find the position of the second string in the first string
///
/// This is used to find a browser ID string in the userAgent string
///
/// \param agent The navigator.userAgent string
///	\param browser The browser string to look for
///
///	\return place The place of the substring if found.
////////////////////////////////////////////////////////////////////////

function agentFind(agent, browser) {
	agent = agent.toLowerCase();
	var place = agent.indexOf(browser);
	//adjust a reponse of -1 to 0 so that calling this function can
	//return a "false" boolean value of 0
	place = place + 1;
	return place;
}

////////////////////////////////////////////////////////////////////////
///	Generates a function for the onClick event handler
///
///	This is used by the JKYMenu_cell class to generate the function
/// fo the onClick event handler.
///
/// \param link The URL of the hyperlink
/// \param target The target attribute of the anchor
///
/// \return func The generated function
////////////////////////////////////////////////////////////////////////

function genOnClick(link, target) {
	var funcStr;	//temp function string

	//if a target was not specified
	if (!target) {
		funcStr = "self.location = '" + link + "';";
	} else {
		funcStr = "window.open('" + link + "', '" + target + "');";
	}
	var func = new Function(funcStr);
	return func;
}

////////////////////////////////////////////////////////////////////////
/// Finds the left position of an element
///
/// This function determines the left position of an element by
/// recursively finding the left position of parent elements and adding
/// them all together
///
///	\param el The element to find the left position of
///
/// \return The left position of el
////////////////////////////////////////////////////////////////////////

function getOffsetLeft(el) {
	//initialize
	var offset = 0;
	
	//if this element has an offset
	if (el.offsetLeft) {
		offset += el.offsetLeft;
	}
	
	//if this element has a parent, recursively get the parent offsets
	if (el.offsetParent) {
		offset += getOffsetLeft(el.offsetParent);
	}
	
	return offset;
}

////////////////////////////////////////////////////////////////////////
/// Finds the top position of an element
///
/// This function determines the top position of an element by
/// recursively finding the top position of parent elements and adding
/// them all together
///
///	\param el The element to find the top position of
///
/// \return The top position of el
////////////////////////////////////////////////////////////////////////

function getOffsetTop(el) {
	//initialize
	var offset = 0;
	
	//if this element has an offset
	if (el.offsetTop) {
		offset += el.offsetTop;
	}
	
	//if this element has a parent, recursively get the parent offsets
	if (el.offsetParent) {
		offset += getOffsetTop(el.offsetParent);
	}
	return offset;
}

////////////////////////////////////////////////////////////////////////
/// Hides the specified element on the page
///
///	\param id The ID attribute of the element to hide
////////////////////////////////////////////////////////////////////////

function JKYMenu_hide(id) {
	var el = document.getElementById(id);
	el.style.display = "none";
}

////////////////////////////////////////////////////////////////////////
/// Shows the specified element on the page
///
///	\param id The ID attribute of the element to show
////////////////////////////////////////////////////////////////////////

function JKYMenu_show(id) {
	var el = document.getElementById(id);
	el.style.display = "block";
}