// remove styles which hide menu - primitive, need rewriting to some more logical way
EventUtil.addEventHandler(window, "load", killStyles);
function killStyles() {
	if(document.styleSheets[0].cssRules) {
		document.styleSheets[0].deleteRule(0);
	} else {
		document.styleSheets[0].removeRule(0);	
	}
}

/******************************************************
author: DAroo, darooo7@interia.pl
do not remove this comment! (nie usuwac tego komentarza!)
******************************************************/


// configuration
var time_1 = 30; // unrolling time
var time_2 = 30; // delay between unrolling and appearing
var time_3 = 10; //delay between rolling and disappearing
var time_4 = 80; // rolling time
var time_5 = 20; // appearing / disappearing time
var bDelayOpening = false; // delay while menu opening
var bDelayClosing = false; // delay while menu closing

var sMenuID = "menu_1"; // ID of the main <ul/> menu tag
var sVisible = "visible"; // class name for <li/> tags opened by default

var bVisible = true; // soft menu rolling
var iOpacity = 1; // 1 - soft menu rolling and opacity changing; 2 - immediately rolling with soft opacity changing; 3 - immediately apeparing / disappearing
var bAutoClosing = true; // close utomaticly opened menus

var bOnClick = true; // animate menu after click - true or hover - false (hover effect isn't implemented yet!)
// end of configuration

var itime_0;
var aGlobalInnerLIs = [[]];
var aHidden = [];
var aMenuVisible = [];
var aMenuOpacity = [];
var aOpacity =[[]];
var aOpenedMenus = [];
var bIsExcluded = 1;

// universal events handler
var EventUtil = new Object;
EventUtil.addEventHandler = function (oTarget, sEventType, fnHandler) {
	if (oTarget.addEventListener) {
		oTarget.addEventListener(sEventType, fnHandler, false);
	} else if (oTarget.attachEvent) {
		oTarget.attachEvent("on" + sEventType, fnHandler);
	} else {
		oTarget["on" + sEventType] = fnHandler;
	}
};

// start script after full site load
EventUtil.addEventHandler(window, "load", menu_init);

// script starts here
function menu_init(){
	var oMainUL = document.getElementById(sMenuID);
	var aMainLIs = document.getElementsByTagName("li");
	
	lookForTheSpans(aMainLIs);	
}

function lookForTheSpans(aMainLIs) {
	for(var i = 0; i < aMainLIs.length; i++) {
		// check if <li/> contain a <span/> tag
		var oSpan = getSpan(aMainLIs[i]);
		if(oSpan){
			// if contain get all <li/> tags in the sibling <ul/> tag
			var aInnerLIs = getInnerLIs(oSpan);
			// hide these <li/> tags
			hideLIs(aInnerLIs);
			// make visible <li/> tags which have class = sVisible
			makeVisibleWithClass(oSpan, aInnerLIs);
			// add event to the <span/> tag
			if(bOnClick)
				oSpan.onclick = function showHideMenu() { addEventToTheSpan(this); };
			else { ;
				// place for hover event					
			}
		}
	}
}

function getSpan(oLI) {
	// universal metod to get first <li/> child Node, in IE it's always first child but in ff/opera it might be first or second child
	if(oLI.childNodes[0] && oLI.childNodes[0].nodeName == "SPAN")
		var oSpan = oLI.childNodes[0];
	else if (oLI.childNodes[1] && oLI.childNodes[1].nodeName == "SPAN")
		var oSpan = oLI.childNodes[1];
	else var oSpan = 0;
	return oSpan;
}

function getInnerLIs(oSpan){
	//get sibling <ul/> tag
	var oUL = getUL(oSpan);	
	var aInnerLIs = [];
	if(oUL.childNodes[0] && oUL.childNodes[0].nodeName == "LI")
		aInnerLIs[0] = oUL.childNodes[0];
	else aInnerLIs[0] = oUL.childNodes[1];

	var j = 0;
	// get all <li/> tags inside the <ul/>, in ff/opera ignore the text nodes (spaces and enters between the tags)
	for(var i = 0; oUL.childNodes[i] || oUL.childNodes[i+1]; i++){
		if(oUL.childNodes[j] && oUL.childNodes[j].nodeName == "LI") {
				aInnerLIs[i] = oUL.childNodes[j];
				j = j + 1;
			}
		else if(oUL.childNodes[j+1] && oUL.childNodes[j+1].nodeName == "LI") {
				aInnerLIs[i] = oUL.childNodes[j+1];
				j = j + 2;
			}
	}
	return aInnerLIs;
}

function getUL(oSpan){
	// universal metod to get sibling <ul/> , in ff/opera ignore text node
	if(oSpan.nextSibling && oSpan.nextSibling.nodeName == "UL")
		return oSpan.nextSibling;
	else if(oSpan.nextSibling.nextSibling && oSpan.nextSibling.nextSibling.nodeName == "UL")
		return oSpan.nextSibling.nextSibling;
}

function hideLIs(aInnerLIs){
	// hide all </li> in an array
	for(var j = 0; j < aInnerLIs.length; j++) {
		aInnerLIs[j].style.display = "none";
		// version for ff / opera
		aInnerLIs[j].style.opacity = 0;
		// version for IE - without width it doesn't work
		aInnerLIs[j].style.width = "100%";
		aInnerLIs[j].style.filter = "alpha(opacity=0)";
	}
}

function makeVisibleWithClass(oSpan, aInnerLIs) {
	// make visible <li/> nodes  which have class = sVisible
	var oParentLI = oSpan.parentNode;
	if(oParentLI.className && oParentLI.className == sVisible) {
		// add <li/> tags to the global array to make them available for functions in setTimeout()
		var iArrayIndex = addToGlobalArray(aInnerLIs);
		aOpenedMenus.push(iArrayIndex);
		for(var j = 0; j < aGlobalInnerLIs[iArrayIndex].length; j++) {
			aGlobalInnerLIs[iArrayIndex][j].style.display = "block";
			// version for ff / opera
			aGlobalInnerLIs[iArrayIndex][j].style.opacity = 1;
			// version for IE
			aGlobalInnerLIs[iArrayIndex][j].style.filter = "alpha(opacity=100)";
		}
		// mark menu as opened
		aHidden[iArrayIndex] = 0;
	}
}

function addEventToTheSpan(oSpan){
	// get all <li/>
	aInnerLIs = getInnerLIs(oSpan);
	// add them to the global array to make them available for functions in setTimeout()
	var iArrayIndex = addToGlobalArray(aInnerLIs);
	// if menu was never used, check if it's opened or closed
	if(typeof aHidden[iArrayIndex] == "undefined") 
		aHidden[iArrayIndex] = Boolean(aInnerLIs[0].style.display == "none");
	// show time ^^
	animateMenu(iArrayIndex);
}

function addToGlobalArray(aInnerLIs){
	// functions inside setTime(out) don't accept objects as a prameters, add objects to the global array to make available them for these functions
	for(var i = 0; i < aGlobalInnerLIs.length; i++){
		// if <li/> tags are already in a global array return their index
		if(aGlobalInnerLIs[i][0] == aInnerLIs[0])
			return i;
	}
	// if <li/> tags aren't in a global array
	aGlobalInnerLIs.push(aInnerLIs);
	return aGlobalInnerLIs.length - 1;
}

function animateMenu(iArrayIndex){
	// kill old , not finished menu animations to prevent weird behaviour
	killOldMenuAnimation(aMenuVisible);
	killOldMenuAnimation(aMenuOpacity);
	killOldMenuOpacity(aOpacity);
	// when auto-closing option is enabled and it's not a closeOpenedMenus() function, close useless, opened menus
	if(bAutoClosing && bIsExcluded) closeOpenedMenus(iArrayIndex);
	// when menu isn't opened
	if(aHidden[iArrayIndex]){
		// add menu to the opened menus array
		aOpenedMenus.push(iArrayIndex);
		if(bDelayOpening)
			var iDelay = aGlobalInnerLIs[iArrayIndex].length*time_1;
		else
			var iDelay = 0;
		for(var j = 0; j < aGlobalInnerLIs[iArrayIndex].length; j++) {
			if(bVisible)
				// one by one menu visible changing 
				aMenuVisible[j] = setTimeout('visibleControl('+iArrayIndex+','+j+','+aHidden[iArrayIndex]+')', time_1*j);
			else
				// make visible <li/>
				visibleControl(iArrayIndex, j, aHidden[iArrayIndex]);
			if(iOpacity == 1) 
				// one by one menu transparency changing
				aMenuOpacity[j] = setTimeout('opacityControl('+iArrayIndex+','+j+','+aHidden[iArrayIndex]+')', iDelay + time_2*j);
			else 
				// make not transparented <li/>
				opacityControl(iArrayIndex, j, aHidden[iArrayIndex]);
		}
		// mark menu as opened
		aHidden[iArrayIndex] = 0;
	} else {
		// remove menu from the opened menus array
		deleteOpenedMenu(iArrayIndex);
		if(bDelayClosing)
			var iDelay = aGlobalInnerLIs[iArrayIndex].length*time_3+20*time_5;
		else
			var iDelay = 0;
		for(var j = aGlobalInnerLIs[iArrayIndex].length - 1; j >= 0; j--) {	
			var i = aGlobalInnerLIs[iArrayIndex].length - j - 1;
			if(iOpacity == 1) 
				// one by one menu transparency changing 
				aMenuOpacity[i] = setTimeout('opacityControl('+iArrayIndex+','+j+','+aHidden[iArrayIndex]+')', time_3*i);
			else 
				// make full transparented </li>
				opacityControl(iArrayIndex, j, aHidden[iArrayIndex]);
			if(bVisible)
				// one by one menu visible changing 
				aMenuVisible[i] = setTimeout('visibleControl('+iArrayIndex+','+j+','+aHidden[iArrayIndex]+')', iDelay + time_4*i);
			else
				// make not visible </li>
				visibleControl(iArrayIndex, j, aHidden[iArrayIndex]);
		}
		// mark menu as closed
		aHidden[iArrayIndex] = 1;
	}		
}

function killOldMenuAnimation(aArrayWithEvents) {
	do {
		// remove setTimeout()
		clearTimeout(aArrayWithEvents[0]);
		// remove from array
		aArrayWithEvents.shift();
	} while (aArrayWithEvents.length);
}

function killOldMenuOpacity(aOpacity) {
	for(var i = 0; i < aOpacity.length; i++) {
		do {
			// remove setTimeout()
			clearTimeout(aOpacity[i][0]);
			// remove from array
			aOpacity[i].shift();
		} while (aOpacity[i].length);
	}
}

function closeOpenedMenus(iArrayIndex) {
	var aExcludedNodes = [[]];
	// get menus which shouldn't be closed - parent nodes of the iArrayIndex node
	aExcludedNodes = getExcludedNodes(iArrayIndex);
	for(var i = aOpenedMenus.length - 1; i >= 0; i--) {
		bIsExcluded = 0;
		for(var j = 0; j < aExcludedNodes.length; j++) {
			// check if opened menu should be closed
			if(aGlobalInnerLIs[aOpenedMenus[i]][0] == aExcludedNodes[j][0]) {
				bIsExcluded = 1;
				break;
			} 
		}
		// when menu isn't excluded
		if(!bIsExcluded) {
			// to prevent endless recurrence
			aMenuVisible = [];
			// close menu
			animateMenu(aOpenedMenus[i]);
		}
	}
	bIsExcluded = 1;
}

function getExcludedNodes(iArrayIndex) {
	var aULs = [];
	// get all <ul/> tags which shouldn't be closed
	aULs[0] = aGlobalInnerLIs[iArrayIndex][0].parentNode;
	// get parent <ul/> until it's the last one
	for(var i = 0; aULs[i].parentNode.parentNode.getAttribute("id") != sMenuID; i++)
		aULs[i+1] = aULs[i].parentNode.parentNode;
	var aExcludedNodes = [[]];
	//get sibling <span/> tags 
	for(var i = 0; i < aULs.length; i++) {
		if(aULs[i].previousSibling && aULs[i].previousSibling.nodeName == "SPAN") 
			aExcludedNodes[i] = getInnerLIs(aULs[i].previousSibling);
		else 
			aExcludedNodes[i] = getInnerLIs(aULs[i].previousSibling.previousSibling);
	}
	return aExcludedNodes;
}

function deleteOpenedMenu(iArrayIndex) {
	// find menu index in an array and delete it
	for(var i = 0; i < aOpenedMenus.length; i++)	
		if(aOpenedMenus[i] == iArrayIndex) aOpenedMenus.splice(i, 1);
}

function visibleControl(iArrayIndex, iArrayIndex2, direction) {
	// remove from not finished animations array
	aMenuVisible.shift();
	if(direction) {
		aGlobalInnerLIs[iArrayIndex][iArrayIndex2].style.display = "block";		
	}
	 else {	
		aGlobalInnerLIs[iArrayIndex][iArrayIndex2].style.display = "none";	
	}
}

function opacityControl(iArrayIndex, iArrayIndex2, direction) {
	// remove from not finished animations array
	aMenuOpacity.shift();
	var aTemp = [];
	if(direction) {
		if(iOpacity == 3)
			// make not transparented
			opacity(iArrayIndex, iArrayIndex2, 20);
		else {
			for(var i = 0; i <= 20; i++) {
				// soft transparency changing
				aTemp[i] = setTimeout('opacity('+iArrayIndex+', '+iArrayIndex2+', '+i+')', time_5*i);
			}
		}
		// add to the not finished animations array
		aOpacity.push(aTemp);
	} else {
		if(iOpacity == 3)
			// make full transparented
			opacity(iArrayIndex, iArrayIndex2, 0);
		else {
			for(var i = 20; i >= 0; i--) {
				// soft transparency changing
				aTemp[20 - i] = setTimeout('opacity('+iArrayIndex+', '+iArrayIndex2+', '+i+')', time_5*(20 - i));	
			}
		}
		// add to the not finished animations array
		aOpacity.push(aTemp);
	}
}

function opacity(iArrayIndex, iArrayIndex2, iValue) {
	// remove from not finished animations array
	if(aOpacity[iArrayIndex2])
		aOpacity[iArrayIndex2].shift();
	else
		aOpacity[aGlobalInnerLIs[iArrayIndex].length - iArrayIndex2 - 1].shift();
	oLI = aGlobalInnerLIs[iArrayIndex][iArrayIndex2];
	oLI.style.opacity = iValue/20;
	oLI.style.filter = "alpha(opacity="+ 5*iValue +")";
}
