var ContextMenu = {
			open : function(e, cContents, opts){
				var evt = e || window.event;
				this.evt = evt;
				var oSourceElement = this.evt.target || this.evt.srcElement;
				if(typeof this.sourceElement != 'undefined'){
					if(oSourceElement == this.sourceElement && typeof(this.oParent) != 'undefined'){
						if(this.oParent.style.display == '')
							return false;
					}
				}
				clearTimeout(ContextMenu.showTimeout);
				clearTimeout(ContextMenu.hideTimeout);
				this.sourceElement = oSourceElement;
				this.clientX = this.evt.clientX;
				this.clientY = this.evt.clientY;
				this._loadOptions(opts);
				if(cContents.indexOf('.') > -1){
					this.isAjax = true;
					var nMouseoverDelayInSeconds = this.ajaxDelayInSeconds;
				}else{
					this.isAjax = false;
					var nMouseoverDelayInSeconds = this.delayInSeconds;
				}
				this.showTimeout = setTimeout(function(){
					ContextMenu._showMenu(cContents);
					Ajax.requestType = 'GET';
					Ajax.Execute(cContents , function(cResponse){
						if(document.getElementById('divContextMenuLoading')){
							ContextMenu.oParent.innerHTML = cResponse;
							ContextMenu._positionMenu();
							ContextMenu.onComplete();
						}
					});
					Ajax.requestType = 'POST';
					if(!ContextMenu.isAjax)
						ContextMenu.onComplete();
					} , nMouseoverDelayInSeconds );				
				if(typeof(this.sourceElement.hasContextMenuEvents) == 'undefined' && this.closeOnMouseOut == true){
					EventManager.Add(this.sourceElement ,'mouseout', function(){ContextMenu._sourceElementMouseOut()});
					this.sourceElement.hasContextMenuEvents = 'true';
				}
				return this;
			},
			close :function (){
				clearTimeout(this.showTimeout);
				if(typeof this.oParent != 'undefined'){
					this.oParent.style.display = 'none';
					if(typeof this.oIframe != 'undefined')
						this.oIframe.style.display = 'none';
				}
			},
			_loadOptions : function (opts){
				this.opts = opts || {};
				this.hideTimeout = null;
				this.showTimeout = null;
				this.onComplete = this.opts.onComplete || function(){};
				this.delayInSeconds = this.opts.delayInSeconds * 1000 || .1 * 1000;
				this.ajaxDelayInSeconds = this.opts.ajaxDelayInSeconds * 1000 || .7 * 1000;
				this.menuWidth = this.opts.menuWidth || '300px';
				this.className = this.opts.className || 'gs-contextMenu';
				this.closeOnMouseOut = this.opts.closeOnMouseOut != undefined ? this.opts.closeOnMouseOut : true;
			},
			_sourceElementMouseOut : function (){
				if(this.evt.relatedTarget){
					this.toElement = this.evt.relatedTarget;
				}else if(this.evt.toElement){
					this.toElement = this.evt.toElement;
				}
				this.hideTimeout = setTimeout(function(){
						if(ContextMenu.toElement != ContextMenu.oParent && ContextMenu.toElement != ContextMenu.sourceElement){
							ContextMenu.close();
						}
					},'500');
			},
			_menuMouseOut : function (){
				if(this.evt.relatedTarget){
					this.toElement = this.evt.relatedTarget;
				}else if(this.evt.toElement){
					this.toElement = this.evt.toElement;
				}
				this.hideTimeout = setTimeout(function(){
						if(!ContextMenu.isChildNode(ContextMenu.oParent, ContextMenu.toElement)){
							ContextMenu.close();
						}
					},'500');
			},
			_showLoading : function(){
				var oDiv = document.createElement('DIV');
				oDiv.style.textAlign="center";
				oDiv.style.width = this.menuWidth;
				var oLoadingDiv = document.createElement('DIV');
				oLoadingDiv.className = 'gs-contextMenuLoading';
				oLoadingDiv.id = 'divContextMenuLoading';
				oLoadingDiv.style.margin = '20px auto';
				oDiv.appendChild(oLoadingDiv);
				var oDivMain = this.oParent;
				oDivMain.innerHTML = '';
				oDivMain.appendChild(oDiv);
			},
			_showMenu : function(cContents){
					this._appendMenu();
					this.oParent = document.getElementById('divContextMenuParent');
					if(this.isAjax == true){
						this._showLoading();
					}else{
						this.oParent.innerHTML = document.getElementById(cContents).innerHTML;
					}
					this._positionMenu();
			},
			_appendMenu : function (){
				if(!document.getElementById('divContextMenuParent')){
					var oBody = document.getElementsByTagName('body')[0];
					this.oParent = document.createElement('div');
					oBody.appendChild(this.oParent);
					this.oParent.id	= 'divContextMenuParent';
					this.oParent.style.position	= 'absolute';
					this.oParent.style.width = this.menuWidth;
					this.oParent.style.zIndex	= '100';
					this.oParent.style.display	= 'none';
					this.oParent.className=ContextMenu.className;
					if(this.closeOnMouseOut == true){
						EventManager.Add(this.oParent ,'mouseout', function(){ContextMenu._menuMouseOut()});
					}
					EventManager.Add(this.oParent ,'mouseover', function(){clearTimeout(ContextMenu.hideTimeout);});
				}
			},
			_appendIframeShim : function (nElementWidth , nElementHeight){ // <=IE 6 selectlist fix
				if(typeof this.oIframe == 'undefined' && (document.all && !window.opera && typeof document.body.style.maxHeight == "undefined")){
					this.oIframe = document.createElement('IFRAME');
					this.oIframe.style.position = 'absolute';
					this.oIframe.style.zIndex = (this.oParent.style.zIndex - 1);
					this.oIframe.src="javascript:false;"
					this.oIframe.frameBorder="0";
					this.oIframe.scrolling="no";
					var oBody = document.getElementsByTagName('body')[0];
					oBody.appendChild(this.oIframe);
				}
				this._positionIframeShim(nElementWidth , nElementHeight)
			},
			_positionIframeShim : function (nElementWidth , nElementHeight){ // <=IE 6 selectlist fix
				if(typeof this.oIframe != 'undefined'){
					this.oIframe.style.width = nElementWidth + 'px';
					this.oIframe.style.height = nElementHeight + 'px';
					this.oIframe.style.top = this.oParent.style.top;
					this.oIframe.style.left = this.oParent.style.left;
					this.oIframe.style.display = '';
				}
			},
			_positionMenu : function (){
				this.oParent.style.top = this.clientY + 'px';
				this.oParent.style.left = this.clientX + 'px';
				this.oParent.style.display = '';
				var arrWindowSize = this._getWindowSize();
				var nClientWidth = arrWindowSize[0];
				var nClientHeight = arrWindowSize[1];
				var rightedge=nClientWidth-this.clientX;
				var bottomedge=nClientHeight-this.clientY;
				var oBody = document.documentElement || document.body;
				var nElementWidth = this.oParent.contentWidth || this.oParent.offsetWidth;
				var nElementHeight = this.oParent.contentHeight || this.oParent.offsetHeight;
				if (rightedge<nElementWidth)
					this.oParent.style.left= typeof(window.pageXOffset) == 'undefined' ? oBody.scrollLeft+this.clientX-nElementWidth+"px" : window.pageXOffset+this.clientX-nElementWidth+"px"
				else
					this.oParent.style.left=typeof(window.pageXOffset) == 'undefined' ? oBody.scrollLeft+(this.clientX)+"px" : window.pageXOffset+(this.clientX)+"px"
				if (bottomedge<nElementHeight){
					this.oParent.style.top=typeof(window.pageYOffset) == 'undefined' ? oBody.scrollTop+this.clientY-nElementHeight+"px" : window.pageYOffset+this.clientY-nElementHeight+"px"
					this.oParent.style.left= ((this.oParent.style.left.replace(/px/gi,'') * 1 )+ 2 ) + 'px'
				}else
					this.oParent.style.top=typeof(window.pageYOffset) == 'undefined' ? oBody.scrollTop+this.clientY+"px" : window.pageYOffset+this.clientY+"px"
				this._appendIframeShim(nElementWidth , nElementHeight);
			},
			_getWindowSize :  function() {
				var myWidth = 0, myHeight = 0;
				if(typeof( window.innerWidth ) == 'number' ) {
					myWidth = window.innerWidth;
					myHeight = window.innerHeight;
				} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
					myWidth = document.documentElement.clientWidth;
					myHeight = document.documentElement.clientHeight;
				} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
					myWidth = document.body.clientWidth;
					myHeight = document.body.clientHeight;
				}
				return [myWidth, myHeight];
			},
			isChildNode : function(a, b) {
				while (b.parentNode)
					if ((b = b.parentNode) == a)
						return true;
				return false;
			}
		}