menubar.js 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  1. /********************************************************************************************************************************
  2. * Licensed Materials - Property of IBM *
  3. * *
  4. * IBM Cognos Products: AGS *
  5. * *
  6. * (C) Copyright IBM Corp. 2005, 2009 *
  7. * *
  8. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *
  9. *********************************************************************************************************************************/
  10. //css custom style constants
  11. var MENU_MENUBAR="menuBar";
  12. var MENU_CONTAINER="menuContainerOld";
  13. var MENU_HORIZONTAL_SEPERATOR = "menuHorizontalSeperator"
  14. var MI_NORMAL="menuItem_normal";
  15. var MI_HOVER="menuItem_hover";
  16. var MI_PRESSED="menuItem_pressed";
  17. var MI_DISABLED="menuItem_disabled";
  18. var MT_NORMAL="menuTitle_normal";
  19. var MT_HOVER="menuTitle_hover";
  20. var MT_PRESSED="menuTitle_pressed";
  21. var TEXT="";
  22. //the id of the menu bar placement tag
  23. var AGS_MENUBAR_ID="menuBar"
  24. //positioning tweaks for the menus
  25. var DROP_DOWN_X_TWEAK=2;
  26. var DROP_DOWN_Y_TWEAK=3;
  27. var DROP_DOWN_SUBMENU_Y_TWEAK=2;
  28. //the menu bar object
  29. var agsMenuBar = new MenuBar(MENU_MENUBAR);
  30. //the timeout identifier used to auto close any open menus after a period of time defined in TIMEOUT_MS
  31. var windowTimeout = null;
  32. //the number of milliseconds to wait before all open menus are closed, set to 4 seconds
  33. var TIMEOUT_MS=4000;
  34. /*
  35. **********************
  36. * START MenuBar object
  37. **********************
  38. */
  39. function MenuBar(barName) {
  40. //methods
  41. this.writeMenuBar=writeMenuBar;
  42. this.displayMenu=displayMenu;
  43. this.addLabel=addLabel;
  44. this.closeLastOpenMenu=closeLastOpenMenu;
  45. this.showMenu=showMenu;
  46. this.showMenuSide=showMenuSide;
  47. this.findById=findById;
  48. this.findRowElement=findRowElement;
  49. this.hideOpenSubMenus=hideOpenSubMenus;
  50. this.hideMenu = hideMenu;
  51. this.resetMenus = resetMenus;
  52. this.getMenuLabelLink = getMenuLabelLink;
  53. this.getMenuLabelDiv = getMenuLabelDiv;
  54. this.changeObjectVisibility = changeObjectVisibility;
  55. this.getElementLeft = getElementLeft;
  56. this.getElementTop = getElementTop;
  57. this.getElementHeight = getElementHeight;
  58. this.moveXY = moveXY;
  59. //assign values
  60. this.barName=barName;
  61. this.menus = new Array();
  62. this.autoOpen=false;
  63. this.lastOpenMenu=null;
  64. this.lastOpenSubMenu=null;
  65. this.numLabels = 0;
  66. }
  67. /*
  68. * Add a label to the menu bar. This equates to one of the top level menu items
  69. */
  70. function addLabel(labelText) {
  71. var menuNo = this.numLabels;
  72. var labelId = 'labelCell' + menuNo;
  73. var newMenu = new MenuItem(labelText,this,null,null);
  74. newMenu.id=labelId;
  75. newMenu.index = this.numLabels;
  76. this.menus[menuNo]=newMenu;
  77. //set the id suffix
  78. newMenu.menuContainerId=this.numLabels;
  79. //update the label count
  80. this.numLabels += 1;
  81. return newMenu;
  82. }
  83. /*
  84. * Display the menu bar, first the menu labels are drawn
  85. * A menu label is rendered with the current menu id defined as [id] :
  86. * <div id='labelCell[id]'>
  87. * <a id='menuLink[id]' class="menuTitle[normal|pressed]" href=''>the name</a>
  88. * </div>
  89. *
  90. * followed by each menu container which container one or more menu items. Initially
  91. * these are hidden and only displayed when the mouse is clicked
  92. */
  93. function writeMenuBar() {
  94. var parentMenuBar = this;
  95. var AGSMenuBar = document.getElementById(AGS_MENUBAR_ID);
  96. if (AGSMenuBar != null) {
  97. //create the menu bar div
  98. var menuBarDiv = document.createElement("div");
  99. menuBarDiv.id="labelContainer";
  100. menuBarDiv.className=MENU_MENUBAR;
  101. menuBarDiv.style.width="100%";
  102. //add each menu label to the menu bar
  103. for (var count = 0; count < this.numLabels; count++) {
  104. var menuLabel = this.menus[count];
  105. var menuLinkId = 'menuLink' + count;
  106. //create the top level div for the label
  107. var menuLabelDiv = document.createElement("div");
  108. menuLabelDiv.id=menuLabel.id;
  109. menuLabelDiv.style.paddingTop="4px";
  110. menuLabelDiv.style.paddingLeft="3px";
  111. menuLabelDiv.style.paddingRight="3px";
  112. menuLabelDiv.style.paddingBottom="4px";
  113. if (document.all) {
  114. menuLabelDiv.style.styleFloat="left"; //for netscape use cssFloat property
  115. } else {
  116. menuLabelDiv.style.cssFloat="left";
  117. }
  118. //create the label anchor
  119. var menuLabelAnchor = document.createElement("span");
  120. //set the correct 'hand' pointer for firefox
  121. //for some reason firefox render the 'hand' setting
  122. //as a text caret
  123. if (browserCheck.isNav6Up()) {
  124. menuLabelAnchor.style.cursor='pointer';
  125. }
  126. menuLabelAnchor.unselectable="on";
  127. menuLabelAnchor.id=menuLinkId;
  128. // force the href to do nothing
  129. //menuLabelAnchor.href="javascript:return false;";
  130. // create the text
  131. var text = document.createTextNode(menuLabel.name);
  132. // add it as a child
  133. menuLabelAnchor.appendChild(text);
  134. menuLabelAnchor.className=MT_NORMAL;
  135. menuLabelDiv.appendChild(menuLabelAnchor);
  136. /*
  137. * The mouse has left a menu label. When autoOpen is set then the menu label style remains unchanged
  138. * otherwise change the style from hover to normal
  139. */
  140. var onMouseOutHandler = function(event) {
  141. var target = (event.target) ? event.target : event.srcElement;
  142. //only set timeouts on menuLink ids i.e. anchor tags
  143. //this event handler is fired for both menu items in sub menus and label menu items
  144. //This is useful because the timeout clear can be handled in one place
  145. if (target.id.indexOf('menuLink') != -1) {
  146. //the reset function
  147. var f = function(){
  148. parentMenuBar.resetMenus();
  149. }
  150. windowTimeout = window.setTimeout(f,TIMEOUT_MS);
  151. }
  152. //only reset the class when auto open is switched off. The menu label should
  153. //always be highlighted when a menu is open and the sub menus are being traversed. This is the
  154. //normal behaviour for Windows type applications
  155. if (!parentMenuBar.autoOpen) {
  156. //because this event propagates according to the IE event model
  157. //ensure this event has come from the menu label and not a menu item
  158. var menuLabelLinkEle = parentMenuBar.getMenuLabelLink(event);
  159. var menuLabelDivEle = parentMenuBar.getMenuLabelDiv(event);
  160. if (menuLabelLinkEle != null && menuLabelDivEle != null) {
  161. menuLabelLinkEle.className=MT_NORMAL;
  162. }
  163. }
  164. }
  165. /*
  166. * The mouse has entered a menu label. When autoOpen is set this method will close any open menus,
  167. * display the new menu and then change the menu style to pressed. When autoOpen is false then the
  168. * style is changed to hover
  169. */
  170. var onMouseOverHandler = function(event) {
  171. var target = (event.target) ? event.target : event.srcElement;
  172. var menuLabelLinkEle = parentMenuBar.getMenuLabelLink(event);
  173. var menuLabelDivEle = parentMenuBar.getMenuLabelDiv(event);
  174. //ensure the menu is kept open
  175. window.clearTimeout(windowTimeout);
  176. //label link not found we are over a menu item so just ignore
  177. if (menuLabelDivEle != null && menuLabelLinkEle != null) {
  178. //we have a top level menu item
  179. if (parentMenuBar.autoOpen) {
  180. var menuItem = parentMenuBar.findById(menuLabelDivEle.id);
  181. if (menuItem != null) {
  182. var menuNo = menuItem.index;
  183. //this closes the last open menu and also resets the menu class
  184. //only show it when we had a succesful close
  185. if (menuItem != parentMenuBar.lastOpenMenu) {
  186. if (parentMenuBar.closeLastOpenMenu()) {
  187. parentMenuBar.showMenu(menuNo,event);
  188. }
  189. }
  190. //update the last open property
  191. parentMenuBar.lastOpenMenu = menuItem;
  192. parentMenuBar.lastOpenSubMenu=null;
  193. menuLabelLinkEle.className=MT_PRESSED;
  194. //hide any open sub menus
  195. parentMenuBar.hideOpenSubMenus();
  196. }
  197. }
  198. else {
  199. menuLabelLinkEle.className = MT_HOVER;
  200. }
  201. }
  202. }
  203. //create an anonymous event handler, there is a small hack that is necessary here
  204. //because when inside the handler 'this' becomes the document and not the menu bar
  205. //so the menu bar needs to be explicitly defined here as parentMenuBar. This only seems to
  206. //happen with properties and not object methods so this.findById is okay but this.numLabels is undefined
  207. var onClickHandler = function(event) {
  208. var returnVal=false;
  209. var target = (event.target) ? event.target : event.srcElement;
  210. var menuLabelLinkEle = null;
  211. var menuLabelDivEle = null;
  212. menuLabelLinkEle = parentMenuBar.getMenuLabelLink(event);
  213. menuLabelDivEle = parentMenuBar.getMenuLabelDiv(event);
  214. //this mouse click event is fired from both clicking a menu item and clicking a label item
  215. //so if the label div is null then a menu item has been clicked and we should propagate the event to
  216. //the lower echelons of the web page
  217. if (menuLabelDivEle != null) {
  218. var menuItem = parentMenuBar.findById(menuLabelDivEle.id);
  219. var menuNo = menuItem.index;
  220. if (browserCheck.isIE5dot5Up()) {
  221. //remove the focus outline around the element
  222. target.blur();
  223. }
  224. //the last open menu is the same as this one, so close the menu
  225. if (parentMenuBar.lastOpenMenu == menuItem) {
  226. parentMenuBar.hideMenu(menuItem);
  227. menuLabelLinkEle.className = MT_HOVER;
  228. parentMenuBar.autoOpen = false;
  229. parentMenuBar.lastOpenMenu=null;
  230. }
  231. else {
  232. parentMenuBar.autoOpen = true;
  233. returnVal = !parentMenuBar.showMenu(menuNo,event);
  234. parentMenuBar.lastOpenMenu = menuItem;
  235. menuLabelLinkEle.className = MT_PRESSED;
  236. }
  237. }
  238. //propagate the event
  239. else {
  240. window.event.cancelBubble = false;
  241. returnVal = true;
  242. }
  243. return returnVal;
  244. }
  245. // set the event handlers for the menu labels
  246. parent.addEvent(menuLabelAnchor,"mouseover",onMouseOverHandler);
  247. parent.addEvent(menuLabelAnchor,"mouseout",onMouseOutHandler);
  248. parent.addEvent(menuLabelAnchor,"click",onClickHandler);
  249. //END OF ONCLICK EVENT HANDLER
  250. menuLabel.writeContainer(menuLabelDiv);
  251. menuBarDiv.appendChild(menuLabelDiv);
  252. }
  253. //end for loop
  254. AGSMenuBar.appendChild(menuBarDiv);
  255. //document.onmousedown = pageMousedown;
  256. //parent.getMessageIFrame().onmousedown = pageMousedown;
  257. cfgSet(MENU_MENUBAR,this);
  258. }
  259. else {
  260. document.write('<p>Cannot find a placement &lt;div&gt; tag with the required id['+AGS_MENUBAR_ID+']</p>');
  261. }
  262. }
  263. /*
  264. * Hide a menu item, this method will also hide any open child menu items
  265. * menuItem The menu item to be hidden
  266. */
  267. function hideMenu(menuItem) {
  268. if (menuItem != null) {
  269. menuItem.state=MenuItem.CLOSED;
  270. //ensure their are no child menus still open
  271. var openMenus = menuItem.getOpenMenuItems();
  272. for (var i=0;i<openMenus.length;i++) {
  273. this.hideMenu(openMenus[i]);
  274. }
  275. //hide it now
  276. if(changeObjectVisibility('menu' + menuItem.menuContainerId, 'hidden')) {
  277. return true;
  278. }
  279. else {
  280. return false;
  281. }
  282. }
  283. }
  284. /*
  285. * Switch the visibility of the element, which is accomplished by switch
  286. * the visibility style for either hidden or visible
  287. * objectId The id of the element to be changed
  288. * newVisibility The visibility property either 'hidden' or 'visible'
  289. */
  290. function changeObjectVisibility(objectId, newVisibility) {
  291. var returnVal=false;
  292. if(document.getElementById && document.getElementById(objectId)) {
  293. var div = document.getElementById(objectId);
  294. if(div.style) {
  295. var ifr_id = div.id+"_ifr";
  296. var ifr = document.getElementById(ifr_id);
  297. // Process the iframe shim. An iframe is created under the div element so order that the
  298. // select controls do not bleed through the menu.
  299. //
  300. if( newVisibility=="hidden" ) {
  301. // Delete the iframe shim.
  302. //
  303. if( ifr!=null )
  304. div.parentNode.removeChild(document.getElementById(ifr_id));
  305. }
  306. else if( ifr==null && browserCheck.isIE5dot5Up() ) {
  307. // Construct an iframe shim between the div and the document so that the div
  308. // covers the select controls.
  309. //
  310. var ifr = document.createElement("iframe");
  311. ifr.id=ifr_id;
  312. ifr.style.position="absolute";
  313. ifr.src="#"
  314. ifr.scrolling="no"
  315. ifr.frameborder="0"
  316. ifr.style.width = div.offsetWidth;
  317. ifr.style.height = div.offsetHeight;
  318. ifr.style.top = div.offsetTop;
  319. ifr.style.left = div.offsetLeft;
  320. ifr.style.zIndex = div.style.zIndex - 1;
  321. div.parentNode.insertBefore(ifr, div);
  322. }
  323. div.style.visibility = newVisibility;
  324. returnVal = true;
  325. }
  326. }
  327. return returnVal;
  328. }
  329. /*
  330. * Get the menu label cell from the event source
  331. */
  332. function getMenuLabelDiv(event) {
  333. var target = (event.target) ? event.target : event.srcElement;
  334. var tagName = target.nodeName;
  335. var menuLabelDiv = null;
  336. //sometimes when the mouse is moving quickly we pick up the inner anchor even though the
  337. //even handler is bound to the div, so we need to check for this phenomenon
  338. if (tagName == 'DIV') {
  339. menuLabelDiv = target;
  340. }
  341. else if (tagName == 'SPAN') {
  342. menuLabelDiv = target.parentNode;
  343. }
  344. if (menuLabelDiv != null) {
  345. //the id must be labelCell[nn] which is the top level menu label
  346. if (menuLabelDiv.id.indexOf('labelCell')==-1) {
  347. menuLabelDiv=null;
  348. }
  349. }
  350. return menuLabelDiv;
  351. }
  352. /*
  353. * Get the menu link from the event source
  354. */
  355. function getMenuLabelLink(event) {
  356. var target = (event.target) ? event.target : event.srcElement;
  357. var tagName = target.nodeName;
  358. var menuLabelLinkEle = null;
  359. //sometimes when the mouse is moving quickly we pick up the inner anchor even though the
  360. //even handler is bound to the div, so we need to check for this phenomenon
  361. if (tagName == 'DIV') {
  362. menuLabelLinkEle = target.firstChild;
  363. }
  364. else if (tagName == 'SPAN') {
  365. menuLabelLinkEle = target;
  366. }
  367. if (menuLabelLinkEle != null) {
  368. //the id must be MenuLink[nn] which is the link contained within a label cell
  369. if (menuLabelLinkEle.id.indexOf('menuLink')==-1) {
  370. menuLabelLinkEle=null;
  371. }
  372. }
  373. return menuLabelLinkEle;
  374. }
  375. /*
  376. * close the last open menu if it exists. Nothing happens if there is no last menu defined
  377. */
  378. function closeLastOpenMenu() {
  379. var hasClosed = false;
  380. if (this.lastOpenMenu != null) {
  381. var menuLink = 'menuLink' + this.lastOpenMenu.index;
  382. menuLinkEle = document.getElementById(menuLink);
  383. if (menuLinkEle!=null) {
  384. menuLinkEle.className=MT_NORMAL;
  385. this.hideMenu(this.lastOpenMenu);
  386. hasClosed = true;
  387. }
  388. }
  389. return hasClosed;
  390. }
  391. /*
  392. * Display a drop down menu
  393. */
  394. function showMenu(menuNo, eventObj) {
  395. var showIt=false;
  396. //hide open sub menus
  397. //this.hideOpenSubMenus();
  398. //get the menu dimensions and apply a small amount of 'tweakage'
  399. labelObj = 'labelCell'+menuNo;
  400. x = getElementLeft(labelObj)+DROP_DOWN_X_TWEAK;
  401. y = getElementTop(labelObj) + getElementHeight(labelObj)+DROP_DOWN_Y_TWEAK;
  402. //move the puppy
  403. moveXY('menu' + menuNo, x, y);
  404. //toggle visibility
  405. if(changeObjectVisibility('menu' + menuNo, 'visible')) {
  406. showIt = true;
  407. }
  408. else {
  409. showIt = false;
  410. }
  411. return showIt;
  412. }
  413. /*
  414. * Hide open menus
  415. * selectedMenuItem The current selected menu item that has been activated by a mouse click or mouse over etc.
  416. */
  417. function hideOpenSubMenus(selectedMenuItem) {
  418. var startPos = 0;
  419. var excludeSuffixRoot = null;
  420. var prefix = null;
  421. //select the correct menu label
  422. if (selectedMenuItem != undefined) {
  423. excludeSuffixRoot = selectedMenuItem.menuContainerId;
  424. startPos = parseInt(excludeSuffixRoot.charAt(0));
  425. prefix = selectedMenuItem.menuContainerId;
  426. }
  427. for (var i=startPos;i<this.numLabels;i++) {
  428. //get the next menu label
  429. var menuLabel = this.menus[i];
  430. //get the open menu items
  431. var menuItems = menuLabel.getOpenMenuItems();
  432. for (var j=0;j<menuItems.length;j++) {
  433. var menuItem = menuItems[j];
  434. //the event has originated from a menu item label
  435. if (selectedMenuItem == undefined) {
  436. this.hideMenu(menuItem);
  437. }
  438. //ensure the menu item we have is not the same as the selected one and that the selected menu item parent is not the same as the one that was last opened
  439. else if (menuItem.id != selectedMenuItem.id && selectedMenuItem.parent != null && selectedMenuItem.parent != this.lastOpenSubMenu) {
  440. //only hide if there is a valid last sub menu item
  441. if (this.lastOpenSubMenu != null) {
  442. //only hide if this open menu item is not an ancestor of the selected item
  443. if (menuItem.hasAncestor(selectedMenuItem)==false) {
  444. this.hideMenu(menuItem);
  445. }
  446. }
  447. }
  448. }
  449. }
  450. }
  451. /*
  452. * Reset the menu bar by closing all menus
  453. */
  454. function resetMenus() {
  455. //turn off auto open
  456. this.autoOpen = false;
  457. this.lastOpenMenu=null;
  458. //loop through each label and close all open submenus
  459. for (var i=0;i<this.numLabels;i++) {
  460. //get the next menu label
  461. var menuLabel = this.menus[i];
  462. //hacky way to get the link for the label and reset the class
  463. var menuItemElement = document.getElementById('menuLink'+menuLabel.menuContainerId);
  464. menuItemElement.className=MT_NORMAL;
  465. this.hideMenu(menuLabel);
  466. }
  467. }
  468. /*
  469. * Show a submenu off to the side of the parent menu
  470. */
  471. function showMenuSide(menuItem) {
  472. //guard clause, return if this menu is already showing
  473. if (menuItem.state==MenuItem.OPEN) {
  474. return;
  475. }
  476. var menuId = 'menu'+menuItem.menuContainerId;
  477. var parentId = 'menu'+menuItem.parent.menuContainerId;
  478. var selectedItemId = menuItem.id;
  479. var showIt=false;
  480. var parentDiv = document.getElementById(parentId);
  481. var selectedDiv = document.getElementById(selectedItemId);
  482. menuItem.state = MenuItem.OPEN;
  483. //get the dimensions and tweak them
  484. x = parentDiv.offsetLeft + parentDiv.offsetWidth + DROP_DOWN_X_TWEAK;
  485. y= parentDiv.offsetTop + selectedDiv.offsetTop - DROP_DOWN_SUBMENU_Y_TWEAK;
  486. //place the menu
  487. moveXY(menuId, x, y);
  488. this.lastOpenSubMenu=menuItem;
  489. //toggle it
  490. if(changeObjectVisibility(menuId, 'visible')) {
  491. showIt=true;
  492. }
  493. else {
  494. showIt=false;
  495. }
  496. return showIt;
  497. }
  498. /*
  499. * Get the y value for the element
  500. */
  501. function getElementTop(Elem) {
  502. if(document.getElementById) {
  503. var elem = document.getElementById(Elem);
  504. }
  505. yPos = elem.offsetTop;
  506. tempEl = elem.offsetParent;
  507. while (tempEl != null) {
  508. yPos += tempEl.offsetTop;
  509. tempEl = tempEl.offsetParent;
  510. }
  511. return yPos;
  512. }
  513. /*
  514. * Get the x value for the element
  515. */
  516. function getElementLeft(Elem) {
  517. var elem;
  518. if(document.getElementById) {
  519. var elem = document.getElementById(Elem);
  520. }
  521. xPos = elem.offsetLeft;
  522. tempEl = elem.offsetParent;
  523. while (tempEl != null) {
  524. xPos += tempEl.offsetLeft;
  525. tempEl = tempEl.offsetParent;
  526. }
  527. return xPos;
  528. }
  529. /*
  530. * Get the element width
  531. */
  532. function getElementWidth(Elem) {
  533. var elem;
  534. if(document.getElementById) {
  535. var elem = document.getElementById(Elem);
  536. }
  537. xPos = elem.offsetWidth;
  538. return xPos;
  539. }
  540. /*
  541. * Get the element height
  542. */
  543. function getElementHeight(Elem) {
  544. var elem;
  545. if(document.getElementById) {
  546. var elem = document.getElementById(Elem);
  547. }
  548. xPos = elem.offsetHeight;
  549. return xPos;
  550. }
  551. /*
  552. * Move an element
  553. */
  554. function moveXY(objectId, x, y) {
  555. if(document.getElementById && document.getElementById(objectId)) {
  556. var obj = document.getElementById(objectId).style;
  557. obj.top = y + 'px';
  558. obj.left = x + 'px';
  559. }
  560. }
  561. /*
  562. * Find an element
  563. * menuId A menu id
  564. */
  565. function findById(menuId) {
  566. var menuItem = null;
  567. for (var i=0;(i<this.numLabels && (menuItem == null));i++) {
  568. menuItem = this.menus[i].getItemById(menuId);
  569. }
  570. return menuItem;
  571. }
  572. /*
  573. * Find the W3C DOM row element for the menu item key
  574. */
  575. function findRowElement(key) {
  576. var row = null;
  577. for (var i=0;(i<this.numLabels && (row == null));i++) {
  578. menuItem = this.menus[i].getItemByKey(key);
  579. if (menuItem != null) {
  580. row = document.getElementById(menuItem.id);
  581. }
  582. }
  583. return row;
  584. }
  585. /*
  586. * Debug function to display the entire menu bar contents
  587. */
  588. function displayMenu() {
  589. for (var i=0;i<this.numLabels;i++) {
  590. this.menus[i].display();
  591. }
  592. }
  593. /*
  594. **********************
  595. * END MenuBar object
  596. **********************
  597. */
  598. /*
  599. **********************
  600. * START StringBuffer object
  601. **********************
  602. */
  603. function StringBuffer(size, chr) {
  604. this.value = new String(duplicateString(size, chr));
  605. this.size = size;
  606. this.index = 0;
  607. this.append = append;
  608. this.toString = getValue;
  609. }
  610. function append(value) {
  611. if (this.value.index + value.length > this.size) {
  612. value = (this.value.substring(0,this.index) + value).substring(0, this.value.size);
  613. this.size = this.index = value.length;
  614. }
  615. else {
  616. value = this.value.substring(0,this.index) + value;
  617. this.index = value.length;
  618. }
  619. this.value = value + this.value.substring(value.length, this.value.length);
  620. }
  621. function getValue() {
  622. return this.value;
  623. }
  624. function duplicateString(size, chr) {
  625. var text = '';
  626. for (var i=0; i<size; i++)
  627. text += chr;
  628. return text;
  629. }
  630. /*
  631. **********************
  632. * END StringBuffer object
  633. **********************
  634. */
  635. /*
  636. =================================
  637. START MenuItem object
  638. This object respresents a collection of menu items
  639. =================================
  640. id The menu item id
  641. name The menu item text
  642. url The menu item url(can be null)
  643. menuBar The parent menu bar
  644. */
  645. function MenuItem(name,menuBar,url,icon, tooltip) {
  646. //constants
  647. MenuItem.OPEN = 'open';
  648. MenuItem.CLOSED = 'closed';
  649. //properties
  650. this.id = "";
  651. this.name=name;
  652. this.url=url;
  653. this.icon=icon;
  654. this.tooltip=tooltip;
  655. this.menuBar = menuBar;
  656. this.state=MenuItem.CLOSED;
  657. this.children=new Array();
  658. this.isRoot=true;
  659. this.parent=null;
  660. this.index=0;
  661. this.key=null;
  662. //convenience property used to hold the container(if it exists) that is associated with this item
  663. //a container id is only available when this menu item has children
  664. this.menuContainerId=0;
  665. //methods
  666. this.hasItems=hasItems;
  667. this.getItemById=getItemById;
  668. this.addItem=addItem;
  669. this.getItems=getItems;
  670. this.display=display;
  671. this.toString=toString;
  672. this.flatten=flatten;
  673. this.getOpenMenuItems=getOpenMenuItems;
  674. this.getParent=getParent;
  675. this.writeContainer=writeContainer;
  676. this.hasAncestor=hasAncestor;
  677. this.getLabelMenu=getLabelMenu;
  678. this.setKey=setKey;
  679. this.getItemByKey=getItemByKey;
  680. }
  681. /*
  682. Determine whether this menu item has subitems
  683. */
  684. function hasItems() {
  685. return this.children.length > 0;
  686. }
  687. function getItemById(id) {
  688. var item = null;
  689. var flattened = this.flatten();
  690. if (flattened != null) {
  691. item = flattened[id];
  692. }
  693. return item;
  694. }
  695. /*
  696. * set the menu item key
  697. */
  698. function setKey(newKey) {
  699. this.key = newKey;
  700. }
  701. /*
  702. * Get the row element defined by the key
  703. */
  704. function getItemByKey(theKey,list) {
  705. var found = null;
  706. var parentList = null;
  707. if (list==undefined) {
  708. parentList = this.children;
  709. }
  710. else {
  711. parentList = list;
  712. }
  713. for (var i=0;(i < parentList.length && found == null);i++) {
  714. var child = parentList[i];
  715. if (child.key != theKey) {
  716. var children = child.getItems();
  717. found = getItemByKey(theKey,children);
  718. }
  719. else {
  720. found = child;
  721. }
  722. }
  723. return found;
  724. }
  725. /*
  726. * Add a menu item
  727. * name The menu item text
  728. * action The url to be fired when the menu item is clicked, can be null for non clickable menu items
  729. */
  730. function addItem(name, action, icon, tooltip) {
  731. var item = new MenuItem(name,this.menuBar,action,icon, tooltip);
  732. item.parent=this;
  733. var index = 0;
  734. item.isRoot = false;
  735. //get the number of child items and set the index for the next item
  736. var size = this.children.length;
  737. if (size > 0) {
  738. index = size;
  739. }
  740. //add the item to the array
  741. this.children[index]=item;
  742. item.index = index;
  743. return item;
  744. }
  745. /*
  746. * Write the HMTL for the container and all its menu items including nested menu items
  747. * parentElement The dom element to append the menu to, basically the the menu label div
  748. * 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
  749. * nested containers properly e.g. 0,1,1_2,1_2 etc.
  750. */
  751. function writeContainer(parentElement,idRoot) {
  752. //first of all create the top level label
  753. var parentMenuNo = this.index;
  754. var menuItemsDiv = document.createElement("div");
  755. menuItemsDiv.className=MENU_CONTAINER;
  756. //set the correct menu id
  757. if (idRoot==null) {
  758. idRoot=parentMenuNo;
  759. }
  760. else {
  761. idRoot=idRoot+'_'+this.index;
  762. }
  763. menuItemsDiv.id='menu'+idRoot;
  764. menuItemsDiv.style.position="absolute";
  765. menuItemsDiv.style.visibility="hidden";
  766. menuItemsDiv.style.zIndex=200;
  767. var table = document.createElement("table");
  768. var tbody = document.createElement("tbody");
  769. table.appendChild(tbody);
  770. for (var i = 0; i < this.children.length; i++) {
  771. var row = tbody.insertRow(i);
  772. row.className=TEXT;
  773. var col = row.insertCell(0);
  774. col.noWrap="true";
  775. //<tr><td><a>...</a></td></tr>
  776. //the children array contains Menu objects
  777. var menuItem = this.children[i];
  778. col.title= menuItem.tooltip;
  779. var menuNo = this.index;
  780. //create the table row
  781. fillMenuItemRow(menuItem,row);
  782. //create the column
  783. fillMenuItemCol(this.menuBar,menuItem,col,idRoot+'_'+i);
  784. //drill down
  785. if (menuItem.children.length > 0) {
  786. //write the HTML to menuItemsDiv
  787. menuItem.writeContainer(parentElement,idRoot);
  788. }
  789. }
  790. //add the table to the menu item container
  791. menuItemsDiv.appendChild(table);
  792. //add the menu item container to the parent div element
  793. parentElement.appendChild(menuItemsDiv);
  794. /*
  795. * INNER FUNCTION
  796. * Create the menu row element, essentially a <tr> tag with an optional id
  797. */
  798. function fillMenuItemRow(menuItem,menuItemRow) {
  799. var menuNo = menuItem.index;
  800. var hasSubItems = menuItem.hasItems();
  801. //the menu has sub menu items
  802. if (hasSubItems) {
  803. menuItemRow.id='labelRow'+menuNo;
  804. }
  805. return menuItemRow;
  806. }
  807. /*
  808. * INNER FUNCTION
  809. */
  810. function fillMenuItemCol(menuBar,menuItem,menuItemCol,idSuffix) {
  811. var itemText = menuItem.name;
  812. var menuNo = menuItem.index;
  813. var parentMenuNo = menuItem.parent.index;
  814. var hasSubItems = menuItem.hasItems();
  815. var itemURL = menuItem.url;
  816. var iconURL = menuItem.icon;
  817. menuItem.menuContainerId=idSuffix;
  818. var spaceImg = "../ags/images/spacer.gif";
  819. var subMenuImg = "../ags/images/menu_arrow.gif";
  820. var rightArrowImg = document.createElement("img");
  821. rightArrowImg.style.verticalAlign="middle";
  822. rightArrowImg.src = subMenuImg;
  823. rightArrowImg.style.width="13px";
  824. var menuIcon = document.createElement("img");
  825. menuIcon.style.verticalAlign="middle";
  826. menuIcon.style.width="16px";
  827. //spaceIcon.style.width="3px";
  828. if (iconURL=='') {
  829. menuIcon.src=spaceImg;
  830. }
  831. else {
  832. //set the icon
  833. menuIcon.src=iconURL;
  834. }
  835. //create the column and anchor elements
  836. var menuItemLink = document.createElement("span");
  837. //set the correct 'hand' pointer for firefox
  838. //for some reason firefox render the 'hand' setting
  839. //as a text caret
  840. if (browserCheck.isNav6Up()) {
  841. menuItemCol.style.cursor='pointer';
  842. }
  843. menuItemLink.unselectable="on";
  844. //set the common menu item properties
  845. menuItemCol.className=MI_NORMAL;
  846. menuItemCol.style.verticalAlign="middle";
  847. //set the common anchor properties
  848. //menuItemLink.href=itemURL;
  849. menuItemLink.style.color="blue";
  850. menuItemLink.style.textDecoration="underline";
  851. // create a text element
  852. var text = document.createTextNode(itemText);
  853. // add it as a child element
  854. menuItemLink.appendChild(text);
  855. // START define the handler functions for this element
  856. // menu item mouse click event handler
  857. var onMenuItemMouseClickEvent = function menuItemClicked(event) {
  858. var target = (event.target) ? event.target : event.srcElement;
  859. if (browserCheck.isIE5dot5Up()) {
  860. //remove the focus outline around the element
  861. target.blur();
  862. }
  863. //process the action for this link, then hide the open label menu
  864. if (menuItem.hasItems()==false) {
  865. menuBar.resetMenus();
  866. eval(itemURL);
  867. return true;
  868. }
  869. //this link has sub items so simply ignore the mouse click
  870. else {
  871. event.cancelBubble=true;
  872. return false;
  873. }
  874. }
  875. // menu item mouse over event handler
  876. var onMenuItemMouseOverEvent= function menuItemOver(event) {
  877. var target = (event.target) ? event.target : event.srcElement;
  878. //hide any open sub menu items
  879. menuBar.hideOpenSubMenus(menuItem);
  880. if (menuItem.hasItems()) {
  881. menuBar.showMenuSide(menuItem);
  882. }
  883. //clear the timeout when we have moved onto
  884. //another menu item, this will ensure the menu
  885. //is not closed when navigating the menu structure
  886. window.clearTimeout(windowTimeout);
  887. var menuItemElement = document.getElementById(menuItem.id);
  888. menuItemElement.className=MI_HOVER;
  889. }
  890. // menu item mouse out event handler
  891. var onMenuItemMouseOutEvent= function menuItemOut(event) {
  892. var target = (event.target) ? event.target : event.srcElement;
  893. var menuItemElement = document.getElementById(menuItem.id);
  894. menuItemElement.className=MI_NORMAL;
  895. if (target.id.indexOf('itemCell') != -1) {
  896. //the reset function
  897. var f = function(){
  898. agsMenuBar.resetMenus();
  899. }
  900. windowTimeout = window.setTimeout(f,TIMEOUT_MS);
  901. }
  902. }
  903. // FINISH define the handler functions for this element
  904. //attach the event handlers for the menu items
  905. addEvent(menuItemCol,"mouseover",onMenuItemMouseOverEvent);
  906. addEvent(menuItemCol,"mouseout",onMenuItemMouseOutEvent);
  907. addEvent(menuItemCol,"click",onMenuItemMouseClickEvent);
  908. //only parent menu items have row ids
  909. var rowId=null;
  910. var eventHandlers=null;
  911. var menuLinkId = null;
  912. //the id for a submenu
  913. menuItemLink.id="menuLink" + idSuffix;
  914. menuItemCol.id="itemCell" + idSuffix;
  915. var innerSpanImg = document.createElement("span");
  916. innerSpanImg.style.marginRight="3px";
  917. innerSpanImg.appendChild(menuIcon);
  918. menuItemCol.appendChild(innerSpanImg);
  919. menuItemCol.appendChild(menuItemLink);
  920. if (hasSubItems==true) {
  921. var innerSpanLinkAndArrow_arrow = document.createElement("span");
  922. innerSpanLinkAndArrow_arrow.appendChild(rightArrowImg);
  923. menuItemCol.appendChild(innerSpanLinkAndArrow_arrow);
  924. }
  925. //set the menu item id to the generated one
  926. menuItem.id = menuItemCol.id;
  927. // link the menuItem to the menuItemCol
  928. menuItemCol.menuItem = menuItem;
  929. return menuItemCol;
  930. }
  931. }
  932. /*
  933. * Get the menu item parent
  934. */
  935. function getParent() {
  936. return this.parent;
  937. }
  938. /*
  939. * Get the menu item children
  940. */
  941. function getItems() {
  942. return this.children;
  943. }
  944. /*
  945. * Display the contents of this menu item, including all children
  946. * For debug purposes only
  947. */
  948. function display() {
  949. buf = new StringBuffer();
  950. buf.append(this.toString());
  951. buf.append('\n');
  952. buf = displayNode(buf,this.getItems(),0);
  953. (buf.toString());
  954. }
  955. /*
  956. * Helper function to recurse through the child nodes and collect information
  957. */
  958. function displayNode(buf,childList,level) {
  959. ++level;
  960. for (var i=0;i < childList.length;i++) {
  961. var child = childList[i];
  962. displayIndent(buf,level);
  963. buf.append(child.toString());
  964. buf.append('\n');
  965. if (child.hasItems()) {
  966. displayNode(buf,child.getItems(),level);
  967. }
  968. }
  969. --level;
  970. return buf;
  971. }
  972. /*
  973. * Display an indent
  974. */
  975. function displayIndent(buf,level) {
  976. for (var i=0;i<level;i++) {
  977. buf.append(' ');
  978. }
  979. }
  980. /*
  981. * Get a list of all opem menu items
  982. */
  983. function getOpenMenuItems() {
  984. var open = new Array();
  985. //check if this item is open
  986. if (this.state==MenuItem.OPEN) {
  987. open[0] = this;
  988. }
  989. if (this.hasItems()) {
  990. open = getOpenNodes(this.getItems(),open);
  991. }
  992. return open;
  993. }
  994. /*
  995. * Helper function to recurse through the menu items
  996. */
  997. function getOpenNodes(parentList,openList) {
  998. for (var i=0;i < parentList.length;i++) {
  999. var count = openList.length;
  1000. var child = parentList[i];
  1001. if (child.state==MenuItem.OPEN) {
  1002. openList[count] = child;
  1003. if (count==0) {
  1004. count+=1;
  1005. }
  1006. }
  1007. var children = child.getItems();
  1008. openList = getOpenNodes(children,openList);
  1009. }
  1010. return openList;
  1011. }
  1012. /*
  1013. * Flatten the menu bar structure into a single array, note that the elements are indexed by ID not position
  1014. */
  1015. function flatten() {
  1016. var flattened = new Array();
  1017. flattened[this.id] = this;
  1018. if (this.hasItems()) {
  1019. flattened = getNodes(this.getItems(),flattened);
  1020. }
  1021. return flattened;
  1022. }
  1023. /*
  1024. * Helper function to recurse through the menu items
  1025. */
  1026. function getNodes(parentList,flattenedList) {
  1027. for (var i=0;i < parentList.length;i++) {
  1028. var child = parentList[i];
  1029. flattenedList[child.id] = child;
  1030. var children = child.getItems();
  1031. flattenedList = getNodes(children,flattenedList);
  1032. }
  1033. return flattenedList;
  1034. }
  1035. /*
  1036. * Determine whether the menu item exists in the family tree as an ancestor
  1037. */
  1038. function hasAncestor(menuItem) {
  1039. var exists = false;
  1040. var flattened = this.flatten();
  1041. if (flattened[menuItem.id]!= null) {
  1042. exists = true;
  1043. }
  1044. return exists;
  1045. }
  1046. function getLabelMenu(menuItem) {
  1047. var children = null;
  1048. var labelMenu = null;
  1049. //the first time through
  1050. if (menuItem == null) {
  1051. menuItem = this;
  1052. }
  1053. //check for a root parent
  1054. if (menuItem.parent != null && menuItem.parent.isRoot) {
  1055. labelMenu = menuItem.parent;
  1056. }
  1057. //keep travelling up the tree
  1058. else if (menuItem.parent != null){
  1059. labelMenu = getLabelMenu(menuItem.parent);
  1060. }
  1061. return labelMenu;
  1062. }
  1063. /*
  1064. * Return a string describing the menu item
  1065. */
  1066. function toString() {
  1067. return 'MenuItem[id:'+this.id+', index:'+this.index+', name:'+this.name+', state:'+this.state+', isRoot:'+this.isRoot+', hasItems:'+this.hasItems()+',suffix:'+this.menuContainerId+']';
  1068. }
  1069. /*
  1070. =================================
  1071. END MenuItem object
  1072. This object represents a collection of menu items
  1073. =================================
  1074. */
  1075. function pageMousedown(evt) {
  1076. evt = (evt) ? evt: ((event)? event : null);
  1077. if (evt) {
  1078. // get the target id
  1079. var el = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
  1080. var eleId = el.id;
  1081. var isMenuItem=false;
  1082. if (eleId != null && eleId != undefined && menuBar != null) {
  1083. //test for label/menu item containers 'menuLink_n_n'
  1084. //and also the links within those containers 'itemCell_n_n'
  1085. isMenuItem = eleId.indexOf('menuLink') != -1 || eleId.indexOf('itemCell') != -1;
  1086. if (!isMenuItem) {
  1087. //close all menus
  1088. agsMenuBar.resetMenus();
  1089. }
  1090. window.defaultStatus=eleId;
  1091. }
  1092. //propagate the event
  1093. evt.cancelBubble = false;
  1094. }
  1095. return true;
  1096. }