﻿function menu(_elmMenuFrame, _arySubMenues, _sBaseURL, _option)
{
	this.elmMenuFrame		= _elmMenuFrame;
	this.arySubMenues		= _arySubMenues;
	this.arySubMenuesHTML	= new Array();
	this.elmMenuFrameStyle	= null;
	this.sBaseURL			= _sBaseURL;

	if (this.elmMenuFrame.style){ this.elmMenuFrameStyle = _elmMenuFrame.style; }
	else						{ this.elmMenuFrameStyle = _elmMenuFrame; }

	opt = arguments[3] || [];
	this.options = Object.extend({
		delay: !(opt.showOn && opt.showOn == "click") ? 0.12 : false,
		duration: 0.3,
		effect: false,
		hideAfter: false,
		hideOn: "mouseleave",
		hook: opt.hook,
		offset: opt.hook ? {
			x: 0,
			y: 0
		} : {
			x: 16,
			y: 16
		},
		fixed: opt.hook ? true : false,
		showOn: "mousemove",
		target: this.element,
		title: false,
		viewport: opt.hook ? false : true,
		zIndex: 100
	}, opt);

	if (this.fixIE) {
		this.iframeShim = Element.extend(document.createElement("iframe"));
		Element.writeAttribute(this.iframeShim, {
			className: "iframeShim",
			src: "javascript:false;",
			frameBorder: 0
		}).setStyle({
			display: "none",
			zIndex: this.options.zIndex - 1,
			opacity: 0
		});
		Element.insert($(document.body), this.iframeShim);
	}
}
menu.prototype.buildSubMenu = function(_aryItems)
{
	if (_aryItems.constructor != Array) { return null; }
	var sMenu		= "";
	var sStyle		= "MenuView";
	var i, len		= _aryItems.length;
	for(i=0; i<len; i++)
	{
		if (_aryItems[i][0] == "-----")
		{
			sStyle = "MenuWithSeparater";
		}
		else
		{
			sMenu
					+=	"<a class='MenuItem' href='" + _aryItems[i][1] + "'>"+ _aryItems[i][0] +"</a>"
					;
			sStyle = "MenuView";
		}
	}
	return sMenu;
}
menu.prototype.showMenu = function(_event, _sMenuName)
{
	if(!document.getElementById) return true;

	var eSource = $(Event.element(_event));
	var aryItems = this.arySubMenues[_sMenuName];
	if (aryItems == null) { return false; }
	if (aryItems.constructor != Array)
	{
		window.location.replace(this.sBaseURL + aryItems);
		return false;
	}
	if(!this.arySubMenuesHTML[_sMenuName])
	{
		this.arySubMenuesHTML[_sMenuName] = this.buildSubMenu(aryItems);
	}
	if (this.elmMenuFrame.currentMenu != _sMenuName)
	{
		this.elmMenuFrame.innerHTML = this.arySubMenuesHTML[_sMenuName];
	}

	if (this.options.hook) {
		var properties = Object.extend({
				offset: this.options.offset
			},
			{
				element: this.options.hook.item,
				target: this.options.hook.target
			}
		);
		this.hook(this.elmMenuFrame, eSource, properties);
		if (this.fixIE) {
			this.hook(this.iframeShim, eSource, properties)
		}
	} else {
		var posTargetOffset = Element.cumulativeOffset(eSource),
			sizeMenu = this.getHiddenDimensions(this.elmMenuFrame),
			oStylePos = {
				left: ((this.options.fixed) ? posTargetOffset[0] : Event.pointerX(_event)) + this.options.offset.x,
				top: ((this.options.fixed) ? posTargetOffset[1] : Event.pointerY(_event)) + this.options.offset.y
			};
		// Make sure that the tip will show in the viewport.
		if (!this.options.fixed && this.options.viewport) {
			var posViewportScrollOffset = document.viewport.getScrollOffsets(),
				sizeViewport = document.viewport.getDimensions(),
				oSizePropertyName = {
					left: "width",
					top: "height"
				};
			for (var sName in oSizePropertyName) {
				if ((oStylePos[sName] + sizeMenu[oSizePropertyName[sName]] - posViewportScrollOffset[sName]) > sizeViewport[oSizePropertyName[sName]]) {
					oStylePos[sName] = oStylePos[sName] - sizeMenu[oSizePropertyName[sName]] - 2 * this.options.offset[sName == "top" ? "x" : "y"]
				}
			}
		}
		oStylePos = {
			left: oStylePos.left + "px",
			top: oStylePos.top + "px"
		};
		this.elmMenuFrame.setStyle(oStylePos);
		if (this.fixIE) {
			this.iframeShim.setStyle(oStylePos)
		}
	}
	this.elmMenuFrame.show();

	return cancelEvent(_event);
}

menu.prototype.hook = function (_e, _eTarget) {
	_e = $(_e),
	_eTarget = $(_eTarget);
	var option = Object.extend({
			element: "bottomLeft",
			target: "topLeft",
			offset: {
				x: 0,
				y: 0
			}
		}, arguments[2] || {});
	var posTargetOffset = Element.cumulativeOffset(_eTarget);
	posTargetOffset.left += option.offset.x;
	posTargetOffset.top += option.offset.y;
	var posTargetScrollOffset = Element.cumulativeScrollOffset(_eTarget),
		posViewportScrollOffset = document.viewport.getScrollOffsets();
	posTargetOffset.left += (-1 * (posTargetScrollOffset[0] - posViewportScrollOffset[0]));
	posTargetOffset.top += (-1 * (posTargetScrollOffset[1] - posViewportScrollOffset[1]));

	var oElemSizes = {
			element: Element.getDimensions(_e),
			target: Element.getDimensions(_eTarget)
		},
		oElemPoss = {
			element: Object.clone(posTargetOffset),
			target: Object.clone(posTargetOffset)
		};
	for (var sElementOrTarget in oElemPoss) {
		switch (option[sElementOrTarget]) {
		case "topRight":
			oElemPoss[sElementOrTarget][0] += oElemSizes[sElementOrTarget].width;
			break;
		case "topMiddle":
			oElemPoss[sElementOrTarget][0] += (oElemSizes[sElementOrTarget].width / 2);
			break;
		case "rightMiddle":
			oElemPoss[sElementOrTarget][0] += oElemSizes[sElementOrTarget].width;
			oElemPoss[sElementOrTarget][1] += (oElemSizes[sElementOrTarget].height / 2);
			break;
		case "bottomLeft":
			oElemPoss[sElementOrTarget][1] += oElemSizes[sElementOrTarget].height;
			break;
		case "bottomRight":
			oElemPoss[sElementOrTarget][0] += oElemSizes[sElementOrTarget].width;
			oElemPoss[sElementOrTarget][1] += oElemSizes[sElementOrTarget].height;
			break;
		case "bottomMiddle":
			oElemPoss[sElementOrTarget][0] += (oElemSizes[sElementOrTarget].width / 2);
			oElemPoss[sElementOrTarget][1] += oElemSizes[sElementOrTarget].height;
			break;
		case "leftMiddle":
			oElemPoss[sElementOrTarget][1] += (oElemSizes[sElementOrTarget].height / 2);
			break
		}
	}
	posTargetOffset.left += -1 * (oElemPoss.element[0] - oElemPoss.target[0]);
	posTargetOffset.top += -1 * (oElemPoss.element[1] - oElemPoss.target[1]);
	_e.setStyle({
		left: posTargetOffset.left + "px",
		top: posTargetOffset.top + "px"
	});
};
menu.prototype.getHiddenDimensions = function(_elem) {
	_elem = $(_elem);
	var oAncestors = Element.ancestors(_elem),
	aryChengedElem = [],
	aryOriginalStyle = [];
	oAncestors.push(_elem);
	oAncestors.each(function (_e) {
		if (_e != _elem && _e.visible()) {
			return
		}
		aryChengedElem.push(_e);
		aryOriginalStyle.push({
			display: _e.getStyle("display"),
			position: _e.getStyle("position"),
			visibility: _e.getStyle("visibility")
		});
		_e.setStyle({
			display: "block",
			position: "absolute",
			visibility: "visible"
		})
	});
	var size = {
		width: _elem.clientWidth,
		height: _elem.clientHeight
	};
	aryChengedElem.each(function (_e, _i) {
		_e.setStyle(aryOriginalStyle[_i])
	});
	return size;
};

menu.prototype.hideMenu = function()
{
	this.elmMenuFrame.hide();
	this.FadeOutMenu();
}

menu.prototype.FadeInMenu = function()
{
	if (this.elmMenuFrameStyle.filter) { this.elmMenuFrameStyle.filter = ""; }
}
menu.prototype.fixIE = (function (_sNavi) {
	var blIE = new RegExp("MSIE ([\\d.]+)").exec(_sNavi);
	return blIE ? (parseFloat(blIE[1]) < 7) : false
})(navigator.userAgent);

menu.prototype.FadeOutMenu = function()
{
	if (this.elmMenuFrameStyle.filter && this.elmMenuFrameStyle.filter != "alpha(opacity=85)") { this.elmMenuFrameStyle.filter = "alpha(opacity=85)"; }
}

