// Copyright (C) 2008 Cognos ULC, an IBM Company. All rights reserved.
// Cognos and the Cognos logo are trademarks of Cognos ULC, (formerly Cognos Incorporated).

//static property an array that has all the instances of CCPopupMenu
CCPopupMenu.menus = new Array();

//static property the currently active menu
CCPopupMenu.activeMenu = null;

//Used to temporarily ignore all onclick events - this mechanism
//gives other containers a chance to react to the onclick event.
CCPopupMenu.bIgnoreHideActiveMenu = false;

CCPopupMenu.minSize = 3;

var sPopUpWebRoot = "..";  // default this to a relative location

if (window.g_PS_getWebRoot)
{
	if (g_PS_getWebRoot() != "")
		sPopUpWebRoot = g_PS_getWebRoot();  // set up the official path to the C8 web root
}

CCPopupMenu.imagesRoot = sPopUpWebRoot + "/ps";
CCPopupMenu.psImagesPath = CCPopupMenu.imagesRoot + "/images";
CCPopupMenu.portalImagesPath = CCPopupMenu.imagesRoot + "/portal/images";

//creates an event handler for the given event.  Note that events should be assume the w3c names not the 
//ie names as this function will create the correct event type name based on the browser
function addEvent(obj, evType, fn)
{ 
	if (obj.addEventListener)
	{ 
		obj.addEventListener(evType, fn, false); 
		return true; 
	} else if (obj.attachEvent)
	{ 
		var r = obj.attachEvent("on"+evType, fn); 
		return r; 
	} else
	{ 
		return false; 
	} 
}


//removes the function fn from the event listeners for the object and the particular event
function removeEvent( obj, type, fn ) 
{ 
  if (obj.removeEventListener)
	return obj.removeEventListener( type, fn, false ); 
  else if ( obj.detachEvent ) 
	return obj.detachEvent( 'on'+type, fn ); 
  else 
	return false;
} 

//returns the width of the browser window
function windowWidth()
{
	if (window.innerWidth)
	{
		return window.innerWidth;
	}	
	else
	{
		return document.body.offsetWidth  - 20;	
	}	
}

//returns the height of the drop down based on the style or the offsetHeight 
function getDropDownHeight(dropDownElement)
{
	if (dropDownElement.style.height == "") {
		var height = dropDownElement.offsetHeight;

		if (window.navigator.userAgent.indexOf("Gecko") != -1) {
			var paddingTop = dropDownElement.style.paddingTop;
			var indexOfPX = paddingTop.indexOf("px");
			var v = ((indexOfPX != -1) ? parseInt(paddingTop.substring(0, indexOfPX)) : parseInt(paddingTop));
			height -= (isNaN(v) ? 0 : v);

			var paddingBottom = dropDownElement.style.paddingBottom;
			var indexOfPX = paddingBottom.indexOf("px");
			v = ((indexOfPX != -1) ? parseInt(paddingBottom.substring(0, indexOfPX)) : parseInt(paddingBottom));
			height -= (isNaN(v) ? 0 : v);

			var borderWidth = 1;
			height -= (2 * borderWidth);
		}
		return height;
	} else {
		//return teh style height converted to an integer
		var styleHeight = dropDownElement.style.height;
		var indexOfPX = styleHeight.indexOf("px");
		if (indexOfPX != -1) {
			styleHeight = styleHeight.substring(0, indexOfPX);
		}
		return parseInt(styleHeight);	
	}
	
}

//returns the width of the drop down based on the style or the offsetWidth 
function getDropDownWidth(dropDownElement)
{
	if (dropDownElement.style.width == "") {
		var width = dropDownElement.offsetWidth;

		if (window.navigator.userAgent.indexOf("Gecko") != -1) {
			var paddingLeft = dropDownElement.style.paddingLeft;
			var indexOfPX = paddingLeft.indexOf("px");
			var v = ((indexOfPX != -1) ? parseInt(paddingLeft.substring(0, indexOfPX)) : parseInt(paddingLeft));
			width -= (isNaN(v) ? 0 : v);

			var paddingRight = dropDownElement.style.paddingRight;
			var indexOfPX = paddingRight.indexOf("px");
			v = ((indexOfPX != -1) ? parseInt(paddingRight.substring(0, indexOfPX)) : parseInt(paddingRight));
			width -= (isNaN(v) ? 0 : v);

			var borderWidth = 1;
			width -= (2 * borderWidth);
		}
		return width;
	} else {
		//return teh style width converted to an integer
		var styleWidth = dropDownElement.style.width;
		var indexOfPX = styleWidth.indexOf("px");
		if (indexOfPX != -1) {
			styleWidth = styleWidth.substring(0, indexOfPX);
		}
		return parseInt(styleWidth);	
	}
}

//get the offset for the scrolling 
function getScrollXY() {
  var scrOfX = 0, scrOfY = 0;
  if( typeof( window.pageYOffset ) == 'number' ) {
    //Netscape compliant
    scrOfY = window.pageYOffset;
    scrOfX = window.pageXOffset;
  } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
    //DOM compliant
    scrOfY = document.body.scrollTop;
    scrOfX = document.body.scrollLeft;
  } else if( document.documentElement &&
      ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
    //IE6 standards compliant mode
    scrOfY = document.documentElement.scrollTop;
    scrOfX = document.documentElement.scrollLeft;
  }
  return [ scrOfX, scrOfY ];
}


//returns the width of the browser window
function windowHeight()
{
	//have to account for the vertical scroll to get a good idea where we are at	
	if (window.innerHeight)
	{
		return window.innerHeight + getScrollXY()[1];;
	}	
	else
	{
		return document.body.offsetHeight + getScrollXY()[1];	
	} 	
}

//unfortunately netscape and firefox do not correctly support overflowY.  To enable removal of the horizontal 
//scrollbar in these browsers you must use a gecko(??some component of these browsers???) specific value for overflow 
//called -moz-scrollbars-vertical
function setOverflowStyle(anEl)
{
	//Gecko is the relevant thing we are looking for here as -moz-scrollbars-vertical is apparently defined in this component
	if (window.navigator.userAgent.indexOf("Gecko") != -1)
		anEl.style.overflow = "-moz-scrollbars-vertical";
	else
		anEl.style.overflowY = "auto";
}

//sets the focus to the element with the id equal to the controlId of the menu associated with id
//if the element does not exist then do nothing
function CCPopupMenu_setControlFocus()
{
	var currentMenu = CCPopupMenu.getMenu(CCPopupMenu.activeMenu.id);
	var controlElement = document.getElementById(currentMenu.controlId);
	if (controlElement != null)
		controlElement.focus();
}


function CCPopupMenu_checkBounds(event)
{
	if(typeof event != "undefined" && event != null)
	{
		var tr = event.srcElement;
		var table = tr.parentNode;
		var id= CCPopupMenu.activeMenu.id;
		if(tr.tagName == 'TR')
		{
			if( window.event.keyCode == '27' || window.event.keyCode == '13')
			{
				return true;
			}
			if(tr.rowIndex == 0 && event.shiftKey && event.shiftKey != false)
			{
					CCPopupMenu.hideActiveMenu();
					CCPopupMenu.setControlFocus();
					return false;
			} else if ((tr.rowIndex+1) == table.rows.length && window.event.shiftKey == false)
			{
					CCPopupMenu.hideActiveMenu();
					CCPopupMenu.setControlFocus();
					return false;
			}
		}
	}
	return true;
}

//static method to close the currextly open drop down menu
function CCPopupMenu_hideActiveMenu()
{
	if (!CCPopupMenu.bIgnoreHideActiveMenu && CCPopupMenu.activeMenu != null)
		CCPopupMenu.activeMenu.removeDropDown();
}

function CCPopupMenu_ignoreHideActiveMenu(ignore)
{
	CCPopupMenu.bIgnoreHideActiveMenu = (ignore == "ignore") ? true : false;
}

//static method to create an iframe that is positioned under the dropdown so that controls don't show through
function CCPopupMenu_createInsulatingIframe(currentMenu, divEl)
{
	var iframeEl = document.createElement("iframe");
	iframeEl.id = currentMenu.id + "inslIframe";
	iframeEl.style.display="block";
	iframeEl.style.border="0px";
	iframeEl.style.padding="2px";
	iframeEl.style.position="absolute";
	iframeEl.style.zIndex = "1";
	
	iframeEl.src=CCPopupMenu.psImagesPath + "/space.gif";
	
	var controlEl = document.getElementById(currentMenu.controlId);
	controlEl.appendChild(iframeEl);
	
	iframeEl.style.top = divEl.style.top;
	iframeEl.style.left = divEl.style.left;
	iframeEl.style.height = divEl.offsetHeight;
	iframeEl.style.width = divEl.offsetWidth;
}

function CCPopupMenu_sizeDropDown(dropDownElement,maxHeight, elementHeight)
{
	//size the height of the drop down if a height was given
	//this is to support scrolling of menu items (to ensure the drop down is not humungous)
	if (this.mnHeight != -1)
	{
		var elems = dropDownElement.getElementsByTagName('td');
		providedHeight = elementHeight * this.mnHeight;
		
		var allowableHieght = Math.min(maxHeight, providedHeight );
		var allowableHieght = providedHeight;
		if (dropDownElement.offsetHeight > allowableHieght)	
		{
			dropDownElement.style.height= allowableHieght  + "px";
		}
	}
	else
	{
		
		if (getDropDownHeight(dropDownElement) > maxHeight)	
		{
			dropDownElement.style.height= maxHeight + "px";
		}
	}
}

//updates the height of the browser and determines whether to open the browser up or down
function CCPopupMenu_fitHeightToBrowser(x,y)
{

	var dropDownElement = this.dropDownElement;
	getDropDownWidth(dropDownElement);
	var winHeight = windowHeight();
	var originalMenuHeight = this.mnHeight;
	var originalHeight = getDropDownHeight(dropDownElement);
	var originalWidth = getDropDownWidth(dropDownElement);
	dropDownElement.style.height = originalHeight + "px";

	var controlElement = document.getElementById(this.controlId);
	var controlElementTop = y;
	var controlElementHeight = 0;
	if (controlElement != null)
	{
		controlElementTop = controlElement.offsetTop;
		controlElementHeight = getDropDownHeight(controlElement);
	}
	
	//determine how much space we have above the control element and how much space we have below	
	var spaceAboveControl = Math.max(0,controlElementTop);
	var spaceBelowControl = Math.max(0,winHeight - controlElementTop - controlElementHeight);
	
	//determine the height of a menu item
	var elems = dropDownElement.getElementsByTagName('td');
	var elementHeight = 20;
	if (elems.length > 0)
		elementHeight = getDropDownHeight(elems[1]);
	
	//find the minumum number of items to show based on what is smaller the number of menu items available or the 
	//default minimum items to show
	var minimumDropSize = Math.min(CCPopupMenu.minSize, this.menuItems.length) * elementHeight;
		
	//try and size the drop down as if droped below
	
	this.sizeDropDown(dropDownElement,spaceBelowControl, elementHeight);
	
	var downHeight = getDropDownHeight(dropDownElement);
	var downWidth = getDropDownWidth(dropDownElement);
	
	//try and size the drop down as if droped above
	dropDownElement.style.height = originalHeight + "px";
	dropDownElement.style.width =originalWidth + "px";
	
	this.sizeDropDown(dropDownElement,spaceAboveControl, elementHeight);
	var upHeight = getDropDownHeight(dropDownElement);
	var upWidth = getDropDownWidth(dropDownElement);
	
	dropDownElement.style.height = originalHeight + "px";
	dropDownElement.style.width =originalWidth + "px";
	
		
	//now check what is better to show the menu droped down or dropped up
	if (downHeight < upHeight)
	{
		//if the size of the drop down would be less than the min size in the drop down or drop up case
		//then force the min size
		if (upHeight < minimumDropSize)
		{
			//if we are forcing the height to be the minimum then we may as well just open down
			dropDownElement.style.height = minimumDropSize + "px";
			dropDownElement.style.top = y + controlElement.offsetHeight + "px";
		}
		else	
		{
			//in this case we should show it up
			dropDownElement.style.top = (controlElementTop - upHeight) + "px";
			dropDownElement.style.width = upWidth + "px";
		}	
	}
	else
	{
		//droping down is better so restore the size to the drop down scenario
		
		//if the size of the drop down would be less than the min size in the drop down or drop up case
		//then force the min size
		if (downHeight < minimumDropSize)
		{
			downHeight = minimumDropSize;
		}	
		dropDownElement.style.width = downWidth + "px";
		dropDownElement.style.height = downHeight + "px";
		dropDownElement.style.top = y + controlElement.offsetHeight + "px";
	}
	
	//must check to see if we have shrunk the menu so that we need to show scrollbars
		
	if (getDropDownHeight(dropDownElement) < originalHeight)
	{
		//have to account for the scroll bars....if there are verticle bars then must widen the div a little
		//NOTE: because we may change the width of the menu, we have to do the width positioning after this step!!!
		dropDownElement.style.width=(getDropDownWidth(dropDownElement) + 20) + "px";
		setOverflowStyle(dropDownElement);
	}
	this.mnHeight = originalMenuHeight; 
}

//determines the width of the browser to ensure nothing falls off the edge of the browser
function CCPopupMenu_fitWidthToBrowser(x, y)
{
	var controlElement = document.getElementById(this.controlId);
	if (controlElement == null)
		//if we can't find the control element....give up
		return;
	
	var controlElementLeft = controlElement.offsetLeft;
	var dropDownElement = this.dropDownElement;
	
	//position the drop down based on the size of the browser window 
	var winWidth = windowWidth();
	var dropDownRight = controlElementLeft + dropDownElement.offsetWidth;
	//if what was provided would pass off the right of the browser
	//move the popup so that is flush with the right (with a small margin) of the of the browser to get it
	//close to where you wanted it but not letting anything fall off the edge
	if (winWidth < dropDownRight)
	{
		var dropDownLeft = controlElement.offsetWidth - dropDownElement.offsetWidth;
		var dropDownAbsoluteLeft = controlElementLeft + dropDownLeft;
		if (dropDownAbsoluteLeft < 0)
		{
			//in this case we have very little room to show the menu so we need to position it to 
			//take up the entire width of the window
			dropDownElement.style.left = controlElement.offsetLeft * -1;
		}
		else
		{
			dropDownElement.style.left = (controlElement.offsetWidth - dropDownElement.offsetWidth) + "px";
		}	
	}
	else
	{
		dropDownElement.style.left = x + "px";
	}		
}

//static method to create and show the drop down for the menu with the passed in id
function CCPopupMenu_dropDown(event,x,y,id)
{
	if (event.type == "keypress" && event.keyCode == 9)
		return true; //Ignore tabs.
		
	var currentMenu = CCPopupMenu.getMenu(id);
	if (currentMenu != null)
	{
		//check to make sure the menu was created
		if (currentMenu.dropDownElement == null)
			return;
			
		//make sure that if there is a menu already open to close it
		var isAlreadyOpen = false;
		if ((CCPopupMenu.activeMenu != null) && (CCPopupMenu.activeMenu.id == id))
			isAlreadyOpen = CCPopupMenu.activeMenu.isOpen;
		
		CCPopupMenu.hideActiveMenu();
		if ((event.type == "keypress" && event.keyCode == 27) || (isAlreadyOpen))
			return true;

		//position the drop down based on the passed in x, and y parameters and the size of the browser window 
		currentMenu.fitHeightToBrowser(x,y);
		currentMenu.fitWidthToBrowser(x,y);
		
		//create an iframe so things don't peek through...no peeking allowed!
		CCPopupMenu.createInsulatingIframe(currentMenu, currentMenu.dropDownElement);
		
				
		//show the drop down menu and set the focus to the firt menu item
		currentMenu.dropDownElement.style.visibility="visible";
		CCPopupMenu.activeMenu = currentMenu;
		currentMenu.isOpen = true;
		//if the event is a kepress then set the focus to the first menu item so that the tabbing order appears correct
		if (event.type == "keypress")
			currentMenu.firstMenuItemEl.focus();
	}   

	CCPopupMenu.ignoreHideActiveMenu("ignore");
	setTimeout('CCPopupMenu.ignoreHideActiveMenu("unignore")', 100);

	return false;
}

//This function stops the propagation of the onclick event past the dropdown div
function CCPopupMenu_dropDownOnclick(event) {
	if (event.stopPropagation) {
		event.stopPropagation();
	} else {
		event.cancelBubble='true';
	}
}

function CCPopupMenu_createDropDown()
{
	//create the drop down consisting of the following html structure <div><table> ...menuitems </table></div>	
	var divEl = document.createElement("div");
	this.dropDownElment = divEl;
	var tableEl = document.createElement("table");
	var tbody = document.createElement("tbody");
	//can only add table rows to table bodies...can not add them to the table directly
	tableEl.appendChild(tbody);
	tableEl.style.borderCollapse = "collapse";
	divEl.id = "flyout_" + this.id;
	divEl.className = "flyOutMenu";
	divEl.style.display="block";
	divEl.style.position="absolute";
	divEl.style.overflow="visible";
	divEl.style.zIndex = "2";
	divEl.style.visibility="hidden";
	divEl.style.padding = "2px";
	
	addEvent(divEl, "click", CCPopupMenu_dropDownOnclick);
										
	tableEl.id = "flyoutTab_" + this.id; 
	//add drop down element as a child of the control element
	//this will ensure there are no tabing irregularities
	var controlEl = document.getElementById(this.controlId);
	if (controlEl != null)
		controlEl.appendChild(divEl);
	else 
		//add the drop down to the body if you can't find the control element
		document.body.appendChild(divEl);

	divEl.appendChild(tableEl);
	//need to maintain the first menu item as when all is said and done the focus must end up on that element

	var maxItmWidth = 0;
	var moz = (window.navigator.userAgent.indexOf("Gecko") != -1);
	for (index = 0; index < this.menuItems.length; index++)
	{
		var itm;
		if (index == 0)
			itm = this.firstMenuItemEl = this.menuItems[index].renderItem(tbody, this.id);
		else
			itm = this.menuItems[index].renderItem(tbody, this.id);

		if (moz && itm && itm.offsetWidth && maxItmWidth < itm.offsetWidth) {
			maxItmWidth = itm.offsetWidth;
		}
	}

	if (moz && maxItmWidth > 0)
		divEl.style.width = maxItmWidth + "px";
	
	this.dropDownElement = divEl;
	//stick it in the upperleft corner of the browser so as not to make the browser bigger
	this.fitHeightToBrowser(0,0);
	this.fitWidthToBrowser(0,0);
	
	//unfortunately need to do this switch of visibility to ensure that the menu separators get hidden
	this.dropDownElement.style.visibility="visible";
	this.dropDownElement.style.visibility="hidden";
}

//static function to create all the drop down divs so that they can be show later
function CCPopupMenu_createDropDowns()
{
	for (var index=0;index < CCPopupMenu.menus.length; index++)
	{
		CCPopupMenu.menus[index].createDropDown();
	}
}

//static function returns the menu object associated with the passed in id
function CCPopupMenu_getMenu(id)
{
	for (index = 0;index < CCPopupMenu.menus.length; index++)
	{
		if (CCPopupMenu.menus[index].id == id)
		{
			return CCPopupMenu.menus[index];
		}	   
	}
}

//constructor to create an new CCPopupMenu object with the passed in id
function CCPopupMenu(sId, controlId, nHeight)
{
	this.controlId = controlId;
	this.id = sId;
	this.menuItems = new Array();
	this.isOpen = false;
	this.dropDownElement = null;
	this.mnHeight = -1;
	//if a height was passed in use it so that vertical scrolling is enabled...otherwise disable vertical scrolling
	//by setting the mnHeight to -1
	if (nHeight != "")
		this.mnHeight = parseInt(nHeight);
		
	this.firstMenuItemEl = null;	
	CCPopupMenu.menus.push(this);
	
}

//instance method to add a menu item with the passed in label and clickFunction 
//clickFunction is expected to be a string with valid javascript code
function CCPopupMenu_addMenuItem(id, groupId, label, icon, clickFunction)
{
	var newMenuItem = new CCPopupMenuItem(id, groupId, label, icon, clickFunction);
	this.menuItems.push(newMenuItem);
}

//returns the menu item with the assoicated id
function CCPopupMenu_getMenuItem(id)
{
	for (index=0;index < this.menuItems.length;index++)
	{
		if (this.menuItems[index].id == id)
			return this.menuItems[index];
	}
}

//sets the selections state of each menu item in the group with the passed in id to "none"
function CCPopupMenu_clearGroup(id)
{
	for (index=0;index < this.menuItems.length;index++)
	{
		if (this.menuItems[index].groupId == id)
			this.menuItems[index].clearSelectionState()
	}
}

//sets the menu item with the associated id to be checked
function CCPopupMenu_setMenuItemChecked(id)
{
	//sets the checked attrute of the menuitem
	var currentMenuItem = this.getMenuItem(id);
	if (currentMenuItem.isInGroup())
	{
		this.clearGroup(currentMenuItem.groupId);
	}
	currentMenuItem.check();
}

//returns the menu items with a selection state not set to none
function CCPopupMenu_getCurrentSelected()
{
	for (index=0;index < this.menuItems.length;index++)
	{
		if (this.menuItems[index].itemSelectedState != "none")
			return this.menuItems[index];
	}
}

//sets the menu item with the associated id to be selected
function CCPopupMenu_setMenuItemSelected(id)
{
	//sets the checked attrute of the menuitem
	var currentMenuItem = this.getMenuItem(id);
	if (currentMenuItem.isInGroup())
	{
		this.clearGroup(currentMenuItem.groupId);
	}
	currentMenuItem.select();
}

//instance method to add a menu separator 
function CCPopupMenu_addMenuSeparator()
{
	var newMenuItem = new CCPopupMenuSeparator();
	this.menuItems.push(newMenuItem);
}

//instance method to hide the current drop down
function CCPopupMenu_removeDropDown()
{
	if ((this.dropDownElement != null))
	{
		this.dropDownElement.style.visibility="hidden";
		this.isOpen = false;
  		var iframeID = this.id + "inslIframe";
 		var iframeEl = document.getElementById(iframeID);
  		if (iframeEl != null)
  		{
  			var controlElement = document.getElementById(this.controlId);
  			controlElement.removeChild(iframeEl);
  		}	
	}	
	
}
		
//***********************CCPopupMenu specification 
CCPopupMenu.prototype.addMenuItem = CCPopupMenu_addMenuItem;
CCPopupMenu.prototype.addMenuSeparator = CCPopupMenu_addMenuSeparator;
CCPopupMenu.prototype.removeDropDown = CCPopupMenu_removeDropDown;
CCPopupMenu.prototype.fitHeightToBrowser = CCPopupMenu_fitHeightToBrowser;
CCPopupMenu.prototype.fitWidthToBrowser = CCPopupMenu_fitWidthToBrowser;
CCPopupMenu.prototype.getMenuItem = CCPopupMenu_getMenuItem;
CCPopupMenu.prototype.clearGroup = CCPopupMenu_clearGroup;
CCPopupMenu.prototype.setMenuItemChecked = CCPopupMenu_setMenuItemChecked;
CCPopupMenu.prototype.setMenuItemSelected = CCPopupMenu_setMenuItemSelected;
CCPopupMenu.prototype.sizeDropDown = CCPopupMenu_sizeDropDown;
CCPopupMenu.prototype.getCurrentSelected = CCPopupMenu_getCurrentSelected;
CCPopupMenu.prototype.createDropDown = CCPopupMenu_createDropDown;

CCPopupMenu.hideActiveMenu = CCPopupMenu_hideActiveMenu;
CCPopupMenu.ignoreHideActiveMenu = CCPopupMenu_ignoreHideActiveMenu;
CCPopupMenu.getMenu = CCPopupMenu_getMenu;
CCPopupMenu.dropDown = CCPopupMenu_dropDown
CCPopupMenu.checkBounds = CCPopupMenu_checkBounds;
CCPopupMenu.createInsulatingIframe = CCPopupMenu_createInsulatingIframe;
CCPopupMenu.setControlFocus = CCPopupMenu_setControlFocus;
CCPopupMenu.createDropDowns = CCPopupMenu_createDropDowns;
//***********************CCPopupMenu specification 

//constructor for CCFlyoutSeparator
//CCFlyoutSeparator has no real state...it just knows how to render itself
function CCPopupMenuSeparator(){this.type = "separator";}

function CCPopupMenuSeparator_isInGroup()
{
	return false;
}

//instance method for rendering a flyout separator
//consisting of the following html: <tr><td><img/></td></tr>
function CCPopupMenuSeparator_renderItem(menuElement, id)
{
	var menuItemEl =  document.createElement("tr");
	//menu separators should not be in the tabbing order
	menuItemEl.tabIndex = -1;
	menuElement.appendChild(menuItemEl);
	var menuSeparatorContainer = document.createElement("td");
	menuSeparatorContainer.colSpan = 3;
	var menuSeparator = document.createElement("div");
	menuSeparator.className = "flyOutMenuSeparator";
	menuSeparatorContainer.appendChild(menuSeparator);
	//menuSeparator.className = "flyOutMenuSeparator";
	
	menuItemEl.appendChild(menuSeparatorContainer); 
}
//***********************CCFlyoutSeparator specification 
CCPopupMenuSeparator.prototype.renderItem = CCPopupMenuSeparator_renderItem;
CCPopupMenuSeparator.prototype.isInGroup = CCPopupMenuSeparator_isInGroup;
//***********************CCFlyoutSeparator specification 

//constructor for CCPopupMenuItem
//clickFunction is expected to be a string with valid javascript code
function CCPopupMenuItem(sId, groupId, slabel, icon, clickFunction)
{
	this.id = sId;
	this.label = slabel;
	this.icon = icon;
	this.itemSelectedState = "none";
	this.groupId = groupId;
	this.enabled = true;
	this.menuItemEl = null;
	this.menuLabelEl = null;
	this.iconImageEl = null;
	this.selectionStateIcon = null;
	this.selectionElement = null;
		
	//the passed in click action is the action the consumer of the menu item wants to take when clicking on the item
	//we must enhance that with some menu caretaking code which will take care of hiding the menu after the click
	var clickActionCode = clickFunction + ";CCPopupMenu.hideActiveMenu();";
		
	//keypress actions act similarly to click action but require some additional care taking
	var keypressActionCode = "if( event.keyCode == '13'){" + clickFunction + "}else if( event.keyCode == '27' ){CCPopupMenu.hideActiveMenu();}cancelBubble = true;return false;";
	
	this.keyPressFunction = new Function("event", keypressActionCode);
	this.clickFunction = new Function("event", clickActionCode);

}

function CCPopupMenuItem_isInGroup()
{
	return (this.groupId != "");
}

function CCPopupMenuItem_disable()
{
	this.enabled = false;
	this.updateForEnabled();
}

function CCPopupMenuItem_enable()
{
	this.enabled = true;
	this.updateForEnabled();
}

//sets the selectedState to none
function CCPopupMenuItem_clearSelectionState()
{
	this.itemSelectedState = "none";
	this.updateForSelectionState();
}

//set the selectionState to checked (note selection state and check state are mutually exlusive...an element can not be selected and checked)
function CCPopupMenuItem_check()
{
	this.itemSelectedState = "checked";
	this.updateForSelectionState();
}

//set the selectionState to selected (note selection state and check state are mutually exlusive...an element can not be selected and checked)
function CCPopupMenuItem_select()
{
	this.itemSelectedState = "selected";
	this.updateForSelectionState();
}

//renders the label for the menuitem
function CCPopupMenuItem_renderLabel(menuElement)
{
	var menuItemLabel = document.createElement("td");
	
	//menuItemLabel.style.cursor = "pointer";
	//menuItemLabel.style.textDecoration = "underline";
	menuItemLabel.style.padding = "2px";
	menuItemLabel.className = "menuItemNormal";
	this.menuLabelEl = menuItemLabel; 
	menuElement.appendChild(menuItemLabel);
		
	var nonbreakingSpace = document.createElement("nobr");
	menuItemLabel.appendChild(nonbreakingSpace);
	
	nonbreakingSpace.appendChild(document.createTextNode(this.label));
}

//render the items checked, selected or icon if necessary
function CCPopupMenuItem_renderDecorations(menuElement)
{
	var decorationTD = document.createElement("td");
	decorationTD.className = "text";
	decorationTD.style.cursor = "pointer";
	decorationTD.style.textDecoration = "underline";
	menuElement.appendChild(decorationTD);
	this.selectionElement = decorationTD;

	if (this.icon != "")
	{
		var imgEl = document.createElement("img");
		imgEl.src = this.icon;
		imgEl.style.height = "16px";
		imgEl.style.width = "16px";
		this.iconImageEl = imgEl;
		decorationTD.className = "menuItemIcon";
		decorationTD.appendChild(imgEl);
	}
}

function CCPopupMenuItem_updateForSelectionState()
{
	if (this.menuItemEl ==null)
		return;
	if(this.itemSelectedState == "none")
	{
		if (this.selectionStateIcon != null)
		{
			//in this case we remove the selection icon
			this.selectionStateIcon.parentNode.removeChild(this.selectionStateIcon);
			this.selectionStateIcon = null;	
		}	
	}
	else 
	{
		if (this.selectionStateIcon == null)
		{
			var imgEl = document.createElement("img");
			if (this.itemSelectedState == "checked")
			{
				imgEl.src = CCPopupMenu.portalImagesPath + "/checkmark.gif";
			}	
			else
			{
				imgEl.src = CCPopupMenu.portalImagesPath + "/dot.gif";
			}
			this.selectionElement.appendChild(imgEl);
			this.selectionStateIcon = imgEl;
		}
		else
		{
			if (this.itemSelectedState == "checked")
			{
				this.selectionStateIcon.src = CCPopupMenu.portalImagesPath + "/checkmark.gif";
			}	
			else
			{
				this.selectionStateIcon.src = CCPopupMenu.portalImagesPath + "/dot.gif";
			}
			this.updateForEnabled();
		}
	}
}

//updates the rendered menu item based on the enabled state
function CCPopupMenuItem_updateForEnabled()
{
	if (this.menuItemEl ==null)
		return;
	
	//only register the click/keypress handlers if the element is enabled
	if (this.enabled)
	{
		//enable the click/keypress events
		addEvent(this.menuItemEl,'keypress', this.keyPressFunction);
		addEvent(this.menuItemEl,'click', this.clickFunction); 
		//update the style
		this.menuItemEl.style.MozOpacity = "1.0";
		this.menuItemEl.style.filter = "alpha(opacity=100)";
		this.menuLabelEl.className = "text";
		if 	(this.itemSelectedState != "none")
		{
			this.selectionStateIcon.style.MozOpacity = "1.0";
			this.selectionStateIcon.style.filter = "alpha(opacity=100)";
		}	
			
		if (this.iconImageEl != null)
		{
			this.iconImageEl.style.MozOpacity = "1.0";
			this.iconImageEl.style.filter = "alpha(opacity=100)";
		}	
	}
	else
	{
		//disable the click/keypress events
		removeEvent(this.menuItemEl,'keypress',this.keyPressFunction);
		removeEvent(this.menuItemEl,'click',this.clickFunction); 
		//update the style
		this.menuItemEl.style.MozOpacity = "0.5";
		this.menuItemEl.style.filter = "alpha(opacity=50)";
		if 	(this.itemSelectedState != "none")
		{
			this.selectionStateIcon.style.MozOpacity = "0.5";
			this.selectionStateIcon.style.filter = "alpha(opacity=50)";
		}
		if (this.iconImageEl != null)
		{
			this.iconImageEl.style.MozOpacity = "0.5";
			this.iconImageEl.style.filter = "alpha(opacity=50)";
		}	
		
		this.menuLabelEl.className = "inactiveText";
	}
}

function menuItemOverEventHandler(id)
{
	return function ccmenuitemovereventhandler(){var menuItemEl=document.getElementById(id); menuItemEl.className='menuItemOver';};
}

function menuItemOutEventHandler(id)
{
	return function ccmenuitemouteventhandler() {var menuItemEl=document.getElementById(id); menuItemEl.className='menuItemNormal';};
}

function menuItemBlurEventHandler(id)
{
	return function ccmenuitemblureventhandler() {var menuItemEl=document.getElementById(id); menuItemEl.className='menuItemNormal';CCPopupMenu.checkBounds(window.event);};
}

function CCPopupMenuItem_createCommonEventHandlers(menuItemEl)
{
	addEvent(menuItemEl,'focus',menuItemOverEventHandler(menuItemEl.id));
	addEvent(menuItemEl,'mouseout',menuItemOutEventHandler(menuItemEl.id));
	addEvent(menuItemEl,'mouseover',menuItemOverEventHandler(menuItemEl.id));
	addEvent(menuItemEl,'blur',menuItemBlurEventHandler(menuItemEl.id)); 
}

//instance method for rendering a flyout menu item
//consisting of the following html: <tr><td><nobr>..label...</nobr></td></tr>
function CCPopupMenuItem_renderItem(menuElement, id)
{
	var menuItemEl =  document.createElement("tr");
	menuItemEl.tabIndex = 0;
	menuItemEl.className = "menuItemNormal";
	menuItemEl.id = this.id + "menuItemTR";
	
	this.createCommonEventHandlers(menuItemEl);
	
	menuItemEl.style.width = "100%";
	menuItemEl.style.overflow ="visible";
	menuElement.appendChild(menuItemEl);
	
	this.renderDecorations(menuItemEl);
	this.renderLabel(menuItemEl);
	
	var cascadingTD = document.createElement("td");
	cascadingTD.className = "text";
	cascadingTD.style.cursor = "pointer";
	cascadingTD.style.textDecoration = "underline";
	menuItemEl.appendChild(cascadingTD)
	this.menuItemEl = menuItemEl;
	this.updateForSelectionState();
	this.updateForEnabled();
	return menuItemEl;
}
//***********************CCPopupMenuItem specification 	
CCPopupMenuItem.prototype.renderItem = CCPopupMenuItem_renderItem;	  
CCPopupMenuItem.prototype.renderDecorations = CCPopupMenuItem_renderDecorations;
CCPopupMenuItem.prototype.renderLabel = CCPopupMenuItem_renderLabel;
CCPopupMenuItem.prototype.clearSelectionState = CCPopupMenuItem_clearSelectionState;
CCPopupMenuItem.prototype.check = CCPopupMenuItem_check;
CCPopupMenuItem.prototype.select = CCPopupMenuItem_select;
CCPopupMenuItem.prototype.isInGroup = CCPopupMenuItem_isInGroup;
CCPopupMenuItem.prototype.disable = CCPopupMenuItem_disable;
CCPopupMenuItem.prototype.enable = CCPopupMenuItem_enable;
CCPopupMenuItem.prototype.updateForEnabled = CCPopupMenuItem_updateForEnabled;
CCPopupMenuItem.prototype.updateForSelectionState = CCPopupMenuItem_updateForSelectionState;
CCPopupMenuItem.prototype.createCommonEventHandlers = CCPopupMenuItem_createCommonEventHandlers;
//***********************CCPopupMenuItem specification 	


//these event handlers will close active menus whenever the browser is resized or one clicks outside of a menu
addEvent(document,'click',CCPopupMenu.hideActiveMenu);
addEvent(window,'resize',CCPopupMenu.hideActiveMenu);
//add this event handler to prebuild the drop downs for the page
addEvent(window,'load',CCPopupMenu.createDropDowns);