function PCSMenu(MenuId, ClientId){
	this.Groups = new Array();
	this.Menu=null;
	this.MenuId=MenuId;
	this.ClientId=ClientId;
	this.GroupCssClass=null;
	this.ItemCssClass=null;
	this.ItemLabelCssClass=null;
	this.ItemHoverCssClass=null;
	this.LeftImageCssClass=null;
	this.RightImageCssClass=null;
	this.SeperatorCssClass=null;
	this.CollapseDelay=500;
	this.BaseImagePath=null;
	this.LeftArrowImageURL=null;
	this.RightArrowImageURL=null;
	this.giCurrentRowID=null;
	this.giCurrentRowFullID=null;
	this.CallbackArguments=null;
	this.DynamicCallbackArguments=null;
	this.MenuImages = new Array();
	this.MinWidth=null;
	this.MaxHeight=null;
	this.MatchSrcElementWidth=null;
	this.RightAlign=null;
	this.DropShadowOffset=2;
	this.Props=new Array();
	this.Props=['GroupCssClass','GroupCellSpacing','BaseImagePath','ItemCssClass','ItemHoverCssClass','ItemLabelCssClass',
	'LeftImageCssClass','RightImageCssClass','LeftArrowImageURL','RightArrowImageURL','SeperatorCssClass'];
	this.Size = function(MinWidth,MaxHeight,Match){
		if(MinWidth=='null') MinWidth=null;
		if(MaxHeight=='null') MaxHeight=null;
		if(Match=='null') Match=null;
		this.MinWidth=MinWidth;
		this.MaxHeight=MaxHeight;
		this.MatchSrcElementWidth = Match;
		return this;
	}
	this.Align = function(align){
		if(!align) return this;
		this.RightAlign = (align.toLowerCase() == 'right');
		return this;
	}
	this.onCollapse=null;
}
function PCSMenuHideLoader(menuid,groupid){
	document.getElementById(groupid + '_loader').style.display='none';
	document.getElementById(groupid + '_iframe').style.display='inline';
	window[menuid].GetGroup(groupid).Reposition();
	document.getElementById(groupid + '_iframe').focus();
	//document.frames[groupid + '_iframe'].document.all.cboRegistrant.focus();
}
PCSMenu.prototype.Show=function(groupid, el, callbackTarget){
	
	this.DynamicCallbackArguments='';
	var Group = this.GetGroup(groupid);	
	if(!Group) alert('ERROR: The menu item (' + groupid + ') does not exist!');
	if(Group.ExternalURL){
		this.ShowURL(groupid,el,Group.ExternalURL);
		return;
	}
	
	if(!Group.ParentGroup){
		this.HideAll();
	}else{
		for(var i=0;i<this.Groups.length;i++){
			if(this.Groups[i].ParentGroup == Group.ParentGroup && this.Groups[i].GroupId != Group.GroupId && this.Groups[i].Visible){
				this.Groups[i].ForceHide();
			}
		}
	}
	
	if(Group.Visible) return;
	
	Group.MinWidth = (this.MinWidth!=null ? this.MinWidth : Group.OriginalMinWidth);
	Group.MaxHeight = (this.MaxHeight!=null ? this.MaxHeight : Group.OriginalMaxHeight);
	Group.RightAlign = (this.RightAlign!=null ? this.RightAlign : Group.OriginalRightAlign);
	Group.MatchSrcElementWidth = (this.MatchSrcElementWidth!=null ? this.MatchSrcElementWidth : Group.OriginalMatchSrcElementWidth);
	
	this.MinWidth=null;
	this.MaxHeight=null;
	this.RightAlign=null;
	this.MatchSrcElementWidth=null 
	
	var MenuDiv = Group.BuildMenu();
	var callbackArguments;
	var callbackArgument='';
	
	if (arguments.length > 3)
		callbackArguments = new Array(arguments.length - 4);
	else
		callbackArguments = new Array(0);
	
	for (var i=0;i<arguments.length;i++){
		if (i>2) callbackArguments[i-3] = this.EvaluateString(arguments[i]);
	}
	
	callbackArgument=callbackArguments.join(String.fromCharCode(123));
	
	if(callbackArgument != ''){
		this.CallbackArguments = callbackArgument;
	}else{
		if(this.CallbackArguments != null){
			callbackArgument = this.CallbackArguments;
		}
	}
	
	this.DynamicCallbackArguments=callbackArgument;
	
	if(!el){
		if(Group.ParentGroup){
			//If this is a sub group then we must ensure the src element is the menu row and not one of the cells or divs
			var src = event.srcElement
			var i=0;
			while(src.tagName != 'TR'){
				src = src.parentElement;
				i++
				if(i>10) return;
			}
			Group.srcElement = src;
		}else{
			Group.srcElement = event.srcElement;
			this.giCurrentRowID=giCurrentRowID;
			this.giCurrentRowFullID=giCurrentRowFullID;
		}
	}else{
		Group.srcElement=el;
		if(!Group.ParentGroup){
			 this.giCurrentRowID=giCurrentRowID;
			 this.giCurrentRowFullID=giCurrentRowFullID;
		}
	}
	
	//See if any groups are currently open. If so, then don't do any event handling
	var bfound=false;
	if(Group.ParentGroup){
		for(var i=0;i<this.Groups.length;i++){
			if(this.Groups[i].Visible && this.Groups[i].GroupId != Group.GroupId && this.Groups[i].ParentGroup == Group.ParentGroup){
				bfound=true;
				break;
			}
		}
	}
	
	if(!Group.LeaveOpen && !bfound){
		this.addEvent(MenuDiv,'mouseleave', function(){Group.BeginHide()});
		this.addEvent(MenuDiv,'mouseenter', function(){Group.StopHide()});
		this.addEvent(Group.srcElement,'mouseleave', function(){Group.BeginHide()}, false);
		this.addEvent(Group.srcElement,'mouseenter', function(){Group.StopHide()}, false);
	}
	
	if(!Group.MinWidth) Group.MinWidth=0;
	if(!Group.MaxHeight) Group.MaxHeight=0;
	if(!Group.RightAlign) Group.RightAlign=false;

	if(Group.LoadByCallback) Group.DisplayCallbackLoadingMessage();
	
	Group.Reposition();
	
	MenuDiv.style.visibility='visible';
	
	Group.Visible=true;
	Group.StopHide();
	Group.Active=true;
	
	if(Group.LoadByCallback){
		var Menu = this;
		var target = (Group.LoadByCallbackTarget=='' ? Menu.ClientId : Group.LoadByCallbackTarget);
		if(callbackTarget) target = callbackTarget;
		var temparray = new Array();
		if(Group.LoadByCallbackArguments || callbackArgument != ''){
			//if(Group.LoadByCallbackArguments){
				for(var i=0;i<Group.LoadByCallbackArguments.length;i++){
					temparray[i] = this.EvaluateString(Group.LoadByCallbackArguments[i]);
				}
			//}
			var args = temparray.join(String.fromCharCode(123));
			if(callbackArgument != ''){
				if(args != '') args = args + String.fromCharCode(123);
				args = args + callbackArgument;
			}
			if(Group.LoadByCallbackAssembly != ''){
				Callback.Constructor(target,PCSMenuCallback,Menu.MenuId + '|' + Group.Index,false,true).AjaxCallback('ASSEMBLY', 
					Group.LoadByCallbackAssembly, Group.LoadByCallbackNamespace, Group.LoadByCallbackMethod, args);
			}else{ 
				Callback.Constructor(target,PCSMenuCallback,Menu.MenuId + '|' + Group.Index,false,true).AjaxCallback(Group.GroupId,args);
			}
		}else{
			Callback.Constructor(target,PCSMenuCallback,Menu.MenuId + '|' + Group.Index,false,true).AjaxCallback(Group.GroupId);
		}
	}else{
		Group.Reposition();
	}
}
PCSMenu.prototype.HideAll=function(){
	for(var i=0; i<this.Groups.length; i++){
		if(this.Groups[i].Visible && !this.Groups[i].Opening){
			this.Groups[i].Active=false;
			this.Groups[i].Visible=false;
			this.Groups[i].Visible=false;
			this.Groups[i].ForceHide();
		}
	}
	this.CallbackArguments='';
}
PCSMenu.prototype.GetCallbackArgument=function(index){
	var arg = this.DynamicCallbackArguments.split(String.fromCharCode(123));
	return arg[index];
}
PCSMenu.prototype.EvaluateString=function(arrayelement){
	var value=null;
	if(arrayelement.indexOf('/') > -1) return arrayelement;
	try{
		value=eval(arrayelement);
	}catch(e){
	}
	if(!value) return arrayelement;
	return value;
}
function PCSMenuCallback(args,context){
	var temp = context.split('|');
	var Menu = window[temp[0]];
	var Group = Menu.Groups[temp[1]];
	setHTML(Menu.Decode(args), Group.MenuDiv);
	//Group.MenuDiv.innerHTML = Menu.Decode(args);
	Group.Reposition();
}

PCSMenu.prototype.Init=function (props,groups,items){
    for(var i=0;i<props.length;i++){
		if(props[i]) this[this.Props[i]] = props[i];
	}
    this.InitGroups(groups);    
    this.InitItems(items);
    this.Menu=this;
    var menu=this;
	if(this.LeftArrowImageURL != null && this.LeftArrowImageURL != ''){
		this.LeftArrowImageURL=this.BaseImagePath + this.LeftArrowImageURL;
		var img = new Image();
		img.src = this.LeftArrowImageURL;
		this.Menu.MenuImages[this.Menu.MenuImages.length] = img;
	}
	
	if(this.RightArrowImageURL != null && this.RightArrowImageURL != ''){
		this.RightArrowImageURL=this.BaseImagePath + this.RightArrowImageURL;
		var img = new Image();
		img.src = this.RightArrowImageURL;
		this.Menu.MenuImages[this.Menu.MenuImages.length] = img;
	}
}
PCSMenu.prototype.InitGroups=function(groups){
	for (var i=0; i<groups.length; i++){
        var group=new PCSMenuGroup();
        group.Menu=this;
        group.Index=this.Groups.length;
        group.Init(groups[i]);
        this.Groups[this.Groups.length]=group; 
    }
}

PCSMenu.prototype.GetGroup=function(id){
	if(typeof(id)=='undefined') return this.Groups;
	if(typeof(id)=='number') return this.Groups[id];
	for(var i=0;i<this.Groups.length;i++){
		if(this.Groups[i].GroupId.toLowerCase() == id.toLowerCase()){
			return this.Groups[i];
		}
	}
}

PCSMenu.prototype.InitItems=function(items){
	for (var i=0; i<items.length; i++){
		var itm=new PCSMenuItem();
		itm.Menu=this;
		if(items[i]) itm.Init(items[i]); 
	}
}

PCSMenu.prototype.addEvent=function(obj, evType, fn)
{
	var evTypeRef = '__' + evType;
	if (obj[evTypeRef]){
		if (this.array_search(fn, obj[evTypeRef]) > -1) return;
	}else{
		obj[evTypeRef] = [];
		if (obj['on'+evType]) obj[evTypeRef][0] = obj['on'+evType];
		obj['on'+evType] = this.handleEvent;
	}
	obj[evTypeRef][obj[evTypeRef].length] = fn;
}

PCSMenu.prototype.removeEvent=function(obj, evType, fn)
{
	var evTypeRef = '__' + evType;
	if (obj[evTypeRef]){
		var i = this.array_search(fn, obj[evTypeRef]);
		if (i > -1) delete obj[evTypeRef][i];
	}
}

PCSMenu.prototype.handleEvent=function(e)
{
	e = e || window.event;
	var evTypeRef = '__' + e.type, retValue = true;

	for (var i = 0, j = this[evTypeRef].length; i < j; i++){
		if (this[evTypeRef][i]){
			this.__fn = this[evTypeRef][i];
			retValue = this.__fn(e) && retValue;
		}
	}

	if (this.__fn) try { delete this.__fn; } catch(e) { this.__fn = null; }

	return retValue;
}

PCSMenu.prototype.array_search=function(val, arr)
{
	var i = arr.length;
	while (i--){
		if (arr[i] && arr[i].toString() == val.toString()){
			break;
		}
	}
	return i;
}
PCSMenu.prototype.HandleEvent= function (eventName,eventArgs){
    switch (eventName){
        case "mouseover":
			event.srcElement.className=this.ItemHoverCssClass;
        break;
        case "mouseout":
			event.srcElement.className=this.ItemCssClass;
        break;
        case "click":
			var temp1 = this.ReplaceAll(this.ReplaceAll(eventArgs,'Group',''), 'Item','');
			var temp2 = temp1.split('_');
			var GroupIndex = temp2[0];
			var ItemIndex = temp2[1];
			this.Groups[GroupIndex].Items[ItemIndex].Click();
		break;
    }
}
PCSMenu.prototype.Decode=function(val){
	if(val.indexOf('[ENCODED]') > -1){
		var temp = this.ReplaceAll(val,'[ENCODED]','');
		temp = this.ReplaceAll(temp,'&quot;','"');
		return temp;
	}
	return val;
}

PCSMenu.prototype.ReplaceAll=function(str,from,to){
	var idx = str.indexOf(from);
	while ( idx > -1 ) {
		str = str.replace( from, to ); 
		idx = str.indexOf( from );
	}
	return str;
}
PCSMenu.prototype.ShowURL=function(groupid, el, url){
		
	var Group = this.GetGroup(groupid);
	if(!Group.ParentGroup){
		this.HideAll();
	}else{
		for(var i=0;i<this.Groups.length;i++){
			if(this.Groups[i].ParentGroup == Group.ParentGroup && this.Groups[i].GroupId != Group.GroupId && this.Groups[i].Visible){
				this.Groups[i].ForceHide();
			}
		}
	}
	if(Group.Visible) return;
	Group.Opening=true;
	var MenuDiv = Group.BuildMenu();
	
	if(!el){
		if(Group.ParentGroup){
			//If this is a sub group then we must ensure the src element is the menu row and not one of the cells or divs
			var src = event.srcElement
			var i=0;
			while(src.tagName != 'TR'){
				src = src.parentElement;
				i++
				if(i>10) return;
			}
			Group.srcElement = src;
		}else{
			Group.srcElement = event.srcElement;
			this.giCurrentRowID=giCurrentRowID;
			this.giCurrentRowFullID=giCurrentRowFullID;
		}
	}else{
		Group.srcElement=el;
		if(!Group.ParentGroup){
			 this.giCurrentRowID=giCurrentRowID;
			 this.giCurrentRowFullID=giCurrentRowFullID;
		}
	}
	
	//See if any groups are currently open. If so, then don't do any event handling
	var bfound=false;
	if(Group.ParentGroup){
		for(var i=0;i<this.Groups.length;i++){
			if(this.Groups[i].Visible && this.Groups[i].GroupId != Group.GroupId && this.Groups[i].ParentGroup == Group.ParentGroup){
				bfound=true;
				break;
			}
		}
	}
	if(!Group.LeaveOpen && !bfound){
		this.addEvent(MenuDiv,'mouseleave', function(){Group.BeginHide()});
		this.addEvent(MenuDiv,'mouseenter', function(){Group.StopHide()});
		this.addEvent(Group.srcElement,'mouseleave', function(){Group.BeginHide()}, false);
		this.addEvent(Group.srcElement,'mouseenter', function(){Group.StopHide()}, false);
	}
	
	if(!Group.MinWidth) Group.MinWidth=0;
	if(!Group.MaxHeight) Group.MaxHeight=0;
	if(!Group.RightAlign) Group.RightAlign=false;
		
	var loader = document.createElement('table');
	var row = document.createElement('tr');
	var col = document.createElement('td');
	loader.id=Group.GroupId+'_loader';
	loader.style.width='100%';
	loader.style.height='100%';
	col.valign='middle';
	col.align='center';
	col.innerHTML = '<SPAN id="LoadingLabel">Loading...</SPAN>&nbsp;<IMG height="16" src="../images/loading.gif" width="16" align="absMiddle" border="0">'
	row.appendChild(col);
	loader.appendChild(row);
	
	Group.ToggleLoading(true,'Loading...');
	MenuDiv.innerHTML = MenuDiv.innerHTML + 
		'<iframe scrolling="no" style="display: none;" onload="PCSMenuHideLoader(\'' + this.MenuId + '\',\'' + Group.GroupId + '\')" id="' + Group.GroupId + '_iframe" src="' + this.EvaluateString(url) + '" width=100% height=100%></iframe>';
	
	Group.Reposition();
	
	MenuDiv.style.visibility='visible';
	
	Group.Visible=true;
	
	Group.Reposition();
	
	setTimeout(function(){Group.Opening=false},50);
	
}