/hudson-war/src/main/webapp/scripts/yui/menu/menu-debug.js

http://github.com/hudson/hudson · JavaScript · 2598 lines · 981 code · 895 blank · 722 comment · 214 complexity · 02ce98fb12a81dca9942333550fa7f57 MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. Copyright (c) 2008, Yahoo! Inc. All rights reserved.
  3. Code licensed under the BSD License:
  4. http://developer.yahoo.net/yui/license.txt
  5. version: 2.5.1
  6. */
  7. /**
  8. * @module menu
  9. * @description <p>The Menu family of components features a collection of
  10. * controls that make it easy to add menus to your website or web application.
  11. * With the Menu Controls you can create website fly-out menus, customized
  12. * context menus, or application-style menu bars with just a small amount of
  13. * scripting.</p><p>The Menu family of controls features:</p>
  14. * <ul>
  15. * <li>Keyboard and mouse navigation.</li>
  16. * <li>A rich event model that provides access to all of a menu's
  17. * interesting moments.</li>
  18. * <li>Support for
  19. * <a href="http://en.wikipedia.org/wiki/Progressive_Enhancement">Progressive
  20. * Enhancement</a>; Menus can be created from simple,
  21. * semantic markup on the page or purely through JavaScript.</li>
  22. * </ul>
  23. * @title Menu
  24. * @namespace YAHOO.widget
  25. * @requires Event, Dom, Container
  26. */
  27. (function () {
  28. var Dom = YAHOO.util.Dom,
  29. Event = YAHOO.util.Event;
  30. /**
  31. * Singleton that manages a collection of all menus and menu items. Listens
  32. * for DOM events at the document level and dispatches the events to the
  33. * corresponding menu or menu item.
  34. *
  35. * @namespace YAHOO.widget
  36. * @class MenuManager
  37. * @static
  38. */
  39. YAHOO.widget.MenuManager = function () {
  40. // Private member variables
  41. // Flag indicating if the DOM event handlers have been attached
  42. var m_bInitializedEventHandlers = false,
  43. // Collection of menus
  44. m_oMenus = {},
  45. // Collection of visible menus
  46. m_oVisibleMenus = {},
  47. // Collection of menu items
  48. m_oItems = {},
  49. // Map of DOM event types to their equivalent CustomEvent types
  50. m_oEventTypes = {
  51. "click": "clickEvent",
  52. "mousedown": "mouseDownEvent",
  53. "mouseup": "mouseUpEvent",
  54. "mouseover": "mouseOverEvent",
  55. "mouseout": "mouseOutEvent",
  56. "keydown": "keyDownEvent",
  57. "keyup": "keyUpEvent",
  58. "keypress": "keyPressEvent"
  59. },
  60. m_oFocusedMenuItem = null;
  61. var m_oLogger = new YAHOO.widget.LogWriter("MenuManager");
  62. // Private methods
  63. /**
  64. * @method getMenuRootElement
  65. * @description Finds the root DIV node of a menu or the root LI node of
  66. * a menu item.
  67. * @private
  68. * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
  69. * level-one-html.html#ID-58190037">HTMLElement</a>} p_oElement Object
  70. * specifying an HTML element.
  71. */
  72. function getMenuRootElement(p_oElement) {
  73. var oParentNode;
  74. if (p_oElement && p_oElement.tagName) {
  75. switch (p_oElement.tagName.toUpperCase()) {
  76. case "DIV":
  77. oParentNode = p_oElement.parentNode;
  78. // Check if the DIV is the inner "body" node of a menu
  79. if (
  80. (
  81. Dom.hasClass(p_oElement, "hd") ||
  82. Dom.hasClass(p_oElement, "bd") ||
  83. Dom.hasClass(p_oElement, "ft")
  84. ) &&
  85. oParentNode &&
  86. oParentNode.tagName &&
  87. oParentNode.tagName.toUpperCase() == "DIV")
  88. {
  89. return oParentNode;
  90. }
  91. else {
  92. return p_oElement;
  93. }
  94. break;
  95. case "LI":
  96. return p_oElement;
  97. default:
  98. oParentNode = p_oElement.parentNode;
  99. if (oParentNode) {
  100. return getMenuRootElement(oParentNode);
  101. }
  102. break;
  103. }
  104. }
  105. }
  106. // Private event handlers
  107. /**
  108. * @method onDOMEvent
  109. * @description Generic, global event handler for all of a menu's
  110. * DOM-based events. This listens for events against the document
  111. * object. If the target of a given event is a member of a menu or
  112. * menu item's DOM, the instance's corresponding Custom Event is fired.
  113. * @private
  114. * @param {Event} p_oEvent Object representing the DOM event object
  115. * passed back by the event utility (YAHOO.util.Event).
  116. */
  117. function onDOMEvent(p_oEvent) {
  118. // Get the target node of the DOM event
  119. var oTarget = Event.getTarget(p_oEvent),
  120. // See if the target of the event was a menu, or a menu item
  121. oElement = getMenuRootElement(oTarget),
  122. sCustomEventType,
  123. sTagName,
  124. sId,
  125. oMenuItem,
  126. oMenu;
  127. if (oElement) {
  128. sTagName = oElement.tagName.toUpperCase();
  129. if (sTagName == "LI") {
  130. sId = oElement.id;
  131. if (sId && m_oItems[sId]) {
  132. oMenuItem = m_oItems[sId];
  133. oMenu = oMenuItem.parent;
  134. }
  135. }
  136. else if (sTagName == "DIV") {
  137. if (oElement.id) {
  138. oMenu = m_oMenus[oElement.id];
  139. }
  140. }
  141. }
  142. if (oMenu) {
  143. sCustomEventType = m_oEventTypes[p_oEvent.type];
  144. // Fire the Custom Event that corresponds the current DOM event
  145. if (oMenuItem && !oMenuItem.cfg.getProperty("disabled")) {
  146. oMenuItem[sCustomEventType].fire(p_oEvent);
  147. if (
  148. p_oEvent.type == "keyup" ||
  149. p_oEvent.type == "mousedown")
  150. {
  151. if (m_oFocusedMenuItem != oMenuItem) {
  152. if (m_oFocusedMenuItem) {
  153. m_oFocusedMenuItem.blurEvent.fire();
  154. }
  155. oMenuItem.focusEvent.fire();
  156. }
  157. }
  158. }
  159. oMenu[sCustomEventType].fire(p_oEvent, oMenuItem);
  160. }
  161. else if (p_oEvent.type == "mousedown") {
  162. if (m_oFocusedMenuItem) {
  163. m_oFocusedMenuItem.blurEvent.fire();
  164. m_oFocusedMenuItem = null;
  165. }
  166. /*
  167. If the target of the event wasn't a menu, hide all
  168. dynamically positioned menus
  169. */
  170. for (var i in m_oVisibleMenus) {
  171. if (YAHOO.lang.hasOwnProperty(m_oVisibleMenus, i)) {
  172. oMenu = m_oVisibleMenus[i];
  173. if (oMenu.cfg.getProperty("clicktohide") &&
  174. !(oMenu instanceof YAHOO.widget.MenuBar) &&
  175. oMenu.cfg.getProperty("position") == "dynamic") {
  176. oMenu.hide();
  177. }
  178. else {
  179. oMenu.clearActiveItem(true);
  180. }
  181. }
  182. }
  183. }
  184. else if (p_oEvent.type == "keyup") {
  185. if (m_oFocusedMenuItem) {
  186. m_oFocusedMenuItem.blurEvent.fire();
  187. m_oFocusedMenuItem = null;
  188. }
  189. }
  190. }
  191. /**
  192. * @method onMenuDestroy
  193. * @description "destroy" event handler for a menu.
  194. * @private
  195. * @param {String} p_sType String representing the name of the event
  196. * that was fired.
  197. * @param {Array} p_aArgs Array of arguments sent when the event
  198. * was fired.
  199. * @param {YAHOO.widget.Menu} p_oMenu The menu that fired the event.
  200. */
  201. function onMenuDestroy(p_sType, p_aArgs, p_oMenu) {
  202. if (m_oMenus[p_oMenu.id]) {
  203. this.removeMenu(p_oMenu);
  204. }
  205. }
  206. /**
  207. * @method onMenuFocus
  208. * @description "focus" event handler for a MenuItem instance.
  209. * @private
  210. * @param {String} p_sType String representing the name of the event
  211. * that was fired.
  212. * @param {Array} p_aArgs Array of arguments sent when the event
  213. * was fired.
  214. */
  215. function onMenuFocus(p_sType, p_aArgs) {
  216. var oItem = p_aArgs[0];
  217. if (oItem) {
  218. m_oFocusedMenuItem = oItem;
  219. }
  220. }
  221. /**
  222. * @method onMenuBlur
  223. * @description "blur" event handler for a MenuItem instance.
  224. * @private
  225. * @param {String} p_sType String representing the name of the event
  226. * that was fired.
  227. * @param {Array} p_aArgs Array of arguments sent when the event
  228. * was fired.
  229. */
  230. function onMenuBlur(p_sType, p_aArgs) {
  231. m_oFocusedMenuItem = null;
  232. }
  233. /**
  234. * @method onMenuVisibleConfigChange
  235. * @description Event handler for when the "visible" configuration
  236. * property of a Menu instance changes.
  237. * @private
  238. * @param {String} p_sType String representing the name of the event
  239. * that was fired.
  240. * @param {Array} p_aArgs Array of arguments sent when the event
  241. * was fired.
  242. */
  243. function onMenuVisibleConfigChange(p_sType, p_aArgs) {
  244. var bVisible = p_aArgs[0],
  245. sId = this.id;
  246. if (bVisible) {
  247. m_oVisibleMenus[sId] = this;
  248. m_oLogger.log(
  249. this +
  250. " added to the collection of visible menus.");
  251. }
  252. else if (m_oVisibleMenus[sId]) {
  253. delete m_oVisibleMenus[sId];
  254. m_oLogger.log(
  255. this +
  256. " removed from the collection of visible menus.");
  257. }
  258. }
  259. /**
  260. * @method onItemDestroy
  261. * @description "destroy" event handler for a MenuItem instance.
  262. * @private
  263. * @param {String} p_sType String representing the name of the event
  264. * that was fired.
  265. * @param {Array} p_aArgs Array of arguments sent when the event
  266. * was fired.
  267. */
  268. function onItemDestroy(p_sType, p_aArgs) {
  269. removeItem(this);
  270. }
  271. function removeItem(p_oMenuItem) {
  272. var sId = p_oMenuItem.id;
  273. if (sId && m_oItems[sId]) {
  274. if (m_oFocusedMenuItem == p_oMenuItem) {
  275. m_oFocusedMenuItem = null;
  276. }
  277. delete m_oItems[sId];
  278. p_oMenuItem.destroyEvent.unsubscribe(onItemDestroy);
  279. m_oLogger.log(p_oMenuItem + " successfully unregistered.");
  280. }
  281. }
  282. /**
  283. * @method onItemAdded
  284. * @description "itemadded" event handler for a Menu instance.
  285. * @private
  286. * @param {String} p_sType String representing the name of the event
  287. * that was fired.
  288. * @param {Array} p_aArgs Array of arguments sent when the event
  289. * was fired.
  290. */
  291. function onItemAdded(p_sType, p_aArgs) {
  292. var oItem = p_aArgs[0],
  293. sId;
  294. if (oItem instanceof YAHOO.widget.MenuItem) {
  295. sId = oItem.id;
  296. if (!m_oItems[sId]) {
  297. m_oItems[sId] = oItem;
  298. oItem.destroyEvent.subscribe(onItemDestroy);
  299. m_oLogger.log(oItem + " successfully registered.");
  300. }
  301. }
  302. }
  303. return {
  304. // Privileged methods
  305. /**
  306. * @method addMenu
  307. * @description Adds a menu to the collection of known menus.
  308. * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
  309. * instance to be added.
  310. */
  311. addMenu: function (p_oMenu) {
  312. var oDoc;
  313. if (p_oMenu instanceof YAHOO.widget.Menu && p_oMenu.id &&
  314. !m_oMenus[p_oMenu.id]) {
  315. m_oMenus[p_oMenu.id] = p_oMenu;
  316. if (!m_bInitializedEventHandlers) {
  317. oDoc = document;
  318. Event.on(oDoc, "mouseover", onDOMEvent, this, true);
  319. Event.on(oDoc, "mouseout", onDOMEvent, this, true);
  320. Event.on(oDoc, "mousedown", onDOMEvent, this, true);
  321. Event.on(oDoc, "mouseup", onDOMEvent, this, true);
  322. Event.on(oDoc, "click", onDOMEvent, this, true);
  323. Event.on(oDoc, "keydown", onDOMEvent, this, true);
  324. Event.on(oDoc, "keyup", onDOMEvent, this, true);
  325. Event.on(oDoc, "keypress", onDOMEvent, this, true);
  326. m_bInitializedEventHandlers = true;
  327. m_oLogger.log("DOM event handlers initialized.");
  328. }
  329. p_oMenu.cfg.subscribeToConfigEvent("visible",
  330. onMenuVisibleConfigChange);
  331. p_oMenu.destroyEvent.subscribe(onMenuDestroy, p_oMenu,
  332. this);
  333. p_oMenu.itemAddedEvent.subscribe(onItemAdded);
  334. p_oMenu.focusEvent.subscribe(onMenuFocus);
  335. p_oMenu.blurEvent.subscribe(onMenuBlur);
  336. m_oLogger.log(p_oMenu + " successfully registered.");
  337. }
  338. },
  339. /**
  340. * @method removeMenu
  341. * @description Removes a menu from the collection of known menus.
  342. * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
  343. * instance to be removed.
  344. */
  345. removeMenu: function (p_oMenu) {
  346. var sId,
  347. aItems,
  348. i;
  349. if (p_oMenu) {
  350. sId = p_oMenu.id;
  351. if (m_oMenus[sId] == p_oMenu) {
  352. // Unregister each menu item
  353. aItems = p_oMenu.getItems();
  354. if (aItems && aItems.length > 0) {
  355. i = aItems.length - 1;
  356. do {
  357. removeItem(aItems[i]);
  358. }
  359. while (i--);
  360. }
  361. // Unregister the menu
  362. delete m_oMenus[sId];
  363. m_oLogger.log(p_oMenu + " successfully unregistered.");
  364. /*
  365. Unregister the menu from the collection of
  366. visible menus
  367. */
  368. if (m_oVisibleMenus[sId] == p_oMenu) {
  369. delete m_oVisibleMenus[sId];
  370. m_oLogger.log(p_oMenu + " unregistered from the" +
  371. " collection of visible menus.");
  372. }
  373. // Unsubscribe event listeners
  374. if (p_oMenu.cfg) {
  375. p_oMenu.cfg.unsubscribeFromConfigEvent("visible",
  376. onMenuVisibleConfigChange);
  377. }
  378. p_oMenu.destroyEvent.unsubscribe(onMenuDestroy,
  379. p_oMenu);
  380. p_oMenu.itemAddedEvent.unsubscribe(onItemAdded);
  381. p_oMenu.focusEvent.unsubscribe(onMenuFocus);
  382. p_oMenu.blurEvent.unsubscribe(onMenuBlur);
  383. }
  384. }
  385. },
  386. /**
  387. * @method hideVisible
  388. * @description Hides all visible, dynamically positioned menus
  389. * (excluding instances of YAHOO.widget.MenuBar).
  390. */
  391. hideVisible: function () {
  392. var oMenu;
  393. for (var i in m_oVisibleMenus) {
  394. if (YAHOO.lang.hasOwnProperty(m_oVisibleMenus, i)) {
  395. oMenu = m_oVisibleMenus[i];
  396. if (!(oMenu instanceof YAHOO.widget.MenuBar) &&
  397. oMenu.cfg.getProperty("position") == "dynamic") {
  398. oMenu.hide();
  399. }
  400. }
  401. }
  402. },
  403. /**
  404. * @method getVisible
  405. * @description Returns a collection of all visible menus registered
  406. * with the menu manger.
  407. * @return {Array}
  408. */
  409. getVisible: function () {
  410. return m_oVisibleMenus;
  411. },
  412. /**
  413. * @method getMenus
  414. * @description Returns a collection of all menus registered with the
  415. * menu manger.
  416. * @return {Array}
  417. */
  418. getMenus: function () {
  419. return m_oMenus;
  420. },
  421. /**
  422. * @method getMenu
  423. * @description Returns a menu with the specified id.
  424. * @param {String} p_sId String specifying the id of the
  425. * <code>&#60;div&#62;</code> element representing the menu to
  426. * be retrieved.
  427. * @return {YAHOO.widget.Menu}
  428. */
  429. getMenu: function (p_sId) {
  430. var oMenu = m_oMenus[p_sId];
  431. if (oMenu) {
  432. return oMenu;
  433. }
  434. },
  435. /**
  436. * @method getMenuItem
  437. * @description Returns a menu item with the specified id.
  438. * @param {String} p_sId String specifying the id of the
  439. * <code>&#60;li&#62;</code> element representing the menu item to
  440. * be retrieved.
  441. * @return {YAHOO.widget.MenuItem}
  442. */
  443. getMenuItem: function (p_sId) {
  444. var oItem = m_oItems[p_sId];
  445. if (oItem) {
  446. return oItem;
  447. }
  448. },
  449. /**
  450. * @method getMenuItemGroup
  451. * @description Returns an array of menu item instances whose
  452. * corresponding <code>&#60;li&#62;</code> elements are child
  453. * nodes of the <code>&#60;ul&#62;</code> element with the
  454. * specified id.
  455. * @param {String} p_sId String specifying the id of the
  456. * <code>&#60;ul&#62;</code> element representing the group of
  457. * menu items to be retrieved.
  458. * @return {Array}
  459. */
  460. getMenuItemGroup: function (p_sId) {
  461. var oUL = Dom.get(p_sId),
  462. aItems,
  463. oNode,
  464. oItem,
  465. sId;
  466. if (oUL && oUL.tagName &&
  467. oUL.tagName.toUpperCase() == "UL") {
  468. oNode = oUL.firstChild;
  469. if (oNode) {
  470. aItems = [];
  471. do {
  472. sId = oNode.id;
  473. if (sId) {
  474. oItem = this.getMenuItem(sId);
  475. if (oItem) {
  476. aItems[aItems.length] = oItem;
  477. }
  478. }
  479. }
  480. while ((oNode = oNode.nextSibling));
  481. if (aItems.length > 0) {
  482. return aItems;
  483. }
  484. }
  485. }
  486. },
  487. /**
  488. * @method getFocusedMenuItem
  489. * @description Returns a reference to the menu item that currently
  490. * has focus.
  491. * @return {YAHOO.widget.MenuItem}
  492. */
  493. getFocusedMenuItem: function () {
  494. return m_oFocusedMenuItem;
  495. },
  496. /**
  497. * @method getFocusedMenu
  498. * @description Returns a reference to the menu that currently
  499. * has focus.
  500. * @return {YAHOO.widget.Menu}
  501. */
  502. getFocusedMenu: function () {
  503. if (m_oFocusedMenuItem) {
  504. return (m_oFocusedMenuItem.parent.getRoot());
  505. }
  506. },
  507. /**
  508. * @method toString
  509. * @description Returns a string representing the menu manager.
  510. * @return {String}
  511. */
  512. toString: function () {
  513. return "MenuManager";
  514. }
  515. };
  516. }();
  517. })();
  518. (function () {
  519. /**
  520. * The Menu class creates a container that holds a vertical list representing
  521. * a set of options or commands. Menu is the base class for all
  522. * menu containers.
  523. * @param {String} p_oElement String specifying the id attribute of the
  524. * <code>&#60;div&#62;</code> element of the menu.
  525. * @param {String} p_oElement String specifying the id attribute of the
  526. * <code>&#60;select&#62;</code> element to be used as the data source
  527. * for the menu.
  528. * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
  529. * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
  530. * specifying the <code>&#60;div&#62;</code> element of the menu.
  531. * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
  532. * level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
  533. * Object specifying the <code>&#60;select&#62;</code> element to be used as
  534. * the data source for the menu.
  535. * @param {Object} p_oConfig Optional. Object literal specifying the
  536. * configuration for the menu. See configuration class documentation for
  537. * more details.
  538. * @namespace YAHOO.widget
  539. * @class Menu
  540. * @constructor
  541. * @extends YAHOO.widget.Overlay
  542. */
  543. YAHOO.widget.Menu = function (p_oElement, p_oConfig) {
  544. if (p_oConfig) {
  545. this.parent = p_oConfig.parent;
  546. this.lazyLoad = p_oConfig.lazyLoad || p_oConfig.lazyload;
  547. this.itemData = p_oConfig.itemData || p_oConfig.itemdata;
  548. }
  549. YAHOO.widget.Menu.superclass.constructor.call(this, p_oElement, p_oConfig);
  550. };
  551. /**
  552. * @method checkPosition
  553. * @description Checks to make sure that the value of the "position" property
  554. * is one of the supported strings. Returns true if the position is supported.
  555. * @private
  556. * @param {Object} p_sPosition String specifying the position of the menu.
  557. * @return {Boolean}
  558. */
  559. function checkPosition(p_sPosition) {
  560. if (typeof p_sPosition == "string") {
  561. return ("dynamic,static".indexOf((p_sPosition.toLowerCase())) != -1);
  562. }
  563. }
  564. var Dom = YAHOO.util.Dom,
  565. Event = YAHOO.util.Event,
  566. Module = YAHOO.widget.Module,
  567. Overlay = YAHOO.widget.Overlay,
  568. Menu = YAHOO.widget.Menu,
  569. MenuManager = YAHOO.widget.MenuManager,
  570. CustomEvent = YAHOO.util.CustomEvent,
  571. Lang = YAHOO.lang,
  572. UA = YAHOO.env.ua,
  573. m_oShadowTemplate,
  574. /**
  575. * Constant representing the name of the Menu's events
  576. * @property EVENT_TYPES
  577. * @private
  578. * @final
  579. * @type Object
  580. */
  581. EVENT_TYPES = {
  582. "MOUSE_OVER": "mouseover",
  583. "MOUSE_OUT": "mouseout",
  584. "MOUSE_DOWN": "mousedown",
  585. "MOUSE_UP": "mouseup",
  586. "CLICK": "click",
  587. "KEY_PRESS": "keypress",
  588. "KEY_DOWN": "keydown",
  589. "KEY_UP": "keyup",
  590. "FOCUS": "focus",
  591. "BLUR": "blur",
  592. "ITEM_ADDED": "itemAdded",
  593. "ITEM_REMOVED": "itemRemoved"
  594. },
  595. /**
  596. * Constant representing the Menu's configuration properties
  597. * @property DEFAULT_CONFIG
  598. * @private
  599. * @final
  600. * @type Object
  601. */
  602. DEFAULT_CONFIG = {
  603. "VISIBLE": {
  604. key: "visible",
  605. value: false,
  606. validator: Lang.isBoolean
  607. },
  608. "CONSTRAIN_TO_VIEWPORT": {
  609. key: "constraintoviewport",
  610. value: true,
  611. validator: Lang.isBoolean,
  612. supercedes: ["iframe","x","y","xy"]
  613. },
  614. "POSITION": {
  615. key: "position",
  616. value: "dynamic",
  617. validator: checkPosition,
  618. supercedes: ["visible", "iframe"]
  619. },
  620. "SUBMENU_ALIGNMENT": {
  621. key: "submenualignment",
  622. value: ["tl","tr"],
  623. suppressEvent: true
  624. },
  625. "AUTO_SUBMENU_DISPLAY": {
  626. key: "autosubmenudisplay",
  627. value: true,
  628. validator: Lang.isBoolean,
  629. suppressEvent: true
  630. },
  631. "SHOW_DELAY": {
  632. key: "showdelay",
  633. value: 250,
  634. validator: Lang.isNumber,
  635. suppressEvent: true
  636. },
  637. "HIDE_DELAY": {
  638. key: "hidedelay",
  639. value: 0,
  640. validator: Lang.isNumber,
  641. suppressEvent: true
  642. },
  643. "SUBMENU_HIDE_DELAY": {
  644. key: "submenuhidedelay",
  645. value: 250,
  646. validator: Lang.isNumber,
  647. suppressEvent: true
  648. },
  649. "CLICK_TO_HIDE": {
  650. key: "clicktohide",
  651. value: true,
  652. validator: Lang.isBoolean,
  653. suppressEvent: true
  654. },
  655. "CONTAINER": {
  656. key: "container",
  657. suppressEvent: true
  658. },
  659. "SCROLL_INCREMENT": {
  660. key: "scrollincrement",
  661. value: 1,
  662. validator: Lang.isNumber,
  663. supercedes: ["maxheight"],
  664. suppressEvent: true
  665. },
  666. "MIN_SCROLL_HEIGHT": {
  667. key: "minscrollheight",
  668. value: 90,
  669. validator: Lang.isNumber,
  670. supercedes: ["maxheight"],
  671. suppressEvent: true
  672. },
  673. "MAX_HEIGHT": {
  674. key: "maxheight",
  675. value: 0,
  676. validator: Lang.isNumber,
  677. supercedes: ["iframe"],
  678. suppressEvent: true
  679. },
  680. "CLASS_NAME": {
  681. key: "classname",
  682. value: null,
  683. validator: Lang.isString,
  684. suppressEvent: true
  685. },
  686. "DISABLED": {
  687. key: "disabled",
  688. value: false,
  689. validator: Lang.isBoolean,
  690. suppressEvent: true
  691. }
  692. };
  693. YAHOO.lang.extend(Menu, Overlay, {
  694. // Constants
  695. /**
  696. * @property CSS_CLASS_NAME
  697. * @description String representing the CSS class(es) to be applied to the
  698. * menu's <code>&#60;div&#62;</code> element.
  699. * @default "yuimenu"
  700. * @final
  701. * @type String
  702. */
  703. CSS_CLASS_NAME: "yuimenu",
  704. /**
  705. * @property ITEM_TYPE
  706. * @description Object representing the type of menu item to instantiate and
  707. * add when parsing the child nodes (either <code>&#60;li&#62;</code> element,
  708. * <code>&#60;optgroup&#62;</code> element or <code>&#60;option&#62;</code>)
  709. * of the menu's source HTML element.
  710. * @default YAHOO.widget.MenuItem
  711. * @final
  712. * @type YAHOO.widget.MenuItem
  713. */
  714. ITEM_TYPE: null,
  715. /**
  716. * @property GROUP_TITLE_TAG_NAME
  717. * @description String representing the tagname of the HTML element used to
  718. * title the menu's item groups.
  719. * @default H6
  720. * @final
  721. * @type String
  722. */
  723. GROUP_TITLE_TAG_NAME: "h6",
  724. /**
  725. * @property OFF_SCREEN_POSITION
  726. * @description Array representing the default x and y position that a menu
  727. * should have when it is positioned outside the viewport by the
  728. * "poistionOffScreen" method.
  729. * @default [-10000, -10000]
  730. * @final
  731. * @type Array
  732. */
  733. OFF_SCREEN_POSITION: [-10000, -10000],
  734. // Private properties
  735. /**
  736. * @property _nHideDelayId
  737. * @description Number representing the time-out setting used to cancel the
  738. * hiding of a menu.
  739. * @default null
  740. * @private
  741. * @type Number
  742. */
  743. _nHideDelayId: null,
  744. /**
  745. * @property _nShowDelayId
  746. * @description Number representing the time-out setting used to cancel the
  747. * showing of a menu.
  748. * @default null
  749. * @private
  750. * @type Number
  751. */
  752. _nShowDelayId: null,
  753. /**
  754. * @property _nSubmenuHideDelayId
  755. * @description Number representing the time-out setting used to cancel the
  756. * hiding of a submenu.
  757. * @default null
  758. * @private
  759. * @type Number
  760. */
  761. _nSubmenuHideDelayId: null,
  762. /**
  763. * @property _nBodyScrollId
  764. * @description Number representing the time-out setting used to cancel the
  765. * scrolling of the menu's body element.
  766. * @default null
  767. * @private
  768. * @type Number
  769. */
  770. _nBodyScrollId: null,
  771. /**
  772. * @property _bHideDelayEventHandlersAssigned
  773. * @description Boolean indicating if the "mouseover" and "mouseout" event
  774. * handlers used for hiding the menu via a call to "window.setTimeout" have
  775. * already been assigned.
  776. * @default false
  777. * @private
  778. * @type Boolean
  779. */
  780. _bHideDelayEventHandlersAssigned: false,
  781. /**
  782. * @property _bHandledMouseOverEvent
  783. * @description Boolean indicating the current state of the menu's
  784. * "mouseover" event.
  785. * @default false
  786. * @private
  787. * @type Boolean
  788. */
  789. _bHandledMouseOverEvent: false,
  790. /**
  791. * @property _bHandledMouseOutEvent
  792. * @description Boolean indicating the current state of the menu's
  793. * "mouseout" event.
  794. * @default false
  795. * @private
  796. * @type Boolean
  797. */
  798. _bHandledMouseOutEvent: false,
  799. /**
  800. * @property _aGroupTitleElements
  801. * @description Array of HTML element used to title groups of menu items.
  802. * @default []
  803. * @private
  804. * @type Array
  805. */
  806. _aGroupTitleElements: null,
  807. /**
  808. * @property _aItemGroups
  809. * @description Multi-dimensional Array representing the menu items as they
  810. * are grouped in the menu.
  811. * @default []
  812. * @private
  813. * @type Array
  814. */
  815. _aItemGroups: null,
  816. /**
  817. * @property _aListElements
  818. * @description Array of <code>&#60;ul&#62;</code> elements, each of which is
  819. * the parent node for each item's <code>&#60;li&#62;</code> element.
  820. * @default []
  821. * @private
  822. * @type Array
  823. */
  824. _aListElements: null,
  825. /**
  826. * @property _nCurrentMouseX
  827. * @description The current x coordinate of the mouse inside the area of
  828. * the menu.
  829. * @default 0
  830. * @private
  831. * @type Number
  832. */
  833. _nCurrentMouseX: 0,
  834. /**
  835. * @property _bStopMouseEventHandlers
  836. * @description Stops "mouseover," "mouseout," and "mousemove" event handlers
  837. * from executing.
  838. * @default false
  839. * @private
  840. * @type Boolean
  841. */
  842. _bStopMouseEventHandlers: false,
  843. /**
  844. * @property _sClassName
  845. * @description The current value of the "classname" configuration attribute.
  846. * @default null
  847. * @private
  848. * @type String
  849. */
  850. _sClassName: null,
  851. // Public properties
  852. /**
  853. * @property lazyLoad
  854. * @description Boolean indicating if the menu's "lazy load" feature is
  855. * enabled. If set to "true," initialization and rendering of the menu's
  856. * items will be deferred until the first time it is made visible. This
  857. * property should be set via the constructor using the configuration
  858. * object literal.
  859. * @default false
  860. * @type Boolean
  861. */
  862. lazyLoad: false,
  863. /**
  864. * @property itemData
  865. * @description Array of items to be added to the menu. The array can contain
  866. * strings representing the text for each item to be created, object literals
  867. * representing the menu item configuration properties, or MenuItem instances.
  868. * This property should be set via the constructor using the configuration
  869. * object literal.
  870. * @default null
  871. * @type Array
  872. */
  873. itemData: null,
  874. /**
  875. * @property activeItem
  876. * @description Object reference to the item in the menu that has is selected.
  877. * @default null
  878. * @type YAHOO.widget.MenuItem
  879. */
  880. activeItem: null,
  881. /**
  882. * @property parent
  883. * @description Object reference to the menu's parent menu or menu item.
  884. * This property can be set via the constructor using the configuration
  885. * object literal.
  886. * @default null
  887. * @type YAHOO.widget.MenuItem
  888. */
  889. parent: null,
  890. /**
  891. * @property srcElement
  892. * @description Object reference to the HTML element (either
  893. * <code>&#60;select&#62;</code> or <code>&#60;div&#62;</code>) used to
  894. * create the menu.
  895. * @default null
  896. * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
  897. * level-one-html.html#ID-94282980">HTMLSelectElement</a>|<a
  898. * href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.
  899. * html#ID-22445964">HTMLDivElement</a>
  900. */
  901. srcElement: null,
  902. // Events
  903. /**
  904. * @event mouseOverEvent
  905. * @description Fires when the mouse has entered the menu. Passes back
  906. * the DOM Event object as an argument.
  907. */
  908. mouseOverEvent: null,
  909. /**
  910. * @event mouseOutEvent
  911. * @description Fires when the mouse has left the menu. Passes back the DOM
  912. * Event object as an argument.
  913. * @type YAHOO.util.CustomEvent
  914. */
  915. mouseOutEvent: null,
  916. /**
  917. * @event mouseDownEvent
  918. * @description Fires when the user mouses down on the menu. Passes back the
  919. * DOM Event object as an argument.
  920. * @type YAHOO.util.CustomEvent
  921. */
  922. mouseDownEvent: null,
  923. /**
  924. * @event mouseUpEvent
  925. * @description Fires when the user releases a mouse button while the mouse is
  926. * over the menu. Passes back the DOM Event object as an argument.
  927. * @type YAHOO.util.CustomEvent
  928. */
  929. mouseUpEvent: null,
  930. /**
  931. * @event clickEvent
  932. * @description Fires when the user clicks the on the menu. Passes back the
  933. * DOM Event object as an argument.
  934. * @type YAHOO.util.CustomEvent
  935. */
  936. clickEvent: null,
  937. /**
  938. * @event keyPressEvent
  939. * @description Fires when the user presses an alphanumeric key when one of the
  940. * menu's items has focus. Passes back the DOM Event object as an argument.
  941. * @type YAHOO.util.CustomEvent
  942. */
  943. keyPressEvent: null,
  944. /**
  945. * @event keyDownEvent
  946. * @description Fires when the user presses a key when one of the menu's items
  947. * has focus. Passes back the DOM Event object as an argument.
  948. * @type YAHOO.util.CustomEvent
  949. */
  950. keyDownEvent: null,
  951. /**
  952. * @event keyUpEvent
  953. * @description Fires when the user releases a key when one of the menu's items
  954. * has focus. Passes back the DOM Event object as an argument.
  955. * @type YAHOO.util.CustomEvent
  956. */
  957. keyUpEvent: null,
  958. /**
  959. * @event itemAddedEvent
  960. * @description Fires when an item is added to the menu.
  961. * @type YAHOO.util.CustomEvent
  962. */
  963. itemAddedEvent: null,
  964. /**
  965. * @event itemRemovedEvent
  966. * @description Fires when an item is removed to the menu.
  967. * @type YAHOO.util.CustomEvent
  968. */
  969. itemRemovedEvent: null,
  970. /**
  971. * @method init
  972. * @description The Menu class's initialization method. This method is
  973. * automatically called by the constructor, and sets up all DOM references
  974. * for pre-existing markup, and creates required markup if it is not
  975. * already present.
  976. * @param {String} p_oElement String specifying the id attribute of the
  977. * <code>&#60;div&#62;</code> element of the menu.
  978. * @param {String} p_oElement String specifying the id attribute of the
  979. * <code>&#60;select&#62;</code> element to be used as the data source
  980. * for the menu.
  981. * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
  982. * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
  983. * specifying the <code>&#60;div&#62;</code> element of the menu.
  984. * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
  985. * level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
  986. * Object specifying the <code>&#60;select&#62;</code> element to be used as
  987. * the data source for the menu.
  988. * @param {Object} p_oConfig Optional. Object literal specifying the
  989. * configuration for the menu. See configuration class documentation for
  990. * more details.
  991. */
  992. init: function (p_oElement, p_oConfig) {
  993. this._aItemGroups = [];
  994. this._aListElements = [];
  995. this._aGroupTitleElements = [];
  996. if (!this.ITEM_TYPE) {
  997. this.ITEM_TYPE = YAHOO.widget.MenuItem;
  998. }
  999. var oElement;
  1000. if (typeof p_oElement == "string") {
  1001. oElement = document.getElementById(p_oElement);
  1002. }
  1003. else if (p_oElement.tagName) {
  1004. oElement = p_oElement;
  1005. }
  1006. if (oElement && oElement.tagName) {
  1007. switch(oElement.tagName.toUpperCase()) {
  1008. case "DIV":
  1009. this.srcElement = oElement;
  1010. if (!oElement.id) {
  1011. oElement.setAttribute("id", Dom.generateId());
  1012. }
  1013. /*
  1014. Note: we don't pass the user config in here yet
  1015. because we only want it executed once, at the lowest
  1016. subclass level.
  1017. */
  1018. Menu.superclass.init.call(this, oElement);
  1019. this.beforeInitEvent.fire(Menu);
  1020. this.logger = new YAHOO.widget.LogWriter(this.toString());
  1021. this.logger.log("Source element: " + this.srcElement.tagName);
  1022. break;
  1023. case "SELECT":
  1024. this.srcElement = oElement;
  1025. /*
  1026. The source element is not something that we can use
  1027. outright, so we need to create a new Overlay
  1028. Note: we don't pass the user config in here yet
  1029. because we only want it executed once, at the lowest
  1030. subclass level.
  1031. */
  1032. Menu.superclass.init.call(this, Dom.generateId());
  1033. this.beforeInitEvent.fire(Menu);
  1034. this.logger = new YAHOO.widget.LogWriter(this.toString());
  1035. this.logger.log("Source element: " + this.srcElement.tagName);
  1036. break;
  1037. }
  1038. }
  1039. else {
  1040. /*
  1041. Note: we don't pass the user config in here yet
  1042. because we only want it executed once, at the lowest
  1043. subclass level.
  1044. */
  1045. Menu.superclass.init.call(this, p_oElement);
  1046. this.beforeInitEvent.fire(Menu);
  1047. this.logger = new YAHOO.widget.LogWriter(this.toString());
  1048. this.logger.log("No source element found. " +
  1049. "Created element with id: " + this.id);
  1050. }
  1051. if (this.element) {
  1052. Dom.addClass(this.element, this.CSS_CLASS_NAME);
  1053. // Subscribe to Custom Events
  1054. this.initEvent.subscribe(this._onInit);
  1055. this.beforeRenderEvent.subscribe(this._onBeforeRender);
  1056. this.renderEvent.subscribe(this._onRender);
  1057. this.renderEvent.subscribe(this.onRender);
  1058. this.beforeShowEvent.subscribe(this._onBeforeShow);
  1059. this.hideEvent.subscribe(this.positionOffScreen);
  1060. this.showEvent.subscribe(this._onShow);
  1061. this.beforeHideEvent.subscribe(this._onBeforeHide);
  1062. this.mouseOverEvent.subscribe(this._onMouseOver);
  1063. this.mouseOutEvent.subscribe(this._onMouseOut);
  1064. this.clickEvent.subscribe(this._onClick);
  1065. this.keyDownEvent.subscribe(this._onKeyDown);
  1066. this.keyPressEvent.subscribe(this._onKeyPress);
  1067. if (UA.gecko || UA.webkit) {
  1068. this.cfg.subscribeToConfigEvent("y", this._onYChange);
  1069. }
  1070. if (p_oConfig) {
  1071. this.cfg.applyConfig(p_oConfig, true);
  1072. }
  1073. // Register the Menu instance with the MenuManager
  1074. MenuManager.addMenu(this);
  1075. this.initEvent.fire(Menu);
  1076. }
  1077. },
  1078. // Private methods
  1079. /**
  1080. * @method _initSubTree
  1081. * @description Iterates the childNodes of the source element to find nodes
  1082. * used to instantiate menu and menu items.
  1083. * @private
  1084. */
  1085. _initSubTree: function () {
  1086. var oSrcElement = this.srcElement,
  1087. sSrcElementTagName,
  1088. nGroup,
  1089. sGroupTitleTagName,
  1090. oNode,
  1091. aListElements,
  1092. nListElements,
  1093. i;
  1094. if (oSrcElement) {
  1095. sSrcElementTagName =
  1096. (oSrcElement.tagName && oSrcElement.tagName.toUpperCase());
  1097. if (sSrcElementTagName == "DIV") {
  1098. // Populate the collection of item groups and item group titles
  1099. oNode = this.body.firstChild;
  1100. if (oNode) {
  1101. nGroup = 0;
  1102. sGroupTitleTagName = this.GROUP_TITLE_TAG_NAME.toUpperCase();
  1103. do {
  1104. if (oNode && oNode.tagName) {
  1105. switch (oNode.tagName.toUpperCase()) {
  1106. case sGroupTitleTagName:
  1107. this._aGroupTitleElements[nGroup] = oNode;
  1108. break;
  1109. case "UL":
  1110. this._aListElements[nGroup] = oNode;
  1111. this._aItemGroups[nGroup] = [];
  1112. nGroup++;
  1113. break;
  1114. }
  1115. }
  1116. }
  1117. while ((oNode = oNode.nextSibling));
  1118. /*
  1119. Apply the "first-of-type" class to the first UL to mimic
  1120. the "first-of-type" CSS3 psuedo class.
  1121. */
  1122. if (this._aListElements[0]) {
  1123. Dom.addClass(this._aListElements[0], "first-of-type");
  1124. }
  1125. }
  1126. }
  1127. oNode = null;
  1128. this.logger.log("Searching DOM for items to initialize.");
  1129. if (sSrcElementTagName) {
  1130. switch (sSrcElementTagName) {
  1131. case "DIV":
  1132. aListElements = this._aListElements;
  1133. nListElements = aListElements.length;
  1134. if (nListElements > 0) {
  1135. this.logger.log("Found " + nListElements +
  1136. " item groups to initialize.");
  1137. i = nListElements - 1;
  1138. do {
  1139. oNode = aListElements[i].firstChild;
  1140. if (oNode) {
  1141. this.logger.log("Scanning " +
  1142. aListElements[i].childNodes.length +
  1143. " child nodes for items to initialize.");
  1144. do {
  1145. if (oNode && oNode.tagName &&
  1146. oNode.tagName.toUpperCase() == "LI") {
  1147. this.logger.log("Initializing " +
  1148. oNode.tagName + " node.");
  1149. this.addItem(new this.ITEM_TYPE(oNode,
  1150. { parent: this }), i);
  1151. }
  1152. }
  1153. while ((oNode = oNode.nextSibling));
  1154. }
  1155. }
  1156. while (i--);
  1157. }
  1158. break;
  1159. case "SELECT":
  1160. this.logger.log("Scanning " +
  1161. oSrcElement.childNodes.length +
  1162. " child nodes for items to initialize.");
  1163. oNode = oSrcElement.firstChild;
  1164. do {
  1165. if (oNode && oNode.tagName) {
  1166. switch (oNode.tagName.toUpperCase()) {
  1167. case "OPTGROUP":
  1168. case "OPTION":
  1169. this.logger.log("Initializing " +
  1170. oNode.tagName + " node.");
  1171. this.addItem(
  1172. new this.ITEM_TYPE(
  1173. oNode,
  1174. { parent: this }
  1175. )
  1176. );
  1177. break;
  1178. }
  1179. }
  1180. }
  1181. while ((oNode = oNode.nextSibling));
  1182. break;
  1183. }
  1184. }
  1185. }
  1186. },
  1187. /**
  1188. * @method _getFirstEnabledItem
  1189. * @description Returns the first enabled item in the menu.
  1190. * @return {YAHOO.widget.MenuItem}
  1191. * @private
  1192. */
  1193. _getFirstEnabledItem: function () {
  1194. var aItems = this.getItems(),
  1195. nItems = aItems.length,
  1196. oItem;
  1197. for(var i=0; i<nItems; i++) {
  1198. oItem = aItems[i];
  1199. if (oItem && !oItem.cfg.getProperty("disabled") &&
  1200. oItem.element.style.display != "none") {
  1201. return oItem;
  1202. }
  1203. }
  1204. },
  1205. /**
  1206. * @method _addItemToGroup
  1207. * @description Adds a menu item to a group.
  1208. * @private
  1209. * @param {Number} p_nGroupIndex Number indicating the group to which the
  1210. * item belongs.
  1211. * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
  1212. * instance to be added to the menu.
  1213. * @param {String} p_oItem String specifying the text of the item to be added
  1214. * to the menu.
  1215. * @param {Object} p_oItem Object literal containing a set of menu item
  1216. * configuration properties.
  1217. * @param {Number} p_nItemIndex Optional. Number indicating the index at
  1218. * which the menu item should be added.
  1219. * @return {YAHOO.widget.MenuItem}
  1220. */
  1221. _addItemToGroup: function (p_nGroupIndex, p_oItem, p_nItemIndex) {
  1222. var oItem,
  1223. nGroupIndex,
  1224. aGroup,
  1225. oGroupItem,
  1226. bAppend,
  1227. oNextItemSibling,
  1228. nItemIndex;
  1229. function getNextItemSibling(p_aArray, p_nStartIndex) {
  1230. return (p_aArray[p_nStartIndex] || getNextItemSibling(p_aArray,
  1231. (p_nStartIndex+1)));
  1232. }
  1233. if (p_oItem instanceof this.ITEM_TYPE) {
  1234. oItem = p_oItem;
  1235. oItem.parent = this;
  1236. }
  1237. else if (typeof p_oItem == "string") {
  1238. oItem = new this.ITEM_TYPE(p_oItem, { parent: this });
  1239. }
  1240. else if (typeof p_oItem == "object") {
  1241. p_oItem.parent = this;
  1242. oItem = new this.ITEM_TYPE(p_oItem.text, p_oItem);
  1243. }
  1244. if (oItem) {
  1245. if (oItem.cfg.getProperty("selected")) {
  1246. this.activeItem = oItem;
  1247. }
  1248. nGroupIndex = typeof p_nGroupIndex == "number" ? p_nGroupIndex : 0;
  1249. aGroup = this._getItemGroup(nGroupIndex);
  1250. if (!aGroup) {
  1251. aGroup = this._createItemGroup(nGroupIndex);
  1252. }
  1253. if (typeof p_nItemIndex == "number") {
  1254. bAppend = (p_nItemIndex >= aGroup.length);
  1255. if (aGroup[p_nItemIndex]) {
  1256. aGroup.splice(p_nItemIndex, 0, oItem);
  1257. }
  1258. else {
  1259. aGroup[p_nItemIndex] = oItem;
  1260. }
  1261. oGroupItem = aGroup[p_nItemIndex];
  1262. if (oGroupItem) {
  1263. if (bAppend && (!oGroupItem.element.parentNode ||
  1264. oGroupItem.element.parentNode.nodeType == 11)) {
  1265. this._aListElements[nGroupIndex].appendChild(
  1266. oGroupItem.element);
  1267. }
  1268. else {
  1269. oNextItemSibling = getNextItemSibling(aGroup,
  1270. (p_nItemIndex+1));
  1271. if (oNextItemSibling && (!oGroupItem.element.parentNode ||