var sfMenu = {
	//menu flags
	RIGHT: 0x1,
	LEFT: 0x2,
	TOP: 0x4,
	BOTTOM: 0x8,
	INLINE: 0x16,

	GC:{
		map:{
			'idx1':{'top':'GC28','sub':'GC30','back':'GC30'},
			'idx2':{'top':'GC32','sub':'GC34','back':'GC34'}
		},
		toHover:{
			'GC28':'GC29','GC30':'GC31','GC32':'GC33','GC34':'GC35',
			'GC29':'GC29','GC31':'GC31','GC33':'GC33','GC35':'GC35'
		},
		toUnhover:{
			'GC29':'GC28','GC31':'GC30','GC33':'GC32','GC35':'GC34',
			'GC28':'GC28','GC30':'GC30','GC32':'GC32','GC34':'GC34'
		}
	},

	id:'',
	type:'',
	className:'',
	root:null,
	currentItem:null,

	//FUNCTION init - initialise UL node as menu
	//
	//PARAM id - String, id of top-level UL node
	//PARAM type - Bitwise Mask, menu positions/type flags (optional)
	//PARAM className - String,  class name of nested UL's (optional)
	//PARAM root - String, id of element to position menus against
	//
	init: function(id, type, className, root, openAtID) {
		if(id)sfMenu.id = id;else id = sfMenu.id;
		if(type)sfMenu.type = type;else type = sfMenu.type;
		if(className)sfMenu.className = className;else className = sfMenu.className;

		var el = document.getElementById(id);

		//set sfMenu root this way only first call needs to set root node
		//and  subsequent will use the same.
		sfMenu.root = (sfMenu.root)? document.getElementById(root): document.body;
		var className = (className)? className: id;

		//no flags so figure out sub-menu orientation
		if(!type || type &~sfMenu.INLINE) {
			if(!type) {
				type |= (sfMenu.getTop(el) > sfMenu.root.scrollHeight/2)? sfMenu.TOP: sfMenu.BOTTOM;
			}
			if(type & ~(sfMenu.LEFT | sfMenu.RIGHT)) {
				type |= (sfMenu.getLeft(el) > sfMenu.root.clientWidth/2)? sfMenu.LEFT: sfMenu.RIGHT;
			}
		}


		//recursive loop for initialising menu's items and sub-menus
		var exec = function(parentEl, type, index, className, par, openAtID) {
			var el = parentEl.firstChild;
			var index = (index)? index: 0;
			//store menu item for grouping with when we hit a sub-menu
			var a = null;
			//store widest node in submenu
			var dnode = null;
			do {
				//found 'LI' (menu_item) (contains an 'A' or 'SPAN' Node and possibly a 'UL' (sub-menu))
				switch (el.nodeName) {
				case 'LI':
					//process children
					var n = exec(el, type, index, className, par, openAtID);
					//record menu item with maximum width
					if(!dnode || dnode && n.innerHTML.length > dnode.innerHTML.length)
						dnode = n;
					break;

				//found 'DIV' (left or right area), so process it's contents
				case 'DIV':
					exec(el, type, index, className, par, openAtID);
					break;

				//found 'A'  or 'SPAN' (either of these are our event recipients)
				case 'A':
				case 'SPAN':
					//only process if it's in the right place
					if(el.parentNode.nodeName == 'LI') {

						//handle mouse over events if menu is floating
						if(type &~sfMenu.INLINE) {
							el.onmouseover = function() {
								sfMenu.hideEvent++;
								sfMenu.hide(sfMenu.hideEvent, this);
								var sfindex = node.item.getAttribute('sfmenu:index');
								var id = node.item.getAttribute('sfmenu:id');
								var nlist = [document.getElementById(sfindex+id), document.getElementById(sfindex+'Left'+id), document.getElementById(sfindex+'Right'+id)];
								for(var i = 0, n = nlist.length; i < n; i++) {
									var cls = nlist[i].getAttribute('sf:object');
									nlist[i].className = sfMenu.GC.toHover[nlist[i].className.split(' ')[0]]+' '+cls.replace('MouseOver', '')+'MouseOver';
								}
							}
							el.onmouseout = function() {
								if(!this.sfMenu) {
									var sfindex = node.item.getAttribute('sfmenu:index');
									var id = node.item.getAttribute('sfmenu:id');
									var nlist = [document.getElementById(sfindex+id), document.getElementById(sfindex+'Left'+id), document.getElementById(sfindex+'Right'+id)];
									for(var i = 0, n = nlist.length; i < n; i++) {
										var cls = nlist[i].getAttribute('sf:object');
										nlist[i].className = sfMenu.GC.toUnhover[nlist[i].className.split(' ')[0]]+' '+nlist[i].className.replace(cls+'MouseOver', cls);
									}
								}
								sfMenu.hideTimer();
							}
						}
						//menu is tree
						else {
							el.onmouseover = function() {
								var sfindex = this.getAttribute('sfmenu:index');
								var id = this.getAttribute('sfmenu:id');
								var nlist = [document.getElementById(sfindex+id), document.getElementById(sfindex+'Left'+id), document.getElementById(sfindex+'Right'+id)];
								for(var i = 0, n = nlist.length; i < n; i++) {
									var cls = nlist[i].getAttribute('sf:object'), classes = nlist[i].className.split(' '), clsGC = sfMenu.GC.toHover[classes[0]];
									delete classes[0];
									classes = classes.join(' ');
									nlist[i].className = clsGC+classes.replace('('+cls+')(MouseOver)?', '$1MouseOver');
								}
								return false;
							}
							el.onmouseout = function() {
								var sfindex = this.getAttribute('sfmenu:index');
								var id = this.getAttribute('sfmenu:id');
								var nlist = [document.getElementById(sfindex+id), document.getElementById(sfindex+'Left'+id), document.getElementById(sfindex+'Right'+id)];
								for(var i = 0, n = nlist.length; i < n; i++) {
									var cls = nlist[i].getAttribute('sf:object'), classes = nlist[i].className.split(' '), clsGC = sfMenu.GC.toUnhover[classes[0]];
									delete classes[0];
									classes = classes.join(' ');
									nlist[i].className = clsGC+classes.replace(cls+'MouseOver', cls);
								}
								return false;
							}
						}

						//'A' only contains textNodes but 'SPAN' contains anything
						if(el.nodeName != 'A')
							exec(el, type, index, className, par, openAtID);

						//store 'A' for grouping with subsequent 'UL'
						a = el;
						a.parentItem = par;
					}

					// Don't show the +- icons if there aren't any children.
					if(el.nodeName == 'SPAN') {
						if((type & sfMenu.INLINE) == sfMenu.INLINE) {
							// For Firefox...
							if (el.nextSibling && el.nextSibling.nodeName == '#text'
							&& (!el.nextSibling.nextSibling || el.nextSibling.nextSibling.nodeName == 'SPAN')) {
								el.childNodes[1].style.backgroundImage = 'none';
							}
							// For IE...
							else if(!el.nextSibling || el.nextSibling.nodeName == 'SPAN') {
								el.childNodes[0].style.backgroundImage = 'none';
							}

							// Make the specified item (and all its parents) visible
							if(openAtID && el.getAttribute('sfmenu:id') == openAtID) {
								sfMenu.currentItem = el;
							}
						}
					}

					break;

				//found 'UL' this means the 'A' or 'SPAN' we just passed has a sub-menu
				case 'UL':
					//assign this 'sub-menu' to the 'A' or 'SPAN'
					a.sfMenu = el;

					//menu is floating type
					if(type &~sfMenu.INLINE) {

						//top-level menu will ignore LEFT and RIGHT if TOP or BOTTOM are set
						if(index == 0) {
							if(type & (sfMenu.TOP | sfMenu.BOTTOM))
								el.style.width = a.offsetWidth + 'px';
							a.sfMenuRoot = true
							a.sfMenuType = (type &(sfMenu.TOP | sfMenu.BOTTOM))? type & ~(sfMenu.LEFT | sfMenu.RIGHT): type;

						//sub-menus use all flags
						} else
							a.sfMenuType = type;

						//give menu item ('LI' for floating) class name, add mouseover events to both menu and menu item
						//current shopfactory is limited, no interface to edit styles for menu items with children
						//a.parentNode.className = 'menuItem';
						a.onmouseover = sfMenu.show;
						el.onmouseover = function() { sfMenu.hideEvent++ };
						el.onmouseout = sfMenu.hideTimer;

					//menu is tree
					} else {
						//give menu item ('A' for tree) class name, add click event to menu item
						//current shopfactory is limited, no interface to edit styles for menu items with children
						a.sfMenuType = type;
						if(tf.isIE6){
							a.style.position = 'relative';
							a.style.display = 'block';
						}
						a.onclick = sfMenu.inlineShow;
						a.onmouseover = function() {
							var sfindex = this.getAttribute('sfmenu:index');
							var id = this.getAttribute('sfmenu:id');
							var nlist = [document.getElementById(sfindex+id), document.getElementById(sfindex+'Left'+id), document.getElementById(sfindex+'Right'+id)];
							for(var i = 0, n = nlist.length; i < n; i++) {
								var cls = nlist[i].getAttribute('sf:object'), classes = nlist[i].className.split(' '), clsGC = sfMenu.GC.toHover[classes[0]];
								delete classes[0];
								classes = classes.join(' ');
								nlist[i].className = clsGC+classes.replace('('+cls+')(MouseOver)?', '$1MouseOver');
							}
							return false;
						}
						a.onmouseout = function() {
							var sfindex = this.getAttribute('sfmenu:index');
							var id = this.getAttribute('sfmenu:id');
							var nlist = [document.getElementById(sfindex+id), document.getElementById(sfindex+'Left'+id), document.getElementById(sfindex+'Right'+id)];
							for(var i = 0, n = nlist.length; i < n; i++) {
								var cls = nlist[i].getAttribute('sf:object'), classes = nlist[i].className.split(' '), clsGC = sfMenu.GC.toUnhover[classes[0]];
								delete classes[0];
								classes = classes.join(' ');
								nlist[i].className = clsGC+classes.replace(cls+'MouseOver', cls);
							}
							return false;
						}
					}

					//set sub-menu classname, hide it if it isn't already hidden, and set z-index
					el.className = className;
					el.style.display = 'none';
					el.style.zIndex = index+1;

					//clear 'A' | 'SPAN' store, set sub-menus widest node
					par = a;
					a = null;
					el.sfNode = exec(el, type, index+1, className, par, openAtID);

					//if floating menu then we move sub-menus ('UL') to document.body
					if(type &~sfMenu.INLINE)
						document.body.appendChild(el);

					break;
				}
			} while((el = el.nextSibling) != null);
			return dnode;
		};


		//start the processing
		el.style.display = 'block';
		exec(el, type, 0, className, null, openAtID);

		// Make the specified item (and all its parents) visible
		if(openAtID && sfMenu.currentItem) {
			var elOpen = sfMenu.currentItem.parentItem;
			if (elOpen)
			{
				do
				{
					var sfindex = elOpen.getAttribute('sfmenu:index');
					var id = elOpen.getAttribute('sfmenu:id');
					var left = document.getElementById(sfindex+'Left'+id);
					left.className = left.className.replace(' opened', '')+' opened';
					elOpen.sfMenu.style.visibility = 'visible';
					elOpen.sfMenu.style.display = 'block';
				} while ((elOpen = elOpen.parentItem) != null);
			}

			if (sfMenu.currentItem.sfMenu) sfMenu.inlineShow(null, -1, -1, sfMenu.currentItem);
		}
	},

	//returns the node that holds menu items text (incase of nested )
	getTextNode: function(el) {
		var el = el.firstChild;
		do {
			if(el.nodeName == 'A') break;
			else if(el.nodeName == 'DIV' || el.nodeName == 'SPAN') {
				el = sfMenu.getTextNode(el);
				break;
			}
		} while((el = el.nextSibling) != null);
		return el;
	},

	//position functions
	getLeft: function(el) {
		var left = 0;
		do left += el.offsetLeft;
		while((el = el.offsetParent) != null);
		return left;
	},
	getTop: function(el) {
		var top = 0;
		do top += el.offsetTop;
		while((el = el.offsetParent) != null);
		return top;
	},

	//current menu position stack
	current: new Array(),

	//event id so for hideTimer
	hideEvent: 0,

	//calls hide after a set time, so users don't get frustrated when they move
	//the cursor away from the menus for a brief second and have them disappear
	hideTimer: function() {
		window.setTimeout('sfMenu.hide('+(++sfMenu.hideEvent)+')', 500);
	},


	//the show function for inline menu types
	inlineShow: function(caller, x, y, _el) {
		var el = _el || caller || this;

		if (el.currentTarget) el = el.currentTarget;
		if (el.href) location = el.href;

		//sub-menu is visible so hide
		if(el.sfMenu.style.display == 'block') {
			var sfindex = el.getAttribute('sfmenu:index');
			var id = el.getAttribute('sfmenu:id');
			var left = document.getElementById(sfindex+'Left'+id);
			left.className = left.className.replace(' opened', '');
			el.sfMenu.style.display = 'none';
			if(el.onmouseout)el.onmouseout();
		}
		//sub-menu is hidden so display
		else {
			var sfindex = el.getAttribute('sfmenu:index');
			var id = el.getAttribute('sfmenu:id');
			var left = document.getElementById(sfindex+'Left'+id);
			left.className = left.className.replace(' opened', '')+' opened';
			el.sfMenu.style.visibility = 'visible';
			el.sfMenu.style.display = 'block';
			if(el.onmouseout)el.onmouseout();
		}

		if(typeof(equalHeight) != 'undefined')equalHeight();
		if(tf.utils && tf.utils.applyms)tf.utils.applyms();

		return true;
	},

	//the show function for floating menus
	show: function(e) {

		//set hideEvent so any hide are cancelled
		sfMenu.hideEvent++;
		//now hide all menus, except this ones, that are below this item
		sfMenu.hide(sfMenu.hideEvent, this);

		//hilight menu item
		sfMenu.current.push({item: this, menu: this.sfMenu});
		this.className = 'active';

		//get menu item, top/left position of menu item and document width/hieght
		var d = this.parentNode;
		var left = sfMenu.getLeft(d);
		var top = sfMenu.getTop(this);
		var docHeight = sfMenu.root.clientHeight + document.body.scrollTop;
		var docWidth = sfMenu.root.clientWidth + document.body.scrollLeft;

		//work-around when css attr display: none set clientWidth is 0
		if(this.sfMenu.style.display == 'none')
			this.sfMenu.style.visibility = 'hidden';

		//display sub-menu (still not visible though)
		this.sfMenu.style.display = 'block';


		//check if we dont have the real width of menu item (for overflow issues)
		if(!this.sfMenu.sfRealWidth) {

			//get textnode of widest menu item and set all menu items of sub-menu to it's width
			var n = sfMenu.getTextNode(this.sfMenu.sfNode);
			if(n && n.offsetWidth < n.scrollWidth) {
				var nWidth = n.style.width = n.scrollWidth + 'px';
				var sWidth = this.sfMenu.sfNode.style.width = (this.sfMenu.sfNode.offsetWidth < this.sfMenu.sfNode.scrollWidth)?
					this.sfMenu.sfNode.scrollWidth + 'px': this.sfMenu.sfNode.offsetWidth + 'px';
				for(var i = 0; i < this.sfMenu.childNodes.length; i++) {
					if(this.sfMenu.childNodes[i].nodeName == 'LI') {
						sfMenu.getTextNode(this.sfMenu.childNodes[i]).style.width = nWidth;
						this.sfMenu.childNodes[i].style.width = sWidth;
					}
				}
			}
			this.sfMenu.sfRealWidth = true;
		}


		//check orientation flags and set position accordingly
		if(this.sfMenuType & sfMenu.RIGHT) {
			left += d.offsetWidth;
		}
		else if(this.sfMenuType & sfMenu.LEFT) {
			left -= this.sfMenu.offsetWidth;
		}
		if(this.sfMenuType & sfMenu.TOP) {
			top -= (this.sfMenuRoot)? this.sfMenu.offsetHeight: this.sfMenu.offsetHeight - this.offsetHeight;
		}
		else if(this.sfMenuType & sfMenu.BOTTOM) {
			top += (this.sfMenuRoot)? d.offsetHeight: 0;
		}

		//beyond page boundaries, so adjust accordingly
		if(top + this.sfMenu.offsetHeight > docHeight)
			top = docHeight - this.sfMenu.offsetHeight;

		if(left + this.sfMenu.offsetWidth > docWidth) {
			var nleft = sfMenu.getLeft(d) - this.sfMenu.offsetWidth;
			left = (nleft >= 0)? nleft: left;
		}

		if(this.sfMenuType & sfMenu.LEFT && left - this.sfMenu.offsetWidth < 0)
			left = sfMenu.getLeft(d) + d.offsetWidth;

		if(this.sfMenuType & sfMenu.TOP && top - this.sfMenu.offsetHeight < 0)
			top = sfMenu.getTop(d) + d.offsetWidth;


		//put the sub-menu where it should be and make it visible
		this.sfMenu.style.left = left + 'px';
		this.sfMenu.style.top = top + 'px';
		this.sfMenu.style.visibility = 'visible';
	},


	//the hide function for floating menu
	// if sfMenu.hideEvent = n hide all sub-menus (below d if set)
	hide: function(n, d) {
		if(sfMenu.hideEvent == n) {
			var p, c;
			if(d) {
				p = d.parentNode.parentNode;
				c = d.sfMenu;
			} else
				sfMenu.hideEvent = 0;
			for(var i = sfMenu.current.length-1; i >= 0; i--) {
				var node = sfMenu.current[i];
				if(node.menu != p && node.menu != c) {
					node.item.style.display = 'none';
					var index = node.item.getAttribute('sfmenu:index');
					var id = node.item.getAttribute('sfmenu:id');
					var nlist = [document.getElementById(index+id), document.getElementById(index+'Left'+id), document.getElementById(index+'Right'+id)];
					for(var i = 0, n = nlist.length; i < n; i++) {
						var cls = nlist[i].getAttribute('sf:object');
						nlist[i].className = nlist[i].className.replace(cls+'MouseOver', cls);
					}
					sfMenu.current.pop();
				} else
					break;
			}
		}
	}
}

// $Revision: 3942 $
// $HeadURL: svn://3d3-p432/ShopFactory/branches/V8_10/bin/Templates/Website/shared_files/sfmenu.js $
