CCflyoutMenu.js 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. // Licensed Materials - Property of IBM
  2. //
  3. // IBM Cognos Products: ps
  4. //
  5. // (C) Copyright IBM Corp. 2005, 2014
  6. //
  7. // US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  8. // Copyright (C) 2008 Cognos ULC, an IBM Company. All rights reserved.
  9. // Cognos and the Cognos logo are trademarks of Cognos ULC, (formerly Cognos Incorporated).
  10. //static property an array that has all the instances of CCPopupMenu
  11. CCPopupMenu.menus = [];
  12. //static property the currently active menu
  13. CCPopupMenu.activeMenu = null;
  14. //Used to temporarily ignore all onclick events - this mechanism
  15. //gives other containers a chance to react to the onclick event.
  16. CCPopupMenu.bIgnoreHideActiveMenu = false;
  17. CCPopupMenu.minSize = 3;
  18. var sPopUpWebRoot = ".."; // default this to a relative location
  19. if (window.g_PS_getWebRoot) {
  20. if (g_PS_getWebRoot() != "") {
  21. sPopUpWebRoot = g_PS_getWebRoot(); // set up the official path to the C8 web root
  22. }
  23. }
  24. CCPopupMenu.imagesRoot = sPopUpWebRoot + "/ps";
  25. CCPopupMenu.psImagesPath = CCPopupMenu.imagesRoot + "/images";
  26. CCPopupMenu.portalImagesPath = CCPopupMenu.imagesRoot + "/portal/images";
  27. //creates an event handler for the given event. Note that events should be assume the w3c names not the
  28. //ie names as this function will create the correct event type name based on the browser
  29. function addEvent(obj, evType, fn) {
  30. if (obj.addEventListener) {
  31. obj.addEventListener(evType, fn, false);
  32. return true;
  33. } else if (obj.attachEvent) {
  34. var r = obj.attachEvent("on" + evType, fn);
  35. return r;
  36. } else {
  37. return false;
  38. }
  39. }
  40. var extensions = {
  41. associate: function (target, obj, methodName) {
  42. return function (e) {
  43. e = e || window.event;
  44. return obj[methodName](e, target);
  45. };
  46. }
  47. };
  48. //removes the function fn from the event listeners for the object and the particular event
  49. function removeEvent(obj, type, fn) {
  50. if (obj.removeEventListener) {
  51. return obj.removeEventListener(type, fn, false);
  52. } else if (obj.detachEvent) {
  53. return obj.detachEvent('on' + type, fn);
  54. } else {
  55. return false;
  56. }
  57. }
  58. //Stops the event at current event handler
  59. function haltEventProcessing(event) {
  60. event.cancelBubble = 'true';
  61. event.returnValue = 'false';
  62. if (event.stopPropagation) {
  63. event.stopPropagation();
  64. event.preventDefault();
  65. }
  66. return false;
  67. }
  68. //returns the width of the browser window
  69. function windowWidth() {
  70. if (window.innerWidth) {
  71. return window.innerWidth;
  72. } else {
  73. return document.body.offsetWidth - 20;
  74. }
  75. }
  76. //returns the height of the drop down based on the style or the offsetHeight
  77. function getDropDownHeight(dropDownElement) {
  78. var indexOfPX;
  79. if (dropDownElement.style.height == "") {
  80. var height = dropDownElement.offsetHeight;
  81. if (window.navigator.userAgent.indexOf("Gecko") != -1) {
  82. var paddingTop = dropDownElement.style.paddingTop;
  83. indexOfPX = paddingTop.indexOf("px");
  84. var v = ((indexOfPX != -1) ? parseInt(paddingTop.substring(0, indexOfPX), 10) : parseInt(paddingTop, 10));
  85. height -= (isNaN(v) ? 0 : v);
  86. var paddingBottom = dropDownElement.style.paddingBottom;
  87. indexOfPX = paddingBottom.indexOf("px");
  88. v = ((indexOfPX != -1) ? parseInt(paddingBottom.substring(0, indexOfPX), 10) : parseInt(paddingBottom, 10));
  89. height -= (isNaN(v) ? 0 : v);
  90. var borderWidth = 1;
  91. height -= (2 * borderWidth);
  92. }
  93. return height;
  94. } else {
  95. //return the style height converted to an integer
  96. var styleHeight = dropDownElement.style.height;
  97. indexOfPX = styleHeight.indexOf("px");
  98. if (indexOfPX != -1) {
  99. styleHeight = styleHeight.substring(0, indexOfPX);
  100. }
  101. return parseInt(styleHeight, 10);
  102. }
  103. }
  104. //returns the width of the drop down based on the style or the offsetWidth
  105. function getDropDownWidth(dropDownElement) {
  106. var indexOfPX;
  107. if (dropDownElement.style.width == "") {
  108. var width = dropDownElement.offsetWidth;
  109. if (window.navigator.userAgent.indexOf("Gecko") != -1) {
  110. var paddingLeft = dropDownElement.style.paddingLeft;
  111. indexOfPX = paddingLeft.indexOf("px");
  112. var v = ((indexOfPX != -1) ? parseInt(paddingLeft.substring(0, indexOfPX), 10) : parseInt(paddingLeft, 10));
  113. width -= (isNaN(v) ? 0 : v);
  114. var paddingRight = dropDownElement.style.paddingRight;
  115. indexOfPX = paddingRight.indexOf("px");
  116. v = ((indexOfPX != -1) ? parseInt(paddingRight.substring(0, indexOfPX), 10) : parseInt(paddingRight, 10));
  117. width -= (isNaN(v) ? 0 : v);
  118. var borderWidth = 1;
  119. width -= (2 * borderWidth);
  120. }
  121. return width;
  122. } else {
  123. //return teh style width converted to an integer
  124. var styleWidth = dropDownElement.style.width;
  125. indexOfPX = styleWidth.indexOf("px");
  126. if (indexOfPX != -1) {
  127. styleWidth = styleWidth.substring(0, indexOfPX);
  128. }
  129. return parseInt(styleWidth, 10);
  130. }
  131. }
  132. //get the offset for the scrolling
  133. function getScrollXY() {
  134. var scrOfX = 0, scrOfY = 0;
  135. if (typeof window.pageYOffset == 'number') {
  136. //Netscape compliant
  137. scrOfY = window.pageYOffset;
  138. scrOfX = window.pageXOffset;
  139. } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
  140. //DOM compliant
  141. scrOfY = document.body.scrollTop;
  142. scrOfX = document.body.scrollLeft;
  143. } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
  144. //IE6 standards compliant mode
  145. scrOfY = document.documentElement.scrollTop;
  146. scrOfX = document.documentElement.scrollLeft;
  147. }
  148. return [scrOfX, scrOfY];
  149. }
  150. //returns the width of the browser window
  151. function windowHeight() {
  152. //have to account for the vertical scroll to get a good idea where we are at
  153. if (window.innerHeight) {
  154. return window.innerHeight + getScrollXY()[1];
  155. } else {
  156. return document.body.offsetHeight + getScrollXY()[1];
  157. }
  158. }
  159. //unfortunately netscape and firefox do not correctly support overflowY. To enable removal of the horizontal
  160. //scrollbar in these browsers you must use a gecko(??some component of these browsers???) specific value for overflow
  161. //called -moz-scrollbars-vertical
  162. function setOverflowStyle(anEl) {
  163. //Gecko is the relevant thing we are looking for here as -moz-scrollbars-vertical is apparently defined in this component
  164. if (window.navigator.userAgent.indexOf("Gecko") != -1) {
  165. anEl.style.overflow = "-moz-scrollbars-vertical";
  166. } else {
  167. anEl.style.overflowY = "auto";
  168. }
  169. }
  170. //sets the focus to the element with the id equal to the controlId of the menu associated with id
  171. //if the element does not exist then do nothing
  172. function CCPopupMenu_setControlFocus() {
  173. var currentMenu = CCPopupMenu.getMenu(CCPopupMenu.activeMenu.id);
  174. var controlElement = document.getElementById(currentMenu.controlId);
  175. if (controlElement != null) {
  176. controlElement.focus();
  177. }
  178. }
  179. function CCPopupMenu_checkBounds(event) {
  180. if (typeof event != "undefined" && event != null && CCPopupMenu.activeMenu.doCheckBounds) {
  181. var tr = event.srcElement;
  182. var table = tr.parentNode;
  183. var id = CCPopupMenu.activeMenu.id;
  184. if (tr.tagName == 'TR') {
  185. if (window.event.keyCode == 27 || window.event.keyCode == 13 || window.event.keyCode == 38 || window.event.keyCode == 40) {
  186. return true;
  187. }
  188. if (tr.rowIndex == 0 && event.shiftKey && event.shiftKey != false) {
  189. CCPopupMenu.hideActiveMenu();
  190. CCPopupMenu.setControlFocus();
  191. return false;
  192. } else if ((tr.rowIndex + 1) == table.rows.length && window.event.shiftKey == false) {
  193. CCPopupMenu.hideActiveMenu();
  194. CCPopupMenu.setControlFocus();
  195. return false;
  196. }
  197. }
  198. }
  199. return true;
  200. }
  201. //static method to close the currextly open drop down menu
  202. function CCPopupMenu_hideActiveMenu() {
  203. if (!CCPopupMenu.bIgnoreHideActiveMenu && CCPopupMenu.activeMenu != null) {
  204. CCPopupMenu.activeMenu.activeMenuItemIndex = -1;
  205. CCPopupMenu.activeMenu.removeDropDown();
  206. }
  207. }
  208. function CCPopupMenu_ignoreHideActiveMenu(ignore) {
  209. CCPopupMenu.bIgnoreHideActiveMenu = (ignore == "ignore") ? true : false;
  210. }
  211. //static method to create an iframe that is positioned under the dropdown so that controls don't show through
  212. function CCPopupMenu_createInsulatingIframe(currentMenu, divEl) {
  213. var iframeEl = document.createElement("iframe");
  214. iframeEl.id = currentMenu.id + "inslIframe";
  215. iframeEl.setAttribute("role","presentation");
  216. iframeEl.title = currentMenu.id;
  217. iframeEl.style.display = "block";
  218. iframeEl.style.border = "0px";
  219. iframeEl.style.padding = "2px";
  220. iframeEl.style.position = "absolute";
  221. iframeEl.style.zIndex = "1";
  222. iframeEl.tabIndex = "-1";
  223. iframeEl.src = CCPopupMenu.psImagesPath + "/space.gif";
  224. var controlEl = document.getElementById(currentMenu.controlId);
  225. controlEl.appendChild(iframeEl);
  226. iframeEl.style.top = divEl.style.top;
  227. iframeEl.style.left = divEl.style.left;
  228. iframeEl.style.right = divEl.style.right;
  229. iframeEl.style.height = divEl.offsetHeight;
  230. iframeEl.style.width = divEl.offsetWidth;
  231. }
  232. function CCPopupMenu_sizeDropDown(dropDownElement, maxHeight, elementHeight) {
  233. //size the height of the drop down if a height was given
  234. //this is to support scrolling of menu items (to ensure the drop down is not humungous)
  235. if (this.mnHeight != -1) {
  236. var elems = dropDownElement.getElementsByTagName('td');
  237. providedHeight = elementHeight * this.mnHeight;
  238. var allowableHeight = Math.min(maxHeight, providedHeight);
  239. allowableHeight = providedHeight;
  240. if (dropDownElement.offsetHeight > allowableHeight) {
  241. dropDownElement.style.height = allowableHeight + "px";
  242. }
  243. } else {
  244. if (getDropDownHeight(dropDownElement) > maxHeight) {
  245. dropDownElement.style.height = maxHeight + "px";
  246. }
  247. }
  248. }
  249. //updates the height of the browser and determines whether to open the browser up or down
  250. function CCPopupMenu_fitHeightToBrowser(x, y) {
  251. var dropDownElement = this.dropDownElement;
  252. getDropDownWidth(dropDownElement);
  253. var winHeight = windowHeight();
  254. var originalMenuHeight = this.mnHeight;
  255. var originalHeight = getDropDownHeight(dropDownElement);
  256. var originalWidth = getDropDownWidth(dropDownElement);
  257. dropDownElement.style.height = originalHeight + "px";
  258. var controlElement = document.getElementById(this.controlId);
  259. var controlElementTop = y;
  260. var controlElementHeight = 0;
  261. if (controlElement != null) {
  262. controlElementTop = controlElement.offsetTop;
  263. controlElementHeight = getDropDownHeight(controlElement);
  264. }
  265. //determine how much space we have above the control element and how much space we have below
  266. var spaceAboveControl = Math.max(0, controlElementTop);
  267. var spaceBelowControl = Math.max(0, winHeight - controlElementTop - controlElementHeight);
  268. //determine the height of a menu item
  269. var elems = dropDownElement.getElementsByTagName('td');
  270. var elementHeight = 20;
  271. if (elems.length > 0) {
  272. elementHeight = getDropDownHeight(elems[1]);
  273. }
  274. //find the minumum number of items to show based on what is smaller the number of menu items available or the
  275. //default minimum items to show
  276. var minimumDropSize = Math.min(CCPopupMenu.minSize, this.menuItems.length) * elementHeight;
  277. //try and size the drop down as if droped below
  278. this.sizeDropDown(dropDownElement, spaceBelowControl, elementHeight);
  279. var downHeight = getDropDownHeight(dropDownElement);
  280. var downWidth = getDropDownWidth(dropDownElement);
  281. //try and size the drop down as if droped above
  282. dropDownElement.style.height = originalHeight + "px";
  283. dropDownElement.style.width = originalWidth + "px";
  284. this.sizeDropDown(dropDownElement, spaceAboveControl, elementHeight);
  285. var upHeight = getDropDownHeight(dropDownElement);
  286. var upWidth = getDropDownWidth(dropDownElement);
  287. dropDownElement.style.height = originalHeight + "px";
  288. dropDownElement.style.width = originalWidth + "px";
  289. //now check what is better to show the menu droped down or dropped up
  290. if (downHeight < upHeight) {
  291. //if the size of the drop down would be less than the min size in the drop down or drop up case
  292. //then force the min size
  293. if (upHeight < minimumDropSize) {
  294. //if we are forcing the height to be the minimum then we may as well just open down
  295. dropDownElement.style.height = minimumDropSize + "px";
  296. dropDownElement.style.top = y + controlElement.offsetHeight + "px";
  297. } else {
  298. //in this case we should show it up
  299. dropDownElement.style.top = (controlElementTop - upHeight) + "px";
  300. dropDownElement.style.width = upWidth + "px";
  301. }
  302. } else {
  303. //droping down is better so restore the size to the drop down scenario
  304. //if the size of the drop down would be less than the min size in the drop down or drop up case
  305. //then force the min size
  306. if (downHeight < minimumDropSize) {
  307. downHeight = minimumDropSize;
  308. }
  309. dropDownElement.style.width = downWidth + "px";
  310. dropDownElement.style.height = downHeight + "px";
  311. dropDownElement.style.top = y + controlElement.offsetHeight + "px";
  312. }
  313. //must check to see if we have shrunk the menu so that we need to show scrollbars
  314. if (getDropDownHeight(dropDownElement) < originalHeight) {
  315. //have to account for the scroll bars....if there are verticle bars then must widen the div a little
  316. //NOTE: because we may change the width of the menu, we have to do the width positioning after this step!!!
  317. dropDownElement.style.width = (getDropDownWidth(dropDownElement) + 20) + "px";
  318. setOverflowStyle(dropDownElement);
  319. }
  320. this.mnHeight = originalMenuHeight;
  321. }
  322. //determines the width of the browser to ensure nothing falls off the edge of the browser
  323. function CCPopupMenu_fitWidthToBrowser(x, y) {
  324. var controlElement = document.getElementById(this.controlId);
  325. if (controlElement == null) {
  326. //if we can't find the control element....give up
  327. return;
  328. }
  329. var dropDownElement = this.dropDownElement;
  330. var rtl=document.body.dir=="rtl";
  331. if(rtl)
  332. CCPopupMenu_fitWidthToBrowserRTL(controlElement, dropDownElement, x, y);
  333. else
  334. CCPopupMenu_fitWidthToBrowserLTR(controlElement, dropDownElement, x, y);
  335. }
  336. //determines the width of the browser to ensure nothing falls off the edge of the browser in LTR case
  337. function CCPopupMenu_fitWidthToBrowserLTR(controlElement, dropDownElement, x, y) {
  338. var controlElementLeft = controlElement.offsetLeft;
  339. //position the drop down based on the size of the browser window
  340. var winWidth = windowWidth();
  341. var dropDownRight = controlElementLeft + dropDownElement.offsetWidth;
  342. //if what was provided would pass off the right of the browser
  343. //move the popup so that is flush with the right (with a small margin) of the of the browser to get it
  344. //close to where you wanted it but not letting anything fall off the edge
  345. if (winWidth < dropDownRight) {
  346. var dropDownLeft = controlElement.offsetWidth - dropDownElement.offsetWidth;
  347. var dropDownAbsoluteLeft = controlElementLeft + dropDownLeft;
  348. if (dropDownAbsoluteLeft < 0) {
  349. //in this case we have very little room to show the menu so we need to position it to
  350. //take up the entire width of the window
  351. dropDownElement.style.left = controlElement.offsetLeft * -1;
  352. } else {
  353. dropDownElement.style.left = (controlElement.offsetWidth - dropDownElement.offsetWidth) + "px";
  354. }
  355. } else {
  356. dropDownElement.style.left = x + "px";
  357. }
  358. }
  359. //determines the width of the browser to ensure nothing falls off the edge of the browser in RTL case
  360. function CCPopupMenu_fitWidthToBrowserRTL(controlElement, dropDownElement, x, y) {
  361. var controlElementRight = controlElement.offsetLeft + controlElement.offsetWidth;
  362. //position the drop down based on the size of the browser window
  363. var winWidth = windowWidth();
  364. var dropDownLeft = controlElementRight - dropDownElement.offsetWidth;
  365. //if what was provided would pass off the left of the browser
  366. //move the popup so that is flush with the left (with a small margin) of the of the browser to get it
  367. //close to where you wanted it but not letting anything fall off the edge
  368. if (dropDownLeft < 0) {
  369. var dropDownRight = controlElement.offsetWidth - dropDownElement.offsetWidth;
  370. var dropDownAbsoluteRight = controlElementRight - dropDownRight;
  371. if (dropDownAbsoluteRight > winWidth) {
  372. //in this case we have very little room to show the menu so we need to position it to
  373. //take up the entire width of the window
  374. dropDownElement.style.right = controlElement.offsetRight * -1;
  375. } else {
  376. //dropDownElement.style.right = (controlElement.scrollWidth - dropDownElement.scrollWidth) + "px";
  377. dropDownElement.style.left = 0 + "px";
  378. }
  379. } else {
  380. dropDownElement.style.right = x + "px";
  381. }
  382. }
  383. //static method to create and show the drop down for the menu with the passed in id
  384. function CCPopupMenu_dropDown(event, x, y, id) {
  385. if (event.type == "keypress" && event.keyCode == 9) {
  386. CCPopupMenu.hideActiveMenu();
  387. return true; //Ignore tabs.
  388. }
  389. var currentMenu = CCPopupMenu.getMenu(id);
  390. if (currentMenu != null) {
  391. //check to make sure the menu was created
  392. if (currentMenu.dropDownElement == null) {
  393. return;
  394. }
  395. //make sure that if there is a menu already open to close it
  396. var isAlreadyOpen = false;
  397. if ((CCPopupMenu.activeMenu != null) && (CCPopupMenu.activeMenu.id == id)) {
  398. isAlreadyOpen = CCPopupMenu.activeMenu.isOpen;
  399. }
  400. CCPopupMenu.hideActiveMenu();
  401. if ((event.type == "keypress" && event.keyCode == 27) && (isAlreadyOpen)) {
  402. return true;
  403. }
  404. //position the drop down based on the passed in x, and y parameters and the size of the browser window
  405. currentMenu.fitHeightToBrowser(x, y);
  406. currentMenu.fitWidthToBrowser(x, y);
  407. //create an iframe so things don't peek through...no peeking allowed!
  408. CCPopupMenu.createInsulatingIframe(currentMenu, currentMenu.dropDownElement);
  409. //show the drop down menu and set the focus to the first menu item
  410. currentMenu.dropDownElement.style.visibility = "visible";
  411. CCPopupMenu.activeMenu = currentMenu;
  412. currentMenu.isOpen = true;
  413. //if the event is a kepress then set the focus to the first menu item so that the tabbing order appears correct
  414. if (event.type == "keypress" || event.type == 'click') {
  415. CCPopupMenu.activeMenu.doCheckBounds = false;
  416. CCPopupMenu.activeMenu.activeMenuItemIndex = -1;
  417. selectedObject = CCPopupMenu.activeMenu.getCurrentSelected();
  418. if (!selectedObject) {
  419. currentMenu.menuItems[0].menuItemEl.focus();
  420. } else {
  421. CCPopupMenu.setActiveMenuItem("current");
  422. }
  423. }
  424. }
  425. CCPopupMenu.ignoreHideActiveMenu("ignore");
  426. setTimeout('CCPopupMenu.ignoreHideActiveMenu("unignore")', 100);
  427. return haltEventProcessing(event);
  428. }
  429. //This function stops the propagation of the onclick event past the dropdown div
  430. function CCPopupMenu_dropDownOnclick(event) {
  431. if (event.stopPropagation) {
  432. event.stopPropagation();
  433. } else {
  434. event.cancelBubble = 'true';
  435. }
  436. }
  437. function CCPopupMenu_isTapInsideMenu(tapObject) {
  438. var tapX = tapObject.pageX;
  439. var tapY = tapObject.pageY;
  440. var menuRect = this.dropDownElement.getBoundingClientRect();
  441. if (!((tapX >= menuRect.left) && (tapX <= menuRect.right) && (tapY <= menuRect.bottom) && (tapY >= menuRect.top))) {
  442. return true;
  443. }
  444. return false;
  445. }
  446. function CCPopupMenu_createDropDown() {
  447. //create the drop down consisting of the following html structure <div><table> ...menuitems </table></div>
  448. var divEl = document.createElement("div");
  449. var tableEl = document.createElement("table");
  450. var tbody = document.createElement("tbody");
  451. var itm;
  452. //can only add table rows to table bodies...can not add them to the table directly
  453. tableEl.appendChild(tbody);
  454. tableEl.style.borderCollapse = "collapse";
  455. tableEl.summary = "";
  456. tableEl.setAttribute("role", "menu");
  457. divEl.id = "flyout_" + this.id;
  458. divEl.className = "flyOutMenu";
  459. divEl.style.display = "block";
  460. divEl.style.position = "absolute";
  461. divEl.style.overflow = "visible";
  462. //ensure that the popup is going to be the highest in the zorder so that things don't peek through
  463. //randomly choose 100 as it seemed like a pretty high number
  464. divEl.style.zIndex = "2";
  465. divEl.style.visibility = "hidden";
  466. divEl.style.padding = "2px";
  467. divEl.setAttribute("role", "presentation");
  468. if (this.label != null) {
  469. tableEl.setAttribute("aria-label", this.label);
  470. }
  471. divEl.tabIndex = -1;
  472. addEvent(divEl, "click", CCPopupMenu_dropDownOnclick);
  473. // Depending on the browser, define the appropriate key event handler for the pop-up menu items
  474. var moz = (window.navigator.userAgent.indexOf("Gecko") != -1);
  475. addEvent(divEl, (moz ? "keypress" : "keydown"), extensions.associate(itm, this, "presskey"));
  476. tableEl.id = "flyoutTab_" + this.id;
  477. //add drop down element as a child of the control element
  478. //this will ensure there are no tabing irregularities
  479. var controlEl = document.getElementById(this.controlId);
  480. if (controlEl != null) {
  481. controlEl.appendChild(divEl);
  482. } else {
  483. //add the drop down to the body if you can't find the control element
  484. document.body.appendChild(divEl);
  485. }
  486. divEl.appendChild(tableEl);
  487. //need to maintain the first menu item as when all is said and done the focus must end up on that element
  488. var maxItmWidth = 0;
  489. for (index = 0; index < this.menuItems.length; index++) {
  490. if (index == 0) {
  491. itm = this.firstMenuItemEl = this.menuItems[index].renderItem(tbody, this.id);
  492. } else {
  493. itm = this.menuItems[index].renderItem(tbody, this.id);
  494. }
  495. if (moz && itm && itm.offsetWidth && maxItmWidth < itm.offsetWidth) {
  496. maxItmWidth = itm.offsetWidth;
  497. }
  498. }
  499. if (moz && maxItmWidth > 0) {
  500. divEl.style.width = maxItmWidth + "px";
  501. }
  502. this.dropDownElement = divEl;
  503. //stick it in the upperleft corner of the browser so as not to make the browser bigger
  504. this.fitHeightToBrowser(0, 0);
  505. this.fitWidthToBrowser(0, 0);
  506. //unfortunately need to do this switch of visibility to ensure that the menu separators get hidden
  507. this.dropDownElement.style.visibility = "visible";
  508. this.dropDownElement.style.visibility = "hidden";
  509. }
  510. //static function to create all the drop down divs so that they can be show later
  511. function CCPopupMenu_createDropDowns() {
  512. for (var index = 0; index < CCPopupMenu.menus.length; index++) {
  513. CCPopupMenu.menus[index].createDropDown();
  514. }
  515. }
  516. //static function returns the menu object associated with the passed in id
  517. function CCPopupMenu_getMenu(id) {
  518. for (var index = 0; index < CCPopupMenu.menus.length; index++) {
  519. if (CCPopupMenu.menus[index].id == id) {
  520. return CCPopupMenu.menus[index];
  521. }
  522. }
  523. }
  524. //constructor to create an new CCPopupMenu object with the passed in id
  525. function CCPopupMenu(sId, controlId, nHeight, hasCheckbox, messagesJSON) {
  526. this.controlId = controlId;
  527. this.id = sId;
  528. this.menuItems = [];
  529. this.isOpen = false;
  530. this.dropDownElement = null;
  531. this.mnHeight = -1;
  532. this.hasCheckbox = ((hasCheckbox != null) && (hasCheckbox == 'true'));
  533. //if a height was passed in use it so that vertical scrolling is enabled...otherwise disable vertical scrolling
  534. //by setting the mnHeight to -1
  535. if (nHeight != "") {
  536. this.mnHeight = parseInt(nHeight, 10);
  537. }
  538. //indicates which index has focus - defaults to -1 so using down key positions correctly on first item in menu list
  539. this.activeMenuItemIndex = -1;
  540. this.firstMenuItemEl = null;
  541. this.doCheckBounds = true;
  542. this.label=null;
  543. this.messages = messagesJSON;
  544. CCPopupMenu.menus.push(this);
  545. }
  546. function CCPopupMenu_setLabel(newLabel){
  547. this.label = newLabel;
  548. }
  549. //instance method to add a menu item with the passed in label and clickFunction
  550. //clickFunction is expected to be a string with valid javascript code
  551. function CCPopupMenu_addMenuItem(id, groupId, label, icon, clickFunction) {
  552. var newMenuItem = new CCPopupMenuItem(id, groupId, label, icon, clickFunction, this.hasCheckbox, this);
  553. this.menuItems.push(newMenuItem);
  554. }
  555. //returns the menu item with the assoicated id
  556. function CCPopupMenu_getMenuItem(id) {
  557. for (var index = 0; index < this.menuItems.length; index++) {
  558. if (this.menuItems[index].id == id) {
  559. return this.menuItems[index];
  560. }
  561. }
  562. }
  563. //sets the selections state of each menu item in the group with the passed in id to "none"
  564. function CCPopupMenu_clearGroup(id) {
  565. for (var index = 0; index < this.menuItems.length; index++) {
  566. if (this.menuItems[index].groupId == id) {
  567. this.menuItems[index].clearSelectionState();
  568. }
  569. }
  570. }
  571. //sets the menu item with the associated id to be checked
  572. function CCPopupMenu_setMenuItemChecked(id) {
  573. //sets the checked attrute of the menuitem
  574. var currentMenuItem = this.getMenuItem(id);
  575. if (currentMenuItem.isInGroup()) {
  576. this.clearGroup(currentMenuItem.groupId);
  577. }
  578. currentMenuItem.check();
  579. }
  580. //returns the menu items with a selection state not set to none
  581. function CCPopupMenu_getCurrentSelected() {
  582. for (var index = 0; index < this.menuItems.length; index++) {
  583. if (this.menuItems[index].type != "item") {
  584. index++;
  585. }
  586. if (this.menuItems[index].itemSelectedState != "none") {
  587. return this.menuItems[index];
  588. }
  589. }
  590. return this.menuItems[index];
  591. }
  592. //returns the menu items with a selection state not set to none
  593. function CCPopupMenu_getCurrentSelectedIndex() {
  594. for (var index = 0;index < this.menuItems.length; index++) {
  595. if (this.menuItems[index].type != "item") {
  596. index++;
  597. }
  598. if (this.menuItems[index].itemSelectedState != "none") {
  599. return index;
  600. }
  601. }
  602. return this.activeMenuItemIndex;
  603. }
  604. // Navigation on the flyout from pressing up and down arrow keys. Also passing current sets first entry that is selected.
  605. // When going 'up' or 'down' check to make sure that the next type is an item, if not then move by 1.
  606. function CCPopupMenu_setActiveMenuItem(direction) {
  607. currentMenu = CCPopupMenu.activeMenu;
  608. var index = direction == 'current' ? currentMenu.getCurrentSelectedIndex() : currentMenu.activeMenuItemIndex;
  609. if (direction == 'up') {
  610. if (index > 0) {
  611. if (currentMenu.menuItems[index - 1].type != "item") {
  612. index--;
  613. }
  614. index--;
  615. }
  616. } else if (direction == 'down') {
  617. if (index < currentMenu.menuItems.length - 1) {
  618. if (currentMenu.menuItems[index + 1].type != "item") {
  619. index++;
  620. }
  621. index++;
  622. }
  623. }
  624. if (index > -1 && index != currentMenu.activeMenuItemIndex) {
  625. currentMenu.activeMenuItemIndex = index;
  626. }
  627. currentMenu.menuItems[index].menuItemEl.focus();
  628. }
  629. //sets the menu item with the associated id to be selected
  630. function CCPopupMenu_setMenuItemSelected(id) {
  631. //sets the checked attrute of the menuitem
  632. currentMenuItem = this.getMenuItem(id);
  633. if (currentMenuItem.isInGroup()) {
  634. this.clearGroup(currentMenuItem.groupId);
  635. }
  636. currentMenuItem.select();
  637. }
  638. //Set the active item index when focus is set.
  639. function CCPopupMenu_setCurrentItemIndex(id) {
  640. currentMenu = CCPopupMenu.activeMenu;
  641. for (var index = 0; index < currentMenu.menuItems.length; index++) {
  642. if (currentMenu.menuItems[index].type != "item") {
  643. continue;
  644. }
  645. if (currentMenu.menuItems[index].menuItemEl.id == id) {
  646. currentMenu.activeMenuItemIndex = index;
  647. currentMenu.menuItems[index].menuItemEl.className = "menuItemOver";
  648. } else {
  649. currentMenu.menuItems[index].menuItemEl.className = "menuItemNormal";
  650. }
  651. }
  652. }
  653. //instance method to add a menu separator
  654. function CCPopupMenu_addMenuSeparator() {
  655. var newMenuItem = new CCPopupMenuSeparator();
  656. this.menuItems.push(newMenuItem);
  657. }
  658. //instance method to hide the current drop down
  659. function CCPopupMenu_removeDropDown() {
  660. if ((this.dropDownElement != null)) {
  661. this.dropDownElement.style.visibility = "hidden";
  662. this.isOpen = false;
  663. var iframeID = this.id + "inslIframe";
  664. var iframeEl = document.getElementById(iframeID);
  665. if (iframeEl != null) {
  666. var controlElement = document.getElementById(this.controlId);
  667. controlElement.removeChild(iframeEl);
  668. }
  669. }
  670. }
  671. // Handle pop-up menu key event to hide the active pop-up menu and reset focus when necessary
  672. function CCPopupMenu_hidePopupForKeyPress() {
  673. var moz = (window.navigator.userAgent.indexOf("Gecko") != -1);
  674. if (moz) {
  675. var currentMenu = CCPopupMenu.getMenu(CCPopupMenu.activeMenu.id);
  676. var controlContainerElement = document.getElementById(currentMenu.controlId);
  677. CCPopupMenu.hideActiveMenu();
  678. if (controlContainerElement != null) {
  679. controlContainerElement.focus();
  680. }
  681. } else {
  682. CCPopupMenu.hideActiveMenu();
  683. }
  684. }
  685. // Handle the pop-up menu key events.
  686. function CCPopupMenu_presskey(evt) {
  687. evt = evt != null ? evt : window.event;
  688. if (evt.keyCode == 13) {
  689. // Enter: Act on the current menu
  690. if (CCPopupMenu.activeMenu.activeMenuItemIndex > -1) {
  691. CCPopupMenu.activeMenu.menuItems[CCPopupMenu.activeMenu.activeMenuItemIndex].keypressFunction();
  692. CCPopupMenu.hidePopupForKeyPress();
  693. }
  694. } else if (evt.keyCode == 27 || evt.keyCode == 9) {
  695. // Esc Key: Close menu and halt
  696. // Tab Key: Close menu and continue
  697. CCPopupMenu.hidePopupForKeyPress();
  698. if (evt.keyCode == 9) {
  699. return true;
  700. }
  701. } else if (evt.keyCode == 38) {
  702. // Up Arrow Key
  703. CCPopupMenu.setActiveMenuItem('up');
  704. } else if (evt.keyCode == 40) {
  705. // Down arrow Key
  706. CCPopupMenu.setActiveMenuItem('down');
  707. }
  708. return haltEventProcessing(evt);
  709. }
  710. //***********************CCPopupMenu specification
  711. CCPopupMenu.prototype.addMenuItem = CCPopupMenu_addMenuItem;
  712. CCPopupMenu.prototype.addMenuSeparator = CCPopupMenu_addMenuSeparator;
  713. CCPopupMenu.prototype.removeDropDown = CCPopupMenu_removeDropDown;
  714. CCPopupMenu.prototype.fitHeightToBrowser = CCPopupMenu_fitHeightToBrowser;
  715. CCPopupMenu.prototype.fitWidthToBrowser = CCPopupMenu_fitWidthToBrowser;
  716. CCPopupMenu.prototype.getMenuItem = CCPopupMenu_getMenuItem;
  717. CCPopupMenu.prototype.clearGroup = CCPopupMenu_clearGroup;
  718. CCPopupMenu.prototype.setMenuItemChecked = CCPopupMenu_setMenuItemChecked;
  719. CCPopupMenu.prototype.setMenuItemSelected = CCPopupMenu_setMenuItemSelected;
  720. CCPopupMenu.prototype.sizeDropDown = CCPopupMenu_sizeDropDown;
  721. CCPopupMenu.prototype.getCurrentSelected = CCPopupMenu_getCurrentSelected;
  722. CCPopupMenu.prototype.createDropDown = CCPopupMenu_createDropDown;
  723. CCPopupMenu.prototype.getCurrentSelectedIndex = CCPopupMenu_getCurrentSelectedIndex;
  724. CCPopupMenu.prototype.presskey = CCPopupMenu_presskey;
  725. CCPopupMenu.prototype.setLabel = CCPopupMenu_setLabel;
  726. CCPopupMenu.prototype.isTapInsideMenu = CCPopupMenu_isTapInsideMenu;
  727. CCPopupMenu.hideActiveMenu = CCPopupMenu_hideActiveMenu;
  728. CCPopupMenu.hidePopupForKeyPress = CCPopupMenu_hidePopupForKeyPress;
  729. CCPopupMenu.ignoreHideActiveMenu = CCPopupMenu_ignoreHideActiveMenu;
  730. CCPopupMenu.getMenu = CCPopupMenu_getMenu;
  731. CCPopupMenu.dropDown = CCPopupMenu_dropDown;
  732. CCPopupMenu.checkBounds = CCPopupMenu_checkBounds;
  733. CCPopupMenu.createInsulatingIframe = CCPopupMenu_createInsulatingIframe;
  734. CCPopupMenu.setControlFocus = CCPopupMenu_setControlFocus;
  735. CCPopupMenu.createDropDowns = CCPopupMenu_createDropDowns;
  736. CCPopupMenu.setActiveMenuItem = CCPopupMenu_setActiveMenuItem;
  737. CCPopupMenu.setCurrentItemIndex = CCPopupMenu_setCurrentItemIndex;
  738. //***********************CCPopupMenu specification
  739. //constructor for CCFlyoutSeparator
  740. //CCFlyoutSeparator has no real state...it just knows how to render itself
  741. function CCPopupMenuSeparator() {
  742. this.type = "separator";
  743. }
  744. function CCPopupMenuSeparator_isInGroup() {
  745. return false;
  746. }
  747. //instance method for rendering a flyout separator
  748. //consisting of the following html: <tr><td><img/></td></tr>
  749. function CCPopupMenuSeparator_renderItem(menuElement, id) {
  750. var menuItemEl = document.createElement("tr");
  751. //menu separators should not be in the tabbing order
  752. menuItemEl.tabIndex = -1;
  753. menuItemEl.setAttribute("role", "separator");
  754. menuElement.appendChild(menuItemEl);
  755. var menuSeparatorContainer = document.createElement("td");
  756. menuSeparatorContainer.colSpan = 3;
  757. var menuSeparator = document.createElement("div");
  758. menuSeparator.className = "flyOutMenuSeparator";
  759. menuSeparatorContainer.appendChild(menuSeparator);
  760. //menuSeparator.className = "flyOutMenuSeparator";
  761. menuItemEl.appendChild(menuSeparatorContainer);
  762. }
  763. //***********************CCFlyoutSeparator specification
  764. CCPopupMenuSeparator.prototype.renderItem = CCPopupMenuSeparator_renderItem;
  765. CCPopupMenuSeparator.prototype.isInGroup = CCPopupMenuSeparator_isInGroup;
  766. //***********************CCFlyoutSeparator specification
  767. //constructor for CCPopupMenuItem
  768. //clickFunction is expected to be a string with valid javascript code
  769. function CCPopupMenuItem(sId, groupId, slabel, icon, clickFunction, hasCheckbox, menu) {
  770. this.id = sId;
  771. this.label = slabel;
  772. this.icon = icon;
  773. this.itemSelectedState = "none";
  774. this.type = "item";
  775. this.groupId = groupId;
  776. this.enabled = true;
  777. this.menuItemEl = null;
  778. this.menuLabelEl = null;
  779. this.iconImageEl = null;
  780. this.selectionStateIcon = null;
  781. this.selectionElement = null;
  782. this.menuIdx = -1;
  783. this.hasCheckbox = hasCheckbox;
  784. this.parentMenu = menu;
  785. //the passed in click action is the action the consumer of the menu item wants to take when clicking on the item
  786. //we must enhance that with some menu caretaking code which will take care of hiding the menu after the click
  787. var clickActionCode = clickFunction + ";CCPopupMenu.hideActiveMenu();";
  788. //keypress actions act similarly to click action but require some additional care taking
  789. // var keypressActionCode = "if (event.keyCode == '13'){" + clickFunction + "} else if (event.keyCode == '27'){CCPopupMenu.hideActiveMenu();}cancelBubble = true;return false;";
  790. this.keypressFunction = new Function("event", clickActionCode);
  791. // this.keyArrowFunction = new Function("event", clickFunction);
  792. // this.keyPressFunction = new Function("event", keypressActionCode);
  793. this.clickFunction = new Function("event", clickActionCode);
  794. }
  795. function CCPopupMenuItem_isInGroup() {
  796. return (this.groupId != "");
  797. }
  798. function CCPopupMenuItem_disable() {
  799. this.enabled = false;
  800. this.updateForEnabled();
  801. }
  802. function CCPopupMenuItem_enable() {
  803. this.enabled = true;
  804. this.updateForEnabled();
  805. }
  806. //sets the selectedState to none
  807. function CCPopupMenuItem_clearSelectionState() {
  808. this.itemSelectedState = "none";
  809. this.updateForSelectionState();
  810. }
  811. //set the selectionState to checked (note selection state and check state are mutually exlusive...an element can not be selected and checked)
  812. function CCPopupMenuItem_check() {
  813. this.itemSelectedState = "checked";
  814. this.updateForSelectionState();
  815. }
  816. //set the selectionState to selected (note selection state and check state are mutually exlusive...an element can not be selected and checked)
  817. function CCPopupMenuItem_select() {
  818. this.itemSelectedState = "selected";
  819. this.updateForSelectionState();
  820. }
  821. //renders the label for the menuitem
  822. function CCPopupMenuItem_renderLabel(menuElement) {
  823. var menuItemLabel = document.createElement("td");
  824. menuItemLabel.style.padding = "2px";
  825. menuItemLabel.className = "menuItemNormal";
  826. this.menuLabelEl = menuItemLabel;
  827. menuElement.appendChild(menuItemLabel);
  828. var nonbreakingSpace = document.createElement("nobr");
  829. menuItemLabel.appendChild(nonbreakingSpace);
  830. var labelLink = document.createElement("span");
  831. labelLink.tabIndex = -1;
  832. nonbreakingSpace.appendChild(labelLink);
  833. labelLink.appendChild(document.createTextNode(this.label));
  834. }
  835. //render the items checked, selected or icon if necessary
  836. function CCPopupMenuItem_renderDecorations(menuElement) {
  837. var decorationTD = document.createElement("td");
  838. decorationTD.className = "text";
  839. decorationTD.style.cursor = "pointer";
  840. decorationTD.style.textDecoration = "underline";
  841. menuElement.appendChild(decorationTD);
  842. this.selectionElement = decorationTD;
  843. if (this.icon != "") {
  844. var imgEl = document.createElement("img");
  845. imgEl.src = this.icon;
  846. imgEl.style.height = "16px";
  847. imgEl.style.width = "16px";
  848. imgEl.alt="";
  849. imgEl.setAttribute("role","presentation");
  850. this.iconImageEl = imgEl;
  851. decorationTD.className = "menuItemIcon";
  852. decorationTD.appendChild(imgEl);
  853. }
  854. }
  855. function CCPopupMenuItem_updateForSelectionState() {
  856. if (this.menuItemEl == null) {
  857. return;
  858. }
  859. if (this.itemSelectedState == "none") {
  860. if (this.selectionStateIcon != null) {
  861. //in this case we remove the selection icon
  862. this.selectionStateIcon.parentNode.removeChild(this.selectionStateIcon);
  863. this.selectionStateIcon = null;
  864. this.menuItemEl.setAttribute("aria-checked","false");
  865. }
  866. } else {
  867. if (this.selectionStateIcon == null) {
  868. var imgEl = document.createElement("img");
  869. if (this.itemSelectedState == "checked") {
  870. imgEl.src = CCPopupMenu.portalImagesPath + "/checkmark.gif";
  871. if (this.parentMenu.messages != null){
  872. imgEl.alt = this.parentMenu.messages.IDS_CCPOPUP_CHECKED;
  873. }
  874. } else {
  875. imgEl.src = CCPopupMenu.portalImagesPath + "/dot.gif";
  876. if (this.parentMenu.messages != null){
  877. imgEl.alt = this.parentMenu.messages.IDS_CCPOPUP_DOT;
  878. }
  879. }
  880. this.selectionElement.appendChild(imgEl);
  881. this.selectionStateIcon = imgEl;
  882. } else {
  883. if (this.itemSelectedState == "checked") {
  884. this.selectionStateIcon.src = CCPopupMenu.portalImagesPath + "/checkmark.gif";
  885. if (this.parentMenu.messages != null){
  886. this.selectionStateIcon.alt = this.parentMenu.messages.IDS_CCPOPUP_CHECKED;
  887. }
  888. } else {
  889. this.selectionStateIcon.src = CCPopupMenu.portalImagesPath + "/dot.gif";
  890. if (this.parentMenu.messages != null){
  891. this.selectionStateIcon.alt = this.parentMenu.messages.IDS_CCPOPUP_DOT;
  892. }
  893. }
  894. this.updateForEnabled();
  895. }
  896. this.menuItemEl.setAttribute("aria-checked","true");
  897. }
  898. }
  899. //updates the rendered menu item based on the enabled state
  900. function CCPopupMenuItem_updateForEnabled() {
  901. if (this.menuItemEl == null) {
  902. return;
  903. }
  904. //only register the click/keypress handlers if the element is enabled
  905. if (this.enabled) {
  906. //enable the click/keypress events
  907. //addEvent(this.menuItemEl, 'keydown', this.presskey);
  908. addEvent(this.menuItemEl, 'click', this.clickFunction);
  909. //update the style
  910. this.menuItemEl.style.MozOpacity = "1.0";
  911. this.menuItemEl.setAttribute("aria-disabled","false");
  912. this.menuItemEl.style.filter = "alpha(opacity=100)";
  913. this.menuLabelEl.className = "text";
  914. if (this.itemSelectedState != "none") {
  915. this.selectionStateIcon.style.MozOpacity = "1.0";
  916. this.selectionStateIcon.style.filter = "alpha(opacity=100)";
  917. }
  918. if (this.iconImageEl != null) {
  919. this.iconImageEl.style.MozOpacity = "1.0";
  920. this.iconImageEl.style.filter = "alpha(opacity=100)";
  921. }
  922. } else {
  923. //disable the click/keypress events
  924. // removeEvent(this.menuItemEl, 'keydown',this.presskey);
  925. removeEvent(this.menuItemEl, 'click', this.clickFunction);
  926. //update the style
  927. this.menuItemEl.style.MozOpacity = "0.5";
  928. this.menuItemEl.setAttribute("aria-disabled","true");
  929. this.menuItemEl.style.filter = "alpha(opacity=50)";
  930. if (this.itemSelectedState != "none") {
  931. this.selectionStateIcon.style.MozOpacity = "0.5";
  932. this.selectionStateIcon.style.filter = "alpha(opacity=50)";
  933. }
  934. if (this.iconImageEl != null) {
  935. this.iconImageEl.style.MozOpacity = "0.5";
  936. this.iconImageEl.style.filter = "alpha(opacity=50)";
  937. }
  938. this.menuLabelEl.className = "inactiveText";
  939. }
  940. }
  941. function menuItemOverEventHandler(id) {
  942. return function ccmenuitemovereventhandler() {
  943. var menuItemEl = document.getElementById(id);
  944. CCPopupMenu.setCurrentItemIndex(menuItemEl.id);
  945. };
  946. }
  947. function menuItemOutEventHandler(id) {
  948. return function ccmenuitemouteventhandler() {
  949. var menuItemEl = document.getElementById(id);
  950. menuItemEl.className = 'menuItemNormal';
  951. };
  952. }
  953. function menuItemBlurEventHandler(id) {
  954. return function ccmenuitemblureventhandler(event) {
  955. var menuItemEl = document.getElementById(id);
  956. menuItemEl.className = 'menuItemNormal';
  957. CCPopupMenu.checkBounds(event);
  958. };
  959. }
  960. function CCPopupMenuItem_createCommonEventHandlers(menuItemEl) {
  961. addEvent(menuItemEl, 'focus', menuItemOverEventHandler(menuItemEl.id));
  962. addEvent(menuItemEl, 'mouseout', menuItemOutEventHandler(menuItemEl.id));
  963. addEvent(menuItemEl, 'mouseover', menuItemOverEventHandler(menuItemEl.id));
  964. addEvent(menuItemEl, 'blur', menuItemBlurEventHandler(menuItemEl.id));
  965. }
  966. //instance method for rendering a flyout menu item
  967. //consisting of the following html: <tr><td><nobr>..label...</nobr></td></tr>
  968. function CCPopupMenuItem_renderItem(menuElement, id) {
  969. var menuItemEl = document.createElement("tr");
  970. var itemRole = "menuitem";
  971. //if this menu has checkable menu items then the role is slightly different to allow for aria-checked attribute
  972. if (this.hasCheckbox){
  973. itemRole = "menuitemcheckbox";
  974. menuItemEl.setAttribute("aria-checked","false");
  975. }
  976. menuItemEl.setAttribute("role", itemRole);
  977. menuItemEl.className = "menuItemNormal";
  978. menuItemEl.id = this.id + "menuItemTR";
  979. menuItemEl.tabIndex = -1;
  980. this.createCommonEventHandlers(menuItemEl);
  981. menuItemEl.style.width = "100%";
  982. menuItemEl.style.overflow = "visible";
  983. menuElement.appendChild(menuItemEl);
  984. this.renderDecorations(menuItemEl);
  985. this.renderLabel(menuItemEl);
  986. var cascadingTD = document.createElement("td");
  987. cascadingTD.className = "text";
  988. cascadingTD.style.cursor = "pointer";
  989. cascadingTD.style.textDecoration = "underline";
  990. menuItemEl.appendChild(cascadingTD);
  991. this.menuItemEl = menuItemEl;
  992. this.updateForSelectionState();
  993. this.updateForEnabled();
  994. return menuItemEl;
  995. }
  996. //***********************CCPopupMenuItem specification
  997. CCPopupMenuItem.prototype.renderItem = CCPopupMenuItem_renderItem;
  998. CCPopupMenuItem.prototype.renderDecorations = CCPopupMenuItem_renderDecorations;
  999. CCPopupMenuItem.prototype.renderLabel = CCPopupMenuItem_renderLabel;
  1000. CCPopupMenuItem.prototype.clearSelectionState = CCPopupMenuItem_clearSelectionState;
  1001. CCPopupMenuItem.prototype.check = CCPopupMenuItem_check;
  1002. CCPopupMenuItem.prototype.select = CCPopupMenuItem_select;
  1003. CCPopupMenuItem.prototype.isInGroup = CCPopupMenuItem_isInGroup;
  1004. CCPopupMenuItem.prototype.disable = CCPopupMenuItem_disable;
  1005. CCPopupMenuItem.prototype.enable = CCPopupMenuItem_enable;
  1006. CCPopupMenuItem.prototype.updateForEnabled = CCPopupMenuItem_updateForEnabled;
  1007. CCPopupMenuItem.prototype.updateForSelectionState = CCPopupMenuItem_updateForSelectionState;
  1008. CCPopupMenuItem.prototype.createCommonEventHandlers = CCPopupMenuItem_createCommonEventHandlers;
  1009. //***********************CCPopupMenuItem specification
  1010. function respondToTouch(){
  1011. if (CCPopupMenu.activeMenu != null){
  1012. var event = window.event;
  1013. if (CCPopupMenu.activeMenu.isTapInsideMenu(event.targetTouches[0])) {
  1014. var controlElement = document.getElementById(CCPopupMenu.activeMenu.controlId);
  1015. if (event.taget != controlElement){
  1016. CCPopupMenu.hideActiveMenu();
  1017. }
  1018. }
  1019. }
  1020. }
  1021. //these event handlers will close active menus whenever the browser is resized or one clicks outside of a menu
  1022. addEvent(document, 'click', CCPopupMenu.hideActiveMenu);
  1023. addEvent(document, 'touchstart', respondToTouch);
  1024. addEvent(window, 'resize', CCPopupMenu.hideActiveMenu);
  1025. //add this event handler to prebuild the drop downs for the page
  1026. addEvent(window, 'load', CCPopupMenu.createDropDowns);