/* ------------------------------------------------------------------------ * * SAS Institute, Inc. * * * * Copyright (c) 2002-2005 SAS Institute, Inc. All rights reserved. * * * * Purpose: Contains the javascript classes and methods for the * * MenuBar class * * * * Author: * * Version: 1.0 * * * * ------------------------------------------------------------------------ */ var highlightDiv=null; var previousMenu = null; var previousSubmenu = null; var debug = false; if (debug) { w = window.open("", "winname", "width=200 height=200 resizable=1 scrollbars=1 status=0"); w.document.bgColor = "#FFCC00"; } var active = new ActiveMenus(); try { sas_registerEventHandler(document, 'click', function() {MenuBar_hideAll()}, false); } catch (e) // in case sas_Common.js hasn't been loaded { if( document.attachEvent != null) // IE way document.attachEvent( "onclick", function() {MenuBar_hideAll()}); else document.addEventListener( "click", function() {MenuBar_hideAll()}, false); } function MenuBar_Array_splice( array, i ) { if (array.splice) { // $$$ standard now? array.splice(i, 1); } else { while (i " + menu.id + " doesn't exist"); return false } function ActiveMenus_removeMenu( menu ) { for (var i=0; i < this.length; i++) { if (menu == this[i] ) { MenuBar_Array_splice(this,i); return this; } } return this; } function ActiveMenus_clear() { var active = this; for (var i=0; i < active.length; i++) { delete active[i]; } active.length = 0; } function dumpActive() { w.document.close(); w.document.write(active.length + "
"); for (var i=0; i< active.length; i++) { w.document.write(active[i].id + "
"); } } function ActiveMenus_getIndex( menu ) { if (menu == null) return -1; for( var i=0; i" + active[i].id + "
"); if (active[i].id.indexOf("_dropper") < 1) MenuBar_hideMenu(active[i], evt); } //w.document.write("hide after: " + active.getIndex(obj) + "
"); } function MenuBar_showMenu(obj, evt) { if (!active.contains(obj)) active.appendMenu(obj); // dumpActive(); if (obj == null) return; if (document.all) { if ((event.toElement == null) || (!obj.contains(event.toElement))) { obj.style.display = 'block'; } } else if (document.getElementById) { if (!MenuBar_containsNN6 (obj, evt.relatedTarget)) obj.style.display = 'block'; } } function MenuBar_hideMenu(obj, evt) { if (document.all) { if (!obj.contains(event.toElement)) obj.style.display = 'none'; } else if (document.getElementById) { if (!MenuBar_containsNN6 (obj, evt.relatedTarget)) obj.style.display = 'none'; } if (active.contains(obj)) { // active.removeMenu(obj); } // dumpActive(); } function MenuBar_hidePop(_obj, evt) { var obj; MenuBar_hideAll(); if (_obj != null) obj = document.getElementById(_obj); if (previousMenu != null && obj != previousMenu) { MenuBar_hideMenu(previousMenu, evt); } if (previousSubmenu != null) { MenuBar_hideMenu(previousSubmenu, evt); } if (obj == null) return; else MenuBar_hideMenu(obj, evt); } function MenuBar_containsNN6 (container, containee) { var isParent = false; if (containee == null) return isParent; do { if ((isParent = container == containee)) break; } while ((containee = containee.parentNode)); return isParent; } function MenuBar_showPopClick(menuId, relativeToId, _divpos, evt) { if (evt) evt.cancelBubble = true; menu = document.getElementById(menuId); relativeTo = document.getElementById(relativeToId); if (previousMenu != null && previousMenu != menu) { MenuBar_hideMenu(previousMenu, evt); previousMenu = null; } //alert(obj.style.display); if (menu.style.display == 'block') { MenuBar_hideMenu(menu, evt); } else { MenuBar_hideAll(); MenuBar_showMenu(menu, evt); sas_autoPosition(menu,relativeTo); } previousMenu = menu; } ////////////////////////////////////////////////////////////////// // sas_MenuBar_showPop - display the menu items in a given div // div: The div id to display // menuItem: The current menu activating the menu item // horizontal: orientation of the menu // submenu: If submenu // evt event /////////////////////////////////////////////////////////////////// function MenuBar_showPop(div,menuItem,horizontal,submenu,evt) { var divid = document.getElementById(div); if (!submenu) { MenuBar_hideAll(); if (previousMenu != null && divid != previousMenu) { MenuBar_hideMenu(previousMenu, evt); previousMenu = null; } } else { // submenu // find the parent menu var parentMenu = MenuBar_getMenuItemMenu(menuItem); MenuBar_hideMenuItems(parentMenu.id, evt); } MenuBar_showMenu(divid, evt); if (divid == null) return; if (!horizontal || submenu) { relativeTo = document.getElementById(menuItem); sas_autoPositionHorizontally(divid,relativeTo); } else { relativeTo = document.getElementById(menuItem); sas_autoPosition(divid,relativeTo); } if (!submenu) previousMenu = divid; } function MenuBar_getMenuItemMenu(menuItem) { var el = document.getElementById(menuItem); while (el) { if (el != null && el.tagName == "DIV") { var index = active.getIndex(el); if (index >= 0) { return el; } } el = el.parentNode; } return null; } function setHideDelay(){ hideDelay=setTimeout("MenuBar_hideAll()",500) } function MenuBar_menuItemOver(_obj, styleClass) { obj = document.getElementById(_obj); obj.className = styleClass + "Active"; obj.onmouseout = function() { MenuBar_menuItemOut(_obj, styleClass) } } function MenuBar_menuItemOut(_obj, styleClass) { obj = document.getElementById(_obj); obj.className = styleClass; } /** * MENUBAR: keyboard naviation functions **/ /* * This method has been deprecated and is no longer called by the onKeyDown event. */ function sas_MenuBar_getNextMenuId(index, max, menuBarName) { for (var i=index+1; i < max; i++) { id = document.getElementById(menuBarName+"_menu_"+i+"_a"); // alert(id + ":" + i); if (id) return id; } return null; } /* * This method has been deprecated and is no longer called by the onKeyDown event. */ function sas_MenuBar_getPreviousMenuId(index, menuBarName) { for (var i= index - 1; i >= 0; i--) { id = document.getElementById(menuBarName+"_menu_"+i+"_a"); //alert(id + ":::" + i); if (id) return id; } return null; } /* * This method has been deprecated and is no longer called by the onKeyDown event. */ function sas_MenuBar_getNextMenuItemId(index, max, menuBarName) { for (var i=index+1; i < max+1; i++) { id = document.getElementById(menuBarName+"_menuItem_"+i+"_a"); if (id && sas_MenuBar_isVisible(id) != "none") { return i; } } return null; } /* * This method has been deprecated and is no longer called by the onKeyDown event. */ function sas_MenuBar_getPreviousMenuItemId(index, menuBarName) { for (var i=index - 1; i >= 0; i--) { id = document.getElementById(menuBarName+"_menuItem_"+i+"_a"); if (id && sas_MenuBar_isVisible(id) != "none") { return i; } } return null; } /* * This method has been deprecated and is no longer called by the onKeyDown event. */ function sas_MenuBar_isMenu(index, menuBarName) { id = document.getElementById(menuBarName+"_menu_"+index+"_a"); if (id) return true; return false; } /* * This method has been deprecated and is no longer called by the onKeyDown event. */ function sas_MenuBar_getSubMenuId(index, menuBarName) { id = document.getElementById(menuBarName+"_menuItem_"+index+"_a"); if (!id) return; var el = id.parentNode.parentNode; while (el) { el = el.parentNode; if (el != null && el.tagName == "DIV") { if ( el.id.indexOf(menuBarName+"_sub") != -1) return el; } } return null; } /* * This method has been deprecated and is no longer called by the onKeyDown event. */ function sas_MenuBar_getMenuItemContainer(index, menuBarName) { id = document.getElementById(menuBarName+"_menuItem_"+index+"_a"); if (!id) return; var el = id.parentNode.parentNode; while (el) { el = el.parentNode; if (el != null && el.tagName == "DIV") { if (el.id.indexOf(menuBarName+"_sub") != -1 || el.id.indexOf(menuBarName+"_dropper") != -1) return el; } } return null; } function sas_MenuBar_navigateMenu(evt, prevMenuItem, nextMenuItem, prevMenu, nextMenu, subMenuId) { var stopProcessing = false; var event_number = evt.keyCode; var id = null; if (event_number == "40") //DOWN { id = document.getElementById(nextMenuItem+"_a"); } else if (event_number == "38") //UP { id = document.getElementById(prevMenuItem+"_a"); } else if (event_number == "39") //RIGHT { id = document.getElementById(nextMenu+"_a"); if (subMenuId) { // this is a submenu, open it MenuBar_showPop(subMenuId+'_sub', subMenuId, false, true, evt); } else { MenuBar_hideAll(); } } else if (event_number == "37") //LEFT { id = document.getElementById(prevMenu+"_a"); var myMenu = document.getElementById(prevMenu+"_sub"); if (myMenu) { // element was on a submenu, so hide the submenu MenuBar_hideMenu(myMenu,event); } else { MenuBar_hideAll(); } } else if (event_number == "27") //ESCAPE { MenuBar_hideAll(); } if (id) { if (sas_MenuBar_isVisible(id) != "none") { try{ if(id.disabled) id.disabled = false; id.focus(); }catch (e){} } stopProcessing = true; } // IE has different mechanism to cancel event processing if (stopProcessing && navigator.appName.indexOf('Netscape') == -1) { event.returnValue = false; } return stopProcessing; } function sas_MenuBar_highlightMenuItem(element) { //incoming element could either be the anchor or the td that the anchor lives in. anchor = null; if(element.tagName=='A') // if its already anchor then we a { anchor= element; menuItemRow = anchor.parentNode.parentNode; // Menu Item TR menuTable = menuItemRow.parentNode.parentNode; // Menu Table menuDiv = menuTable.parentNode; // Menu container Div } // if table passed in then jump through its first rows columns looking for an anchor if(element.tagName=='TABLE') { firstRow = element.rows[0]; if(firstRow!=null) { cols = firstRow.childNodes; if(cols!=null) { for (var i = 0; i < cols.length; i++) { if(cols[i].tagName=='TD') // should always be a TD but just to be safe { kids = cols[i].childNodes; for (var j = 0; j < kids.length; j++) { if(kids[j].tagName=='A') // is it the anchor { anchor = kids[j]; menuItemRow = anchor.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode; // Menu Item TR menuTable = menuItemRow.parentNode.parentNode; // Menu Table menuDiv = menuTable.parentNode; // Menu container Div break; } } } if(anchor!=null) break; } } } } // if TD passed in then find its internal anchor if(element.tagName=='TD') { kids = element.childNodes; for (var i = 0; i < kids.length; i++) { if(kids[i].tagName=='A') // is it the anchor { anchor = kids[i]; menuItemRow = anchor.parentNode.parentNode; // Menu Item TR menuTable = menuItemRow.parentNode.parentNode; // Menu Table menuDiv = menuTable.parentNode; // Menu container Div break; } } } if(anchor!=null) { if(menuDiv!=null && menuDiv.style.display!='none') // can happen in time span between clicking a menu item adn the menu closing itself { highlightDiv = document.getElementById(menuDiv.id + "_highlightMenuItem"); if(!highlightDiv) { highlightDiv = document.createElement("DIV"); highlightDiv.id = menuDiv.id+"_highlightMenuItem"; highlightDiv.className = "menuItemHighlight"; menuDiv.appendChild(highlightDiv); } // really should put some cross browser event dispatching code in sas_Common // at some point and use that instead of this. if(anchor.dispatchEvent) // DOM2 highlightDiv.onclick=function(event){anchor.dispatchEvent(event);}; // $$$ fix for later Firefox versions else { // IE - could fireEvent but since IE supports click method lets just // call it on the anchor. highlightDiv.onclick=function(event){anchor.click();}; // highlightDiv.onclick=function(event){anchor.fireEvent(window.event.type, window.event);}; } // we will now position the highlighting div over the top of // the menu items TR. rowCoords = new sas_Coordinates(menuItemRow); menuDivCoords = new sas_Coordinates(menuDiv); anchorCoords = new sas_Coordinates(anchor); highlightDiv.style.top = anchorCoords.getY(); highlightDiv.style.height = anchorCoords.getHeight(); highlightDiv.style.left = menuDivCoords.getX()+2; highlightDiv.style.width = menuDivCoords.getWidth()-6; highlightDiv.style.display='block'; } } else { if(highlightDiv!=null) highlightDiv.style.display='none'; } } /* $$$ fix the redispatch for later Firefox versions function sas_MenuBar_redispatchDOM2(e) { var event = document.createEvent("MouseEvents"); event.initMouseEvent(e.type, e.bubbles, e.cancelable, e.view, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget); anchor.dispatchEvent(event); } */ /* * This method has been deprecated and is no longer called by the onKeyDown event. */ function sas_MenuBar_scrollMenu(evt, index, lastIndex, menuBarName, _div) { var stopProcessing = false; var event_number = evt.keyCode; var val; var id = null; if (event_number == "40") //DOWN { if (!sas_MenuBar_isVisible(id) != "none") { previousIndex = sas_MenuBar_getNextMenuItemId(index, lastIndex, menuBarName); id = document.getElementById(menuBarName+"_menuItem_"+previousIndex+"_a"); if (!sas_MenuBar_isMenu(index, menuBarName)) { currentContainer = sas_MenuBar_getMenuItemContainer(index, menuBarName); previousContainer = sas_MenuBar_getMenuItemContainer(previousIndex, menuBarName); if (currentContainer != previousContainer) { stopProcessing = true; id = null; } } } } else if (event_number == "38") //UP { if (!sas_MenuBar_isVisible(id) != "none") { nextIndex = sas_MenuBar_getPreviousMenuItemId(index, menuBarName, false); id = document.getElementById(menuBarName+"_menuItem_"+nextIndex+"_a"); currentContainer = sas_MenuBar_getMenuItemContainer(index, menuBarName); nextContainer = sas_MenuBar_getMenuItemContainer(nextIndex, menuBarName); if (currentContainer != nextContainer) { stopProcessing = true; id = null; } } if (!id) MenuBar_hideAll(); } else if (event_number == "39") //RIGHT { if (!_div) { id = sas_MenuBar_getNextMenuId(index, lastIndex, menuBarName); if (id) { MenuBar_hideAll(); } else { MenuBar_hideAll(); stopProcessing = true; id = null; } //alert("right" + id); } else { val = index+1; id = document.getElementById(menuBarName+"_menuItem_"+val+"_a"); cellid = menuBarName+"_menuItem_"+index; MenuBar_showPop(_div, cellid, false, true, evt); } } else if (event_number == "37") //LEFT { id = sas_MenuBar_getPreviousMenuId(index, menuBarName); divid = sas_MenuBar_getSubMenuId(index, menuBarName, true); if (divid) { divid.style.display = "none"; previousIndex = sas_MenuBar_getPreviousMenuItemId(index, menuBarName); id = document.getElementById(menuBarName+"_menuItem_"+previousIndex+"_a"); } else if (id) MenuBar_hideAll(); } else if (event_number == "27") //ESCAPE { MenuBar_hideAll(); } if (id) { if (sas_MenuBar_isVisible(id) != "none") { try{ id.focus(); }catch (e){} } stopProcessing = true; } // IE has different mechanism to cancel event processing if (stopProcessing && navigator.appName.indexOf('Netscape') == -1) { event.returnValue = false; } return stopProcessing; } function sas_MenuBar_isVisible(id) { if (!id || !id.parentNode) return; var el = id.parentNode.parentNode; while (el) { el = el.parentNode; if (el != null && el.tagName == "DIV") { return el.style.display; } } } /* ------------------------------------------------------------- * * --Begin sas_MenuBar_PositionGraphMenu-- * * Attempt to automatically do an absolute positioning on an html * element relative to a set of x,y coordinates. Will attempt several * predefined relative positions until it finds one that doesn't * cause the element to be clipped. If none of the predefined * positions work without clipping then we just dump the element * in the preferred position despite clipping. * * Example Useage... * DivToPosition = document.getELementById("MyPopupMenu"); * sas_autoPositionXY(DivToPosition, relativeToX, relativeToY, relativeToContainer); * * ------------------------------------------------------------- */ function sas_MenuBar_positionGraphMenu(elementToPosition, div, htmlArea) { var relativeToCoordinates = new sas_Coordinates(div); relativeToCoordinates.setRelativeToSharedBreakoutBox(elementToPosition); relativeToX = htmlArea.offsetLeft + relativeToCoordinates.getX(); relativeToY = htmlArea.offsetTop + relativeToCoordinates.getY(); // lets try several positions which we would consider ideal and // if none of them work without clipping then we'll have to resort to // just dumping it somewhere even though it does clip // 1. try positioning elementToPosition left edge aligned with left edge of area and // top edge aligned with bottom of area proposedLeft = relativeToX; proposedTop = relativeToY + htmlArea.offsetHeight; if(sas_checkClipping(elementToPosition, proposedLeft, proposedTop)==true) { // 2. try positioning element right edge aligned with right edte of area // and top edge aligned with bottom edge of area proposedLeft = relativeToX -(elementToPosition.offsetWidth-htmlArea.offsetWidth); proposedTop = relativeToY + htmlArea.offsetHeight; if(sas_checkClipping(elementToPosition, proposedLeft, proposedTop)==true) { // 3. try positioning elementToPosition left edge aligned with left edge of area // and bottom edge aligned with top of area proposedLeft = relativeToX; proposedTop = relativeToY - elementToPosition.offsetHeight; if(sas_checkClipping(elementToPosition, proposedLeft, proposedTop)==true) { // 4. try positioning elementToPosition right edge aligned with right edge of area // and bottom edge aligned with top of area proposedLeft = relativeToX -(elementToPosition.offsetWidth-htmlArea.offsetWidth); proposedTop = relativeToY - elementToPosition.offsetHeight; if(sas_checkClipping(elementToPosition, proposedLeft, proposedTop)==true) { // 5. try positioning elementToPosition right edge aligned with left edge // of area and center aligned with center of area proposedLeft = relativeToX - elementToPosition.offsetWidth; proposedTop = relativeToY - (elementToPosition.offsetHeight/2) + (relativeToCoordinates.getWidth()/2); if(sas_checkClipping(elementToPosition, proposedLeft, proposedTop)==true) { // 6. last ditch effort... Could probably also do center positioning attemps if these four // aren't sufficient. // Just dump it at our ideal spot (#1) even though it will clip proposedLeft = relativeToX; proposedTop = relativeToY + htmlArea.offsetHeight; } } } } } elementToPosition.style.left = proposedLeft; elementToPosition.style.top = proposedTop; } //SELECTOR MENUBAR var previousObject = null; var previousCell = null; function SelectorMenuBar_hide(objid) { var _objid = document.all ? document.all[objid] : document.getElementById ? document.getElementById(objid) : null; objid.style.display = "none"; } function SelectorMenuBar_hideUnhide(selector,menu) { var selector_div = document.getElementById(selector); var menu_cell = document.getElementById(menu); if (selector_div.style.display == 'block') { selector_div.style.display = "none"; if (menu_cell != null) menu_cell.className = "menu"; } else { selector_div.style.display = 'block'; menu_cell.className = "menuActive"; } if ((previousObject != null) && (previousObject != selector_div)) previousObject.style.display = "none"; if ((previousCell != null) && (menu_cell != previousCell)) previousCell.className ="menu"; previousObject = selector_div; previousCell = menu_cell; } function SelectorMenuBar_openExternalSelector(url, width, height, target, modal) { var args = "width="+width+","+ "height="+height+","+ "toolbar=0,"+ "menubar=0,"+ "scrollbars=0,"+ "resizable=1,"+ "status=0,"+ "location=0,"+ "directories=0,"+ "copyhistory=450"; if (modal != null && modal == 'true') subwindow = sas_modalSelector_openModal(url,"subwin"+target,args,1); else subwindow = window.open(url,"subwin"+target,args,true); if (!subwindow.opener) subwindow.opener = self; window.currentDialog = subwindow; // TODO: Is this needed ? Had problems when trying to open new window // with "_blank" as target. See S0314959. window.name = target; MenuBar_hideAll(); } function SelectorMenuBar_openSelector(selobj, width, height) { var args = "width="+width+","+ "height="+height+","+ "toolbar=0,"+ "menubar=0,"+ "scrollbars=0,"+ "resizable=1,"+ "status=0,"+ "location=0,"+ "directories=0,"+ "copyhistory=450"; subwindow = window.open("","subwin",args); document.SelectorMenuBar_FORM.target = "subwin"; //document.SelectorMenuBar_FORM.action = "/example/selectorMenuBar1.jsp"; document.SelectorMenuBar_FORM.externalCommand.value = selobj; //document.SelectorMenuBar_FORM.menubarName.value = "SelectorMenuBar"; window.name= "opener"; document.SelectorMenuBar_FORM.submit(); }