// Licensed Materials - Property of IBM // // IBM Cognos Products: ps // // (C) Copyright IBM Corp. 2005, 2014 // // US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. // 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 = []; //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; } } var extensions = { associate: function (target, obj, methodName) { return function (e) { e = e || window.event; return obj[methodName](e, target); }; } }; //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; } } //Stops the event at current event handler function haltEventProcessing(event) { event.cancelBubble = 'true'; event.returnValue = 'false'; if (event.stopPropagation) { event.stopPropagation(); event.preventDefault(); } 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) { var indexOfPX; if (dropDownElement.style.height == "") { var height = dropDownElement.offsetHeight; if (window.navigator.userAgent.indexOf("Gecko") != -1) { var paddingTop = dropDownElement.style.paddingTop; indexOfPX = paddingTop.indexOf("px"); var v = ((indexOfPX != -1) ? parseInt(paddingTop.substring(0, indexOfPX), 10) : parseInt(paddingTop, 10)); height -= (isNaN(v) ? 0 : v); var paddingBottom = dropDownElement.style.paddingBottom; indexOfPX = paddingBottom.indexOf("px"); v = ((indexOfPX != -1) ? parseInt(paddingBottom.substring(0, indexOfPX), 10) : parseInt(paddingBottom, 10)); height -= (isNaN(v) ? 0 : v); var borderWidth = 1; height -= (2 * borderWidth); } return height; } else { //return the style height converted to an integer var styleHeight = dropDownElement.style.height; indexOfPX = styleHeight.indexOf("px"); if (indexOfPX != -1) { styleHeight = styleHeight.substring(0, indexOfPX); } return parseInt(styleHeight, 10); } } //returns the width of the drop down based on the style or the offsetWidth function getDropDownWidth(dropDownElement) { var indexOfPX; if (dropDownElement.style.width == "") { var width = dropDownElement.offsetWidth; if (window.navigator.userAgent.indexOf("Gecko") != -1) { var paddingLeft = dropDownElement.style.paddingLeft; indexOfPX = paddingLeft.indexOf("px"); var v = ((indexOfPX != -1) ? parseInt(paddingLeft.substring(0, indexOfPX), 10) : parseInt(paddingLeft, 10)); width -= (isNaN(v) ? 0 : v); var paddingRight = dropDownElement.style.paddingRight; indexOfPX = paddingRight.indexOf("px"); v = ((indexOfPX != -1) ? parseInt(paddingRight.substring(0, indexOfPX), 10) : parseInt(paddingRight, 10)); 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; indexOfPX = styleWidth.indexOf("px"); if (indexOfPX != -1) { styleWidth = styleWidth.substring(0, indexOfPX); } return parseInt(styleWidth, 10); } } //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 && CCPopupMenu.activeMenu.doCheckBounds) { 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 || window.event.keyCode == 38 || window.event.keyCode == 40) { 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.activeMenuItemIndex = -1; 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.setAttribute("role","presentation"); iframeEl.title = currentMenu.id; iframeEl.style.display = "block"; iframeEl.style.border = "0px"; iframeEl.style.padding = "2px"; iframeEl.style.position = "absolute"; iframeEl.style.zIndex = "1"; iframeEl.tabIndex = "-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.right = divEl.style.right; 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 allowableHeight = Math.min(maxHeight, providedHeight); allowableHeight = providedHeight; if (dropDownElement.offsetHeight > allowableHeight) { dropDownElement.style.height = allowableHeight + "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 dropDownElement = this.dropDownElement; var rtl=document.body.dir=="rtl"; if(rtl) CCPopupMenu_fitWidthToBrowserRTL(controlElement, dropDownElement, x, y); else CCPopupMenu_fitWidthToBrowserLTR(controlElement, dropDownElement, x, y); } //determines the width of the browser to ensure nothing falls off the edge of the browser in LTR case function CCPopupMenu_fitWidthToBrowserLTR(controlElement, dropDownElement, x, y) { var controlElementLeft = controlElement.offsetLeft; //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"; } } //determines the width of the browser to ensure nothing falls off the edge of the browser in RTL case function CCPopupMenu_fitWidthToBrowserRTL(controlElement, dropDownElement, x, y) { var controlElementRight = controlElement.offsetLeft + controlElement.offsetWidth; //position the drop down based on the size of the browser window var winWidth = windowWidth(); var dropDownLeft = controlElementRight - dropDownElement.offsetWidth; //if what was provided would pass off the left of the browser //move the popup so that is flush with the left (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 (dropDownLeft < 0) { var dropDownRight = controlElement.offsetWidth - dropDownElement.offsetWidth; var dropDownAbsoluteRight = controlElementRight - dropDownRight; if (dropDownAbsoluteRight > winWidth) { //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.right = controlElement.offsetRight * -1; } else { //dropDownElement.style.right = (controlElement.scrollWidth - dropDownElement.scrollWidth) + "px"; dropDownElement.style.left = 0 + "px"; } } else { dropDownElement.style.right = 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) { CCPopupMenu.hideActiveMenu(); 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 first 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" || event.type == 'click') { CCPopupMenu.activeMenu.doCheckBounds = false; CCPopupMenu.activeMenu.activeMenuItemIndex = -1; selectedObject = CCPopupMenu.activeMenu.getCurrentSelected(); if (!selectedObject) { currentMenu.menuItems[0].menuItemEl.focus(); } else { CCPopupMenu.setActiveMenuItem("current"); } } } CCPopupMenu.ignoreHideActiveMenu("ignore"); setTimeout('CCPopupMenu.ignoreHideActiveMenu("unignore")', 100); return haltEventProcessing(event); } //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_isTapInsideMenu(tapObject) { var tapX = tapObject.pageX; var tapY = tapObject.pageY; var menuRect = this.dropDownElement.getBoundingClientRect(); if (!((tapX >= menuRect.left) && (tapX <= menuRect.right) && (tapY <= menuRect.bottom) && (tapY >= menuRect.top))) { return true; } return false; } function CCPopupMenu_createDropDown() { //create the drop down consisting of the following html structure
...menuitems
var divEl = document.createElement("div"); var tableEl = document.createElement("table"); var tbody = document.createElement("tbody"); var itm; //can only add table rows to table bodies...can not add them to the table directly tableEl.appendChild(tbody); tableEl.style.borderCollapse = "collapse"; tableEl.summary = ""; tableEl.setAttribute("role", "menu"); divEl.id = "flyout_" + this.id; divEl.className = "flyOutMenu"; divEl.style.display = "block"; divEl.style.position = "absolute"; divEl.style.overflow = "visible"; //ensure that the popup is going to be the highest in the zorder so that things don't peek through //randomly choose 100 as it seemed like a pretty high number divEl.style.zIndex = "2"; divEl.style.visibility = "hidden"; divEl.style.padding = "2px"; divEl.setAttribute("role", "presentation"); if (this.label != null) { tableEl.setAttribute("aria-label", this.label); } divEl.tabIndex = -1; addEvent(divEl, "click", CCPopupMenu_dropDownOnclick); // Depending on the browser, define the appropriate key event handler for the pop-up menu items var moz = (window.navigator.userAgent.indexOf("Gecko") != -1); addEvent(divEl, (moz ? "keypress" : "keydown"), extensions.associate(itm, this, "presskey")); 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; for (index = 0; index < this.menuItems.length; index++) { 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 (var 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, hasCheckbox, messagesJSON) { this.controlId = controlId; this.id = sId; this.menuItems = []; this.isOpen = false; this.dropDownElement = null; this.mnHeight = -1; this.hasCheckbox = ((hasCheckbox != null) && (hasCheckbox == 'true')); //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, 10); } //indicates which index has focus - defaults to -1 so using down key positions correctly on first item in menu list this.activeMenuItemIndex = -1; this.firstMenuItemEl = null; this.doCheckBounds = true; this.label=null; this.messages = messagesJSON; CCPopupMenu.menus.push(this); } function CCPopupMenu_setLabel(newLabel){ this.label = newLabel; } //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.hasCheckbox, this); this.menuItems.push(newMenuItem); } //returns the menu item with the assoicated id function CCPopupMenu_getMenuItem(id) { for (var 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 (var 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 (var index = 0; index < this.menuItems.length; index++) { if (this.menuItems[index].type != "item") { index++; } if (this.menuItems[index].itemSelectedState != "none") { return this.menuItems[index]; } } return this.menuItems[index]; } //returns the menu items with a selection state not set to none function CCPopupMenu_getCurrentSelectedIndex() { for (var index = 0;index < this.menuItems.length; index++) { if (this.menuItems[index].type != "item") { index++; } if (this.menuItems[index].itemSelectedState != "none") { return index; } } return this.activeMenuItemIndex; } // Navigation on the flyout from pressing up and down arrow keys. Also passing current sets first entry that is selected. // When going 'up' or 'down' check to make sure that the next type is an item, if not then move by 1. function CCPopupMenu_setActiveMenuItem(direction) { currentMenu = CCPopupMenu.activeMenu; var index = direction == 'current' ? currentMenu.getCurrentSelectedIndex() : currentMenu.activeMenuItemIndex; if (direction == 'up') { if (index > 0) { if (currentMenu.menuItems[index - 1].type != "item") { index--; } index--; } } else if (direction == 'down') { if (index < currentMenu.menuItems.length - 1) { if (currentMenu.menuItems[index + 1].type != "item") { index++; } index++; } } if (index > -1 && index != currentMenu.activeMenuItemIndex) { currentMenu.activeMenuItemIndex = index; } currentMenu.menuItems[index].menuItemEl.focus(); } //sets the menu item with the associated id to be selected function CCPopupMenu_setMenuItemSelected(id) { //sets the checked attrute of the menuitem currentMenuItem = this.getMenuItem(id); if (currentMenuItem.isInGroup()) { this.clearGroup(currentMenuItem.groupId); } currentMenuItem.select(); } //Set the active item index when focus is set. function CCPopupMenu_setCurrentItemIndex(id) { currentMenu = CCPopupMenu.activeMenu; for (var index = 0; index < currentMenu.menuItems.length; index++) { if (currentMenu.menuItems[index].type != "item") { continue; } if (currentMenu.menuItems[index].menuItemEl.id == id) { currentMenu.activeMenuItemIndex = index; currentMenu.menuItems[index].menuItemEl.className = "menuItemOver"; } else { currentMenu.menuItems[index].menuItemEl.className = "menuItemNormal"; } } } //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); } } } // Handle pop-up menu key event to hide the active pop-up menu and reset focus when necessary function CCPopupMenu_hidePopupForKeyPress() { var moz = (window.navigator.userAgent.indexOf("Gecko") != -1); if (moz) { var currentMenu = CCPopupMenu.getMenu(CCPopupMenu.activeMenu.id); var controlContainerElement = document.getElementById(currentMenu.controlId); CCPopupMenu.hideActiveMenu(); if (controlContainerElement != null) { controlContainerElement.focus(); } } else { CCPopupMenu.hideActiveMenu(); } } // Handle the pop-up menu key events. function CCPopupMenu_presskey(evt) { evt = evt != null ? evt : window.event; if (evt.keyCode == 13) { // Enter: Act on the current menu if (CCPopupMenu.activeMenu.activeMenuItemIndex > -1) { CCPopupMenu.activeMenu.menuItems[CCPopupMenu.activeMenu.activeMenuItemIndex].keypressFunction(); CCPopupMenu.hidePopupForKeyPress(); } } else if (evt.keyCode == 27 || evt.keyCode == 9) { // Esc Key: Close menu and halt // Tab Key: Close menu and continue CCPopupMenu.hidePopupForKeyPress(); if (evt.keyCode == 9) { return true; } } else if (evt.keyCode == 38) { // Up Arrow Key CCPopupMenu.setActiveMenuItem('up'); } else if (evt.keyCode == 40) { // Down arrow Key CCPopupMenu.setActiveMenuItem('down'); } return haltEventProcessing(evt); } //***********************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.prototype.getCurrentSelectedIndex = CCPopupMenu_getCurrentSelectedIndex; CCPopupMenu.prototype.presskey = CCPopupMenu_presskey; CCPopupMenu.prototype.setLabel = CCPopupMenu_setLabel; CCPopupMenu.prototype.isTapInsideMenu = CCPopupMenu_isTapInsideMenu; CCPopupMenu.hideActiveMenu = CCPopupMenu_hideActiveMenu; CCPopupMenu.hidePopupForKeyPress = CCPopupMenu_hidePopupForKeyPress; 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.setActiveMenuItem = CCPopupMenu_setActiveMenuItem; CCPopupMenu.setCurrentItemIndex = CCPopupMenu_setCurrentItemIndex; //***********************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: function CCPopupMenuSeparator_renderItem(menuElement, id) { var menuItemEl = document.createElement("tr"); //menu separators should not be in the tabbing order menuItemEl.tabIndex = -1; menuItemEl.setAttribute("role", "separator"); 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, hasCheckbox, menu) { this.id = sId; this.label = slabel; this.icon = icon; this.itemSelectedState = "none"; this.type = "item"; this.groupId = groupId; this.enabled = true; this.menuItemEl = null; this.menuLabelEl = null; this.iconImageEl = null; this.selectionStateIcon = null; this.selectionElement = null; this.menuIdx = -1; this.hasCheckbox = hasCheckbox; this.parentMenu = menu; //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", clickActionCode); // this.keyArrowFunction = new Function("event", clickFunction); // 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.padding = "2px"; menuItemLabel.className = "menuItemNormal"; this.menuLabelEl = menuItemLabel; menuElement.appendChild(menuItemLabel); var nonbreakingSpace = document.createElement("nobr"); menuItemLabel.appendChild(nonbreakingSpace); var labelLink = document.createElement("span"); labelLink.tabIndex = -1; nonbreakingSpace.appendChild(labelLink); labelLink.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"; imgEl.alt=""; imgEl.setAttribute("role","presentation"); 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; this.menuItemEl.setAttribute("aria-checked","false"); } } else { if (this.selectionStateIcon == null) { var imgEl = document.createElement("img"); if (this.itemSelectedState == "checked") { imgEl.src = CCPopupMenu.portalImagesPath + "/checkmark.gif"; if (this.parentMenu.messages != null){ imgEl.alt = this.parentMenu.messages.IDS_CCPOPUP_CHECKED; } } else { imgEl.src = CCPopupMenu.portalImagesPath + "/dot.gif"; if (this.parentMenu.messages != null){ imgEl.alt = this.parentMenu.messages.IDS_CCPOPUP_DOT; } } this.selectionElement.appendChild(imgEl); this.selectionStateIcon = imgEl; } else { if (this.itemSelectedState == "checked") { this.selectionStateIcon.src = CCPopupMenu.portalImagesPath + "/checkmark.gif"; if (this.parentMenu.messages != null){ this.selectionStateIcon.alt = this.parentMenu.messages.IDS_CCPOPUP_CHECKED; } } else { this.selectionStateIcon.src = CCPopupMenu.portalImagesPath + "/dot.gif"; if (this.parentMenu.messages != null){ this.selectionStateIcon.alt = this.parentMenu.messages.IDS_CCPOPUP_DOT; } } this.updateForEnabled(); } this.menuItemEl.setAttribute("aria-checked","true"); } } //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, 'keydown', this.presskey); addEvent(this.menuItemEl, 'click', this.clickFunction); //update the style this.menuItemEl.style.MozOpacity = "1.0"; this.menuItemEl.setAttribute("aria-disabled","false"); 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, 'keydown',this.presskey); removeEvent(this.menuItemEl, 'click', this.clickFunction); //update the style this.menuItemEl.style.MozOpacity = "0.5"; this.menuItemEl.setAttribute("aria-disabled","true"); 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); CCPopupMenu.setCurrentItemIndex(menuItemEl.id); }; } function menuItemOutEventHandler(id) { return function ccmenuitemouteventhandler() { var menuItemEl = document.getElementById(id); menuItemEl.className = 'menuItemNormal'; }; } function menuItemBlurEventHandler(id) { return function ccmenuitemblureventhandler(event) { var menuItemEl = document.getElementById(id); menuItemEl.className = 'menuItemNormal'; CCPopupMenu.checkBounds(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: ..label... function CCPopupMenuItem_renderItem(menuElement, id) { var menuItemEl = document.createElement("tr"); var itemRole = "menuitem"; //if this menu has checkable menu items then the role is slightly different to allow for aria-checked attribute if (this.hasCheckbox){ itemRole = "menuitemcheckbox"; menuItemEl.setAttribute("aria-checked","false"); } menuItemEl.setAttribute("role", itemRole); menuItemEl.className = "menuItemNormal"; menuItemEl.id = this.id + "menuItemTR"; menuItemEl.tabIndex = -1; 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 function respondToTouch(){ if (CCPopupMenu.activeMenu != null){ var event = window.event; if (CCPopupMenu.activeMenu.isTapInsideMenu(event.targetTouches[0])) { var controlElement = document.getElementById(CCPopupMenu.activeMenu.controlId); if (event.taget != controlElement){ CCPopupMenu.hideActiveMenu(); } } } } //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(document, 'touchstart', respondToTouch); addEvent(window, 'resize', CCPopupMenu.hideActiveMenu); //add this event handler to prebuild the drop downs for the page addEvent(window, 'load', CCPopupMenu.createDropDowns);