/****
	DHTML Widget: AT JsMenu version 1.5.1 (20071024)
    This libary is to create DHTML widget of Pull-down menu on web page
	The target browser for this widget are :
		- Netscape 7.1+ / Mozilla 1.4+ or other Gecko browser whose the same
		  or the newer version of Gecko engine.
		- Internet Explorer 6+
		- Opera 8+
		I hope you get the best version so that this script can run correctly
	You should get the documentaion to see how to use this script
    
	Copyright (C) 2001-2007 AT Mulyana (atmulyana@yahoo.com)

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
	or see http://gnu.org/licenses/lgpl.html

Send the bug report to 'atmulyana@yahoo.com' (Tell the exact version of your
browser and under which Operating System you run the script)

Currently, this script is personal work of myself, not involving other people or
company including the company where I work.
*****/

if (typeof AtJsMenuKeys=='undefined') AtJsMenuKeys = false;

function AtJsMenu(sText,icon) {
	AtJsMenuItem.call(this,sText,icon);
	this._popup = new AtJsMenuPopup();
	this._popup.__owner__ = this;
	this._popup.__selectionManager__ = this.__selectionManager__;
	AtJsMenuSelectionManager.__managers__.length -= 1; /*The new popup created its own selection manager or it may not*/
	this._isPopupVisible = false;
	this.__contentSrc__ = '';
}
AtJsMenu.__objects__ = {}; //stores all instance objects of menu element

/***** Global Identifiers ******/
//Because the name of widget is AT JsMenu then they are attached become properties of class AtJsMenu
AtJsMenu.delayOpen = 0;
AtJsMenu.chunkPerSizeOpen = 5;
AtJsMenu.delayOpacity = 0;
AtJsMenu.opacityIncrease = 0.2;

AtJsMenu._zIndexMin = 100;
AtJsMenu.setZIndexMin = function(iZIndex) {
	iZIndex = parseInt(iZIndex); if (isNaN(iZIndex)) iZIndex = 100;
	AtJsMenu._zIndexMin = iZIndex;
}

AtJsMenu.subSign = document.createElement('DIV');
AtJsMenu.subSign.className = 'sub';
AtJsMenu.subSign.appendChild(document.createTextNode(String.fromCharCode(187))); //&raquo;
AtJsMenu.setSubSign = function(oSign) {
	if (typeof oSign == 'object') if (oSign.cloneNode) AtJsMenu.subSign = oSign;
}
if (typeof AtJsMenuSubSign != 'undefined') AtJsMenu.setSubSign(AtJsMenuSubSign);

AtJsMenu.checkSign = document.createElement('DIV');
AtJsMenu.checkSign.className = 'check';
AtJsMenu.checkSign.appendChild(document.createTextNode(String.fromCharCode(8730))); //&radic;
//AtJsMenu.checkSign.appendChild(document.createTextNode(String.fromCharCode(215))); //&times;
AtJsMenu.setCheckSign = function(oSign) {
	if (typeof oSign == 'object') if (oSign.cloneNode) AtJsMenu.checkSign = oSign;
}
if (typeof AtJsMenuCheckSign != 'undefined') AtJsMenu.setCheckSign(AtJsMenuCheckSign);

AtJsMenu.radioSign = document.createElement('DIV');
AtJsMenu.radioSign.className = 'radio';
AtJsMenu.radioSign.appendChild(document.createTextNode(String.fromCharCode(9830))); //&diams;
//AtJsMenu.radioSign.appendChild(document.createTextNode(String.fromCharCode(216))); //&Oslash;
AtJsMenu.setRadioSign = function(oSign) {
	if (typeof oSign == 'object') if (oSign.cloneNode) AtJsMenu.radioSign = oSign;
}
if (typeof AtJsMenuRadioSign != 'undefined') AtJsMenu.setRadioSign(AtJsMenuRadioSign);

AtJsMenu.horizontalSeparatorSign = document.createElement('DIV');
AtJsMenu.horizontalSeparatorSign.className = 'line';
AtJsMenu.horizontalSeparatorSign.style.borderStyle = 'solid';
AtJsMenu.horizontalSeparatorSign.style.borderWidth = '0px 1px 1px 0px';
AtJsMenu.horizontalSeparatorSign.style.fontSize = '1px';
AtJsMenu.verticalSeparatorSign = AtJsMenu.horizontalSeparatorSign.cloneNode(true);
AtJsMenu.verticalSeparatorSign.style.width = '2px';
AtJsMenu.horizontalSeparatorSign.style.height = '2px';
AtJsMenu.setHorizontalSeparatorSign = function(oSign) {
	if (typeof oSign == 'object') if (oSign.cloneNode) AtJsMenu.horizontalSeparatorSign = oSign;
}
if (typeof AtJsMenuHorizontalSeparatorSign != 'undefined')
	AtJsMenu.setHorizontalSeparatorSign(AtJsMenuHorizontalSeparatorSign);
AtJsMenu.setVerticalSeparatorSign = function(oSign) {
	if (typeof oSign == 'object') if (oSign.cloneNode) AtJsMenu.verticalSeparatorSign = oSign;
}
if (typeof AtJsMenuVerticalSeparatorSign != 'undefined')
	AtJsMenu.setVerticalSeparatorSign(AtJsMenuVerticalSeparatorSign);

AtJsMenu.onclick = function(e) {
}
AtJsMenu.onchange = function(e) {
}

AtJsMenu.showCopyright = function(f) {
	if (typeof f != 'function') f = window.alert;
	var sCpyr = 'DHTML Widget: AT JsMenu version 1.5.1\n'
		+ 'Copyright \xA9 2001-2007 AT Mulyana (atmulyana@yahoo.com)\n'
		+ 'It is free to be used and redistributed under GNU LGPL\n'
		+ 'See http://gnu.org/licenses/lgpl.html for details\n\n'
		+ 'The latest version of this widget can be found at\n'
		+ 'http://sourceforge.net/projects/atjsmenu/';
	f(sCpyr);
	return sCpyr;
}

AtJsMenu.closeAllOpenMenu = function(e) {
	for (var i=0; i<AtJsMenuSelectionManager.__managers__.length; i++)
		AtJsMenuSelectionManager.__managers__[i].clearSelectedPath();
}


/******************* == Request Param == **********************/
function AtJsMenuRequestParam(sParamName) {
	this.paramName = sParamName;
	this._form = null;
}
AtJsMenuRequestParam.__params__ = {};
AtJsMenuRequestParam.isExist = false;
AtJsMenuRequestParam.cookieSettings = '';
AtJsMenuRequestParam.isCookieEnabled = true;

AtJsMenuRequestParam.setCookie = function(sName, sValue) {
	if (!AtJsMenuRequestParam.isCookieEnabled) return;
	var sSettings = AtJsMenuRequestParam.cookieSettings;
	if (sSettings && sSettings.substring(0,1) != ';') sSettings = '; ' + sSettings;
	document.cookie = sName + '=' + escape(sValue) + sSettings;
};
AtJsMenuRequestParam.getCookie = function(sName) {
	if (!AtJsMenuRequestParam.isCookieEnabled) return null;
	var arCookies = document.cookie.split('; ');
	for (var i=0; i < arCookies.length; i++) {
		var cookie = arCookies[i].split('=');
		if (sName == cookie[0]) return unescape(cookie[1]);
	}
	return null;
};

(function() {
	var sParams = AtJsMenuRequestParam.getCookie('AtJsMenu');
	if (sParams === null) return;
	AtJsMenuRequestParam.isExist = true;
	sParams = sParams.replace(/^\s+/,'').replace(/\s+$/,''); if (!sParams) return;
	var arParams = sParams.split(':');
	for (var i=0; i < arParams.length; i++) {
		var param = arParams[i].split('=');
		if (param.length < 2) continue;
		AtJsMenuRequestParam.__params__[ param[0] ] = param[1];
	}
})();

AtJsMenuRequestParam.prototype = {
setFormObject: function(oForm) {
	if (oForm && typeof oForm == 'object') if (oForm.tagName == 'FORM') this._form = oForm;
},
setFormId: function(sId) {
	var oForm = document.getElementById(sId);
	if (oForm) if (oForm.tagName == 'FORM') this._form = oForm;
},
setFormName: function(sName) {
	if (typeof document.forms[sName] == 'object') this._form = document.forms[sName];
},
getValue: function() {
	if (typeof AtJsMenuRequestParam.__params__[this.paramName] != 'undefined') return AtJsMenuRequestParam.__params__[this.paramName];
	return null;
},
setValue: function(val) {
	var oParams = AtJsMenuRequestParam.__params__;
	var bRemove = (typeof val == 'object' && val==null);
	if (bRemove) { if (typeof oParams[this.paramName] != 'undefined') delete oParams[this.paramName]; }
	else oParams[this.paramName] = val;
	var sCookie = '';
	for (p in oParams) sCookie += (p + '=' + oParams[p] + ':');
	AtJsMenuRequestParam.setCookie('AtJsMenu', sCookie);
	if (this._form) {
		if (this._form.elements[this.paramName]) {
			if (bRemove) this._form.elements[this.paramName].name = '';
			else this._form.elements[this.paramName].value = val;
		} else if (!bRemove) {
			var oInput = document.createElement('INPUT');
			oInput.type = 'hidden';
			oInput.value = val;
			this._form.appendChild(oInput);
		}
	}
},
removeMe: function() {
	this.setValue(null);
}
} //AtJsMenuRequestParam.prototype


/******************* == Request Param Holder == **********************/
function AtJsMenuRequestParamHolder() {
	this._reqParam = null;
}
AtJsMenuRequestParamHolder.prototype = {
setRequestParam: function(oReqParam) {
	if (oReqParam instanceof AtJsMenuRequestParam) this._reqParam = oReqParam;
},
setRequestParamValue: function(val) {
	if (this._reqParam) this._reqParam.setValue(val);
},
getRequestParamValue: function() {
	if (this._reqParam) return this._reqParam.getValue();
	return null;
},
removeRequestParam: function() {
	if (this._reqParam) this._reqParam.removeMe();
},
setValue: function(val) { //Abstract Method
},
getValue: function() { //Abstract Method
},
setValueFromRequestParam: function() {
	if (this._reqParam) this.setValue( this._reqParam.getValue() );
}
} //AtJsMenuRequestParamHolder.prototype


/******************* == Menu Selection Manager == **********************/
function AtJsMenuSelectionManager(owner) {
	this._path = [];
	this.__owner__ = ((typeof owner == 'object') ? owner : null);
	AtJsMenuSelectionManager.__managers__[AtJsMenuSelectionManager.__managers__.length] = this;
	this._topMnemonics =(this.__owner__ ? this.__owner__.getMnemonics() : []);
	this._mnemonics = [];
}
AtJsMenuSelectionManager.__managers__ = [];
AtJsMenuSelectionManager.__menuShortcuts__ = [[],[],[],[],[],[],[],[]]; //8 combinations of Ctrl,Alt,Shift
AtJsMenuSelectionManager.isPathTrue = function(arPath) {
	var bRet = true;
	for (var i=arPath.length-2; i>=0; i--) bRet = bRet && (arPath[i+1].parentMenu==arPath[i]);
	if (arPath.length)
		bRet = bRet && (arPath[0] instanceof AtJsMenuBar || arPath[0] instanceof AtJsMenuPopup);
	return bRet;
}
AtJsMenuSelectionManager.prototype = {
__setFocusedElm__: function(bToClose) {
	var i = this._path.length, oMenuElm = null;
	if (i) { oMenuElm = this._path[i-1]; oMenuElm.showDescription(); /*window.focus();*/ }
	if (i > 1) {
		if (oMenuElm instanceof AtJsMenu && oMenuElm.isPopupVisible())
			this._mnemonics = oMenuElm.getPopupMenu().getMnemonics();
		else this._mnemonics = oMenuElm.getContainer().getMnemonics();
	} else if (i==1 && oMenuElm instanceof AtJsMenuPopup)
		this._mnemonics = oMenuElm.getMnemonics();
	else this._mnemonics = []; 
},
pushPathElement: function(oMenuElm) {
	var i = this._path.length;
	if (this._path[i-1] != oMenuElm.parentMenu) return;
	this._path[i] = oMenuElm;
	oMenuElm.menuSelectionChanged(true);
	this.__setFocusedElm__();
},
popPathElement: function() {
	var i = this._path.length-1; if (i<0) return null;
	var oMenu = this._path[i];
	oMenu.menuSelectionChanged(false);
	oMenu.clearDescription();
	this._path.length = i;
	this.__setFocusedElm__();
	return oMenu;
},
selectTopMnemonic: function(iMnemonic) {
	var oMenuElm = this._topMnemonics[iMnemonic];
	if (oMenuElm) {
		this._setSelectedPath(0, [oMenuElm.parentMenu, oMenuElm]);
		if (oMenuElm instanceof AtJsMenu) oMenuElm.processKeyEvent('Enter');
		else oMenuElm.doClick();
	}
	return oMenuElm;
},
selectMnemonic: function(iMnemonic) {
	var oMenuElm = this._mnemonics[iMnemonic];
	if (oMenuElm) {
		var i = this._path.length-1, oLastSelected = this._path[i];
		if (oLastSelected == oMenuElm.parentMenu) this._setSelectedPath(i+1, [oMenuElm]);
		else this._setSelectedPath(i, [oMenuElm]);
		oMenuElm.processKeyEvent('Enter');
	}
	return oMenuElm;
},
getSelectedPath: function() {
	return this._path.slice(0,this._path.length); //copies array
},
getLastSelectedMenu: function() {
	if (this._path.length) return this._path[this._path.length-1];
	return null;
},
getPathLength: function() {
	return this._path.length;
},
_setSelectedPath: function(i,arNewElms) {
	for (k=this._path.length-1; k>=i; k--)  //unselects all no longer included menus
		this._path[k].menuSelectionChanged(false);
	if (this._path.length) this._path[this._path.length-1].clearDescription();
	for (k=0; k<arNewElms.length; k++)  //selects all new included menus
		arNewElms[k].menuSelectionChanged(true);
	this._path.length = i; this._path = this._path.concat(arNewElms); //The new path is assigned
	this.__setFocusedElm__();
},
setSelectedPath: function(arPath) {
	if (!AtJsMenuSelectionManager.isPathTrue(arPath)) return;
	var k = ((arPath.length > this._path.length) ? this._path.length : arPath.length); //The less
	for (var i=0; i<k; i++) if (arPath[i] != this._path[i]) break; //from which index, both path differ
	this._setSelectedPath(i, arPath.slice(i,arPath.length));
},
clearSelectedPath: function() {
	this._setSelectedPath(0,[]);
},
getParentIndexOnPath: function(oMenuElm) {
	for (var i=this._path.length-1; i>=0; i--) if (this._path[i]==oMenuElm.parentMenu) return i;
	return -1;
},
getSiblingIndexOnPath: function(oMenuElm) {
	var i = this.getParentIndexOnPath(oMenuElm) + 1;
	return ((i > 0 && i < this._path.length) ? i : -1);
},
processMouseOver: function(oMenuElm) {
	var i = this.getParentIndexOnPath(oMenuElm);
	var oParent = oMenuElm.parentMenu;
	if (i>=0) this._setSelectedPath(i+1,[oMenuElm]);
	else if (oParent instanceof AtJsMenuBar //On index 0, always menu bar or popup menu
	  || oParent instanceof AtJsMenuPopup) //Should always reach this condition, if i <= 0
		this._setSelectedPath(0, [oParent,oMenuElm]);
},
processMouseOut: function(oMenuElm) {
	var i = this.getParentIndexOnPath(oMenuElm);
	if (i>0) this._setSelectedPath(i+1,[]);
	//On index 0, always menu bar or popup menu
	else if (this._path[0] instanceof AtJsMenuPopup || (this._path[0] instanceof AtJsMenuBar
		&& this._path[0].__idxOpenItem__!=-1)) this._setSelectedPath(1,[]);
	else /*if (this._path[1] == oMenuElm)*/ this._setSelectedPath(0,[]); //must be on the path
}
} //AtJsMenuSelectionManager.prototype

AtJsMenuSelectionManager.processKeyDown = function(e) { if (!e || !e.getButton) e = AtJsMenuEvent();
	if (!AtJsMenuKeys) return; var keys = AtJsMenuKeys;
	var iKeyCode = e.keyCode;
	if (iKeyCode==keys.DOM_VK_ALT || iKeyCode==keys.DOM_VK_CONTEXT_MENU) {
		AtJsMenu.closeAllOpenMenu(); return;
	}
	var arManagers = AtJsMenuSelectionManager.__managers__; if (!arManagers.length) return;
	for (var i=0; i<arManagers.length; i++) if (arManagers[i].getPathLength() > 0) break;
	var bNoSelected = (i >= arManagers.length);
	if (iKeyCode >= keys.DOM_VK_A && iKeyCode <= keys.DOM_VK_Z
	  || iKeyCode >= keys.DOM_VK_0 && iKeyCode <= keys.DOM_VK_9) {
		if (bNoSelected) {
			if (e.altKey && ((e.shiftKey && !e.ctrlKey) || (!e.shiftKey && e.ctrlKey)) )
				for (i=0; i<arManagers.length; i++) {if (arManagers[i].selectTopMnemonic(iKeyCode)) return;}
		} else if (!e.altKey && !e.ctrlKey && !e.shiftKey)
			if (arManagers[i].selectMnemonic(iKeyCode)) return;
	}
	
	var iModifiers = 0, oMenu, sNavKey = keys.getNavKeyText(iKeyCode);
	if (e.altKey) iModifiers += keys.ALT_MASK;
	if (e.ctrlKey) iModifiers += keys.CONTROL_MASK;
	if (e.shiftKey) iModifiers += keys.SHIFT_MASK;
	if (oMenu = AtJsMenuSelectionManager.__menuShortcuts__[iModifiers][iKeyCode]) {
		AtJsMenu.closeAllOpenMenu();
		oMenu.doClick();
		if (e.altKey) AtJsMenuSelectionManager._accPressed = true;
	}
	
	if (bNoSelected || !sNavKey) return;
	var oMenuElm = arManagers[i].getLastSelectedMenu(); //The last selected menu which has got the focus
	oMenuElm.processKeyEvent(sNavKey);
	e.cancelBubble = true; e.returnValue = false; return false;
}
AtJsMenuSelectionManager.processKeyUp = function(e) { if (!e || !e.getButton) e = AtJsMenuEvent();
	if (!AtJsMenuKeys) return; var keys = AtJsMenuKeys;
	var iKeyCode = e.keyCode;
	var arManagers = AtJsMenuSelectionManager.__managers__, oMenu = null;
	if (iKeyCode==keys.DOM_VK_ALT && (e.ctrlKey || e.shiftKey)) { // Ctrl/Shift + Alt
		if (AtJsMenuSelectionManager._accPressed) { AtJsMenuSelectionManager._accPressed = false; return; }
		for (var i=0; i<arManagers.length; i++) if (arManagers[i].__owner__ instanceof AtJsMenuBar) {
			oMenu = arManagers[i].__owner__.getMenu(0); break; //first menu
		}
		if (!oMenu) return;
		if (arManagers[i].getPathLength() > 0) return; //There has been an opened menu
		arManagers[i].setSelectedPath([oMenu.parentMenu, oMenu]);
		e.cancelBubble = true; e.returnValue = false; return false;
	} else {
		for (var i=0; i<arManagers.length; i++) if (arManagers[i].getPathLength() > 0) break;
		var sNavKey = keys.getNavKeyText(iKeyCode);
		if (i < arManagers.length && sNavKey)
			arManagers[i].getLastSelectedMenu().processKeyEvent(sNavKey,true);
	}
}


/******************* == Base class for all Menu Component == **********************/
function AtJsMenuElement(oMenuComp,icon) {
	this._component = (oMenuComp ? oMenuComp : null);
	this._id = (oMenuComp ? oMenuComp.id : '');
	this.icon = null;
	this._setIcon(icon);
}
AtJsMenuElement.prototype = {
parentMenu: null,
__selectionManager__: null,
descAttrName: 'desc',
description: '',

_setComponent: function(oComp) { //Abstract Method
},
__setComponent__: function(oComp) {
	this._component = oComp;
	this._setComponent(oComp);
},
getDescription: function(oComp) {
	if (!oComp) { oComp = this.getComponent();	if (!oComp) return ''; }
	var sDescAttrName = oComp.getAttribute('__AtJsMenuDescAttr__');
	if (sDescAttrName) return oComp.getAttribute(sDescAttrName);
	return '';
},
showDescription: function(oComp) {
	var sDesc = this.getDescription(oComp);
	if (sDesc) window.status = sDesc;
},
clearDescription: function(oComp) {
	window.status = '';
},
menuSelectionChanged: function(bIncluded) {
},
getComponent: function() {
	if (this._component) return this._component;
	if (!this._id) return null;
	return (this._component = document.getElementById(this._id));
},
_setIcon: function(icon) {
	if (icon) {
		if (typeof icon == 'string') {
			this.icon = document.createElement('IMG');
			this.icon.src = icon;
		} else if (typeof icon == 'object') {
			if (icon.cloneNode) {
				if (icon.parentNode) this.icon = icon.cloneNode(true);
				else this.icon = icon;
			}
		}
	}
},
_drawIcon: function(oCont) {
	if (this.icon) oCont.appendChild(this.icon);
	else oCont.appendChild( document.createTextNode(String.fromCharCode(160)) ); //&nbsp;
},
setInterface: function(fInterface) {
	for (p in fInterface.prototype) this[p] = fInterface.prototype[p];
}
}//AtJsMenuElement.prototype


/******************* == Menu Separator == **********************/
function AtJsMenuSeparator() {
}
AtJsMenuSeparator.prototype = new AtJsMenuElement();

AtJsMenuSeparator.prototype._setComponent = function(oComp) {
}
AtJsMenuSeparator.prototype.__setComponent__ = function(oComp,cons) {
	AtJsMenuElement.call(this,oComp,null);
	oComp.className = 'AtJsMenuSeparator';
	oComp.setAttribute('__AtJsMenuSeparator__', 1);
	oComp.onmouseover = AtJsMenuSeparator.__onmouseover__;
	this._setComponent(oComp);
}

AtJsMenuSeparator.__onmouseover__ = function(e) { if (!e || !e.getButton) e = AtJsMenuEvent();
	if (!e.fromElement || this.contains(e.fromElement)) return; //this == separator component
	//var oContComp = this.parentNode.parentNode.parentNode; // tr > tbody > table > div
	//if (this.tagName == 'TD') oContComp = oContComp.parentNode; //on menu bar
	var oContComp = document.getElementById(this.getAttribute('__AtJsMenuContId__'));
	var oCont = AtJsMenu.__objects__[oContComp.id];
	var oSelMan = oCont.__selectionManager__;
	var oParent = (oCont.__owner__ ? oCont.__owner__ : oCont);
	var i = oSelMan.getSiblingIndexOnPath(oParent);
	var arSelectedPath = oSelMan.getSelectedPath();
	if (i >= 0) { arSelectedPath.length = i+1; oSelMan.setSelectedPath(arSelectedPath); }
	e.cancelBubble = true;
}


/******************* == Menu Container == **********************/
function AtJsMenuContainer(oComp,icon) {
	AtJsMenuElement.call(this,oComp,icon);
	this._mnemonics = [];
	this._containerComponent = null;
	this.__owner__ = null;
	if (oComp) {
		setNotSelectedElement(oComp);
		this.__selectionManager__ = new AtJsMenuSelectionManager(this);
		AtJsMenu.__objects__[oComp.id] = this;
	}
}
AtJsMenuContainer.prototype = new AtJsMenuElement();
AtJsMenuContainer.prototype._realConstructor = AtJsMenuContainer;

//especially for popup
//return false if not fully shown (hidden or still slided)
AtJsMenuContainer.prototype.isReady = function() {
	return true;
}

AtJsMenuContainer.prototype.__setMnemonic__ = function(oMenuItem,iMnemonic,iOldMnemonic) {
	if (iOldMnemonic && this._mnemonics[iOldMnemonic]) delete this._mnemonics[iOldMnemonic];
	if (iMnemonic) this._mnemonics[iMnemonic] = oMenuItem;
}
AtJsMenuContainer.prototype.getMnemonics = function() {
	return this._mnemonics;
}

AtJsMenuContainer.prototype.getItem = function(idx) {
	var oCont = this._containerComponent; if (!oCont) return null;
	idx = parseInt(idx); if (isNaN(idx) || idx < 0 || idx >= this.getItemCount()) return null;
	var oItemComp = oCont.childNodes[idx];
	if (AtJsMenu.__objects__[oItemComp.id]) return AtJsMenu.__objects__[oItemComp.id];
	return null;
}

AtJsMenuContainer.prototype.getItemCount = function() {
	if (!this._containerComponent) return 0;
	return this._containerComponent.childNodes.length;
}

AtJsMenuContainer.prototype._getNewRow = function(idx,oTable) {
	var oTR = oTable.insertRow(idx);
	var oTD = oTR.insertCell(0);
	oTD.className = 'icon';
	oTD = oTR.insertCell(1);
	oTD.className = 'text';
	oTD.style.whiteSpace = 'nowrap';
	oTD = oTR.insertCell(2);
	oTD.style.whiteSpace = 'nowrap';
	oTD.appendChild( document.createTextNode(String.fromCharCode(160)) ); //&nbsp;
	oTD.className = 'shortcut';
	return oTR;
}
AtJsMenuContainer.prototype._getNewItemComponent = function(idx) {
}
AtJsMenuContainer.prototype.insert = function(oItem,idx) {
	idx = parseInt(idx); if (isNaN(idx) || idx > this.getItemCount()) idx = this.getItemCount();
	var oComp = this._getNewItemComponent(idx);
	oComp.setAttribute('__AtJsMenuContId__',this._id);
	if (oItem.descAttrName && oItem.description) {
		oComp.setAttribute('__AtJsMenuDescAttr__',oItem.descAttrName);
		oComp.setAttribute(oItem.descAttrName,oItem.description);
	}
	oItem.parentMenu = (this.__owner__ ? this.__owner__ : this);
	oItem.__selectionManager__ = this.__selectionManager__;
	oItem.__setComponent__(oComp);
	this.__setMnemonic__(oItem, oItem.getMnemonic());
}
AtJsMenuContainer.prototype.add = function(oItem) {
	this.insert(oItem);
}
AtJsMenuContainer.prototype._removeComponentAt = function(idx) {
}
AtJsMenuContainer.prototype.remove = function(idx) {
	var oItem = ((typeof idx=='object') ? idx : this.getItem(idx));
	if (oItem) {
		idx = (oItem.isTopLevelMenu() ? (oItem.getIndex()+1) : oItem.getIndex());
		oItem.__selectionManager__ = null;
		if (oItem instanceof AtJsMenu) AtJsMenu.__setSelectionManager__(oItem);
		oItem.parentMenu = null;
		oItem.__setComponent__(null);
		delete AtJsMenu.__objects__[oItem.id];
	}
	idx = parseInt(idx);
	if (!isNaN(idx) && idx >= 0 && idx < this.getItemCount()) this._removeComponentAt(idx);
}

AtJsMenuContainer.prototype._getNewHorizontalSeparator = function(idx,oTable) {
	var oTR = oTable.insertRow(idx);
	var oTD = oTR.insertCell(0);
	oTD.colSpan = 3;
	return oTR;
}
AtJsMenuContainer.prototype._getNewSeparatorComponent = function(idx) {
}
AtJsMenuContainer.prototype.insertSeparator = function(idx) {
	idx = parseInt(idx); if (isNaN(idx) || idx < 0 || idx > this.getItemCount()) idx = this.getItemCount();
	var oComp = this._getNewSeparatorComponent(idx);
	oComp.setAttribute('__AtJsMenuContId__',this._id);
	var oSpr = new this._realConstructor.Separator();
	oSpr.__setComponent__(oComp);
}
AtJsMenuContainer.prototype.addSeparator = function() {
	this.insertSeparator();
}


/******************* == Menu Bar == **********************/
function AtJsMenuBar(sId,icon) {
	var oBarComp = document.getElementById(sId); if (!oBarComp) return;
	AtJsMenuContainer.call(this,oBarComp,icon);
	oBarComp.className = 'AtJsMenuBar';
	this.__idxOpenItem__ = -1;
	this._containerComponent = null;
	this._layout = AtJsMenuBar.HORIZONTAL;
	this.isReverseDirection = false;
	this._draw();
}
AtJsMenuBar.prototype = new AtJsMenuContainer();
AtJsMenuBar.prototype._realConstructor = AtJsMenuBar;
AtJsMenuBar.HORIZONTAL = 1;
AtJsMenuBar.VERTICAL = 2;

AtJsMenuBar.prototype._getContainerComponent = function() {
	var sTagName = ((this._layout == AtJsMenuBar.VERTICAL) ? 'TBODY' : 'TR');
	if (this._containerComponent && this._containerComponent.tagName == sTagName)
		return this._containerComponent;
	var oChildTables = document.getElementById(this._id).getElementsByTagName('TABLE');
	for (var i=0; i<oChildTables.length; i++) {
		if (oChildTables[i].getAttribute('__AtJsMenuBar__')) {
			if (this._layout == AtJsMenuBar.VERTICAL) return (this._containerComponent=oChildTables[i].tBodies[0]);
			else return (this._containerComponent=oChildTables[i].rows[0]);
		}
	}
	return null;
}
AtJsMenuBar.prototype._draw = function() {
	var oTbl = this._component.appendChild(document.createElement('TABLE'));
	oTbl.style.borderStyle = 'none'; oTbl.cellSpacing = 0;
	oTbl.setAttribute('__AtJsMenuBar__',1);
	if (this._layout == AtJsMenuBar.VERTICAL) this._containerComponent = oTbl.appendChild(document.createElement('TBODY'));
	else this._containerComponent = oTbl.insertRow(0);
	this.add(new AtJsMenuBarIcon(this.icon));
}
AtJsMenuBar.prototype._redraw = function() {
	if (!this._component) return;
	var arChildTables = this._component.getElementsByTagName('TABLE');
	var arItems = [];
	for (var i=0; i<arChildTables.length; i++) {
		if (arChildTables[i].getAttribute('__AtJsMenuBar__')) {
			for (var k=0, j=this.getMenuCount(); k<j; k++) arItems[k] = this.getMenu(k);
			this._component.removeChild(arChildTables[i]);
		}
	}
	this._draw();
	for (i=0; i<arItems.length; i++) {
		if (arItems[i] == null) this.addSeparator();
		else this.add(arItems[i]);
	}
}

AtJsMenuBar.prototype._getNewItemComponent = function(idx) {
	if (this._layout == AtJsMenuBar.VERTICAL) return this._getNewRow(idx, this._getContainerComponent());
	return this._getContainerComponent().insertCell(idx);
}
AtJsMenuBar.prototype._removeComponentAt = function(idx) {
	if (this._layout == AtJsMenuBar.VERTICAL) this._getContainerComponent().deleteRow(idx);
	else this._getContainerComponent().deleteCell(idx);
}
AtJsMenuBar.prototype._getNewSeparatorComponent = function(idx) {
	if (this._layout == AtJsMenuBar.VERTICAL)
		return this._getNewHorizontalSeparator(idx, this._getContainerComponent());
	return this._getContainerComponent().insertCell(idx);
}

AtJsMenuBar.prototype.menuSelectionChanged = function(bIncluded) {
	if (!bIncluded) this.__idxOpenItem__ = -1;
}

AtJsMenuBar.prototype.getLayout = function() {
	return this._layout;
}
AtJsMenuBar.prototype.getItem = function(idx) {
	if ((oCont=this._containerComponent) && this._layout == AtJsMenuBar.VERTICAL && idx == 0 && oCont.childNodes.length) {
		return AtJsMenu.__objects__[oCont.rows[0].cells[0].id]
	}
	return AtJsMenuContainer.prototype.getItem.call(this,idx);;
}
AtJsMenuBar.prototype.getMenu = function(idx) {
	return this.getItem(idx+1);
}
AtJsMenuBar.prototype.getMenuCount = function() {
	return (this.getItemCount()-1);
}
AtJsMenuBar.prototype.insert = function(oItem,idx) {
	AtJsMenuContainer.prototype.insert.call(this,oItem,idx+1);
}
AtJsMenuBar.prototype.insertSeparator = function(idx) {
	AtJsMenuContainer.prototype.insertSeparator.call(this,idx+1);
}
AtJsMenuBar.prototype.remove = function(idx) {
	if (!isNaN(idx)) idx += 1;
	AtJsMenuContainer.prototype.remove.call(this,idx);
}
AtJsMenuBar.prototype.setLayout = function(iLayout) {
	if (iLayout != AtJsMenuBar.HORIZONTAL && iLayout != AtJsMenuBar.VERTICAL) return;
	if (iLayout == this._layout) return;
	this._layout = iLayout;
	this._redraw();
}

/******************* == Menu Bar Seperator == **********************/
AtJsMenuBar.Separator = function() {
}
AtJsMenuBar.Separator.prototype = new AtJsMenuSeparator();

AtJsMenuBar.Separator.prototype._setComponent = function(oComp) {
	if (oComp.cells) oComp.cells[0].appendChild(AtJsMenu.horizontalSeparatorSign.cloneNode(true));
	else oComp.appendChild(AtJsMenu.verticalSeparatorSign.cloneNode(true));
}


/******************* == Menu == **********************/
function AtJsMenuPopup() {
	var oPopupComp = document.createElement('DIV');
	oPopupComp.id = '__AtJsMenuPopup' + (++AtJsMenuPopup.__idxCounter) + '__';
	AtJsMenuContainer.call(this,oPopupComp,null);
	oPopupComp.className = 'AtJsMenuPopup';
	oPopupComp.style.zIndex = AtJsMenu._zIndexMin;
	this.setOpacity(1);
	oPopupComp.style.position = 'absolute';
	oPopupComp.style.visibility = 'hidden';
	document.body.appendChild(oPopupComp);
	var oTbl = document.createElement('TABLE');
	oTbl.cellSpacing = 0;
	oTbl.appendChild(document.createElement('TBODY'));
	oPopupComp.appendChild(oTbl);
	this._containerComponent = oTbl.tBodies[0];
	oPopupComp.onmousedown = AtJsMenuPopup.__onmousedown__;
	this.__opActCount__ = -1;
}
AtJsMenuPopup.prototype = new AtJsMenuContainer();
AtJsMenuPopup.prototype._realConstructor = AtJsMenuPopup;
AtJsMenuPopup.__timerId = {};
AtJsMenuPopup.__idxCounter = 0;

AtJsMenuPopup.prototype.isReady = function() {
	return (this.__opActCount__ == 0);
}

AtJsMenuPopup.prototype._getNewItemComponent = function(idx) {
	return this._getNewRow(idx, this.getComponent().childNodes[0]);
};
AtJsMenuPopup.prototype._removeComponentAt = function(idx) {
	this.getComponent().childNodes[0].deleteRow(idx);
};
AtJsMenuPopup.prototype._getNewSeparatorComponent = function(idx) {
	return this._getNewHorizontalSeparator(idx, this.getComponent().childNodes[0]);
};

AtJsMenuPopup.__isTimerAlive__ = function() {
	var bAlive = true, i = 0;
	for (sId in AtJsMenuPopup.__timerId) {
		i++;
		bAlive = bAlive && (AtJsMenuPopup.__timerId[sId] !== null);
	}
	return i > 0 ? bAlive : false;
};
AtJsMenuPopup.__clearAllTimer__ = function() {
	for (sId in AtJsMenuPopup.__timerId) if (AtJsMenuPopup.__timerId[sId] !== null) {
		window.clearTimeout(AtJsMenuPopup.__timerId[sId]);
		AtJsMenuPopup.__timerId[sId] = null;
	}
};

AtJsMenuPopup.__initClip = {
south: function(oPopupComp,arClip) { arClip[0] = oPopupComp.offsetHeight + 'px'; },
north: function(oPopupComp,arClip) { arClip[2] = '0px'; },
west: function(oPopupComp,arClip) { arClip[1] = '0px'; },
east: function(oPopupComp,arClip) { arClip[3] = oPopupComp.__offsetWidth__ + 'px'; } //See method show
};
AtJsMenuPopup.__initPos = {
south: function(oPopupComp) {
	oPopupComp.style.top = (parseInt(oPopupComp.style.top)-oPopupComp.offsetHeight) + 'px'; },
north: function(oPopupComp) {
	oPopupComp.style.top = (parseInt(oPopupComp.style.top)+oPopupComp.offsetHeight) + 'px'; },
west: function(oPopupComp) {
	oPopupComp.style.left = (parseInt(oPopupComp.style.left)+oPopupComp.__offsetWidth__) + 'px'; }, //See method show
east: function(oPopupComp) {
	oPopupComp.style.left = (parseInt(oPopupComp.style.left)-oPopupComp.__offsetWidth__) + 'px'; } //See method show
};

AtJsMenuPopup._slideClip = {
south: function(oPopupComp,iStep,arClip) {
	var iChunkSize = Math.ceil(oPopupComp.offsetHeight / AtJsMenu.chunkPerSizeOpen);
	if (iStep < AtJsMenu.chunkPerSizeOpen) {
		arClip[0] = (oPopupComp.offsetHeight-iChunkSize*iStep) + 'px';
	} else {
		iChunkSize = oPopupComp.offsetHeight - (iStep-1)*iChunkSize;
		arClip[0] = '0px';
	}
	return iChunkSize;
},
north: function(oPopupComp,iStep,arClip) {
	var iChunkSize = Math.ceil(oPopupComp.offsetHeight / AtJsMenu.chunkPerSizeOpen);
	if (iStep < AtJsMenu.chunkPerSizeOpen) arClip[2] = (iChunkSize*iStep) + 'px';
	else iChunkSize = oPopupComp.offsetHeight - (iStep-1)*iChunkSize;
	return iChunkSize;
},
west: function(oPopupComp,iStep,arClip) {
	var iChunkSize = Math.ceil(oPopupComp.__offsetWidth__ / AtJsMenu.chunkPerSizeOpen); //See method show
	if (iStep < AtJsMenu.chunkPerSizeOpen) arClip[1] = (iChunkSize*iStep) + 'px';
	else iChunkSize = oPopupComp.__offsetWidth__ - (iStep-1)*iChunkSize;
	return iChunkSize;
},
east: function(oPopupComp,iStep,arClip) {
	var iChunkSize = Math.ceil(oPopupComp.__offsetWidth__ / AtJsMenu.chunkPerSizeOpen); //See method show
	if (iStep < AtJsMenu.chunkPerSizeOpen) {
		arClip[3] = (oPopupComp.__offsetWidth__ - iChunkSize*iStep) + 'px';
	} else {
		iChunkSize = oPopupComp.__offsetWidth__ - (iStep-1)*iChunkSize;
		arClip[3] = '0px';
	}
	return iChunkSize;
}
};
AtJsMenuPopup._slidePos = {
south: function(oPopupComp,iPixel,iTop,iLeft) {
	var iTop1 = parseInt(oPopupComp.style.top) + iPixel;
	if (iTop1 > iTop) iTop1 = iTop; //in the case of out of control
	oPopupComp.style.top = iTop1 + 'px'; },
north: function(oPopupComp,iPixel,iTop,iLeft) {
	var iTop1 = parseInt(oPopupComp.style.top) - iPixel;
	if (iTop1 < iTop) iTop1 = iTop;
	oPopupComp.style.top = iTop1 + 'px'; },
west: function(oPopupComp,iPixel,iTop,iLeft) {
	var iLeft1 = parseInt(oPopupComp.style.left) - iPixel;
	if (iLeft1 < iLeft) iLeft1 = iLeft;
	oPopupComp.style.left = iLeft1 + 'px'; },
east: function(oPopupComp,iPixel,iTop,iLeft) {
	var iLeft1 = parseInt(oPopupComp.style.left) + iPixel;
	if (iLeft1 > iLeft) iLeft1 = iLeft;
	oPopupComp.style.left = iLeft1 + 'px'; }
};

AtJsMenuPopup.__slide__ = function(sPopupCompId,iStep,sDir1,sDir2,iTop,iLeft) {
	oPopupComp = document.getElementById(sPopupCompId);
	var arClip = ['auto','auto','auto','auto'];
	var iPixelMove = AtJsMenuPopup._slideClip[sDir1](oPopupComp,iStep,arClip);
	AtJsMenuPopup._slidePos[sDir1](oPopupComp,iPixelMove,iTop,iLeft);
	if (sDir2) {
		iPixelMove = AtJsMenuPopup._slideClip[sDir2](oPopupComp,iStep,arClip);
		AtJsMenuPopup._slidePos[sDir2](oPopupComp,iPixelMove,iTop,iLeft);
	}
	oPopupComp.style.clip = 'rect(' + arClip.join(' ') + ')';
	if (iStep >= AtJsMenu.chunkPerSizeOpen) {
		AtJsMenuPopup.__timerId.slide = null;
		AtJsMenu.__objects__[sPopupCompId].__opActCount__--;
	} else AtJsMenuPopup.__timerId.slide = window.setTimeout(
		'AtJsMenuPopup.__slide__("'+sPopupCompId+'",'+(iStep+1)+',"'+sDir1+'","'+sDir2+'",'+iTop+','+iLeft+')',
		AtJsMenu.delayOpen);
}

AtJsMenuPopup.__increaseOpacity__ = function(sPopupCompId) {
	var oPopup = AtJsMenu.__objects__[sPopupCompId];
	var iOpacity = oPopup.getOpacity() + AtJsMenu.opacityIncrease;
	if (iOpacity >= 1) {
		oPopup.setOpacity(1);
		AtJsMenuPopup.__timerId.opacity = null;
		oPopup.__opActCount__--;
	} else {
		oPopup.setOpacity(iOpacity);
		AtJsMenuPopup.__timerId.opacity = window.setTimeout(
		'AtJsMenuPopup.__increaseOpacity__("'+sPopupCompId+'")', AtJsMenu.delayOpacity);
	}
}

AtJsMenuPopup.openingBehavior = {
	slide: function(oPopupComp,iLeft,iTop,sDirection) {
		AtJsMenu.delayOpen = parseInt(AtJsMenu.delayOpen);
		if (isNaN(AtJsMenu.delayOpen) || AtJsMenu.delayOpen < 0) AtJsMenu.delayOpen = 0;
		AtJsMenu.chunkPerSizeOpen = parseInt(AtJsMenu.chunkPerSizeOpen);
		if (isNaN(AtJsMenu.chunkPerSizeOpen) || AtJsMenu.chunkPerSizeOpen < 1) AtJsMenu.chunkPerSizeOpen = 1;
		if (AtJsMenu.delayOpen > 0) {
			var arDir = sDirection.split('-'), arClip = ['auto','auto','auto','auto'];
			AtJsMenuPopup.__initClip[arDir[0]](oPopupComp,arClip);
			AtJsMenuPopup.__initPos[arDir[0]](oPopupComp);
			if (arDir[1]) {
				AtJsMenuPopup.__initClip[arDir[1]](oPopupComp,arClip);
				AtJsMenuPopup.__initPos[arDir[1]](oPopupComp);
			} else arDir[1] = '';
			oPopupComp.style.clip = 'rect(' + arClip.join(' ') + ')';
			AtJsMenuPopup.__timerId.slide = window.setTimeout(
				'AtJsMenuPopup.__slide__("'+oPopupComp.id+'",1,"'+arDir[0]+'","'+arDir[1]+'",'+iTop+','+iLeft+')',
				AtJsMenu.delayOpen);
			return true;
		}
		return false;
	},
	opacity: function(oPopupComp) {
		if (isNaN(AtJsMenu.delayOpacity) || AtJsMenu.delayOpacity < 0) AtJsMenu.delayOpacity = 0;
		if (isNaN(AtJsMenu.opacityIncrease) || AtJsMenu.opacityIncrease < 0) AtJsMenu.opacityIncrease = 0;
		if (AtJsMenu.delayOpacity > 0 && AtJsMenu.opacityIncrease > 0) {
			oPopupComp.style.visibility = 'visible'; //IE6, must be visible before transparent (opacity=0)
			AtJsMenu.__objects__[oPopupComp.id].setOpacity(0);
			AtJsMenuPopup.__timerId.opacity = window.setTimeout(
				'AtJsMenuPopup.__increaseOpacity__("'+oPopupComp.id+'")', AtJsMenu.delayOpacity);
			return true;
		}
		return false;
	}
}; 

AtJsMenuPopup.prototype.show = function(iLeft,iTop,sDirection) {
	if (typeof arguments[0] == 'object') {
		return this.showOnInvoker(arguments[0],arguments[1],arguments[2]);
	}
	var oPopupComp = this.getComponent();
	oPopupComp.__offsetWidth__ = oPopupComp.offsetWidth; /*We save the original offsetWidth here
		because this value seems to change if the popup stays closely with the window right side */
	oPopupComp.style.left = iLeft + "px";
	oPopupComp.style.top = iTop + "px";
	this.__opActCount__ = 0;
	for (sBehave in AtJsMenuPopup.openingBehavior)
		if (AtJsMenuPopup.openingBehavior[sBehave](oPopupComp,iLeft,iTop,sDirection)) this.__opActCount__++;
	if (this.__opActCount__ == 0) this.setOpacity(1);
	oPopupComp.style.visibility = 'visible';
	if (!this.__owner__) this.__selectionManager__.setSelectedPath([this]);
}

AtJsMenuPopup.prototype.showOnInvoker = function(oInvoker,iX,iY) {
	oCoords = getElementCoordOnPage(oInvoker);
	iX += oCoords.x; iY += oCoords.y;
	var sHortDir = 'east', sVertDir = 'south';
	if (iX + this.getWidth() > getWinRightSide()-20) {
		iX -= this.getWidth();
		sHortDir = 'west';
		if (iX < getWinLeftSide()) {
			iX = getWinLeftSide();
			sHortDir = 'east';
		}
	}
	if (iY + this.getHeight() > getWinBottomSide()-20) {
		iY -= this.getHeight();
		sVertDir = 'north';
		if (iY < getWinTopSide()) {
			iY = getWinTopSide();
			sVertDir = 'south';
		}
	}
	this.show(iX, iY, sVertDir+'-'+sHortDir);
}

AtJsMenuPopup.prototype.getHeight = function() {
	return this.getComponent().offsetHeight;
}

AtJsMenuPopup.prototype.getWidth = function() {
	return this.getComponent().offsetWidth;
}

AtJsMenuPopup.prototype.setLocation = function(iLeft, iTop) {
	var oComp = this.getComponent();
	oComp.style.left = iLeft + 'px';
	oComp.style.top = iTop + 'px';
}

AtJsMenuPopup.prototype.setOpacity = function(iOpacity) {
	if (iOpacity < 0) iOpacity = 0;
	if (iOpacity > 1.0) iOpacity = 1.0;
	setElementOpacity(this._component,iOpacity);
	this.__opacity = iOpacity;
}
AtJsMenuPopup.prototype.getOpacity = function() {
	return this.__opacity;
}

AtJsMenuPopup.prototype.setVisible = function(bVisible) {
	with (this.getComponent().style) {
		visibility = (bVisible ? 'visible' : 'hidden');
		clip = 'rect(auto auto auto auto)';
		if (!bVisible) zIndex = AtJsMenu._zIndexMin;
	}
	this.__opActCount__ = (bVisible ? 0 : -1);
	if (bVisible && !this.__owner__) this.__selectionManager__.setSelectedPath([this]);
}

AtJsMenuPopup.prototype.isVisible = function() {
	return (this.getComponent().style.visibility!='hidden');
}

AtJsMenuPopup.prototype.menuSelectionChanged = function(bIncluded) {
	if (!bIncluded) this.setVisible(false);
}

AtJsMenuPopup.prototype._process_key_Esc = function(arPath) { //Escape
	this.__selectionManager__.clearSelectedPath();
}
AtJsMenuPopup.prototype._process_key_Up = function(arPath) { //Up arrow
	var i=this.getItemCount()-1, oItem=this.getItem(i); while (!oItem && i >=0) oItem=this.getItem(--i);
	if (oItem) this.__selectionManager__.pushPathElement(oItem);
}
AtJsMenuPopup.prototype._process_key_Down = function(arPath) { //Down arrow
	var i=0, j=this.getItemCount(), oItem=this.getItem(i); while(!oItem && i<=j) oItem=this.getItem(++i);
	if (oItem) this.__selectionManager__.pushPathElement(oItem);
}
AtJsMenuPopup.prototype.processKeyEvent = function(sKeyText) {
	var arPath = this.__selectionManager__.getSelectedPath();
	if (arPath[arPath.length-1] != this) return; //must be the last element having focus
	var sMethod = '_process_key_' + sKeyText; if (!this[sMethod]) return; //not recognized key
	this[sMethod](arPath);
}

AtJsMenuPopup.__onmousedown__ = function(e) { if (!e || !e.getButton) e = AtJsMenuEvent();
	e.cancelBubble = true; e.returnValue = false; return false;
}

/******************* == Popup Menu Seperator == **********************/
AtJsMenuPopup.Separator = function() {
}
AtJsMenuPopup.Separator.prototype = new AtJsMenuSeparator();

AtJsMenuPopup.Separator.prototype._setComponent = function(oComp) {
	oComp.cells[0].appendChild(AtJsMenu.horizontalSeparatorSign.cloneNode(true));
}


/******************* == Menu Item Base == **********************/
function AtJsMenuAbstractButton(oComp,icon) {
	AtJsMenuElement.call(this,oComp,icon);
	this._isArmed = false;
	this._selected = false;
	this._enabled = true;
	this._disabledClass = '';
	this.text = '';
	this._mnemonic = 0;
	if (!this._id) this._id = '__AtJsMenu' + (++AtJsMenuAbstractButton.__idxCounter) + '__';
	AtJsMenu.__objects__[this._id] = this;
}
AtJsMenuAbstractButton.prototype = new AtJsMenuElement();
AtJsMenuAbstractButton.__idxCounter = 0;

AtJsMenuAbstractButton.prototype._isToggle = false;
AtJsMenuAbstractButton.prototype._normalClassName = 'AtJsMenuButton';
AtJsMenuAbstractButton.prototype._hoverClassName = 'AtJsMenuButton-hover';
AtJsMenuAbstractButton.prototype._selectClassName = 'AtJsMenuButton-select';
AtJsMenuAbstractButton.prototype._selectHoverClassName = 'AtJsMenuButton-select-hover';
AtJsMenuAbstractButton.prototype._selectHoverArmedClassName = 'AtJsMenuButton-select-hover-armed';

AtJsMenuAbstractButton.prototype.__setComponent__ = function(oComp) {
	if (oComp) oComp.id = this._id;
	AtJsMenuElement.call(this,oComp,this.icon);
	if (!oComp) return;
	this.setText(this.text);
	oComp.onmouseover = AtJsMenuAbstractButton.__onmouseover__;
	oComp.onmouseout = AtJsMenuAbstractButton.__onmouseout__;
	oComp.onmousedown = AtJsMenuAbstractButton.__onmousedownup__;
	oComp.onmouseup = AtJsMenuAbstractButton.__onmousedownup__;
	this._setComponent(oComp);
	if (this._enabled) this._disabledClass = '';
	else this._disabledClass = (this.isTopLevelMenu() ? '-disabled' : ' disabled');
	this._setCssClass(false);
}

AtJsMenuAbstractButton.prototype._getIndex = function() {
	var oComp = this._component;
	if (isNaN(oComp.rowIndex)) return oComp.cellIndex; else return oComp.rowIndex
}

AtJsMenuAbstractButton.prototype.getContainer = function() {
	var oComp = this.getComponent(); if (!oComp) return null;
	if (this.isTopLevelMenu()) return this.parentMenu;
	var oPopupComp = document.getElementById(oComp.getAttribute('__AtJsMenuContId__'));
		//oComp.parentNode.parentNode.parentNode; // tr > tbody > table > div
	if (oPopupComp) return AtJsMenu.__objects__[oPopupComp.id];
	return null;
}

AtJsMenuAbstractButton.prototype._getTextContainerComponent = function() {
	return this.getComponent();
}

AtJsMenuAbstractButton.prototype.setText = function(sText) {
	this.text = sText; if (!sText) return;
	var oTextCont = this._getTextContainerComponent(); if (!oTextCont) return;
	while(oTextCont.childNodes.length) oTextCont.removeChild(oTextCont.childNodes[0]);
	var sMneChar = ((this._mnemonic && AtJsMenuKeys) ? AtJsMenuKeys.getKeyChar(this._mnemonic) : '');
	var i = (sMneChar ? sText.toLowerCase().indexOf(sMneChar) : -1);
	if (i >= 0) {
		var sBefore=sText.substring(0,i), sAfter = sText.substring(i+1,sText.length);
		if (sBefore) oTextCont.appendChild(document.createTextNode(sBefore));
		var oU = oTextCont.appendChild(document.createElement('U'));
		oU.appendChild(document.createTextNode(sText.charAt(i)));
		if (sAfter) oTextCont.appendChild(document.createTextNode(sAfter));
	} else
		oTextCont.appendChild(document.createTextNode(sText));
}

AtJsMenuAbstractButton.prototype.setMnemonic = function(iKeyCode) {
	if (!AtJsMenuKeys) return; var keys = AtJsMenuKeys;
	if ((iKeyCode < keys.DOM_VK_A || iKeyCode > keys.DOM_VK_Z)
	  && (iKeyCode < keys.DOM_VK_0 || iKeyCode > keys.DOM_VK_9)) return; //Not valid mnemonic char
	var oCont = this.getContainer();
	if (oCont) oCont.__setMnemonic__(this,iKeyCode,this._mnemonic);
	this._mnemonic = iKeyCode;
	this.setText(this.text); //Re-draw the mnemonic sign
}
AtJsMenuAbstractButton.prototype.getMnemonic = function() {
	return this._mnemonic;
}

AtJsMenuAbstractButton.prototype.onclick = function(e) {
}
AtJsMenuAbstractButton.prototype._doClick = function() { //Abstract Method
}
AtJsMenuAbstractButton.prototype.doClick = function() {
	if (AtJsMenuPopup.__isTimerAlive__()) return;
	AtJsMenu.closeAllOpenMenu();
	if (!this._enabled) return;
	this._doClick();
	var e = {src: this, cancelBubble: false};
	var oMenuElm = this;
	while (!e.cancelBubble && oMenuElm) {
		if (oMenuElm instanceof AtJsMenuBar || oMenuElm instanceof AtJsMenuPopup) {
			AtJsMenu.onclick(e); break;
		}
		oMenuElm.onclick(e);
		oMenuElm = oMenuElm.parentMenu;
	}
}

AtJsMenuAbstractButton.prototype.isTopLevelMenu = function() {
	return (this.parentMenu instanceof AtJsMenuBar);
}

AtJsMenuAbstractButton.prototype._isPressed = function() {
	return this._selected;
}
AtJsMenuAbstractButton.prototype._setCssClass = function(bHighlight) {
	var oComp = this._component;
	if (bHighlight) {
		if (this._isPressed()) oComp.className = this._selectHoverClassName + this._disabledClass;
		else oComp.className = this._hoverClassName + this._disabledClass;
	} else {
		if (this._isPressed()) oComp.className = this._selectClassName + this._disabledClass;
		else oComp.className = this._normalClassName + this._disabledClass;
	}
}
AtJsMenuAbstractButton.prototype._fixCssClass = function() {
	this._setCssClass(this.__selectionManager__ && this.__selectionManager__.getLastSelectedMenu() == this);
}
AtJsMenuAbstractButton.prototype.menuSelectionChanged = function(bIncluded) {
	if (!this.getComponent()) return;
	this._setCssClass(bIncluded);
	if (bIncluded && this.isTopLevelMenu() && this.parentMenu.__idxOpenItem__ != -1)
		this.parentMenu.__idxOpenItem__ = this._getIndex();
}
AtJsMenuAbstractButton.prototype.setArmed = function(bArmed) {
	var oComp = this.getComponent(); if (!oComp) return;
	this._isArmed = bArmed;
	if (bArmed && this._enabled) {
		if (this._selected) oComp.className = this._selectHoverArmedClassName;
		else oComp.className = this._selectHoverClassName;
	} else {
		this._fixCssClass();
	}
}
AtJsMenuAbstractButton.prototype.setSelected = function(bSelected) {
	if (!this._isToggle || (this._selected == bSelected)) return;
	this._selected = bSelected;
	if (!this.getComponent()) return;
	this._fixCssClass();
}
AtJsMenuAbstractButton.prototype.isSelected = function() {
	return this._selected;
}

AtJsMenuAbstractButton.prototype.setEnabled = function(bEnabled) {
	if (this._enabled == bEnabled) return;
	this._enabled = bEnabled;
	if (bEnabled) this._disabledClass = '';
	else this._disabledClass = (this.isTopLevelMenu() ? '-disabled' : ' disabled');
	if (!this.getComponent()) return;
	this._fixCssClass();
}
AtJsMenuAbstractButton.prototype.isEnabled = function() {
	return this._enabled;
}

AtJsMenuAbstractButton.prototype._mayHighlightFirstChildOf = function(oMenu) {
	if (oMenu instanceof AtJsMenu && oMenu.isPopupVisible()
		&& oMenu.__selectionManager__.getLastSelectedMenu() == oMenu) oMenu.processKeyEvent('Down');
}
AtJsMenuAbstractButton.prototype._moveToPreviousSibling = function(bKeyEvent) {
	var j = this.parentMenu.getItemCount(), i = this._getIndex();
	var k = i - 1; if (k < 0) k = j - 1;
	var oItem = this.parentMenu.getItem(k);
	while (!oItem) { oItem = this.parentMenu.getItem(--k); if (k==i) break; if (k<0) k = j; }
	this.__selectionManager__.processMouseOver(oItem);
	if (bKeyEvent) this._mayHighlightFirstChildOf(oItem);
}
AtJsMenuAbstractButton.prototype._moveToNextSibling = function(bKeyEvent) {
	var j = this.parentMenu.getItemCount(), i = this._getIndex(), oItem;
	var k = i + 1; if (k >= j) k = 0;
	var oItem = this.parentMenu.getItem(k);
	while (!oItem) { oItem = this.parentMenu.getItem(++k); if (k==i) break; if (k>=j) k = -1; }
	this.__selectionManager__.processMouseOver(oItem);
	if (bKeyEvent) this._mayHighlightFirstChildOf(oItem);
}

AtJsMenuAbstractButton.prototype._process_key_Enter = function(arPath) { //Enter
	if (this.isTopLevelMenu()) this.setArmed(true);
	else this.doClick();
}
AtJsMenuAbstractButton.prototype._process_keyup_Enter = function(arPath) { //Enter
	if (!this.isTopLevelMenu()) return;
	this.setArmed(false);
	this.doClick();
}
AtJsMenuAbstractButton.prototype._process_key_Esc = function(arPath) { //Escape
	if (this.isTopLevelMenu()) AtJsMenu.closeAllOpenMenu();
	else {
		this.__selectionManager__.popPathElement(); //This menu lost focus
		this.parentMenu.processKeyEvent('Esc');
	}
}
AtJsMenuAbstractButton.prototype._process_key_Left = function(arPath) { //Left arrow
	if (this.isTopLevelMenu()) {
		if (this.parentMenu.getLayout() == AtJsMenuBar.HORIZONTAL) this._moveToPreviousSibling(true);
	} else {
		if (this.parentMenu instanceof AtJsMenuPopup) return;
		this.__selectionManager__.popPathElement(); //This menu lost focus
		this.parentMenu.processKeyEvent('Left');
	}
}
AtJsMenuAbstractButton.prototype._process_key_Up = function(arPath) { //Up arrow
	if (!this.isTopLevelMenu() || this.parentMenu.getLayout() == AtJsMenuBar.VERTICAL) this._moveToPreviousSibling(true);
}
AtJsMenuAbstractButton.prototype._process_key_Right = function(arPath) { //Right arrow
	if (this.isTopLevelMenu()) {
		if (this.parentMenu.getLayout() == AtJsMenuBar.HORIZONTAL) this._moveToNextSibling(true);
	} else {
		var oAnc = this.parentMenu;
		while (oAnc instanceof AtJsMenu && !oAnc.isTopLevelMenu()) oAnc = oAnc.parentMenu;
		if (oAnc instanceof AtJsMenu) oAnc.__process_key_Right__();
	}
}
AtJsMenuAbstractButton.prototype._process_key_Down = function(arPath) { //Down arrow
	if (!this.isTopLevelMenu() || this.parentMenu.getLayout() == AtJsMenuBar.VERTICAL) this._moveToNextSibling(true);
}
AtJsMenuAbstractButton.prototype.processKeyEvent = function(sKeyText,bReleased) {
	var oCont = this.getContainer(), sMethod;
	if (!this.__selectionManager__ || !oCont || (oCont && !oCont.isReady())) return;
	var arPath = this.__selectionManager__.getSelectedPath();
	if (arPath[arPath.length-1] != this) return; //last element must have focus
	if (bReleased) sMethod = '_process_keyup_' + sKeyText; else sMethod = '_process_key_' + sKeyText;
	if (this[sMethod]) this[sMethod](arPath); //not recognized key will not fire
}

AtJsMenuAbstractButton.prototype._process_mouseover = function(e) {
	this.__selectionManager__.processMouseOver(this);
}
AtJsMenuAbstractButton.prototype._process_mouseout = function(e) {
	this.setArmed(false);
	this.__selectionManager__.processMouseOut(this);
}
AtJsMenuAbstractButton.prototype._process_mousedown = function(e) {
	this.setArmed(e.getButton() == 1);
	if (this._isArmed) e.returnValue = false; else AtJsMenu.closeAllOpenMenu();
	e.cancelBubble = true;
}
AtJsMenuAbstractButton.prototype._process_mouseup = function(e) {
	if (e.getButton() == 1 && this._isArmed) this.doClick();
	this.setArmed(false);
	e.cancelBubble = true;
	
	//still highlights, the mouse still over it
	if (this.isTopLevelMenu()) this.__selectionManager__.setSelectedPath([this.parentMenu,this]);
}
AtJsMenuAbstractButton.prototype.processMouseEvent = function(e) {
	var oCont = this.getContainer();
	if (!this.__selectionManager__ || !oCont || (oCont && !oCont.isReady())) return;
	this['_process_' + e.type](e);
}

AtJsMenuAbstractButton.__onmouseover__ = function(e) { if (!e || !e.getButton) e = AtJsMenuEvent();
	if (!e.fromElement || this.contains(e.fromElement)) return; //this == menu item component
	if ((typeof AtJsMenu).charAt(0) == 'f') AtJsMenu.__objects__[this.id].processMouseEvent(e);
	e.cancelBubble = true; return true;
}
AtJsMenuAbstractButton.__onmouseout__ = function(e) { if (!e || !e.getButton) e = AtJsMenuEvent();
	if (!e.toElement || this.contains(e.toElement)) return; //this == menu item component
	if ((typeof AtJsMenu).charAt(0) == 'f') AtJsMenu.__objects__[this.id].processMouseEvent(e);
	e.cancelBubble = true; return true;
}
AtJsMenuAbstractButton.__onmousedownup__ = function(e) { if (!e || !e.getButton) e = AtJsMenuEvent();
	AtJsMenu.__objects__[this.id].processMouseEvent(e); //this == menu item component
}


/******************* == Menu Bar Icon == **********************/
function AtJsMenuBarIcon(icon) {
	AtJsMenuAbstractButton.call(this,null,icon);
}
AtJsMenuBarIcon.prototype = new AtJsMenuAbstractButton();
AtJsMenuBarIcon.prototype._normalClassName = 'AtJsMenuButton-icon';
AtJsMenuBarIcon.prototype._hoverClassName = 'AtJsMenuButton-hover-icon';
AtJsMenuBarIcon.prototype._selectClassName = 'AtJsMenuButton-select-hover-icon';
AtJsMenuBarIcon.prototype._selectHoverClassName = 'AtJsMenuButton-select-hover-icon';

AtJsMenuBarIcon.prototype._setComponent = function(oComp) {
	this._drawIcon(oComp);
}
AtJsMenuBarIcon.prototype.__setComponent__ = function(oComp) {
	var oComp1 = (oComp.cells ? oComp.cells[0] : oComp);
	AtJsMenuAbstractButton.prototype.__setComponent__.call(this, oComp1);
}
AtJsMenuBarIcon.prototype.setMnemonic = function(iKeyCode) {
	this._mnemonic = 0;
}
AtJsMenuBarIcon.prototype.setText = function(sText) {
	this.text = '';
}
AtJsMenuBarIcon.prototype.setEnabled = function(bEnabled) {
	this._enabled = true;
}
AtJsMenuBarIcon.prototype.doClick = function() {
	AtJsMenu.showCopyright();
}


/******************* == Menu Item == **********************/
function AtJsMenuItem(sText,icon) {
	AtJsMenuAbstractButton.call(this,null,icon);
	this.setText(sText);
	this._accelerator = {keyCode: 0, modifiers: 0};
}
AtJsMenuItem.prototype = new AtJsMenuAbstractButton();

AtJsMenuItem.prototype._setComponent = function(oComp) { //Abstract Method
	if (this.isTopLevelMenu()) {
		__proto__ = AtJsMenuAbstractButton.prototype;
		this._normalClassName = __proto__._normalClassName;
		this._hoverClassName = __proto__._hoverClassName;
		this._selectClassName = __proto__._selectClassName;
		this._selectHoverClassName = __proto__._selectHoverClassName;
		if (oComp.cells) {
			this._drawIcon(oComp.cells[0]);
			this._setAcceleratorText(oComp.cells[2]);
		} else if (this.icon) {
			if (navigator.family!='IE6') {
				this.icon.align = 'absmiddle'; //if icon is an IMG element
			}
			if (oComp.firstChild) oComp.insertBefore(this.icon, oComp.firstChild);
			else oComp.appendChild(this.icon);
		}
	} else {
		this._normalClassName = 'AtJsMenuItem';
		this._hoverClassName = 'AtJsMenuItem hover';
		this._selectClassName = 'AtJsMenuItem';
		this._selectHoverClassName = 'AtJsMenuItem hover';
		this._drawIcon(oComp.cells[0]);
		this._setAcceleratorText(oComp.cells[2]);
	}
}

AtJsMenuItem.prototype._getTextContainerComponent = function() {
	if (!this.getComponent()) return null;
	else if (this.getComponent().cells) return this.getComponent().cells[1];
	return this.getComponent();
}

AtJsMenuItem.prototype._setAcceleratorText = function(oTextCont) {
	while(oTextCont.childNodes.length) oTextCont.removeChild(oTextCont.childNodes[0]);
	if (AtJsMenuKeys) {
		var sShortcut = AtJsMenuKeys.getKeyText(this._accelerator.keyCode);
		var sModifiers = AtJsMenuKeys.getKeyModifiersText(this._accelerator.modifiers);
		if (sShortcut && sModifiers) sShortcut = sModifiers + '+' + sShortcut;
		if (sShortcut) oTextCont.appendChild(document.createTextNode(sShortcut));
		else oTextCont.appendChild(document.createTextNode(String.fromCharCode(160)));
	} else
		oTextCont.appendChild(document.createTextNode(String.fromCharCode(160)));
}

AtJsMenuItem.prototype.getIndex = function() {
	if (!this.getComponent()) return -1;
	if (this.isTopLevelMenu()) return (this._getIndex() - 1);
	return this._getIndex();
}

AtJsMenuItem.prototype.setArmed = function(bArmed) {
	if (this.isTopLevelMenu()) AtJsMenuAbstractButton.prototype.setArmed.call(this,bArmed);
}

AtJsMenuItem.prototype.setAccelerator = function(iKeyCode,iModifiers) {
	var arShortcuts = AtJsMenuSelectionManager.__menuShortcuts__;
	var iOldKeyCode = this._accelerator.keyCode, iOldModifiers = this._accelerator.modifiers;
	if (arShortcuts[iOldModifiers][iOldKeyCode]) delete arShortcuts[iOldModifiers][iOldKeyCode];
	if (iKeyCode) arShortcuts[iModifiers][iKeyCode] = this;
	this._accelerator.keyCode = iKeyCode; this._accelerator.modifiers = iModifiers;
	var oComp = this.getComponent();
	if (oComp) this._setAcceleratorText(oComp.cells[2]);
}
AtJsMenuItem.prototype.getAccelerator = function() {
	return {keyCode: this._accelerator.keyCode, modifiers: this._accelerator.modifiers};
}

AtJsMenuItem.prototype._process_mousedown = function(e) {
	if (this.isTopLevelMenu()) AtJsMenuAbstractButton.prototype._process_mousedown.call(this,e);
}
AtJsMenuItem.prototype._process_mouseup = function(e) {
	if (this.isTopLevelMenu()) AtJsMenuAbstractButton.prototype._process_mouseup.call(this,e);
	else if (e.getButton() == 1) this.doClick();
}


/******************* == Menu == **********************/
AtJsMenu.prototype = new AtJsMenuItem();

AtJsMenu.__setSelectionManager__ = function(oMenu) {
	oMenu._popup.__selectionManager__ = oMenu.__selectionManager__;
	var iItemCount = oMenu.getItemCount();
	for (var i=0; i<iItemCount; i++) { var oItem = oMenu.getItem(i); if (!oItem) continue;
		oItem.__selectionManager__ = oMenu.__selectionManager__;
		if (oItem instanceof AtJsMenu) AtJsMenu.__setSelectionManager__(oItem);
	}
}

AtJsMenu.prototype._setComponent = function(oComp) {
	AtJsMenuItem.prototype._setComponent.call(this,oComp);
	AtJsMenu.__setSelectionManager__(this);
	if (oComp.cells) {
		oComp.cells[2].replaceChild(AtJsMenu.subSign.cloneNode(true), oComp.cells[2].firstChild);
		oComp.cells[2].className = 'arrow';
	}
}

AtJsMenu.prototype.setAccelerator = function(iKeyCode,iModifiers) {
	this._accelerator.keyCode = 0; this._accelerator.modifiers = 0;
}

AtJsMenu.prototype.doClick = function() {
}

AtJsMenu.prototype.getItem = function(idx) {
	return this._popup.getItem(idx);
}

AtJsMenu.prototype.getItemCount = function() {
	return this._popup.getItemCount();
}

AtJsMenu.prototype.getPopupMenu = function() {
	return this._popup;
}

AtJsMenu.prototype.insert = function(oMenuItem,idx) {
	this._popup.insert(oMenuItem,idx);
}
AtJsMenu.prototype.add = function(oMenuItem) {
	this.insert(oMenuItem);
}
AtJsMenu.prototype.insertSeparator = function(idx) {
	this._popup.insertSeparator(idx);
}
AtJsMenu.prototype.addSeparator = function() {
	this.insertSeparator();
}
AtJsMenu.prototype.remove = function(idx) {
	this._popup.remove(idx);
}

AtJsMenu.prototype._openTopMenu = function() {
	if (!this._enabled) return;
	var oComp = this._component, oMenuBar = this.parentMenu, oPopupComp = this._popup.getComponent(), iLeft, iTop;
	if (this.__contentSrc__) new AtJsMenuRemoteSubXmlDataset(this.__contentSrc__,this);
	var oCoord = getElementCoordOnPage(oComp);
	if (oMenuBar.getLayout() == AtJsMenuBar.HORIZONTAL) {
		iLeft = oCoord.x;
		if (oMenuBar.isReverseDirection) iTop = oCoord.y - oPopupComp.offsetHeight - 1;
		else iTop = oCoord.y + oComp.offsetHeight + 1;
		if (iTop < getWinTopSide()) iTop = getWinTopSide();
		iLeft += oPopupComp.offsetWidth;
		if (iLeft > getWinRightSide()) iLeft = getWinRightSide();
		iLeft -= oPopupComp.offsetWidth;
		if (iLeft < getWinLeftSide()) iLeft = getWinLeftSide();
		if (oMenuBar.isReverseDirection) this._popup.show(iLeft,iTop,'north');
		else this._popup.show(iLeft,iTop,'south');
	} else if (oMenuBar.getLayout() == AtJsMenuBar.VERTICAL) {
		if (oMenuBar.isReverseDirection) iLeft = oCoord.x - oPopupComp.offsetWidth - 1;
		else iLeft = oCoord.x + oComp.offsetWidth + 1;
		if (iLeft < getWinLeftSide()) iLeft = getWinLeftSide();
		iTop = oCoord.y + oPopupComp.offsetHeight;
		if (iTop > getWinBottomSide()) iTop = getWinBottomSide();
		iTop -= oPopupComp.offsetHeight;
		if (iTop < getWinTopSide()) iTop = getWinTopSide();
		if (oMenuBar.isReverseDirection) this._popup.show(iLeft,iTop,'west');
		else this._popup.show(iLeft,iTop,'east');
	}
	this._isPopupVisible = true;
	this.__selectionManager__.__setFocusedElm__();
}
AtJsMenu.prototype._openSubMenu = function() {
	if (!this._enabled) return;
	if (this.__contentSrc__) new AtJsMenuRemoteSubXmlDataset(this.__contentSrc__,this);
	var oComp = this._component;
	var oPopupComp = this._popup.getComponent();
	var oCoord = getElementCoordOnPage(oComp);
	var iTop = oCoord.y - 3 + oPopupComp.offsetHeight; //bottom side coord, 3~=border+padding
	if (iTop > getWinBottomSide()) iTop = getWinBottomSide();
	iTop -= oPopupComp.offsetHeight; //top side's coord
	if (iTop < getWinTopSide()) iTop = getWinTopSide();
	var sDirection = 'east';
	var iLeft = oCoord.x + oComp.offsetWidth + oPopupComp.offsetWidth - 2; //right side's coord, 2~=padding
	if (iLeft > getWinRightSide()) { iLeft = oCoord.x + 2; sDirection = 'west'; }
	iLeft -= oPopupComp.offsetWidth; //left side's coord
	if (iLeft < getWinLeftSide()) iLeft = getWinLeftSide();
	var oParentPopup=((this.parentMenu instanceof AtJsMenu)?this.parentMenu.getPopupMenu():this.parentMenu);
	var iZIndex = parseInt(oParentPopup.getComponent().style.zIndex);
	oPopupComp.style.zIndex = iZIndex + 1;
	this._popup.show(iLeft,iTop,sDirection);
	this._isPopupVisible = true;
	this.__selectionManager__.__setFocusedElm__();
}
AtJsMenu.prototype._close = function() {
	AtJsMenuPopup.__clearAllTimer__();
	this._popup.setVisible(false);
	this._isPopupVisible = false;
	this.__selectionManager__.__setFocusedElm__();
}
AtJsMenu.prototype._pressTopMenu = function() {
	if (!this._enabled) return;
	AtJsMenu.closeAllOpenMenu();
	this.parentMenu.__idxOpenItem__ = this._getIndex(); //Selects this menu
	this.__selectionManager__.setSelectedPath([this.parentMenu,this]);
}
AtJsMenu.prototype._releaseTopMenu = function() {
	AtJsMenu.closeAllOpenMenu(); //close this menu
	this.__selectionManager__.setSelectedPath([this.parentMenu,this]); //highlight this menu
		// (still has focus, e.g. the mouse is still over it)
}

AtJsMenu.prototype._isPressed = function() {
	return this._isPopupVisible;
}
AtJsMenu.prototype.setSelected = function(bSelected) {
	if (!this.getComponent()) return;
	//while (oLast = this.__selectionManager__.getLastSelectedMenu(), (oLast!=this && oLast!=null)) {
	//}
	this._isPopupVisible = (this._enabled && this.isTopLevelMenu() && bSelected && this.parentMenu.__idxOpenItem__!=-1);
	this._setCssClass(bSelected);
	
	if (this._selected == bSelected) return;
	this._selected = bSelected;
	if (this.isTopLevelMenu()) {
		if (bSelected) {
			if (this.parentMenu.__idxOpenItem__ != -1) {
				this._openTopMenu();
				this.parentMenu.__idxOpenItem__ = this._getIndex();
			}
		} else {
			this._close();
		}
	} else {
		if (!bSelected) this._close();
	}
}
AtJsMenu.prototype.isSelected = function() {
	return this._selected;
}
AtJsMenu.prototype.isPopupVisible = function() {
	return this._isPopupVisible;
}
AtJsMenu.prototype.menuSelectionChanged = function(bIncluded) {
	this.setSelected(bIncluded);
}
AtJsMenu.prototype.setEnabled = function(bEnabled) {
	AtJsMenuAbstractButton.prototype.setEnabled.call(this,bEnabled);
	if (!bEnabled && this._isPopupVisible) AtJsMenu.closeAllOpenMenu();
}

AtJsMenu.prototype.onchange = function(e) {
}

AtJsMenu.prototype._highlightFirstChild = function() {
	if (!this._isPopupVisible) return;
	var i=0, j=this.getItemCount(), oItem=this.getItem(i); while(!oItem && i<j) oItem=this.getItem(++i);
	if (oItem) this.__selectionManager__.pushPathElement(oItem);
}
AtJsMenu.prototype._highlightLastChild = function() {
	if (!this._isPopupVisible) return;
	var i=this.getItemCount()-1, oItem=this.getItem(i); while (!oItem && i >=0) oItem=this.getItem(--i);
	if (oItem) this.__selectionManager__.pushPathElement(oItem);
}
AtJsMenu.prototype._process_key_Enter = function(arPath) { //Enter
	if (this._isPopupVisible) {
		if (this.isTopLevelMenu()) this._releaseTopMenu();
		else AtJsMenu.closeAllOpenMenu();
	} else {
		if (this.isTopLevelMenu()) this._pressTopMenu(); else this._openSubMenu();
		this._highlightFirstChild();
	}
}
AtJsMenu.prototype._process_keyup_Enter = function(arPath) {
}
AtJsMenu.prototype._process_key_Esc = function(arPath) { //Escape
	if (this.isTopLevelMenu()) {
		if (this._isPopupVisible) this._releaseTopMenu();
		else AtJsMenu.closeAllOpenMenu();
	} else {
		if (this._isPopupVisible) this._close();
		else AtJsMenuAbstractButton.prototype._process_key_Esc.call(this,arPath);
	}
}
AtJsMenu.prototype._process_key_Left = function(arPath) { //Left arrow
	if (this.isTopLevelMenu()) {
		if (this.parentMenu.getLayout() == AtJsMenuBar.HORIZONTAL) this._moveToPreviousSibling(true);
		else if (this.parentMenu.getLayout() == AtJsMenuBar.VERTICAL) this._releaseTopMenu();
	} else {
		if (this._isPopupVisible) this._close();
		else AtJsMenuAbstractButton.prototype._process_key_Left.call(this,arPath);
	}
}
AtJsMenu.prototype._process_key_Up = function(arPath) { //Up arrow
	if (this._isPopupVisible) {
		this._highlightLastChild();
	} else if (this.isTopLevelMenu() && this.parentMenu.getLayout() == AtJsMenuBar.HORIZONTAL) {
		this._pressTopMenu();
		this._highlightLastChild();
	} else {
		AtJsMenuAbstractButton.prototype._process_key_Up.call(this,arPath);
	}
}
AtJsMenu.prototype._process_key_Right = AtJsMenu.prototype.__process_key_Right__ = function(arPath) { //Right arrow
	if (this.isTopLevelMenu()) {
		if (this.parentMenu.getLayout() == AtJsMenuBar.HORIZONTAL) this._moveToNextSibling(true);
		else if (this.parentMenu.getLayout() == AtJsMenuBar.VERTICAL && !this._isPopupVisible) {
			this._pressTopMenu();
			this._highlightFirstChild();
		}
	} else {
		if (this._isPopupVisible) AtJsMenuAbstractButton.prototype._process_key_Right.call(this,arPath);
		else {
			this._openSubMenu();
			this._highlightFirstChild();
		}
	}
}
AtJsMenu.prototype._process_key_Down = function(arPath) { //Down arrow
	if (this._isPopupVisible) this._highlightFirstChild();
	else if (this.isTopLevelMenu() && this.parentMenu.getLayout() == AtJsMenuBar.HORIZONTAL) this._process_key_Enter();
	else AtJsMenuAbstractButton.prototype._process_key_Down.call(this,arPath);
}

AtJsMenu.prototype._process_mouseover = function(e) {
	if (!this._isPopupVisible) {
		this.__selectionManager__.processMouseOver(this);
		if (!this.isTopLevelMenu()) this._openSubMenu();
	}
}
AtJsMenu.prototype._process_mouseout = function(e) {
	if (!this._isPopupVisible) this.__selectionManager__.processMouseOut(this);
	this._isArmed = false;
}
AtJsMenu.prototype._process_mousedown = function(e) {
	if (!this.isTopLevelMenu()) return;
	if (e.getButton() == 1) {
		if (this.parentMenu.__idxOpenItem__ != this._getIndex()) this._pressTopMenu();
		else if (this._enabled) this._isArmed = true;
		e.returnValue = false;
	} else
		AtJsMenu.closeAllOpenMenu();
	e.cancelBubble = true;
}
AtJsMenu.prototype._process_mouseup = function(e) {
	if (!this.isTopLevelMenu()) return;
	if (this._isArmed) this._releaseTopMenu();
	this._isArmed = false;
	e.cancelBubble = true;
}


/******************* == Checked Menu Item Base == **********************/
function AtJsMenuCheckedItemAbstract(sText,icon,bSelected) {
	AtJsMenuItem.call(this,sText,icon);
	this.setSelected(bSelected==true);
	this.value = '';
	this._checkerSign = null;
}
AtJsMenuCheckedItemAbstract.prototype = new AtJsMenuItem();
AtJsMenuCheckedItemAbstract.prototype._isToggle = true;

AtJsMenuCheckedItemAbstract._iconCache = null; //especially for IE for .ico image
AtJsMenuCheckedItemAbstract.prototype._fillIconCell = function() {
	if (this.icon && this._selected) {
		if (!this._iconCache) {
			this._iconCache = document.createElement('DIV');
			this._iconCache.style.display = 'none';
		}
		this._iconCache.appendChild(this.icon); //especially for IE for .ico image, I don't know why
	}
	var oIconCell = this._component.cells[0];
	while(oIconCell.childNodes.length) oIconCell.removeChild(oIconCell.childNodes[0]);
	if (this._selected) oIconCell.appendChild(this._checkerSign);
	else this._drawIcon(oIconCell);
}
AtJsMenuCheckedItemAbstract.prototype._setComponent = function(oComp) {
	AtJsMenuItem.prototype._setComponent.call(this,oComp);
	if (!this.isTopLevelMenu()) this._fillIconCell();
}

AtJsMenuCheckedItemAbstract.prototype.onchange = function(e) {
}
AtJsMenuCheckedItemAbstract.prototype._setSelected = function() { //Abstract Method
}
AtJsMenuCheckedItemAbstract.prototype.setSelected = function(bSelected) {
	var bLastState = this._selected;
	if (this.isTopLevelMenu()) {
		AtJsMenuAbstractButton.prototype.setSelected.call(this,bSelected);
	} else {
		if (this._selected == bSelected) return;
		this._selected = bSelected;
		if (this.getComponent()) this._fillIconCell();
	}
	this._setSelected();
	
	if (bLastState == this._selected) return;
	var e = {src: this, cancelBubble: false};
	var oMenuElm = this;
	while (!e.cancelBubble && oMenuElm) {
		if (oMenuElm instanceof AtJsMenuBar || oMenuElm instanceof AtJsMenuPopup) {
			AtJsMenu.onchange(e); break;
		}
		oMenuElm.onchange(e);
		oMenuElm = oMenuElm.parentMenu;
	}
}


/******************* == Checkbox Menu Item == **********************/
function AtJsMenuCheckBoxItem(sText,icon,bSelected) {
	AtJsMenuRequestParamHolder.call(this);
	AtJsMenuCheckedItemAbstract.call(this,sText,icon,bSelected);
	this._checkerSign = AtJsMenu.checkSign.cloneNode(true);
}
AtJsMenuCheckBoxItem.prototype = new AtJsMenuCheckedItemAbstract();
AtJsMenuCheckBoxItem.prototype.setInterface(AtJsMenuRequestParamHolder);

AtJsMenuCheckBoxItem.prototype._setSelected = function() {
	if (this.value === null) this.value = '';
	if (this._selected) this.setRequestParamValue(this.value); else this.removeRequestParam();
}

AtJsMenuCheckBoxItem.prototype._doClick = function() {
	this.setSelected(!this._selected);
}

AtJsMenuCheckBoxItem.prototype.setValue = function(val) {
	var bSelected = (val !== null);
	this.setSelected(bSelected);
	this.setRequestParamValue(val);
	this.value = (bSelected ? val : '');
}

AtJsMenuCheckBoxItem.prototype.getValue = function() {
	return (this._selected ? this.value : null);
}


/******************* == Radio Button Menu Item == **********************/
function AtJsMenuRadioButtonItem(sText,icon,bSelected,sValue) {
	AtJsMenuCheckedItemAbstract.call(this,sText,icon,bSelected);
	this._buttonGroup = null;
	this.value = (sValue+'');
	this._checkerSign = AtJsMenu.radioSign.cloneNode(true);
}
AtJsMenuRadioButtonItem.prototype = new AtJsMenuCheckedItemAbstract();

AtJsMenuRadioButtonItem.prototype._doClick = function() {
	this.setSelected(true);
}

AtJsMenuRadioButtonItem.prototype._setSelected = function() {
	if (this._buttonGroup) {
		this._buttonGroup.setSelected(this, this._selected);
		this._buttonGroup.setRequestParamValue(this.value);
	}
}

AtJsMenuRadioButtonItem.prototype.setGroup = function(oButtonGroup) {
	if (typeof(oButtonGroup) != 'object') return;
	if (oButtonGroup != null) if (!(oButtonGroup instanceof AtJsMenuButtonGroup)) return;
	if (this._buttonGroup == oButtonGroup) return;
	if (this._buttonGroup) this._buttonGroup.remove(this);
	this._buttonGroup = oButtonGroup;
	if (oButtonGroup) oButtonGroup.add(this);
}


/******************* == Button Group == **********************/
function AtJsMenuButtonGroup() {
	this._buttons = [];
}
AtJsMenuButtonGroup.prototype = new AtJsMenuRequestParamHolder();

AtJsMenuButtonGroup.prototype._getButtonIndex = function(oRadioButtonMenuItem) {
	var arButtons = this._buttons, iLength = this._buttons.length;
	for (var i=0; i<iLength; i++) if (arButtons[i] === oRadioButtonMenuItem) return i;
	return -1;
}

AtJsMenuButtonGroup.prototype._setOnlyOneSelected = function(idx) {
	var arButtons = this._buttons;
	if (arButtons.length == 0) return;
	var arSelectedIdxs = [];
	if (idx >= 0) if (arButtons[idx].isSelected()) arSelectedIdxs[0] = idx;
	for (var i=0; i<arButtons.length; i++)
		if (arButtons[i].isSelected() && i != idx) arSelectedIdxs[arSelectedIdxs.length] = i;
	if (arSelectedIdxs.length == 0) arButtons[0].setSelected(true); //Must have one selected
	else  //Only one selected is allowed;
		  //the button whose index specified by parameter 'idx', has highest priority
		for (var i=1; i<arSelectedIdxs.length; i++)
			arButtons[ arSelectedIdxs[i] ].setSelected(false);
}

AtJsMenuButtonGroup.prototype.add = function(oRadioButtonMenuItem) {
	var i = this._getButtonIndex(oRadioButtonMenuItem);
	if (i >= 0) return;
	this._buttons[this._buttons.length] = oRadioButtonMenuItem;
	this._setOnlyOneSelected(this._buttons.length-1);
	oRadioButtonMenuItem.setGroup(this);
}

AtJsMenuButtonGroup.prototype.remove = function(oRadioButtonMenuItem) {
	var i = this._getButtonIndex(oRadioButtonMenuItem);
	if (i == -1) return;
	var iLength = this._buttons.length - 1;
	while (i < iLength) this._buttons[i] = this._buttons[i+1];
	this._buttons.length = iLength;
	this._setOnlyOneSelected(-1);
	oRadioButtonMenuItem.setGroup(null);
}

AtJsMenuButtonGroup.prototype.getButtonCount = function() {
	return this._buttons.length;
}

AtJsMenuButtonGroup.prototype.getButtons = function() {
	return this._buttons;
}

AtJsMenuButtonGroup.prototype.setSelected = function(oRadioButtonMenuItem,bSelected) {
	var i = this._getButtonIndex(oRadioButtonMenuItem);
	if (i == -1) return;
	if (oRadioButtonMenuItem.isSelected() != bSelected) {
		oRadioButtonMenuItem.setSelected(bSelected);
		return;
	}
	this._setOnlyOneSelected(i);
}

AtJsMenuButtonGroup.prototype.setValue = function(val) {
	var arButtons = this._buttons, j = this._buttons.length;
	var oRadioButtonMenuItem = null;
	for (var i=0; i<j; i++) if (arButtons[i].value == val) {
		oRadioButtonMenuItem = arButtons[i];
		break;
	}
	if (oRadioButtonMenuItem == null) return;
	oRadioButtonMenuItem.setSelected(true);
}

AtJsMenuButtonGroup.prototype.getValue = function() {
	var arButtons = this._buttons, j = this._buttons.length;
	for (var i=0; i<j; i++) if (arButtons[i].isSelected()) return arButtons[i].value;
	return null;
}


/******************* == Global Event handler == ********************/
document.addEventListener('mousedown', AtJsMenu.closeAllOpenMenu, false);
document.addEventListener('keydown', AtJsMenuSelectionManager.processKeyDown, true);
document.addEventListener('keyup', AtJsMenuSelectionManager.processKeyUp, true);

