// file: menu.js
// version: 1.1
// author: KBE20091103

// Copyright 2010 TechHouse.dk a/s & Kenneth Bernholm



// --- object: menu
TECHHOUSE.menu = {};


/*
This function is added to all button A HREF when button has a sub section.
It's only relevant for clients with touch interfaces.
It blocks the HREF on first touch allowing the section to unfold.
On second touch the HREF is reactivated
*/
TECHHOUSE.menu.go = function( buttonNo ) {

	var retval;

	retval = true;

	if( TECHHOUSE.menu.interface == 'TOUCH' ) {

		if( TECHHOUSE.menu.lastButtonNo != buttonNo ) {
			TECHHOUSE.menu.lastButtonNo = buttonNo;
			retval = false;
			}
		else {
			TECHHOUSE.menu.lastButtonNo = undefined;
			}

		}

	return retval;
	}



// function: menu.parse
// purpose: travels html nodes and builds json structure accordingly
// arguments: html element, menu data structure, menu id
// returns: -
TECHHOUSE.menu.parse = function( htmlNode, menuNode, id ) {

	var child, classRegex, classMatch, parm, parmRegex, parmMatch;

	child = htmlNode.firstChild;

	// splits class name into Type (button,section,item) and Parameters
	classRegex = new RegExp( id + '_([a-z]*)(.*)' );

	// splits parameters into Section Position, Fade Change and Animation Change
	parmRegex = new RegExp( '([A-Z]*)_([A-Z]*)([0-9]*)_([A-Z]*)([0-9]*)' );

	while( child ) {

		classMatch = classRegex.exec( child.className );

		if( classMatch ) {

			switch( classMatch[ 1 ] ) {

				case 'button':
					menuNode.push( { id: child.id, section: {} } );
					TECHHOUSE.menu.parse( child, menuNode[ menuNode.length - 1 ].section, id );
					break;

				case 'section':
					menuNode.id = child.id;

					parm = classMatch[ 2 ].substr( 1, classMatch[ 2 ].length - 1 );
					parmMatch = parmRegex.exec( parm );

					if( parmMatch ) {
						menuNode.position = parmMatch[ 1 ]; // UL, UR, DL, DR, LU, LD, RU, RD

						if( parmMatch[ 2 ] == 'F' ) {
							menuNode.fade = parmMatch[ 3 ];
							}

						if( parmMatch[ 4 ] == 'A' ) {
							menuNode.animation = parmMatch[ 5 ];
							}

						}

					menuNode.offsetWidthWithoutPaddingAndBorder = TECHHOUSE.getOffsetWidthWithoutPaddingAndBorder( child );
					menuNode.offsetHeightWithoutPaddingAndBorder = TECHHOUSE.getOffsetHeightWithoutPaddingAndBorder( child );

					menuNode.items = [];
					TECHHOUSE.menu.parse( child, menuNode.items, id );
					break;

				case 'item':
					menuNode.push( { id: child.id, section: {} } );
					TECHHOUSE.menu.parse( child, menuNode[ menuNode.length - 1 ].section, id );
					break;

				default:
					break;

				}
			}

		child = child.nextSibling;
		}

	}



// method: getParentItem
// purpose: gets first parent item (class is menu.id + '_item' )from any node
// arguments: DOM node
// returns: DOM node or undefined
TECHHOUSE.menu.getParentItem = function( menu, node ) {

	var go, item;

	go = true;

	while( go ) {

		if( node ) {

			if( node == '[object HTMLBodyElement]' ) {
				go = false;
				}

			if( node.className ) {

				if( node.className.indexOf( menu.id + '_item' ) != -1 ) {
					item = node;
					go = false;
					}

				}

			node = node.parentNode;
			}

		else {
			go = false;
			}

		}

	return item;
	}



// function: placeSection
// purpose: places sections according to their parents position (be it a button or another section)
// arguments: section, parent left position, parent top position, parent width, parent height, menu level
// returns: -
TECHHOUSE.menu.placeSection = function( menu, section, parentLeft, parentTop, parentWidth, parentHeight, level ) {

	var elem, itemSectionTop, topPos, leftPos, item, itemHeight, parentItemElem;

	elem = document.getElementById( section.id );

	if( elem ) {

		itemSectionTop = 0;

		// get height of current sections parent item
		parentItemElem = TECHHOUSE.menu.getParentItem( menu, elem );
		if( parentItemElem ) {
			itemHeight = parentItemElem.offsetHeight;
			}

		// calculate section position to up/down/left/right of button (level 0) or left/right to item (level 1+)
		switch( section.position ) {

			// up left
			case 'UL':
				topPos = ( level == 0 ) ? parentTop - elem.offsetHeight : parentTop + TECHHOUSE.getTopPadding( elem ) - elem.offsetHeight + itemHeight;
				leftPos = ( level == 0 ) ? parentLeft : - elem.offsetWidth - TECHHOUSE.getLeftBorder( elem );
				break;

			// up right
			case 'UR':
				topPos = ( level == 0 ) ? parentTop - elem.offsetHeight : parentTop + TECHHOUSE.getTopPadding( elem ) - elem.offsetHeight + itemHeight;
				leftPos = ( level == 0 ) ? parentLeft : parentWidth - TECHHOUSE.getLeftBorder( elem );
				break;

			// down left
			case 'DL':
				topPos = ( level == 0 ) ? parentTop + parentHeight : parentTop + TECHHOUSE.getTopPadding( elem );
				leftPos = ( level == 0 ) ? parentLeft : - elem.offsetWidth - TECHHOUSE.getLeftBorder( elem );
				break;

			// down right
			case 'DR':
				topPos = ( level == 0 ) ? parentTop + parentHeight : parentTop + TECHHOUSE.getTopPadding( elem );
				leftPos = ( level == 0 ) ? parentLeft : parentWidth - TECHHOUSE.getLeftBorder( elem );
				break;

			// left up
			case 'LU':
				topPos = ( level == 0 ) ? ( parentTop + parentHeight ) - elem.offsetHeight : parentTop + TECHHOUSE.getTopPadding( elem ) - elem.offsetHeight + itemHeight;

				if( TECHHOUSE.browser.name == 'MSIE' && TECHHOUSE.browser.major == 7 && level > 3 ) {
					topPos = ( level == 0 ) ? ( parentTop + parentHeight ) - elem.offsetHeight : parentTop - TECHHOUSE.getOffsetHeightWithoutPaddingAndBorder( elem ) + TECHHOUSE.getTopBorder( elem ) + TECHHOUSE.getTopPadding( elem ) + itemHeight;
					}

				leftPos = ( level == 0 ) ? - elem.offsetWidth :  - elem.offsetWidth - TECHHOUSE.getLeftBorder( elem );
				break;

			// left down
			case 'LD':
				topPos = ( level == 0 ) ? parentTop : parentTop + TECHHOUSE.getTopPadding( elem );
				leftPos = ( level == 0 ) ? - elem.offsetWidth : - elem.offsetWidth - TECHHOUSE.getLeftBorder( elem );
			break;

			// right up
			case 'RU':
				topPos = ( level == 0 ) ? ( parentTop + parentHeight ) - elem.offsetHeight : parentTop + TECHHOUSE.getTopPadding( elem ) - elem.offsetHeight + itemHeight;

				if( TECHHOUSE.browser.name == 'MSIE' && TECHHOUSE.browser.major == 7 && level > 3 ) {
					topPos = ( level == 0 ) ? ( parentTop + parentHeight ) - elem.offsetHeight : parentTop - TECHHOUSE.getOffsetHeightWithoutPaddingAndBorder( elem ) + TECHHOUSE.getTopBorder( elem ) + TECHHOUSE.getTopPadding( elem ) + itemHeight;
					}

				leftPos = ( level == 0 ) ? parentLeft + parentWidth : parentWidth - TECHHOUSE.getLeftBorder( elem );
				break;

			// right down
			case 'RD':
				topPos = ( level == 0 ) ? parentTop : parentTop + TECHHOUSE.getTopPadding( elem );
				leftPos = ( level == 0 ) ? parentLeft + parentWidth : parentWidth - TECHHOUSE.getLeftBorder( elem );
				break;

			default:

			}

		// place section
		elem.style.top = topPos + 'px';
		elem.style.left = leftPos + 'px';
		elem.style.width = section.offsetWidthWithoutPaddingAndBorder + 'px';

		section.offsetTop = topPos; //remember offsetTop for animation (expandUp)

		elem.style.height = section.offsetHeightWithoutPaddingAndBorder + 'px';
		elem.style.visibility = 'hidden';

		// loop through items in section
		for( item = 0; item < section.items.length; item++ ) {

			// if item has section (sub menu) with more items
			if( section.items[ item ].section ) {

				// place section
				TECHHOUSE.menu.placeSection(
					menu,
					section.items[ item ].section,
					parseInt( elem.style.left.replace( 'px', '' ) ),
					itemSectionTop,
					parseInt( elem.offsetWidth ),
					parseInt( elem.offsetHeight ),
					++level
					);

				}

			itemSectionTop += parseInt( document.getElementById( section.items[ item ].id ).offsetHeight );
			 
			}

		}

	}



// object: menu.dropdown
// purpose: handles interactive multilevel drop down menu
// arguments:
// returns: -
TECHHOUSE.menu.dropdown = function( parms ) {

	var that = this;
	var button;
	var section, parentLeft, parentTop, parentWidth, parentHeight, level, buttonElem;



	// method: getButtonNumberByButtonId
	// purpose: gets correct button number in that.menu.buttons from a button DOM id
	// arguments: button DOM id
	// returns: buttons number or undefined
	this.getButtonNumberByButtonId = function( buttonId ) {

		var button, buttonNumber;

		for( button = 0; button < that.menu.buttons.length; button++ ) {
			if( that.menu.buttons[ button ].id == buttonId ) {
				buttonNumber = button;
				}
			}

		return buttonNumber;
		}



	// method: getButtonNumberByItemId
	// purpose: gets correct button number in that.menu.buttons from an item DOM id
	// arguments: item DOM id
	// returns: button number or undefined
	this.getButtonNumberByItemId = function( itemId ) {

		var button, match, buttonNumber;
		for( button = 0; button < that.menu.buttons.length; button++ ) {

			if( that.menu.buttons[ button ].section ) {
				match = that.isItemInSection( itemId, that.menu.buttons[ button ].section );

				if( match ) {
					buttonNumber = button;
					}

				}

			}

		return buttonNumber;
		}



	// method: isItemInSection
	// purpose: recursively looks for an item DOM id in a section and sub sections
	// arguments: item DOM id, data structure section reference
	// returns: true if item DOM id is found in section, false if not
	this.isItemInSection = function( itemId, section ) {

		var item, match, childMatch;

		if( section.items ) {

			for( item = 0; item < section.items.length; item++ ) {

				if( itemId == section.items[ item ].id ) {
					match = true;
					}

				else if( section.items[ item ].section ) {
					childMatch = false;
					childMatch = that.isItemInSection( itemId, section.items[ item ].section );

					if( childMatch ) {
						match = true;
						}

					}

				}

			}

		return match;
		}



	// method: getChildSectionIds
	// purpose: recursively find DOM ids of all child sections
	// arguments: data structure reference to button or item
	// returns: array of DOM ids
	this.getChildSectionIds = function( bi ) {

		var item;
		var ids = [];
		var childIds;
		var concatenatedIds = [];

		if( bi != undefined ) {

			if( bi.section.id ) {
				ids.push( bi.section.id );

				if( bi.section.items ) {

					for( item = 0; item < bi.section.items.length; item++ ) {

						if( bi.section.items[ item ].section ) {
							childIds = that.getChildSectionIds( bi.section.items[ item ] );

							if( childIds ) {
									ids = ids.concat( childIds );
								}

							}

						}

					}

				}

			}

		return ids;
		}



	// method: hideSections
	// purpose: hides all specified sections
	// arguments: array of DOM ids
	// returns: -
	this.hideSections = function( sections ) {

		var section, sectionId;

		for( section = 0; section < sections.length; section++ ) {
			sectionId = document.getElementById( sections[ section ] );

			if( sectionId ) {
				sectionId.style.visibility = 'hidden';
				}

			}

		}



	// method: getItemAndParentSectionByItemId
	// purpose: get item and parent section in data structure from item DOM id
	// arguments: item DOM id
	// returns: array with data structure references to item and parent section OR undefined
	this.getItemAndParentSectionByItemId = function( itemId ) {

		var button, item, childItem, parentSection;
		for( button = 0; button < that.menu.buttons.length; button++ ) {

			if( that.menu.buttons[ button ].section ) {
				childItem = that.getItemAndParentSectionByItemIdAndSection( itemId, that.menu.buttons[ button ].section );

				if( childItem[ 0 ] ) {
					item = childItem[ 0 ];
					parentSection = childItem[ 1 ];
					}

				}

			}

		return [ item, parentSection ];
		}



	// method: getItemAndParentSectionByItemIdAndSection
	// purpose: get item and parent section in data structure from item DOM id and section
	// arguments: item DOM id, data structure section reference
	// returns: array with data structure references to item and parent section OR undefined
	this.getItemAndParentSectionByItemIdAndSection = function( itemId, section ) {

		var item, itemRef, childItem, parentSection;

		if( section.items ) {

			for( item = 0; item < section.items.length; item++ ) {

				if( itemId == section.items[ item ].id ) {
					itemRef = section.items[ item ];
					parentSection = section;
					}
				else {

					if( section.items[ item ].section ) {

						childItem = false;
						childItem = that.getItemAndParentSectionByItemIdAndSection( itemId, section.items[ item ].section );

						if( childItem[ 0 ] ) {
							itemRef = childItem[ 0 ];
							parentSection = childItem[ 1 ];
							}

						}

					}

				}

			}

		return [ itemRef, parentSection ];
		}



	// method: getItemNumberByItemIdAndSection
	// purpose: get item number from item DOM id and section
	// arguments: item DOM id, data structure section reference
	// returns: item number OR undefined
	this.getItemNumberByItemIdAndSection = function( itemId, section ) {

		var item, itemNumber;

		if( section.items ) {

			for( item = 0; item < section.items.length; item++ ) {

				if( itemId == section.items[ item ].id ) {
					itemNumber = item;
					}

				}

			}

		return itemNumber;
		}



	// method: getParentButtonByElement (for MSIE)
	// purpose: gets id of parent button from any html element
	// arguments: node element
	// returns: parent button or undefined
	this.getParentButtonByElement = function( node ) {

		var go, button;

		go = true;

		while( go ) {

			if( node == '[object HTMLBodyElement]' ) {
				go = false;
				}

			if( node.className.indexOf( that.menu.id + '_button' ) != -1 ) {
				button = node;
				go = false;
				}

			node = node.parentNode;
			}

		return button;
		}



	// method: getParentItemByElement (for MSIE)
	// purpose: gets id of parent item from any html element
	// arguments: node element
	// returns: parent item or undefined
	this.getParentItemByElement = function( node ) {

		var go, item;

		go = true;

		while( go ) {

			if( node == '[object HTMLBodyElement]' ) {
				go = false;
				}

			if( node.className.indexOf( that.menu.id + '_item' ) != -1 ) {
				item = node;
				go = false;
				}

			node = node.parentNode;
			}

		return item;
		}



	// method: setButtonEventHandlers
	// purpose: sets event handlers for when the mouse enters and leaves a button
	// arguments: data structure reference to menu
	// returns: -
	this.setButtonEventHandlers = function( menu ) {

		var that, showSection, showEffect, hideSection, elem, button, section, item;
		var showButtonSection, opacityFadeUp, hideButtonSection;
		var fadeChange, animationChange;

		this.menu = menu;
		that = this;

		// event handler: showButtonSection
		showButtonSection = function( e ) {
			e = e ? e : window.event;
			TECHHOUSE.stopBubbling( e );
			var target, sectionElem, currentButtonNumber, button;
			target = e.currentTarget || e.toElement;

			// MSIE starts events from bottom, thus we must find the parent button
			if( target.id.indexOf( that.menu.id + '_button' ) == -1 ) {
				target = that.getParentButtonByElement( target );
				}

			// get current button number
			currentButtonNumber = that.getButtonNumberByButtonId( target.id );

			if( currentButtonNumber != undefined ) {

				// entering button must clear any existing button timer
				if( that.menu.buttons[ currentButtonNumber ].timer ) {
					clearTimeout( that.menu.buttons[ currentButtonNumber ].timer );
					that.menu.buttons[ currentButtonNumber ].timer = null;
					}

				// hide all sections to all other buttons
				for( button = 0; button < that.menu.buttons.length; button++ ) {

					// current button : hide any sections items child sections
					if( currentButtonNumber == button ) {

						if( that.menu.buttons[ button ].section ) {

							if( that.menu.buttons[ button ].section.items ) {

								for( item = 0; item < that.menu.buttons[ button ].section.items.length; item++ ) {
									that.hideSections(
										that.getChildSectionIds( that.menu.buttons[ button ].section.items[ item ] ) );
									}
								}									

							}

						}

					// other button : hide any child sections
					else {
						that.hideSections(
							that.getChildSectionIds( that.menu.buttons[ button ] ) );
						}

					}

				// show any child section
				if( that.menu.buttons[ currentButtonNumber ].section ) {
					sectionElem = document.getElementById( that.menu.buttons[ currentButtonNumber ].section.id );

					if( sectionElem ) {

						if( sectionElem.style.visibility == 'hidden' ) {

							// fade up
							fadeChange = parseInt( that.menu.buttons[ currentButtonNumber ].section.fade );
							if( fadeChange > 0 ) {
								TECHHOUSE.opacityFadeUp( sectionElem, 0, fadeChange );
								}

							// expand down or up
							animationChange = parseInt( that.menu.buttons[ currentButtonNumber ].section.animation );
							if( animationChange > 0 ) {

								switch( that.menu.buttons[ currentButtonNumber ].section.position ) {

									case 'DR':
										TECHHOUSE.elementExpandDown(
											sectionElem,
											0,
											that.menu.buttons[ currentButtonNumber ].section.offsetHeightWithoutPaddingAndBorder,
											animationChange
											);
										break;

									case 'DL':
										TECHHOUSE.elementExpandDown(
											sectionElem,
											0,
											that.menu.buttons[ currentButtonNumber ].section.offsetHeightWithoutPaddingAndBorder,
											animationChange
											);
										break;

									case 'UR':
										TECHHOUSE.elementExpandUp(
											sectionElem,
											0,
											that.menu.buttons[ currentButtonNumber ].section.offsetHeightWithoutPaddingAndBorder,
											that.menu.buttons[ currentButtonNumber ].section.offsetTop,
											animationChange
											);
										break;

									case 'UL':
										TECHHOUSE.elementExpandUp(
											sectionElem,
											0,
											that.menu.buttons[ currentButtonNumber ].section.offsetHeightWithoutPaddingAndBorder,
											that.menu.buttons[ currentButtonNumber ].section.offsetTop,
											animationChange
											);
										break;

									case 'LU':
										TECHHOUSE.elementExpandUp(
											sectionElem,
											0,
											that.menu.buttons[ currentButtonNumber ].section.offsetHeightWithoutPaddingAndBorder,
											that.menu.buttons[ currentButtonNumber ].section.offsetTop,
											animationChange
											);
										break;

									case 'LD':
										TECHHOUSE.elementExpandDown(
											sectionElem,
											0,
											that.menu.buttons[ currentButtonNumber ].section.offsetHeightWithoutPaddingAndBorder,
											animationChange
											);
										break;

									case 'RU':
										TECHHOUSE.elementExpandUp(
											sectionElem,
											0,
											that.menu.buttons[ currentButtonNumber ].section.offsetHeightWithoutPaddingAndBorder,
											that.menu.buttons[ currentButtonNumber ].section.offsetTop,
											animationChange
											);
										break;

									case 'RD':
										TECHHOUSE.elementExpandDown(
											sectionElem,
											0,
											that.menu.buttons[ currentButtonNumber ].section.offsetHeightWithoutPaddingAndBorder,
											animationChange
											);
										break;

									}

								}

							sectionElem.style.visibility = 'visible';
							}

						}

					}

				}

			}

		// event handler: hideButtonSection
		hideButtonSection = function( e ) {
			e = e ? e : window.event;
			TECHHOUSE.stopBubbling( e );
			var target, currentButtonNumber;
			target = e.currentTarget || e.srcElement;

			// MSIE starts events from bottom, thus we must find the parent button
			if( target.id.indexOf( that.menu.id + '_button' ) == -1 ) {
				target = that.getParentButtonByElement( target );
				}

			// leaving current button must set a timer for hiding child sections
			currentButtonNumber = that.getButtonNumberByButtonId( target.id );
			if( currentButtonNumber != undefined ) {

				if( ! that.menu.buttons[ currentButtonNumber ].timer ) {
					that.menu.buttons[ currentButtonNumber ].timer =
						setTimeout(
							function() {

								that.hideSections(
									that.getChildSectionIds(
										that.menu.buttons[ currentButtonNumber ] ) );

								that.menu.buttons[ currentButtonNumber ].timer = null;
								return;
								},
							TECHHOUSE.menu.sectionTimeout );

					}

				}

			}

		// set button event handlers
		for( button in menu.buttons ) {
			elem = document.getElementById( menu.buttons[ button ].id );

			if( elem ) {
				if( TECHHOUSE.browser.name == 'MSIE' ) {
					elem.attachEvent( 'onmouseover', showButtonSection );
					elem.attachEvent( 'onmouseout', hideButtonSection );
					TECHHOUSE.menu.interface = 'MOUSE';
					TECHHOUSE.menu.sectionTimeout = 2000;
					}
				else if(
					( TECHHOUSE.browser.platform == 'ANDROID' )
					||
					( TECHHOUSE.browser.platform == 'IPOD' )
					||
					( TECHHOUSE.browser.platform == 'IPHONE' )
					||
					( TECHHOUSE.browser.platform == 'IPAD' )
					) {
					elem.addEventListener( 'touchstart', showButtonSection, false );
					elem.addEventListener( 'touchend', hideButtonSection, false );
					TECHHOUSE.menu.interface = 'TOUCH';
					TECHHOUSE.menu.sectionTimeout = 15000;
					}
				else {
					elem.addEventListener( 'mouseover', showButtonSection, false );
					elem.addEventListener( 'mouseout', hideButtonSection, false );
					TECHHOUSE.menu.interface = 'MOUSE';
					TECHHOUSE.menu.sectionTimeout = 2000;
					}
				}

			// set item event handlers
			that.setItemEventHandlers( menu.buttons[ button ].section );

			}

		}



	// method: setItemEventHandlers
	// purpose: sets event handlers for when the mouse enters and leaves an item
	// arguments: data structure reference to section
	// returns: -
	this.setItemEventHandlers = function( section ) {

		var that, showSection, hideSection, elem, item, itemB;
		var showItemSection, opacityFadeUp, hideItemSection;
		var fadeChange, animationChange;
		var startTop;

		that = this;

		if( typeof( section ) == 'object' ) {

			if( section.id ) {

				// event handler: catchSectionEvent
				catchSectionEvent = function( e ) {
					e = e ? e : window.event;
					TECHHOUSE.stopBubbling( e );
					}

				// event handler: showItemSection
				showItemSection = function( e ) {
					e = e ? e : window.event;
					TECHHOUSE.stopBubbling( e );
					var target, sectionElem, currentButtonNumber, currentItemNumber, itemRef, item, sectionRef;
					target = e.currentTarget || e.toElement;

					// MSIE starts events from bottom, thus we must find the parent item
					if( target.id.indexOf( that.menu.id + 'item' ) == -1 ) {
						target = that.getParentItemByElement( target );
						}

					// entering item must clear any existing button timer
					currentButtonNumber = that.getButtonNumberByItemId( target.id );

					if( currentButtonNumber != undefined ) {

						if( that.menu.buttons[ currentButtonNumber ].timer ) {
							clearTimeout( that.menu.buttons[ currentButtonNumber ].timer );
							that.menu.buttons[ currentButtonNumber ].timer = null;
							}

						}

					// clear all child sections to all other items on this level
					sectionRef = that.getItemAndParentSectionByItemId( target.id )[ 1 ];
					if( sectionRef != undefined ) {

						if( sectionRef.items ) {
							currentItemNumber = that.getItemNumberByItemIdAndSection( target.id, sectionRef );

							for( item = 0; item < sectionRef.items.length; item++ ) {

								// current item : hide any childs sections items child sections
								if( currentItemNumber == item ) {

									if( sectionRef.items[ item ].section ) {

										if( sectionRef.items[ item ].section.items ) {

											for( itemB = 0; itemB < sectionRef.items[ item ].section.items.length; itemB++ ) {
												that.hideSections(
													that.getChildSectionIds( sectionRef.items[ item ].section.items[ itemB ] ) );
												}
											}									

										}

									}

								// other item in this section : hide any child sections
								else {
									that.hideSections(
										that.getChildSectionIds( sectionRef.items[ item ] ) );
									}

								}

							}

						}

					// show any child section
					itemRef = that.getItemAndParentSectionByItemId( target.id )[ 0 ];
					if( itemRef != undefined ) {

						if( itemRef.section ) {
							sectionElem = document.getElementById( itemRef.section.id );

							if( sectionElem ) {

								if( sectionElem.style.visibility == 'hidden' ) {

									// fade up
									fadeChange = parseInt( itemRef.section.fade );
									if( fadeChange > 0 ) {
											TECHHOUSE.opacityFadeUp( sectionElem, 0, fadeChange );
										}

									// expand down or up
									animationChange = parseInt( itemRef.section.animation );
									if( animationChange > 0 ) {

										if( TECHHOUSE.browser.name == 'MSIE' || TECHHOUSE.browser.name == 'OPERA' ) {
											startTop = sectionElem.offsetTop - TECHHOUSE.getTopBorder( sectionElem );
											}
										else {
											startTop = sectionElem.offsetTop;
											}

										if( TECHHOUSE.browser.name == 'MSIE' && TECHHOUSE.browser.major == 7 ) {
											startTop = sectionElem.offsetTop;
											}

										switch( itemRef.section.position ) {

											case 'UL':
												TECHHOUSE.elementExpandUp(
													sectionElem,
													0,
													itemRef.section.offsetHeightWithoutPaddingAndBorder,
													startTop,
													animationChange
													);
												break;

											case 'UR':
												TECHHOUSE.elementExpandUp(
													sectionElem,
													0,
													itemRef.section.offsetHeightWithoutPaddingAndBorder,
													startTop,
													animationChange
													);
												break;

											case 'DL':
												TECHHOUSE.elementExpandDown(
													sectionElem,
													0,
													itemRef.section.offsetHeightWithoutPaddingAndBorder,
													animationChange
													);
												break;

											case 'DR':
												TECHHOUSE.elementExpandDown(
													sectionElem,
													0,
													itemRef.section.offsetHeightWithoutPaddingAndBorder,
													animationChange
													);
												break;

											case 'LU':
												TECHHOUSE.elementExpandUp(
													sectionElem,
													0,
													itemRef.section.offsetHeightWithoutPaddingAndBorder,
													startTop,
													animationChange
													);
												break;

											case 'LD':
												TECHHOUSE.elementExpandDown(
													sectionElem,
													0,
													itemRef.section.offsetHeightWithoutPaddingAndBorder,
													animationChange
													);
												break;

											case 'RU':
												TECHHOUSE.elementExpandUp(
													sectionElem,
													0,
													itemRef.section.offsetHeightWithoutPaddingAndBorder,
													startTop,
													animationChange
													);
												break;

											case 'RD':
												TECHHOUSE.elementExpandDown(
													sectionElem,
													0,
													itemRef.section.offsetHeightWithoutPaddingAndBorder,
													animationChange
													);
												break;

											}

										}

									sectionElem.style.visibility = 'visible';
									}

								}

							}
						}

					}

				// set section event handlers
				elem = document.getElementById( section.id );
				if( elem ) {

					if( TECHHOUSE.browser.name == 'MSIE' ) {
						elem.attachEvent( 'onmouseover', catchSectionEvent );
						}
					else {
						elem.addEventListener( 'mouseover', catchSectionEvent, false );
						}

					}

				// set item event handlers
				for( item = 0; item < section.items.length; item++ ) {
					elem = document.getElementById( section.items[ item ].id );

					if( elem ) {

						if( TECHHOUSE.browser.name == 'MSIE' ) {
							elem.attachEvent( 'onmouseover', showItemSection );
							}
						else {
							elem.addEventListener( 'mouseover', showItemSection, false );
							}

						}

					// set sub section item events
					that.setItemEventHandlers( section.items[ item ].section );
					}

				}

			}

		}



	// setup
	this.htmlRoot = document.getElementById( parms.id + '_menu' );
	this.menu = {};
	this.menu.id = parms.id;
	this.menu.buttons = [];

	// parse menu html elements into data structure for easy reference
	TECHHOUSE.menu.parse( this.htmlRoot, this.menu.buttons, parms.id );

	/*
	how to address the json structure

	this.menu.buttons[ 0 ].id
	this.menu.buttons[ 0 ].section.id
	this.menu.buttons[ 0 ].section.items[ 0 ].id
	this.menu.buttons[ 0 ].section.items[ 0 ].link.id
	this.menu.buttons[ 0 ].section.items[ 0 ].section.items[ 0 ].link.id
	*/

	// dump parsed data structure to screen
//	if( JSON ) {
//		document.getElementById( 'text1' ).innerHTML += '<pre>' + js_beautify( JSON.stringify( this.menu ) ) + "</pre>";
//		}

	// place sections
	for( button = 0; button < this.menu.buttons.length; button++ ) {

		buttonElem = document.getElementById( this.menu.buttons[ button ].id );

		if( buttonElem ) {
			section = this.menu.buttons[ button ].section;
			parentLeft = parseInt( buttonElem.offsetLeft );
			parentTop = parseInt( buttonElem.offsetTop );
			parentWidth = parseInt( buttonElem.offsetWidth );
			parentHeight = parseInt( buttonElem.offsetHeight );
			level = 0;

			if( section.position ) {
				TECHHOUSE.menu.placeSection( this.menu, section, parentLeft, parentTop, parentWidth, parentHeight, level );
				}

			}

		}

	// set event handlers
	this.setButtonEventHandlers( this.menu );

	}


