/********************************************************************************************************************************
* Licensed Materials - Property of IBM *
* *
* IBM Cognos Products: AGS *
* *
* (C) Copyright IBM Corp. 2005, 2009 *
* *
* US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *
*********************************************************************************************************************************/
//css custom style constants
var MENU_MENUBAR="menuBar";
var MENU_CONTAINER="menuContainerOld";
var MENU_HORIZONTAL_SEPERATOR = "menuHorizontalSeperator"
var MI_NORMAL="menuItem_normal";
var MI_HOVER="menuItem_hover";
var MI_PRESSED="menuItem_pressed";
var MI_DISABLED="menuItem_disabled";
var MT_NORMAL="menuTitle_normal";
var MT_HOVER="menuTitle_hover";
var MT_PRESSED="menuTitle_pressed";
var TEXT="";
//the id of the menu bar placement tag
var AGS_MENUBAR_ID="menuBar"
//positioning tweaks for the menus
var DROP_DOWN_X_TWEAK=2;
var DROP_DOWN_Y_TWEAK=3;
var DROP_DOWN_SUBMENU_Y_TWEAK=2;
//the menu bar object
var agsMenuBar = new MenuBar(MENU_MENUBAR);
//the timeout identifier used to auto close any open menus after a period of time defined in TIMEOUT_MS
var windowTimeout = null;
//the number of milliseconds to wait before all open menus are closed, set to 4 seconds
var TIMEOUT_MS=4000;
/*
**********************
* START MenuBar object
**********************
*/
function MenuBar(barName) {
//methods
this.writeMenuBar=writeMenuBar;
this.displayMenu=displayMenu;
this.addLabel=addLabel;
this.closeLastOpenMenu=closeLastOpenMenu;
this.showMenu=showMenu;
this.showMenuSide=showMenuSide;
this.findById=findById;
this.findRowElement=findRowElement;
this.hideOpenSubMenus=hideOpenSubMenus;
this.hideMenu = hideMenu;
this.resetMenus = resetMenus;
this.getMenuLabelLink = getMenuLabelLink;
this.getMenuLabelDiv = getMenuLabelDiv;
this.changeObjectVisibility = changeObjectVisibility;
this.getElementLeft = getElementLeft;
this.getElementTop = getElementTop;
this.getElementHeight = getElementHeight;
this.moveXY = moveXY;
//assign values
this.barName=barName;
this.menus = new Array();
this.autoOpen=false;
this.lastOpenMenu=null;
this.lastOpenSubMenu=null;
this.numLabels = 0;
}
/*
* Add a label to the menu bar. This equates to one of the top level menu items
*/
function addLabel(labelText) {
var menuNo = this.numLabels;
var labelId = 'labelCell' + menuNo;
var newMenu = new MenuItem(labelText,this,null,null);
newMenu.id=labelId;
newMenu.index = this.numLabels;
this.menus[menuNo]=newMenu;
//set the id suffix
newMenu.menuContainerId=this.numLabels;
//update the label count
this.numLabels += 1;
return newMenu;
}
/*
* Display the menu bar, first the menu labels are drawn
* A menu label is rendered with the current menu id defined as [id] :
*
*
*
*
* followed by each menu container which container one or more menu items. Initially
* these are hidden and only displayed when the mouse is clicked
*/
function writeMenuBar() {
var parentMenuBar = this;
var AGSMenuBar = document.getElementById(AGS_MENUBAR_ID);
if (AGSMenuBar != null) {
//create the menu bar div
var menuBarDiv = document.createElement("div");
menuBarDiv.id="labelContainer";
menuBarDiv.className=MENU_MENUBAR;
menuBarDiv.style.width="100%";
//add each menu label to the menu bar
for (var count = 0; count < this.numLabels; count++) {
var menuLabel = this.menus[count];
var menuLinkId = 'menuLink' + count;
//create the top level div for the label
var menuLabelDiv = document.createElement("div");
menuLabelDiv.id=menuLabel.id;
menuLabelDiv.style.paddingTop="4px";
menuLabelDiv.style.paddingLeft="3px";
menuLabelDiv.style.paddingRight="3px";
menuLabelDiv.style.paddingBottom="4px";
if (document.all) {
menuLabelDiv.style.styleFloat="left"; //for netscape use cssFloat property
} else {
menuLabelDiv.style.cssFloat="left";
}
//create the label anchor
var menuLabelAnchor = document.createElement("span");
//set the correct 'hand' pointer for firefox
//for some reason firefox render the 'hand' setting
//as a text caret
if (browserCheck.isNav6Up()) {
menuLabelAnchor.style.cursor='pointer';
}
menuLabelAnchor.unselectable="on";
menuLabelAnchor.id=menuLinkId;
// force the href to do nothing
//menuLabelAnchor.href="javascript:return false;";
// create the text
var text = document.createTextNode(menuLabel.name);
// add it as a child
menuLabelAnchor.appendChild(text);
menuLabelAnchor.className=MT_NORMAL;
menuLabelDiv.appendChild(menuLabelAnchor);
/*
* The mouse has left a menu label. When autoOpen is set then the menu label style remains unchanged
* otherwise change the style from hover to normal
*/
var onMouseOutHandler = function(event) {
var target = (event.target) ? event.target : event.srcElement;
//only set timeouts on menuLink ids i.e. anchor tags
//this event handler is fired for both menu items in sub menus and label menu items
//This is useful because the timeout clear can be handled in one place
if (target.id.indexOf('menuLink') != -1) {
//the reset function
var f = function(){
parentMenuBar.resetMenus();
}
windowTimeout = window.setTimeout(f,TIMEOUT_MS);
}
//only reset the class when auto open is switched off. The menu label should
//always be highlighted when a menu is open and the sub menus are being traversed. This is the
//normal behaviour for Windows type applications
if (!parentMenuBar.autoOpen) {
//because this event propagates according to the IE event model
//ensure this event has come from the menu label and not a menu item
var menuLabelLinkEle = parentMenuBar.getMenuLabelLink(event);
var menuLabelDivEle = parentMenuBar.getMenuLabelDiv(event);
if (menuLabelLinkEle != null && menuLabelDivEle != null) {
menuLabelLinkEle.className=MT_NORMAL;
}
}
}
/*
* The mouse has entered a menu label. When autoOpen is set this method will close any open menus,
* display the new menu and then change the menu style to pressed. When autoOpen is false then the
* style is changed to hover
*/
var onMouseOverHandler = function(event) {
var target = (event.target) ? event.target : event.srcElement;
var menuLabelLinkEle = parentMenuBar.getMenuLabelLink(event);
var menuLabelDivEle = parentMenuBar.getMenuLabelDiv(event);
//ensure the menu is kept open
window.clearTimeout(windowTimeout);
//label link not found we are over a menu item so just ignore
if (menuLabelDivEle != null && menuLabelLinkEle != null) {
//we have a top level menu item
if (parentMenuBar.autoOpen) {
var menuItem = parentMenuBar.findById(menuLabelDivEle.id);
if (menuItem != null) {
var menuNo = menuItem.index;
//this closes the last open menu and also resets the menu class
//only show it when we had a succesful close
if (menuItem != parentMenuBar.lastOpenMenu) {
if (parentMenuBar.closeLastOpenMenu()) {
parentMenuBar.showMenu(menuNo,event);
}
}
//update the last open property
parentMenuBar.lastOpenMenu = menuItem;
parentMenuBar.lastOpenSubMenu=null;
menuLabelLinkEle.className=MT_PRESSED;
//hide any open sub menus
parentMenuBar.hideOpenSubMenus();
}
}
else {
menuLabelLinkEle.className = MT_HOVER;
}
}
}
//create an anonymous event handler, there is a small hack that is necessary here
//because when inside the handler 'this' becomes the document and not the menu bar
//so the menu bar needs to be explicitly defined here as parentMenuBar. This only seems to
//happen with properties and not object methods so this.findById is okay but this.numLabels is undefined
var onClickHandler = function(event) {
var returnVal=false;
var target = (event.target) ? event.target : event.srcElement;
var menuLabelLinkEle = null;
var menuLabelDivEle = null;
menuLabelLinkEle = parentMenuBar.getMenuLabelLink(event);
menuLabelDivEle = parentMenuBar.getMenuLabelDiv(event);
//this mouse click event is fired from both clicking a menu item and clicking a label item
//so if the label div is null then a menu item has been clicked and we should propagate the event to
//the lower echelons of the web page
if (menuLabelDivEle != null) {
var menuItem = parentMenuBar.findById(menuLabelDivEle.id);
var menuNo = menuItem.index;
if (browserCheck.isIE5dot5Up()) {
//remove the focus outline around the element
target.blur();
}
//the last open menu is the same as this one, so close the menu
if (parentMenuBar.lastOpenMenu == menuItem) {
parentMenuBar.hideMenu(menuItem);
menuLabelLinkEle.className = MT_HOVER;
parentMenuBar.autoOpen = false;
parentMenuBar.lastOpenMenu=null;
}
else {
parentMenuBar.autoOpen = true;
returnVal = !parentMenuBar.showMenu(menuNo,event);
parentMenuBar.lastOpenMenu = menuItem;
menuLabelLinkEle.className = MT_PRESSED;
}
}
//propagate the event
else {
window.event.cancelBubble = false;
returnVal = true;
}
return returnVal;
}
// set the event handlers for the menu labels
parent.addEvent(menuLabelAnchor,"mouseover",onMouseOverHandler);
parent.addEvent(menuLabelAnchor,"mouseout",onMouseOutHandler);
parent.addEvent(menuLabelAnchor,"click",onClickHandler);
//END OF ONCLICK EVENT HANDLER
menuLabel.writeContainer(menuLabelDiv);
menuBarDiv.appendChild(menuLabelDiv);
}
//end for loop
AGSMenuBar.appendChild(menuBarDiv);
//document.onmousedown = pageMousedown;
//parent.getMessageIFrame().onmousedown = pageMousedown;
cfgSet(MENU_MENUBAR,this);
}
else {
document.write('Cannot find a placement <div> tag with the required id['+AGS_MENUBAR_ID+']
');
}
}
/*
* Hide a menu item, this method will also hide any open child menu items
* menuItem The menu item to be hidden
*/
function hideMenu(menuItem) {
if (menuItem != null) {
menuItem.state=MenuItem.CLOSED;
//ensure their are no child menus still open
var openMenus = menuItem.getOpenMenuItems();
for (var i=0;i this.size) {
value = (this.value.substring(0,this.index) + value).substring(0, this.value.size);
this.size = this.index = value.length;
}
else {
value = this.value.substring(0,this.index) + value;
this.index = value.length;
}
this.value = value + this.value.substring(value.length, this.value.length);
}
function getValue() {
return this.value;
}
function duplicateString(size, chr) {
var text = '';
for (var i=0; i 0;
}
function getItemById(id) {
var item = null;
var flattened = this.flatten();
if (flattened != null) {
item = flattened[id];
}
return item;
}
/*
* set the menu item key
*/
function setKey(newKey) {
this.key = newKey;
}
/*
* Get the row element defined by the key
*/
function getItemByKey(theKey,list) {
var found = null;
var parentList = null;
if (list==undefined) {
parentList = this.children;
}
else {
parentList = list;
}
for (var i=0;(i < parentList.length && found == null);i++) {
var child = parentList[i];
if (child.key != theKey) {
var children = child.getItems();
found = getItemByKey(theKey,children);
}
else {
found = child;
}
}
return found;
}
/*
* Add a menu item
* name The menu item text
* action The url to be fired when the menu item is clicked, can be null for non clickable menu items
*/
function addItem(name, action, icon, tooltip) {
var item = new MenuItem(name,this.menuBar,action,icon, tooltip);
item.parent=this;
var index = 0;
item.isRoot = false;
//get the number of child items and set the index for the next item
var size = this.children.length;
if (size > 0) {
index = size;
}
//add the item to the array
this.children[index]=item;
item.index = index;
return item;
}
/*
* Write the HMTL for the container and all its menu items including nested menu items
* parentElement The dom element to append the menu to, basically the the menu label div
* idRoot The id suffix used when generating the div ids of the menu container/label cells/menu link elements. Initially null but used to name
* nested containers properly e.g. 0,1,1_2,1_2 etc.
*/
function writeContainer(parentElement,idRoot) {
//first of all create the top level label
var parentMenuNo = this.index;
var menuItemsDiv = document.createElement("div");
menuItemsDiv.className=MENU_CONTAINER;
//set the correct menu id
if (idRoot==null) {
idRoot=parentMenuNo;
}
else {
idRoot=idRoot+'_'+this.index;
}
menuItemsDiv.id='menu'+idRoot;
menuItemsDiv.style.position="absolute";
menuItemsDiv.style.visibility="hidden";
menuItemsDiv.style.zIndex=200;
var table = document.createElement("table");
var tbody = document.createElement("tbody");
table.appendChild(tbody);
for (var i = 0; i < this.children.length; i++) {
var row = tbody.insertRow(i);
row.className=TEXT;
var col = row.insertCell(0);
col.noWrap="true";
//... |
//the children array contains Menu objects
var menuItem = this.children[i];
col.title= menuItem.tooltip;
var menuNo = this.index;
//create the table row
fillMenuItemRow(menuItem,row);
//create the column
fillMenuItemCol(this.menuBar,menuItem,col,idRoot+'_'+i);
//drill down
if (menuItem.children.length > 0) {
//write the HTML to menuItemsDiv
menuItem.writeContainer(parentElement,idRoot);
}
}
//add the table to the menu item container
menuItemsDiv.appendChild(table);
//add the menu item container to the parent div element
parentElement.appendChild(menuItemsDiv);
/*
* INNER FUNCTION
* Create the menu row element, essentially a tag with an optional id
*/
function fillMenuItemRow(menuItem,menuItemRow) {
var menuNo = menuItem.index;
var hasSubItems = menuItem.hasItems();
//the menu has sub menu items
if (hasSubItems) {
menuItemRow.id='labelRow'+menuNo;
}
return menuItemRow;
}
/*
* INNER FUNCTION
*/
function fillMenuItemCol(menuBar,menuItem,menuItemCol,idSuffix) {
var itemText = menuItem.name;
var menuNo = menuItem.index;
var parentMenuNo = menuItem.parent.index;
var hasSubItems = menuItem.hasItems();
var itemURL = menuItem.url;
var iconURL = menuItem.icon;
menuItem.menuContainerId=idSuffix;
var spaceImg = "../ags/images/spacer.gif";
var subMenuImg = "../ags/images/menu_arrow.gif";
var rightArrowImg = document.createElement("img");
rightArrowImg.style.verticalAlign="middle";
rightArrowImg.src = subMenuImg;
rightArrowImg.style.width="13px";
var menuIcon = document.createElement("img");
menuIcon.style.verticalAlign="middle";
menuIcon.style.width="16px";
//spaceIcon.style.width="3px";
if (iconURL=='') {
menuIcon.src=spaceImg;
}
else {
//set the icon
menuIcon.src=iconURL;
}
//create the column and anchor elements
var menuItemLink = document.createElement("span");
//set the correct 'hand' pointer for firefox
//for some reason firefox render the 'hand' setting
//as a text caret
if (browserCheck.isNav6Up()) {
menuItemCol.style.cursor='pointer';
}
menuItemLink.unselectable="on";
//set the common menu item properties
menuItemCol.className=MI_NORMAL;
menuItemCol.style.verticalAlign="middle";
//set the common anchor properties
//menuItemLink.href=itemURL;
menuItemLink.style.color="blue";
menuItemLink.style.textDecoration="underline";
// create a text element
var text = document.createTextNode(itemText);
// add it as a child element
menuItemLink.appendChild(text);
// START define the handler functions for this element
// menu item mouse click event handler
var onMenuItemMouseClickEvent = function menuItemClicked(event) {
var target = (event.target) ? event.target : event.srcElement;
if (browserCheck.isIE5dot5Up()) {
//remove the focus outline around the element
target.blur();
}
//process the action for this link, then hide the open label menu
if (menuItem.hasItems()==false) {
menuBar.resetMenus();
eval(itemURL);
return true;
}
//this link has sub items so simply ignore the mouse click
else {
event.cancelBubble=true;
return false;
}
}
// menu item mouse over event handler
var onMenuItemMouseOverEvent= function menuItemOver(event) {
var target = (event.target) ? event.target : event.srcElement;
//hide any open sub menu items
menuBar.hideOpenSubMenus(menuItem);
if (menuItem.hasItems()) {
menuBar.showMenuSide(menuItem);
}
//clear the timeout when we have moved onto
//another menu item, this will ensure the menu
//is not closed when navigating the menu structure
window.clearTimeout(windowTimeout);
var menuItemElement = document.getElementById(menuItem.id);
menuItemElement.className=MI_HOVER;
}
// menu item mouse out event handler
var onMenuItemMouseOutEvent= function menuItemOut(event) {
var target = (event.target) ? event.target : event.srcElement;
var menuItemElement = document.getElementById(menuItem.id);
menuItemElement.className=MI_NORMAL;
if (target.id.indexOf('itemCell') != -1) {
//the reset function
var f = function(){
agsMenuBar.resetMenus();
}
windowTimeout = window.setTimeout(f,TIMEOUT_MS);
}
}
// FINISH define the handler functions for this element
//attach the event handlers for the menu items
addEvent(menuItemCol,"mouseover",onMenuItemMouseOverEvent);
addEvent(menuItemCol,"mouseout",onMenuItemMouseOutEvent);
addEvent(menuItemCol,"click",onMenuItemMouseClickEvent);
//only parent menu items have row ids
var rowId=null;
var eventHandlers=null;
var menuLinkId = null;
//the id for a submenu
menuItemLink.id="menuLink" + idSuffix;
menuItemCol.id="itemCell" + idSuffix;
var innerSpanImg = document.createElement("span");
innerSpanImg.style.marginRight="3px";
innerSpanImg.appendChild(menuIcon);
menuItemCol.appendChild(innerSpanImg);
menuItemCol.appendChild(menuItemLink);
if (hasSubItems==true) {
var innerSpanLinkAndArrow_arrow = document.createElement("span");
innerSpanLinkAndArrow_arrow.appendChild(rightArrowImg);
menuItemCol.appendChild(innerSpanLinkAndArrow_arrow);
}
//set the menu item id to the generated one
menuItem.id = menuItemCol.id;
// link the menuItem to the menuItemCol
menuItemCol.menuItem = menuItem;
return menuItemCol;
}
}
/*
* Get the menu item parent
*/
function getParent() {
return this.parent;
}
/*
* Get the menu item children
*/
function getItems() {
return this.children;
}
/*
* Display the contents of this menu item, including all children
* For debug purposes only
*/
function display() {
buf = new StringBuffer();
buf.append(this.toString());
buf.append('\n');
buf = displayNode(buf,this.getItems(),0);
(buf.toString());
}
/*
* Helper function to recurse through the child nodes and collect information
*/
function displayNode(buf,childList,level) {
++level;
for (var i=0;i < childList.length;i++) {
var child = childList[i];
displayIndent(buf,level);
buf.append(child.toString());
buf.append('\n');
if (child.hasItems()) {
displayNode(buf,child.getItems(),level);
}
}
--level;
return buf;
}
/*
* Display an indent
*/
function displayIndent(buf,level) {
for (var i=0;i