/* Copyright (c) 2007 by Convoy Design Ltd. All rights reserved. */
var menus = [];

function addMenu(menu) {
	menus.push(menu);
	return menu;
}

function Menu(id,hoverImages,extraHoverImages,extraHoverImageElement) {

	// Initialise the menu
	var menuEl = document.getElementById(id);


    this.currentMenuItem = null;
    this.owner = null;
    this.widthHasBeenFixed = false;
    this.el = menuEl;

    this.hoverImages = {};
    this.extraHoverImages = {};

    this.preloadedImages = {};
    this.preloadedExtraImages = {};

    this.extraHoverImageElement = null;

    this.floatingExtraHoverImageElement = false;

    if (typeof extraHoverImageElement != 'undefined') {
        if (extraHoverImageElement == 'menuFloatingImage') {
            var el = document.createElement('img');
            el.className = 'menuFloatingImage';
            el.style.display = 'none';
            el.style.position = 'absolute';
            document.body.insertBefore(el,document.body.firstChild);
            this.extraHoverImageElement = el;
            this.floatingExtraHoverImageElement = true;
        } else {
            this.extraHoverImageElement = document.getElementById(extraHoverImageElement);
        }
    }


	// Figure out the orientation of the menu
	if (hasClassName(menuEl,'horizontalMenu')) {
		this.orientation = 'horizontal';
	} else {
		this.orientation = 'vertical';
		if (browser.isIE) {
			var menu = this;
			registerEvent(window,'load',function() {
				menu.fixVerticalForIE(); }
			);
		}
	}

	// Create menu item objects for all the links in the menu
	var items = menuEl.getElementsByTagName('A');
	for (var i=0; i < items.length; i++) {
		items[i].menuItem = new MenuItem(this,items[i]);
		items[i].menuItem.setGlobalParentMenu(this);
	}

	// Now add the menu refrences for each drop down menu item
	for (var i=0; i < items.length; i++) {
		if (hasClassName(items[i].parentNode.parentNode,'dropDown')) {
			items[i].menuItem.setParentMenu(items[i].parentNode.parentNode.dropDownMenuObj);
			items[i].menuItem.hoverClassName = 'dropHoverItem';
			items[i].menuItem.arrowClassName = 'dropArrowItem';
			items[i].menuItem.arrowHoverClassName = 'dropArrowHoverItem';
		} else if (hasClassName(items[i].parentNode.parentNode,'expandDown')) {
			items[i].menuItem.setParentMenu(this);
			items[i].menuItem.hoverClassName = 'expandHoverItem';
			items[i].menuItem.arrowClassName = 'expandArrowItem';
			items[i].menuItem.arrowHoverClassName = 'expandArrowHoverItem';
		} else {
			items[i].menuItem.setParentMenu(this);
		}
	}


	// Preload the hover images
    if (typeof extraHoverImages != 'undefined') this.preloadExtraHoverImages(extraHoverImages);
	if (typeof hoverImages != 'undefined') this.preloadHoverImages(hoverImages);




}
Menu.getEmptyPageURL = function() {
	// Locate the reference to handy.js (which is in the root of the site) and make the path to emptyPage relative to that "onClick/Designs/emptyPage.html";
	if (!this.emptyPageURL) {
		var scripts = document.getElementsByTagName('script');
		for (var i = 0; i < scripts.length; i++) {
			var src = scripts[i].src;
			if (src.indexOf('handy.js') != -1) {
				this.emptyPageURL = src.substr(0, src.indexOf('handy.js')) + "onClick/Designs/emptyPage.html";
				break;
			}
		}
		if (!this.emptyPageURL) {
			this.emptyPageURL = 'javascript:false;';	// May break on HTTPS sites
		}
	}
	return this.emptyPageURL;
};


Menu.prototype.preloadHoverImages = function(images) {

	this.preloadedImages = images;
	for (var i in images) if (images.hasOwnProperty(i)) {
		var tmp = new Image();
		tmp.src = images[i];
		this.hoverImages[i] = tmp;
	}
};

Menu.prototype.preloadExtraHoverImages = function(images) {

    this.preloadedExtraImages = images;
    for (var i in images) if (images.hasOwnProperty(i)) {
        var tmp = new Image();
        tmp.src = images[i];
        this.extraHoverImages[i] = tmp;
    }
};

Menu.prototype.fixVerticalForIE = function() {
	// Fix button widths for IE.
	if (browser.isIE) {
		
		if (!this.widthHasBeenFixed) {

			var menuItems = [];
			for (var i=0; i<this.el.firstChild.childNodes.length; i++) menuItems.push(this.el.firstChild.childNodes[i].firstChild);
	
			if (menuItems.length > 0) {
			
				//alert(menuItems[0].tagName);
			
				// First find the maximum width
				var maxW = 0;
				var maxIndex = 0;
				for (var i=0; i<menuItems.length; i++) {
					var width = menuItems[i].offsetWidth;
					if (width > maxW) {
						maxW = width;
						maxIndex = i;
					}
				}

				if (maxW == 0) {
					menuItems[0].style.width = "5px";
					maxW = menuItems[0].offsetWidth;
					//alert('Error fixing menu '+maxW);

				}
				
				
				
				if (maxW != 0) {
					// Then apply the max width to the first menuItem
					menuItems[maxIndex].style.width = maxW+"px";
					var delta = menuItems[maxIndex].offsetWidth-maxW;
					menuItems[maxIndex].style.width = (maxW-delta)+"px";
					menuItems[0].style.width = (maxW-delta)+"px";

					this.widthHasBeenFixed = true;

					//alert('fixed');
				}

			}
		}
	}

};

function MenuItem(menu,el) {
	this.menu = menu;
	this.el = el;
	this.pageID = this.el.parentNode.id.split('_').pop();
	this.parentMenu = null;
	this.globalParentMenu = null;
	this.dropDownMenu = null;
	this.hasDropDownMenu = false;
	this.hoverClassName = 'hoverItem';
    this.arrowClassName = 'arrowItem';
    this.arrowHoverClassName = 'arrowHoverItem'; 
	var menuItem = this;
	this.el.onmouseout = function(event) {
		if (typeof event == 'undefined') event = window.event;
		menuItem.mouseOut(event);
		// Stop the event bubbling up to parent elements
		event.cancelBubble = true;
		if (event.stopPropagation) event.stopPropagation();
	};

	this.el.onmouseover = function(event) {
		if (typeof event == 'undefined') event = window.event;
		menuItem.mouseOver(event);
		// Stop the event bubbling up to parent elements
		event.cancelBubble = true;
		if (event.stopPropagation) event.stopPropagation();
	};

    this.el.onmousemove = function(event) {
        if (typeof event == 'undefined') event = window.event;
        menuItem.mouseMove(fixEvent(event));
        // Stop the event bubbling up to parent elements
        event.cancelBubble = true;
        if (event.stopPropagation) event.stopPropagation();
    };


	if (this.el.nextSibling != null && hasClassName(this.el.nextSibling,'dropDown')) {
		if (hasClassName(this.el.parentNode.parentNode,'dropDown')) {
			// This is a drop down menu from another drop down, so it should be "relative" orientation
			this.addDropDown(new DropDownMenu(this,this.el.nextSibling,'relative'));
		} else {
			this.addDropDown(new DropDownMenu(this,this.el.nextSibling,this.menu.orientation));
		}

	}

}

MenuItem.prototype.addDropDown = function(dropDownMenu) {

	this.hasDropDownMenu = true;
	this.dropDownMenu = dropDownMenu;
	
};
MenuItem.prototype.setParentMenu = function(parentMenu) {
	this.parentMenu = parentMenu;
	
};
MenuItem.prototype.setGlobalParentMenu = function(globalParentMenu) {
	this.globalParentMenu = globalParentMenu;
};

MenuItem.prototype.showHoverImage = function() {

	// If an image is used in the menu item, ensure the image changes by calling the mouseover event
	var img = this.el.firstChild;
	if (img != null && img.nodeName.toLowerCase() == 'img') {
		if (typeof this.menu.preloadedImages[this.pageID] != 'undefined') {
			if (typeof img.oldsrc == 'undefined') img.oldsrc = img.src;
			img.src = this.menu.preloadedImages[this.pageID];
		}
	}
    if (this.globalParentMenu.extraHoverImageElement !== null) {
        if (typeof this.globalParentMenu.preloadedExtraImages[this.pageID] != 'undefined') {
            if (typeof this.globalParentMenu.extraHoverImageElement.oldsrc == 'undefined') this.globalParentMenu.extraHoverImageElement.oldsrc = this.globalParentMenu.extraHoverImageElement.src;
            this.globalParentMenu.extraHoverImageElement.src = this.globalParentMenu.preloadedExtraImages[this.pageID];
            if (this.globalParentMenu.floatingExtraHoverImageElement) {
                show(this.globalParentMenu.extraHoverImageElement);
            }
        }
    }

};

MenuItem.prototype.removeHoverImage = function() {

	// If an image is used in the menu item, ensure the image changes by calling the mouseover event
	var img = this.el.firstChild;
	if (img != null && img.nodeName.toLowerCase() == 'img') {
		if (typeof img.oldsrc != 'undefined') img.src = img.oldsrc;
	}
    if (this.globalParentMenu.extraHoverImageElement !== null) {
        if (typeof this.globalParentMenu.extraHoverImageElement.oldsrc != 'undefined') this.globalParentMenu.extraHoverImageElement.src = this.globalParentMenu.extraHoverImageElement.oldsrc;
        if (this.globalParentMenu.floatingExtraHoverImageElement) {
            hide(this.globalParentMenu.extraHoverImageElement);
        }

    }

};


MenuItem.prototype.mouseOver = function(event) {

	//alert('mouse over');
	if (this.parentMenu.currentMenuItem != this) {
	
		// Blur the existing current menu item
		if (this.parentMenu.currentMenuItem != null) this.parentMenu.currentMenuItem.blur();

		this.focus();	
		
	} else {

		// If an image is used in the menu item, ensure the image changes by calling the mouseover event
		this.showHoverImage();	
		
	}
	
};

MenuItem.prototype.mouseMove = function(event) {

    if (this.globalParentMenu.floatingExtraHoverImageElement) {
        setElementPosition(this.globalParentMenu.extraHoverImageElement, event.pageX + 10 + 'px', event.pageY + 10 + 'px');
    }

};

MenuItem.prototype.focus = function() {

	// Hide any other drop down menus in other menus
	if (typeof menus == 'undefined') {
		return;
	}
	for (var i=0;i<menus.length;i++) {
		if (menus[i].currentMenuItem != null && this.globalParentMenu != menus[i]) {
			menus[i].currentMenuItem.blur();
		}
	}

	// Catch for page unloading
	if (typeof addClassName == 'undefined') return;

	this.parentMenu.currentMenuItem = this;

	// If an image is used in the menu item, ensure the image changes by calling the mouseover event
	this.showHoverImage();

	// Apply the hoverItem classname to the menu 
	addClassName(this.el,this.hoverClassName); // ,'currentItem'  (if not already having currentItem)
    if (hasClassName(this.el, this.arrowClassName)) {
        addClassName(this.el, this.arrowHoverClassName); // Added for IE 6 as .arrowItem.hoverItem doesn't work
    }
			
	// We need to show the drop down menu if it has one
	if (this.hasDropDownMenu) this.dropDownMenu.show();

};

MenuItem.prototype.mouseOut = function(event) {
	
	// See where the mouse moved to

	// First see if we need to close the whole menu
	var reltg = (event.relatedTarget) ? event.relatedTarget : event.toElement;
	var doBlur = false;
	try {
		// Do inside a try/catch because sometimes it might move outside the current document/window, causing problems
		while (reltg.nodeName != 'BODY') {
			// This means that the mouse moved into another dropdown menu
			if (reltg.nodeName == 'UL' && hasClassName(reltg,'dropDown')) break;

			// This means that the mouse moved either into the menu item, or into the image for the menu item.
			// Doesn't really matter if it was a different menu item because the current menu item will be blurred when
			// the new menu item is focused
			if (reltg.nodeName == 'A' && (hasClassName(reltg,'menuItem') || hasClassName(reltg,'expandItem'))) break;
			reltg = reltg.parentNode;
		}
		// If we managed to reach all the way outside to the body, then we've gone outside the menu
		if (reltg.nodeName == 'BODY') {
            doBlur = true;
        }
	} catch (e) {
		doBlur = true;
	}
	
	if (doBlur) {
		if (this.menu.currentMenuItem != null) this.menu.currentMenuItem.blur();
	} else {
		// Otherwise see if the mouse just moved up into the parent menu
		if (this.parentMenu.owner != null && reltg == this.parentMenu.owner.parentMenu.el) this.blur();
	
	}

};

MenuItem.prototype.blur = function() {

	// Catch for patch unloading
	if (typeof removeClassName == 'undefined') return;

	if (this.parentMenu.currentMenuItem == this) this.parentMenu.currentMenuItem = null;

	removeClassName(this.el, this.hoverClassName);
	removeClassName(this.el, this.arrowHoverClassName); // Added for IE 6 as .arrowItem.hoverItem doesn't work

	// If an image is used in the menu item, ensure the image changes by calling the mouseover event
	this.removeHoverImage();

	// We need to hide the drop down menu if it has one
	if (this.hasDropDownMenu) this.dropDownMenu.hide();

};


function DropDownMenu(owner,el,orientation) {

	// Owner is the menu item object that owns this dropdown menu
	this.owner = owner;
	this.el = el;
	this.el.dropDownMenuObj = this;
	this.orientation = orientation;
	this.currentMenuItem = null;
	this.widthHasBeenFixed = false;
	this.doDropLeft = null;
	this.originalOffsetWidth = null;
	this.originalOffsetHeight = null;

	this.el.style.left = '0px';
	this.el.style.top = '0px';
	hide(this.el);

	if (browser.isIE) {
		var iframeEl = document.createElement("iframe");
		iframeEl.frameBorder = 0;
		//iframeEl.src = "onClick/Designs/emptyPage.html";
		iframeEl.style.display = "none";
		iframeEl.src = Menu.getEmptyPageURL();
		iframeEl.style.position = "absolute";
		iframeEl.style.left = '0px';
		iframeEl.style.top = '0px';
		iframeEl.style.filter = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)";
		this.el.iframeEl = this.el.parentNode.insertBefore(iframeEl, this.el);
	}


}

DropDownMenu.prototype.show = function() {

	var x,y;

	if (this.originalOffsetWidth === null) {
		// Save the original offset width as it gets messed up once we set a negative value for style.left
		show(this.el);
		this.originalOffsetWidth = this.el.offsetWidth;
		this.originalOffsetHeight = this.el.offsetHeight;
		hide(this.el);
	}

	
	// Figure out where the drop down needs to be displayed
	if (this.orientation == 'horizontal') {
		// Horizontal - Display the drop down menu beneath the menu item
		x = getPositionedOffsetLeft(this.owner.el);
		y = getPositionedOffsetTop(this.owner.el) + this.owner.el.offsetHeight - 1;
	} else if (this.orientation == 'vertical') {
		// Vertical - Display the drop down menu to the right of the menu item
		x = getPositionedOffsetLeft(this.owner.el) + this.owner.el.offsetWidth - 1;
		y = getPositionedOffsetTop(this.owner.el);

		// Make sure the top level menu widths are all the right width for IE
		this.owner.menu.fixVerticalForIE();
	} else {
		// Relative - for sub drop downs

		// By default it will pop out to the right of the drop down menu, but sometimes that could mean
		// it goes off the edge of the page.  So.. we'll see if it can fit or not.  If it can't fit, then 
		// pop out to the left!
		

		if (this.doDropLeft === null) {
			// First grab the width of the current frame
			// Source: http://www.quirksmode.org/js/winprop.html
			if (self.innerWidth) {
				frameWidth = self.innerWidth;
			} else if (document.documentElement && document.documentElement.clientWidth) {
				frameWidth = document.documentElement.clientWidth;
			} else if (document.body) {
				frameWidth = document.body.clientWidth;
			} else {
				frameWidth = -1;
			}
			
			if (frameWidth != -1) {
                
				// Now see if the menu is going to end up over the edge
				x = this.owner.el.offsetWidth-1;
				var right = getPositionedOffsetLeft(this.owner.el)+x+this.originalOffsetWidth;
				if (right > frameWidth) {
					// Ok so it doesn't fit on the right, lets see if it fits any better on the left
					var overOnRight = right-frameWidth;
					
					var overOnLeft = 0-(getPositionedOffsetLeft(this.owner.el)-this.originalOffsetWidth);
					
					if (overOnRight > overOnLeft) {
						
						if (browser.isGecko && (typeof browser.geckoRv == 'undefined' || browser.geckoRv < 1.9)) {
							// DISABLE for Firefox less than 3.0 (and old revisions of Gecko).  
							// Causes a weird stepping effect in the width of 
							// the sub menu items if we use a negative relative left 
							// Bug is fixed in gecko 1.9.
							this.doDropLeft = false;
						} else {
							this.doDropLeft = true;
						}
					} else {
						this.doDropLeft = false;
					}
				} else {
					this.doDropLeft = false;
				}
			}
		} 
		if (this.doDropLeft) {
			// Drop down to the left
			x = -this.originalOffsetWidth+1;
		} else {
			// Drop down to the right;
			x = this.owner.el.offsetWidth-1;
		}
    
//		y = getPageOffsetTop(this.owner.el)-getPageOffsetTop(this.owner.el.parentNode.parentNode);
		y = getPositionedOffsetTop(this.owner.el);
		
	}
	
	// Now position the menu
	setElementPosition(this.el,x+'px',y+'px');
	show(this.el);
	this.el.style.visibility = 'visible';
	
	// Apply some fixes for IE 6 - Position the Iframe and fix up widths
	this.applyInternetExplorerFixes();
};

DropDownMenu.prototype.applyInternetExplorerFixes = function() {

	if (browser.isIE) {

		// Position an iframe element in the same location as the drop down menu to prevent Flash 
		// and select elements from appearing on top.
		setElementPosition(this.el.iframeEl,this.el.style.left,this.el.style.top);
//		setElementSize(this.el.iframeEl,this.originalOffsetWidth+'px',this.el.offsetHeight+'px');
		setElementSize(this.el.iframeEl,this.originalOffsetWidth+'px',this.originalOffsetHeight+'px');
		show(this.el.iframeEl);
	  
		// Set a width on the first menu item to make the A elements stretch out to fill up their parent LI element
		if (!this.widthHasBeenFixed) {

			//alert('fixing');
			
			var menuItems = [];
			for (var i=0; i<this.el.childNodes.length; i++) menuItems.push(this.el.childNodes[i].firstChild);
	
			if (menuItems.length > 0) {
				// First find the widest element
				var maxW = 0;
				var maxIndex = 0;
				for (i=0; i<menuItems.length; i++) {
					w = menuItems[i].offsetWidth;
					if (w > maxW) {
						maxW = w;
						maxIndex = i;
					}
				}
			
				// If we couldn't find a proper max width then assign a width and then read the offect width of the first item
				if (maxW == 0) {
				   menuItems[0].style.width = "5px";
				   maxW = menuItems[0].offsetWidth;
				 //  alert('Error fixing menu '+maxW);
				}
			
				if (maxW != 0) {
					menuItems[maxIndex].style.width = maxW+"px";
					delta = menuItems[maxIndex].offsetWidth-maxW;
					menuItems[0].style.width = (maxW-delta)+"px";
					/*
					// setting all menu items to the width causes problems on some menus
					// making the last list item disappear until mousing over the menu ???
					for (i=0; i<menuItems.length; i++) {
						menuItems[i].style.width = (maxW-delta)+"px";
					}
					*/	
					this.widthHasBeenFixed = true;
				}

			 } else {
				// Couldn't fix the width
				//alert('no elements found');
			 }
		}	  
	
	}


};

DropDownMenu.prototype.hide = function() {
	// Blur the current menu item of this drop down
	if (this.currentMenuItem != null) this.currentMenuItem.blur();
	hide(this.el);
	this.el.style.visibility = 'hidden';
	setElementPosition(this.el,'0px','0px');

	// Hide the iframe element in the same location as the drop down menu that prevents Flash 
	// and select elements from appearing on top.
	if (browser.isIE) {
		hide(this.el.iframeEl);
	}
	
};

/****************
Utility functions
****************/
function setElementPosition(el,x,y) {
	el.style.left = x;
	el.style.top = y;
}
function setElementSize(el,w,h) {
	el.style.width = w;
	el.style.height = h;
}
// Return the x coordinate of an element relative to the page.
function getPositionedOffsetLeft(el) {
	el = $(el);
	var x;
	x = el.offsetLeft;
	if (el.offsetParent != null) {
        var pos = getStyle(el.offsetParent, "position");
        if (pos == "" || "absolute,fixed,relative".indexOf(pos) == -1) {
            x += getPositionedOffsetLeft(el.offsetParent);
        }
    }    
	return x;
}

function getPositionedOffsetTop(el) {
	el = $(el);
	var y;
	// Return the x coordinate of an element relative to the page.
	y = el.offsetTop;

	if (el.offsetParent != null) {
        var pos = getStyle(el.offsetParent, "position");        
        if (pos == "" || "absolute,fixed,relative".indexOf(pos) == -1) {
            y += getPositionedOffsetTop(el.offsetParent);
        }
    }
	return y;
}

function getStyle(el,styleProp) {
	var x = $(el);
	if (x.currentStyle)
		var y = x.currentStyle[styleProp];
	else if (window.getComputedStyle)
		var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
	return y;
}

