/****
	DHTML Widget: AT JsMenu version 1.4 (20060627)
    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 7+
		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-2006 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.
*****/

/***** Global Identifiers ******/
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 and it may not*/
	this._isPopupVisible = false;
}
AtJsMenu.__objects__ = {}; //stores all instance objects of menu element

//Because the name of widget is AT JsMenu then they are attached become properties of class AtJsMenu
AtJsMenu.delayOpen = 0;
AtJsMenu.chunkPerSizeOpen = 5;

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.4\n'
		+ 'Copyright \xA9 2001-2006 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: '',

_setItemComponent: function(oComp) { //Abstract Method
},
__setItemComponent__: function(oComp) {
	this._component = oComp;
	this._setItemComponent(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._setItemComponent = function(oComp) {
}
AtJsMenuSeparator.prototype.__setItemComponent__ = function(oComp,cons) {
	AtJsMenuElement.call(this,oComp,null);
	oComp.className = 'AtJsMenuSeparator';
	oComp.setAttribute('__AtJsMenuSeparator__', 1);
	oComp.onmouseover = AtJsMenuSeparator.__onmouseover__;
	this._setItemComponent(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);
		this.__isReady__ = true; //especially for popup
		AtJsMenu.__objects__[oComp.id] = this;
	}
}
AtJsMenuContainer.prototype = new AtJsMenuElement();
AtJsMenuContainer.prototype._realConstructor = AtJsMenuContainer;

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._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.__setItemComponent__(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.__setItemComponent__(null);
		delete AtJsMenu.__objects__[oItem.id];
	}
	idx = parseInt(idx);
	if (!isNaN(idx) && idx >= 0 && idx < this.getItemCount()) this._removeComponentAt(idx);
}

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.__setItemComponent__(oComp);
}
AtJsMenuContainer.prototype.addSeparator = function() {
	this.insertSeparator();
}


/******************* == Menu Bar == **********************/
function AtJsMenuBar(sId,icon) {
	var oMenuBarComp = document.getElementById(sId); if (!oMenuBarComp) return;
	AtJsMenuContainer.call(this,oMenuBarComp,icon);
	oMenuBarComp.className = 'AtJsMenuBar';
	var oTbl = oMenuBarComp.appendChild(document.createElement('TABLE'));
	oTbl.style.borderStyle = 'none'; oTbl.cellSpacing = 0;
	oTbl.setAttribute('__AtJsMenuBar__',1);
	var oTR = oTbl.insertRow(0);
	this.__idxOpenItem__ = -1;
	this._containerComponent = oTR;
	//EF this.add(new AtJsMenuBarIcon(icon)); retrait du copyright
}
AtJsMenuBar.prototype = new AtJsMenuContainer();
AtJsMenuBar.prototype._realConstructor = AtJsMenuBar;

AtJsMenuBar.prototype._getContainerComponent = function() {
	if (this._containerComponent && this._containerComponent.tagName=='TR') return this._containerComponent;
	var oBar = document.getElementById(this._id);
	for (var i=0; i<oBar.childNodes.length; i++) {
		var oChild = oBar.childNodes[i];
		if (oChild.tagName=='TABLE' && oChild.getAttribute('__AtJsMenuBar__'))
			return (this._containerComponent=oChild.rows[0]);
	}
}

AtJsMenuBar.prototype._getNewItemComponent = function(idx) {
	return this._getContainerComponent().insertCell(idx);
}
AtJsMenuBar.prototype._removeComponentAt = function(idx) {
	this._getContainerComponent().deleteCell(idx);
}
AtJsMenuBar.prototype._getNewSeparatorComponent = function(idx) {
	return this._getNewItemComponent(idx);
}

AtJsMenuBar.prototype.menuSelectionChanged = function(bIncluded) {
	if (!bIncluded) this.__idxOpenItem__ = -1;
}

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.remove = function(idx) {
	if (!isNaN(idx)) idx += 1;
	AtJsMenuContainer.prototype.remove.call(this,idx);
}
AtJsMenuBar.prototype.insertSeparator = function(idx) {
	AtJsMenuContainer.prototype.insertSeparator.call(this,idx+1);
}

/******************* == Menu Bar Seperator == **********************/
AtJsMenuBar.Separator = function() {
}
AtJsMenuBar.Separator.prototype = new AtJsMenuSeparator();

AtJsMenuBar.Separator.prototype._setItemComponent = function(oComp) {
	oComp.appendChild(AtJsMenu.verticalSeparatorSign.cloneNode(true));
}


/******************* == Menu == **********************/
function AtJsMenuPopup() {
	var oPopupComp = document.createElement('DIV');
	oPopupComp.id = '__AtJsMenuPopup' + (++AtJsMenuPopup.__idxCounter) + '__';
	oPopupComp.className = 'AtJsMenuPopup';
	oPopupComp.style.zIndex = AtJsMenu._zIndexMin;
	oPopupComp.style.position = 'absolute';
	oPopupComp.style.visibility = 'hidden';
	oPopupComp.style.textAlign = 'left';
	document.body.appendChild(oPopupComp);
	var oTbl = document.createElement('TABLE');
	oTbl.cellSpacing = 0;
	oTbl.appendChild(document.createElement('TBODY'));
	oPopupComp.appendChild(oTbl);
	AtJsMenuContainer.call(this,oPopupComp,null);
	this._containerComponent = oTbl.tBodies[0];
	this.__isReady__ = false; //if not fully shown (hidden or still slided)
	oPopupComp.onmousedown = AtJsMenuPopup.__onmousedown__;
}
AtJsMenuPopup.prototype = new AtJsMenuContainer();
AtJsMenuPopup.prototype._realConstructor = AtJsMenuPopup;
AtJsMenuPopup.__timerId__ = null;
AtJsMenuPopup.__idxCounter = 0;

AtJsMenuPopup.prototype._getNewItemComponent = function(idx) {
	var oTbl = this.getComponent().childNodes[0];
	var oTR = oTbl.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;
}
AtJsMenuPopup.prototype._removeComponentAt = function(idx) {
	this.getComponent().childNodes[0].deleteRow(idx);
}
AtJsMenuPopup.prototype._getNewSeparatorComponent = function(idx) {
	var oTbl = this.getComponent().childNodes[0];
	var oTR = oTbl.insertRow(idx);
	var oTD = oTR.insertCell(0);
	oTD.colSpan = 3;
	return oTR;
}

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'; }
};
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'; },
east: function(oPopupComp) {
	oPopupComp.style.left = (parseInt(oPopupComp.style.left)-oPopupComp.offsetWidth) + 'px'; }
};

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);
	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);
	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.__show__ = 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__ = null;
		AtJsMenu.__objects__[sPopupCompId].__isReady__ = true;
	} else AtJsMenuPopup.__timerId__ = window.setTimeout(
		'AtJsMenuPopup.__show__("'+sPopupCompId+'",'+(iStep+1)+',"'+sDir1+'","'+sDir2+'",'+iTop+','+iLeft+')',
		AtJsMenu.delayOpen);
}

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.style.left = iLeft + "px";
	oPopupComp.style.top = iTop + "px";
	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) {
		this.__isReady__ = false;
		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__ = window.setTimeout(
			'AtJsMenuPopup.__show__("'+oPopupComp.id+'",1,"'+arDir[0]+'","'+arDir[1]+'",'+iTop+','+iLeft+')',
			AtJsMenu.delayOpen);
	} else
		this.__isReady__ = true;
	oPopupComp.style.visibility = 'visible';
	if (!this.__owner__) this.__selectionManager__.setSelectedPath([this]);
}

AtJsMenuPopup.prototype.showOnInvoker = function(oInvoker,iX,iY) {
	oCoords = getElementCoordOnPage(oInvoker);
	iX += getWinLeftSide() + oCoords.x; iY += getWinTopSide() + 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.setVisible = function(bVisible) {
	this.getComponent().style.visibility = (bVisible ? 'visible' : 'hidden');
	this.__isReady__ = bVisible;
	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 elemnt 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._setItemComponent = 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.__setItemComponent__ = 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._setItemComponent(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;
	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.__timerId__ !== null) 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()) {
		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._moveToPreviousSibling(true);
}
AtJsMenuAbstractButton.prototype._process_key_Right = function(arPath) { //Right arrow
	if (this.isTopLevelMenu()) {
		this._moveToNextSibling(true);
	} else {
		var oParent = this.parentMenu;
		while (oParent instanceof AtJsMenu && !oParent.isTopLevelMenu()) oParent = oParent.parentMenu;
		if (oParent instanceof AtJsMenu) oParent.__process_key_Right__();
	}
}
AtJsMenuAbstractButton.prototype._process_key_Down = function(arPath) { //Down arrow
	if (!this.isTopLevelMenu()) 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._setItemComponent = function(oComp) {
	this._drawIcon(oComp);
}

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.onclick = function(e) {
	AtJsMenu.showCopyright();
	e.cancelBubble = true;
}


/******************* == 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._setItemComponent = 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;
	} 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.isTopLevelMenu()) return this.getComponent();
	else if (this.getComponent()) return this.getComponent().cells[1];
	return null;
}

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._setItemComponent = function(oComp) {
	AtJsMenuItem.prototype._setItemComponent.call(this,oComp);
	AtJsMenu.__setSelectionManager__(this);
	if (!this.isTopLevelMenu()) {
		oComp.cells[2].replaceChild(AtJsMenu.subSign.cloneNode(true), oComp.cells[2].childNodes[0]);
		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;
	var oCoord = getElementCoordOnPage(oComp);
	var iLeft = oCoord.x;
	var iTop = oCoord.y + oComp.offsetHeight + 1;
	var oPopupComp = this._popup.getComponent();
	iLeft += oPopupComp.offsetWidth;
	if (iLeft > getWinRightSide()) iLeft = getWinRightSide();
	iLeft -= oPopupComp.offsetWidth;
	if (iLeft < getWinLeftSide()) iLeft = getWinLeftSide();
	this._popup.show(iLeft,iTop,'south');
	this._isPopupVisible = true;
	this.__selectionManager__.__setFocusedElm__();
}
AtJsMenu.prototype._openSubMenu = function() {
	if (!this._enabled) return;
	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() {
	if (AtJsMenuPopup.__timerId__ !== null) {
		window.clearTimeout(AtJsMenuPopup.__timerId__);
		AtJsMenuPopup.__timerId__ = null;
	}
	with (this._popup.getComponent().style) { visibility = "hidden"; zIndex = AtJsMenu._zIndexMin;
		clip = 'rect(auto auto auto auto)'; }
	this._popup.__isReady__ = false;
	this._isPopupVisible = false;
	this.__selectionManager__.__setFocusedElm__();
}
AtJsMenu.prototype._pressTopMenu = function() {
	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.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() {
	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() {
	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()) {
		this._moveToPreviousSibling(true);
	} 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._pressTopMenu();
		this._highlightLastChild();
	} else {
		AtJsMenuAbstractButton.prototype._process_key_Up.call(this,arPath);
	}
}
AtJsMenu.prototype._process_key_Right = function(arPath) { //Right arrow
	if (this.isTopLevelMenu()) {
		this._moveToNextSibling(true);
	} else {
		if (this._isPopupVisible) {
			AtJsMenuAbstractButton.prototype._process_key_Right.call(this,arPath);
		} else {
			this._openSubMenu();
			this._highlightFirstChild();
		}
	}
}
AtJsMenu.prototype.__process_key_Right__ = AtJsMenu.prototype._process_key_Right;
AtJsMenu.prototype._process_key_Down = function(arPath) { //Down arrow
	if (this._isPopupVisible) this._highlightFirstChild();
	else if (this.isTopLevelMenu()) 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 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._setItemComponent = function(oComp) {
	AtJsMenuItem.prototype._setItemComponent.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);
