2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
11 * @description <p>The Menu family of components features a collection of
12 * controls that make it easy to add menus to your website or web application.
13 * With the Menu Controls you can create website fly-out menus, customized
14 * context menus, or application-style menu bars with just a small amount of
15 * scripting.</p><p>The Menu family of controls features:</p>
17 * <li>Keyboard and mouse navigation.</li>
18 * <li>A rich event model that provides access to all of a menu's
19 * interesting moments.</li>
21 * <a href="http://en.wikipedia.org/wiki/Progressive_Enhancement">Progressive
22 * Enhancement</a>; Menus can be created from simple,
23 * semantic markup on the page or purely through JavaScript.</li>
26 * @namespace YAHOO.widget
27 * @requires Event, Dom, Container
31 var UA = YAHOO.env.ua,
33 Event = YAHOO.util.Event,
41 _DISABLED = "disabled",
42 _MOUSEOVER = "mouseover",
43 _MOUSEOUT = "mouseout",
44 _MOUSEDOWN = "mousedown",
49 _KEYPRESS = "keypress",
50 _CLICK_TO_HIDE = "clicktohide",
51 _POSITION = "position",
53 _SHOW_DELAY = "showdelay",
54 _SELECTED = "selected",
57 _MENUMANAGER = "MenuManager";
61 * Singleton that manages a collection of all menus and menu items. Listens
62 * for DOM events at the document level and dispatches the events to the
63 * corresponding menu or menu item.
65 * @namespace YAHOO.widget
69 YAHOO.widget.MenuManager = function () {
71 // Private member variables
74 // Flag indicating if the DOM event handlers have been attached
76 var m_bInitializedEventHandlers = false,
79 // Collection of menus
84 // Collection of visible menus
89 // Collection of menu items
94 // Map of DOM event types to their equivalent CustomEvent types
97 "click": "clickEvent",
98 "mousedown": "mouseDownEvent",
99 "mouseup": "mouseUpEvent",
100 "mouseover": "mouseOverEvent",
101 "mouseout": "mouseOutEvent",
102 "keydown": "keyDownEvent",
103 "keyup": "keyUpEvent",
104 "keypress": "keyPressEvent",
105 "focus": "focusEvent",
106 "focusin": "focusEvent",
108 "focusout": "blurEvent"
112 m_oFocusedMenuItem = null;
120 * @method getMenuRootElement
121 * @description Finds the root DIV node of a menu or the root LI node of
124 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
125 * level-one-html.html#ID-58190037">HTMLElement</a>} p_oElement Object
126 * specifying an HTML element.
128 function getMenuRootElement(p_oElement) {
133 if (p_oElement && p_oElement.tagName) {
135 switch (p_oElement.tagName.toUpperCase()) {
139 oParentNode = p_oElement.parentNode;
141 // Check if the DIV is the inner "body" node of a menu
144 Dom.hasClass(p_oElement, _HD) ||
145 Dom.hasClass(p_oElement, _BD) ||
146 Dom.hasClass(p_oElement, _FT)
149 oParentNode.tagName &&
150 oParentNode.tagName.toUpperCase() == _DIV) {
152 returnVal = oParentNode;
157 returnVal = p_oElement;
165 returnVal = p_oElement;
171 oParentNode = p_oElement.parentNode;
175 returnVal = getMenuRootElement(oParentNode);
191 // Private event handlers
196 * @description Generic, global event handler for all of a menu's
197 * DOM-based events. This listens for events against the document
198 * object. If the target of a given event is a member of a menu or
199 * menu item's DOM, the instance's corresponding Custom Event is fired.
201 * @param {Event} p_oEvent Object representing the DOM event object
202 * passed back by the event utility (YAHOO.util.Event).
204 function onDOMEvent(p_oEvent) {
206 // Get the target node of the DOM event
208 var oTarget = Event.getTarget(p_oEvent),
210 // See if the target of the event was a menu, or a menu item
212 oElement = getMenuRootElement(oTarget),
214 sEventType = p_oEvent.type,
224 sTagName = oElement.tagName.toUpperCase();
226 if (sTagName == _LI) {
230 if (sId && m_oItems[sId]) {
232 oMenuItem = m_oItems[sId];
233 oMenu = oMenuItem.parent;
238 else if (sTagName == _DIV) {
242 oMenu = m_oMenus[oElement.id];
253 sCustomEventType = m_oEventTypes[sEventType];
256 There is an inconsistency between Firefox for Mac OS X and
257 Firefox Windows & Linux regarding the triggering of the
258 display of the browser's context menu and the subsequent
259 firing of the "click" event. In Firefox for Windows & Linux,
260 when the user triggers the display of the browser's context
261 menu the "click" event also fires for the document object,
262 even though the "click" event did not fire for the element
263 that was the original target of the "contextmenu" event.
264 This is unique to Firefox on Windows & Linux. For all
265 other A-Grade browsers, including Firefox for Mac OS X, the
266 "click" event doesn't fire for the document object.
268 This bug in Firefox for Windows affects Menu, as Menu
269 instances listen for events at the document level and
270 dispatches Custom Events of the same name. Therefore users
271 of Menu will get an unwanted firing of the "click"
272 custom event. The following line fixes this bug.
277 if (sEventType == "click" &&
278 (UA.gecko && oMenu.platform != "mac") &&
279 p_oEvent.button > 0) {
285 // Fire the Custom Event that corresponds the current DOM event
287 if (bFireEvent && oMenuItem && !oMenuItem.cfg.getProperty(_DISABLED)) {
288 oMenuItem[sCustomEventType].fire(p_oEvent);
292 oMenu[sCustomEventType].fire(p_oEvent, oMenuItem);
296 else if (sEventType == _MOUSEDOWN) {
299 If the target of the event wasn't a menu, hide all
300 dynamically positioned menus
303 for (var i in m_oVisibleMenus) {
305 if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
307 oMenu = m_oVisibleMenus[i];
309 if (oMenu.cfg.getProperty(_CLICK_TO_HIDE) &&
310 !(oMenu instanceof YAHOO.widget.MenuBar) &&
311 oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
315 // In IE when the user mouses down on a focusable
316 // element that element will be focused and become
317 // the "activeElement".
318 // (http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx)
319 // However, there is a bug in IE where if there is
320 // a positioned element with a focused descendant
321 // that is hidden in response to the mousedown
322 // event, the target of the mousedown event will
323 // appear to have focus, but will not be set as
324 // the activeElement. This will result in the
325 // element not firing key events, even though it
326 // appears to have focus. The following call to
327 // "setActive" fixes this bug.
329 if (UA.ie && oTarget.focus) {
336 if (oMenu.cfg.getProperty(_SHOW_DELAY) > 0) {
338 oMenu._cancelShowDelay();
343 if (oMenu.activeItem) {
345 oMenu.activeItem.blur();
346 oMenu.activeItem.cfg.setProperty(_SELECTED, false);
348 oMenu.activeItem = null;
364 * @method onMenuDestroy
365 * @description "destroy" event handler for a menu.
367 * @param {String} p_sType String representing the name of the event
369 * @param {Array} p_aArgs Array of arguments sent when the event
371 * @param {YAHOO.widget.Menu} p_oMenu The menu that fired the event.
373 function onMenuDestroy(p_sType, p_aArgs, p_oMenu) {
375 if (m_oMenus[p_oMenu.id]) {
377 this.removeMenu(p_oMenu);
385 * @method onMenuFocus
386 * @description "focus" event handler for a MenuItem instance.
388 * @param {String} p_sType String representing the name of the event
390 * @param {Array} p_aArgs Array of arguments sent when the event
393 function onMenuFocus(p_sType, p_aArgs) {
395 var oItem = p_aArgs[1];
399 m_oFocusedMenuItem = oItem;
408 * @description "blur" event handler for a MenuItem instance.
410 * @param {String} p_sType String representing the name of the event
412 * @param {Array} p_aArgs Array of arguments sent when the event
415 function onMenuBlur(p_sType, p_aArgs) {
417 m_oFocusedMenuItem = null;
423 * @method onMenuVisibleConfigChange
424 * @description Event handler for when the "visible" configuration
425 * property of a Menu instance changes.
427 * @param {String} p_sType String representing the name of the event
429 * @param {Array} p_aArgs Array of arguments sent when the event
432 function onMenuVisibleConfigChange(p_sType, p_aArgs) {
434 var bVisible = p_aArgs[0],
439 m_oVisibleMenus[sId] = this;
443 else if (m_oVisibleMenus[sId]) {
445 delete m_oVisibleMenus[sId];
454 * @method onItemDestroy
455 * @description "destroy" event handler for a MenuItem instance.
457 * @param {String} p_sType String representing the name of the event
459 * @param {Array} p_aArgs Array of arguments sent when the event
462 function onItemDestroy(p_sType, p_aArgs) {
471 * @description Removes a MenuItem instance from the MenuManager's collection of MenuItems.
473 * @param {MenuItem} p_oMenuItem The MenuItem instance to be removed.
475 function removeItem(p_oMenuItem) {
477 var sId = p_oMenuItem.id;
479 if (sId && m_oItems[sId]) {
481 if (m_oFocusedMenuItem == p_oMenuItem) {
483 m_oFocusedMenuItem = null;
487 delete m_oItems[sId];
489 p_oMenuItem.destroyEvent.unsubscribe(onItemDestroy);
498 * @method onItemAdded
499 * @description "itemadded" event handler for a Menu instance.
501 * @param {String} p_sType String representing the name of the event
503 * @param {Array} p_aArgs Array of arguments sent when the event
506 function onItemAdded(p_sType, p_aArgs) {
508 var oItem = p_aArgs[0],
511 if (oItem instanceof YAHOO.widget.MenuItem) {
515 if (!m_oItems[sId]) {
517 m_oItems[sId] = oItem;
519 oItem.destroyEvent.subscribe(onItemDestroy);
531 // Privileged methods
536 * @description Adds a menu to the collection of known menus.
537 * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
538 * instance to be added.
540 addMenu: function (p_oMenu) {
544 if (p_oMenu instanceof YAHOO.widget.Menu && p_oMenu.id &&
545 !m_oMenus[p_oMenu.id]) {
547 m_oMenus[p_oMenu.id] = p_oMenu;
550 if (!m_bInitializedEventHandlers) {
554 Event.on(oDoc, _MOUSEOVER, onDOMEvent, this, true);
555 Event.on(oDoc, _MOUSEOUT, onDOMEvent, this, true);
556 Event.on(oDoc, _MOUSEDOWN, onDOMEvent, this, true);
557 Event.on(oDoc, _MOUSEUP, onDOMEvent, this, true);
558 Event.on(oDoc, _CLICK, onDOMEvent, this, true);
559 Event.on(oDoc, _KEYDOWN, onDOMEvent, this, true);
560 Event.on(oDoc, _KEYUP, onDOMEvent, this, true);
561 Event.on(oDoc, _KEYPRESS, onDOMEvent, this, true);
563 Event.onFocus(oDoc, onDOMEvent, this, true);
564 Event.onBlur(oDoc, onDOMEvent, this, true);
566 m_bInitializedEventHandlers = true;
571 p_oMenu.cfg.subscribeToConfigEvent(_VISIBLE, onMenuVisibleConfigChange);
572 p_oMenu.destroyEvent.subscribe(onMenuDestroy, p_oMenu, this);
573 p_oMenu.itemAddedEvent.subscribe(onItemAdded);
574 p_oMenu.focusEvent.subscribe(onMenuFocus);
575 p_oMenu.blurEvent.subscribe(onMenuBlur);
585 * @description Removes a menu from the collection of known menus.
586 * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
587 * instance to be removed.
589 removeMenu: function (p_oMenu) {
599 if ((sId in m_oMenus) && (m_oMenus[sId] == p_oMenu)) {
601 // Unregister each menu item
603 aItems = p_oMenu.getItems();
605 if (aItems && aItems.length > 0) {
607 i = aItems.length - 1;
611 removeItem(aItems[i]);
619 // Unregister the menu
621 delete m_oMenus[sId];
626 Unregister the menu from the collection of
630 if ((sId in m_oVisibleMenus) && (m_oVisibleMenus[sId] == p_oMenu)) {
632 delete m_oVisibleMenus[sId];
638 // Unsubscribe event listeners
642 p_oMenu.cfg.unsubscribeFromConfigEvent(_VISIBLE,
643 onMenuVisibleConfigChange);
647 p_oMenu.destroyEvent.unsubscribe(onMenuDestroy,
650 p_oMenu.itemAddedEvent.unsubscribe(onItemAdded);
651 p_oMenu.focusEvent.unsubscribe(onMenuFocus);
652 p_oMenu.blurEvent.unsubscribe(onMenuBlur);
662 * @method hideVisible
663 * @description Hides all visible, dynamically positioned menus
664 * (excluding instances of YAHOO.widget.MenuBar).
666 hideVisible: function () {
670 for (var i in m_oVisibleMenus) {
672 if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
674 oMenu = m_oVisibleMenus[i];
676 if (!(oMenu instanceof YAHOO.widget.MenuBar) &&
677 oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
692 * @description Returns a collection of all visible menus registered
693 * with the menu manger.
696 getVisible: function () {
698 return m_oVisibleMenus;
705 * @description Returns a collection of all menus registered with the
709 getMenus: function () {
718 * @description Returns a menu with the specified id.
719 * @param {String} p_sId String specifying the id of the
720 * <code><div></code> element representing the menu to
722 * @return {YAHOO.widget.Menu}
724 getMenu: function (p_sId) {
728 if (p_sId in m_oMenus) {
730 returnVal = m_oMenus[p_sId];
740 * @method getMenuItem
741 * @description Returns a menu item with the specified id.
742 * @param {String} p_sId String specifying the id of the
743 * <code><li></code> element representing the menu item to
745 * @return {YAHOO.widget.MenuItem}
747 getMenuItem: function (p_sId) {
751 if (p_sId in m_oItems) {
753 returnVal = m_oItems[p_sId];
763 * @method getMenuItemGroup
764 * @description Returns an array of menu item instances whose
765 * corresponding <code><li></code> elements are child
766 * nodes of the <code><ul></code> element with the
768 * @param {String} p_sId String specifying the id of the
769 * <code><ul></code> element representing the group of
770 * menu items to be retrieved.
773 getMenuItemGroup: function (p_sId) {
775 var oUL = Dom.get(p_sId),
783 if (oUL && oUL.tagName && oUL.tagName.toUpperCase() == _UL) {
785 oNode = oUL.firstChild;
797 oItem = this.getMenuItem(sId);
801 aItems[aItems.length] = oItem;
808 while ((oNode = oNode.nextSibling));
811 if (aItems.length > 0) {
827 * @method getFocusedMenuItem
828 * @description Returns a reference to the menu item that currently
830 * @return {YAHOO.widget.MenuItem}
832 getFocusedMenuItem: function () {
834 return m_oFocusedMenuItem;
840 * @method getFocusedMenu
841 * @description Returns a reference to the menu that currently
843 * @return {YAHOO.widget.Menu}
845 getFocusedMenu: function () {
849 if (m_oFocusedMenuItem) {
851 returnVal = m_oFocusedMenuItem.parent.getRoot();
862 * @description Returns a string representing the menu manager.
865 toString: function () {
881 var Lang = YAHOO.lang,
886 _DIV_UPPERCASE = "DIV",
887 _DIV_LOWERCASE = "div",
892 _UL_UPPERCASE = "UL",
893 _UL_LOWERCASE = "ul",
894 _FIRST_OF_TYPE = "first-of-type",
896 _OPTGROUP = "OPTGROUP",
898 _DISABLED = "disabled",
900 _SELECTED = "selected",
901 _GROUP_INDEX = "groupindex",
903 _SUBMENU = "submenu",
904 _VISIBLE = "visible",
905 _HIDE_DELAY = "hidedelay",
906 _POSITION = "position",
907 _DYNAMIC = "dynamic",
909 _DYNAMIC_STATIC = _DYNAMIC + "," + _STATIC,
913 _MAX_HEIGHT = "maxheight",
914 _TOP_SCROLLBAR = "topscrollbar",
915 _BOTTOM_SCROLLBAR = "bottomscrollbar",
917 _TOP_SCROLLBAR_DISABLED = _TOP_SCROLLBAR + _UNDERSCORE + _DISABLED,
918 _BOTTOM_SCROLLBAR_DISABLED = _BOTTOM_SCROLLBAR + _UNDERSCORE + _DISABLED,
919 _MOUSEMOVE = "mousemove",
920 _SHOW_DELAY = "showdelay",
921 _SUBMENU_HIDE_DELAY = "submenuhidedelay",
923 _CONSTRAIN_TO_VIEWPORT = "constraintoviewport",
924 _PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
925 _SUBMENU_ALIGNMENT = "submenualignment",
926 _AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
927 _CLICK_TO_HIDE = "clicktohide",
928 _CONTAINER = "container",
929 _SCROLL_INCREMENT = "scrollincrement",
930 _MIN_SCROLL_HEIGHT = "minscrollheight",
931 _CLASSNAME = "classname",
933 _KEEP_OPEN = "keepopen",
935 _HAS_TITLE = "hastitle",
936 _CONTEXT = "context",
938 _MOUSEDOWN = "mousedown",
939 _KEYDOWN = "keydown",
944 _MONITOR_RESIZE = "monitorresize",
945 _DISPLAY = "display",
947 _VISIBILITY = "visibility",
948 _ABSOLUTE = "absolute",
950 _YUI_MENU_BODY_SCROLLED = "yui-menu-body-scrolled",
951 _NON_BREAKING_SPACE = " ",
953 _MOUSEOVER = "mouseover",
954 _MOUSEOUT = "mouseout",
955 _ITEM_ADDED = "itemAdded",
956 _ITEM_REMOVED = "itemRemoved",
958 _YUI_MENU_SHADOW = "yui-menu-shadow",
959 _YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + "-visible",
960 _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + _SPACE + _YUI_MENU_SHADOW_VISIBLE;
964 * The Menu class creates a container that holds a vertical list representing
965 * a set of options or commands. Menu is the base class for all
967 * @param {String} p_oElement String specifying the id attribute of the
968 * <code><div></code> element of the menu.
969 * @param {String} p_oElement String specifying the id attribute of the
970 * <code><select></code> element to be used as the data source
972 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
973 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
974 * specifying the <code><div></code> element of the menu.
975 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
976 * level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
977 * Object specifying the <code><select></code> element to be used as
978 * the data source for the menu.
979 * @param {Object} p_oConfig Optional. Object literal specifying the
980 * configuration for the menu. See configuration class documentation for
982 * @namespace YAHOO.widget
985 * @extends YAHOO.widget.Overlay
987 YAHOO.widget.Menu = function (p_oElement, p_oConfig) {
991 this.parent = p_oConfig.parent;
992 this.lazyLoad = p_oConfig.lazyLoad || p_oConfig.lazyload;
993 this.itemData = p_oConfig.itemData || p_oConfig.itemdata;
998 YAHOO.widget.Menu.superclass.constructor.call(this, p_oElement, p_oConfig);
1005 * @method checkPosition
1006 * @description Checks to make sure that the value of the "position" property
1007 * is one of the supported strings. Returns true if the position is supported.
1009 * @param {Object} p_sPosition String specifying the position of the menu.
1012 function checkPosition(p_sPosition) {
1014 var returnVal = false;
1016 if (Lang.isString(p_sPosition)) {
1018 returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
1027 var Dom = YAHOO.util.Dom,
1028 Event = YAHOO.util.Event,
1029 Module = YAHOO.widget.Module,
1030 Overlay = YAHOO.widget.Overlay,
1031 Menu = YAHOO.widget.Menu,
1032 MenuManager = YAHOO.widget.MenuManager,
1033 CustomEvent = YAHOO.util.CustomEvent,
1038 bFocusListenerInitialized = false,
1044 ["mouseOverEvent", _MOUSEOVER],
1045 ["mouseOutEvent", _MOUSEOUT],
1046 ["mouseDownEvent", _MOUSEDOWN],
1047 ["mouseUpEvent", "mouseup"],
1048 ["clickEvent", "click"],
1049 ["keyPressEvent", "keypress"],
1050 ["keyDownEvent", _KEYDOWN],
1051 ["keyUpEvent", "keyup"],
1052 ["focusEvent", "focus"],
1053 ["blurEvent", "blur"],
1054 ["itemAddedEvent", _ITEM_ADDED],
1055 ["itemRemovedEvent", _ITEM_REMOVED]
1062 validator: Lang.isBoolean
1065 CONSTRAIN_TO_VIEWPORT_CONFIG = {
1066 key: _CONSTRAIN_TO_VIEWPORT,
1068 validator: Lang.isBoolean,
1069 supercedes: [_IFRAME,"x",_Y,_XY]
1072 PREVENT_CONTEXT_OVERLAP_CONFIG = {
1073 key: _PREVENT_CONTEXT_OVERLAP,
1075 validator: Lang.isBoolean,
1076 supercedes: [_CONSTRAIN_TO_VIEWPORT]
1082 validator: checkPosition,
1083 supercedes: [_VISIBLE, _IFRAME]
1086 SUBMENU_ALIGNMENT_CONFIG = {
1087 key: _SUBMENU_ALIGNMENT,
1091 AUTO_SUBMENU_DISPLAY_CONFIG = {
1092 key: _AUTO_SUBMENU_DISPLAY,
1094 validator: Lang.isBoolean,
1098 SHOW_DELAY_CONFIG = {
1101 validator: Lang.isNumber,
1105 HIDE_DELAY_CONFIG = {
1108 validator: Lang.isNumber,
1112 SUBMENU_HIDE_DELAY_CONFIG = {
1113 key: _SUBMENU_HIDE_DELAY,
1115 validator: Lang.isNumber,
1119 CLICK_TO_HIDE_CONFIG = {
1120 key: _CLICK_TO_HIDE,
1122 validator: Lang.isBoolean,
1126 CONTAINER_CONFIG = {
1131 SCROLL_INCREMENT_CONFIG = {
1132 key: _SCROLL_INCREMENT,
1134 validator: Lang.isNumber,
1135 supercedes: [_MAX_HEIGHT],
1139 MIN_SCROLL_HEIGHT_CONFIG = {
1140 key: _MIN_SCROLL_HEIGHT,
1142 validator: Lang.isNumber,
1143 supercedes: [_MAX_HEIGHT],
1147 MAX_HEIGHT_CONFIG = {
1150 validator: Lang.isNumber,
1151 supercedes: [_IFRAME],
1155 CLASS_NAME_CONFIG = {
1158 validator: Lang.isString,
1165 validator: Lang.isBoolean,
1172 validator: Lang.isBoolean,
1173 suppressEvent: true,
1174 supercedes: [_VISIBLE]
1177 KEEP_OPEN_CONFIG = {
1180 validator: Lang.isBoolean
1184 function onDocFocus(event) {
1186 oFocusedElement = Event.getTarget(event);
1192 YAHOO.lang.extend(Menu, Overlay, {
1199 * @property CSS_CLASS_NAME
1200 * @description String representing the CSS class(es) to be applied to the
1201 * menu's <code><div></code> element.
1202 * @default "yuimenu"
1206 CSS_CLASS_NAME: "yuimenu",
1210 * @property ITEM_TYPE
1211 * @description Object representing the type of menu item to instantiate and
1212 * add when parsing the child nodes (either <code><li></code> element,
1213 * <code><optgroup></code> element or <code><option></code>)
1214 * of the menu's source HTML element.
1215 * @default YAHOO.widget.MenuItem
1217 * @type YAHOO.widget.MenuItem
1223 * @property GROUP_TITLE_TAG_NAME
1224 * @description String representing the tagname of the HTML element used to
1225 * title the menu's item groups.
1230 GROUP_TITLE_TAG_NAME: "h6",
1234 * @property OFF_SCREEN_POSITION
1235 * @description Array representing the default x and y position that a menu
1236 * should have when it is positioned outside the viewport by the
1237 * "poistionOffScreen" method.
1242 OFF_SCREEN_POSITION: "-999em",
1245 // Private properties
1249 * @property _useHideDelay
1250 * @description Boolean indicating if the "mouseover" and "mouseout" event
1251 * handlers used for hiding the menu via a call to "YAHOO.lang.later" have
1252 * already been assigned.
1257 _useHideDelay: false,
1261 * @property _bHandledMouseOverEvent
1262 * @description Boolean indicating the current state of the menu's
1263 * "mouseover" event.
1268 _bHandledMouseOverEvent: false,
1272 * @property _bHandledMouseOutEvent
1273 * @description Boolean indicating the current state of the menu's
1279 _bHandledMouseOutEvent: false,
1283 * @property _aGroupTitleElements
1284 * @description Array of HTML element used to title groups of menu items.
1289 _aGroupTitleElements: null,
1293 * @property _aItemGroups
1294 * @description Multi-dimensional Array representing the menu items as they
1295 * are grouped in the menu.
1304 * @property _aListElements
1305 * @description Array of <code><ul></code> elements, each of which is
1306 * the parent node for each item's <code><li></code> element.
1311 _aListElements: null,
1315 * @property _nCurrentMouseX
1316 * @description The current x coordinate of the mouse inside the area of
1326 * @property _bStopMouseEventHandlers
1327 * @description Stops "mouseover," "mouseout," and "mousemove" event handlers
1333 _bStopMouseEventHandlers: false,
1337 * @property _sClassName
1338 * @description The current value of the "classname" configuration attribute.
1347 // Public properties
1351 * @property lazyLoad
1352 * @description Boolean indicating if the menu's "lazy load" feature is
1353 * enabled. If set to "true," initialization and rendering of the menu's
1354 * items will be deferred until the first time it is made visible. This
1355 * property should be set via the constructor using the configuration
1364 * @property itemData
1365 * @description Array of items to be added to the menu. The array can contain
1366 * strings representing the text for each item to be created, object literals
1367 * representing the menu item configuration properties, or MenuItem instances.
1368 * This property should be set via the constructor using the configuration
1377 * @property activeItem
1378 * @description Object reference to the item in the menu that has is selected.
1380 * @type YAHOO.widget.MenuItem
1387 * @description Object reference to the menu's parent menu or menu item.
1388 * This property can be set via the constructor using the configuration
1391 * @type YAHOO.widget.MenuItem
1397 * @property srcElement
1398 * @description Object reference to the HTML element (either
1399 * <code><select></code> or <code><div></code>) used to
1402 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1403 * level-one-html.html#ID-94282980">HTMLSelectElement</a>|<a
1404 * href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.
1405 * html#ID-22445964">HTMLDivElement</a>
1415 * @event mouseOverEvent
1416 * @description Fires when the mouse has entered the menu. Passes back
1417 * the DOM Event object as an argument.
1422 * @event mouseOutEvent
1423 * @description Fires when the mouse has left the menu. Passes back the DOM
1424 * Event object as an argument.
1425 * @type YAHOO.util.CustomEvent
1430 * @event mouseDownEvent
1431 * @description Fires when the user mouses down on the menu. Passes back the
1432 * DOM Event object as an argument.
1433 * @type YAHOO.util.CustomEvent
1438 * @event mouseUpEvent
1439 * @description Fires when the user releases a mouse button while the mouse is
1440 * over the menu. Passes back the DOM Event object as an argument.
1441 * @type YAHOO.util.CustomEvent
1447 * @description Fires when the user clicks the on the menu. Passes back the
1448 * DOM Event object as an argument.
1449 * @type YAHOO.util.CustomEvent
1454 * @event keyPressEvent
1455 * @description Fires when the user presses an alphanumeric key when one of the
1456 * menu's items has focus. Passes back the DOM Event object as an argument.
1457 * @type YAHOO.util.CustomEvent
1462 * @event keyDownEvent
1463 * @description Fires when the user presses a key when one of the menu's items
1464 * has focus. Passes back the DOM Event object as an argument.
1465 * @type YAHOO.util.CustomEvent
1471 * @description Fires when the user releases a key when one of the menu's items
1472 * has focus. Passes back the DOM Event object as an argument.
1473 * @type YAHOO.util.CustomEvent
1478 * @event itemAddedEvent
1479 * @description Fires when an item is added to the menu.
1480 * @type YAHOO.util.CustomEvent
1485 * @event itemRemovedEvent
1486 * @description Fires when an item is removed to the menu.
1487 * @type YAHOO.util.CustomEvent
1493 * @description The Menu class's initialization method. This method is
1494 * automatically called by the constructor, and sets up all DOM references
1495 * for pre-existing markup, and creates required markup if it is not
1497 * @param {String} p_oElement String specifying the id attribute of the
1498 * <code><div></code> element of the menu.
1499 * @param {String} p_oElement String specifying the id attribute of the
1500 * <code><select></code> element to be used as the data source
1502 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1503 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
1504 * specifying the <code><div></code> element of the menu.
1505 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1506 * level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
1507 * Object specifying the <code><select></code> element to be used as
1508 * the data source for the menu.
1509 * @param {Object} p_oConfig Optional. Object literal specifying the
1510 * configuration for the menu. See configuration class documentation for
1513 init: function (p_oElement, p_oConfig) {
1515 this._aItemGroups = [];
1516 this._aListElements = [];
1517 this._aGroupTitleElements = [];
1519 if (!this.ITEM_TYPE) {
1521 this.ITEM_TYPE = YAHOO.widget.MenuItem;
1528 if (Lang.isString(p_oElement)) {
1530 oElement = Dom.get(p_oElement);
1533 else if (p_oElement.tagName) {
1535 oElement = p_oElement;
1540 if (oElement && oElement.tagName) {
1542 switch(oElement.tagName.toUpperCase()) {
1544 case _DIV_UPPERCASE:
1546 this.srcElement = oElement;
1550 oElement.setAttribute(_ID, Dom.generateId());
1556 Note: we don't pass the user config in here yet
1557 because we only want it executed once, at the lowest
1561 Menu.superclass.init.call(this, oElement);
1563 this.beforeInitEvent.fire(Menu);
1570 this.srcElement = oElement;
1574 The source element is not something that we can use
1575 outright, so we need to create a new Overlay
1577 Note: we don't pass the user config in here yet
1578 because we only want it executed once, at the lowest
1582 Menu.superclass.init.call(this, Dom.generateId());
1584 this.beforeInitEvent.fire(Menu);
1595 Note: we don't pass the user config in here yet
1596 because we only want it executed once, at the lowest
1600 Menu.superclass.init.call(this, p_oElement);
1602 this.beforeInitEvent.fire(Menu);
1610 Dom.addClass(this.element, this.CSS_CLASS_NAME);
1613 // Subscribe to Custom Events
1615 this.initEvent.subscribe(this._onInit);
1616 this.beforeRenderEvent.subscribe(this._onBeforeRender);
1617 this.renderEvent.subscribe(this._onRender);
1618 this.beforeShowEvent.subscribe(this._onBeforeShow);
1619 this.hideEvent.subscribe(this._onHide);
1620 this.showEvent.subscribe(this._onShow);
1621 this.beforeHideEvent.subscribe(this._onBeforeHide);
1622 this.mouseOverEvent.subscribe(this._onMouseOver);
1623 this.mouseOutEvent.subscribe(this._onMouseOut);
1624 this.clickEvent.subscribe(this._onClick);
1625 this.keyDownEvent.subscribe(this._onKeyDown);
1626 this.keyPressEvent.subscribe(this._onKeyPress);
1627 this.blurEvent.subscribe(this._onBlur);
1630 if (!bFocusListenerInitialized) {
1631 Event.onFocus(document, onDocFocus);
1632 bFocusListenerInitialized = true;
1636 // Fixes an issue in Firefox 2 and Webkit where Dom's "getX" and "getY"
1637 // methods return values that don't take scrollTop into consideration
1639 if ((UA.gecko && UA.gecko < 1.9) || UA.webkit) {
1641 this.cfg.subscribeToConfigEvent(_Y, this._onYChange);
1648 this.cfg.applyConfig(p_oConfig, true);
1653 // Register the Menu instance with the MenuManager
1655 MenuManager.addMenu(this);
1658 this.initEvent.fire(Menu);
1670 * @method _initSubTree
1671 * @description Iterates the childNodes of the source element to find nodes
1672 * used to instantiate menu and menu items.
1675 _initSubTree: function () {
1677 var oSrcElement = this.srcElement,
1689 sSrcElementTagName =
1690 (oSrcElement.tagName && oSrcElement.tagName.toUpperCase());
1693 if (sSrcElementTagName == _DIV_UPPERCASE) {
1695 // Populate the collection of item groups and item group titles
1697 oNode = this.body.firstChild;
1703 sGroupTitleTagName = this.GROUP_TITLE_TAG_NAME.toUpperCase();
1708 if (oNode && oNode.tagName) {
1710 switch (oNode.tagName.toUpperCase()) {
1712 case sGroupTitleTagName:
1714 this._aGroupTitleElements[nGroup] = oNode;
1720 this._aListElements[nGroup] = oNode;
1721 this._aItemGroups[nGroup] = [];
1731 while ((oNode = oNode.nextSibling));
1735 Apply the "first-of-type" class to the first UL to mimic
1736 the ":first-of-type" CSS3 psuedo class.
1739 if (this._aListElements[0]) {
1741 Dom.addClass(this._aListElements[0], _FIRST_OF_TYPE);
1754 if (sSrcElementTagName) {
1756 switch (sSrcElementTagName) {
1758 case _DIV_UPPERCASE:
1760 aListElements = this._aListElements;
1761 nListElements = aListElements.length;
1763 if (nListElements > 0) {
1766 i = nListElements - 1;
1770 oNode = aListElements[i].firstChild;
1777 if (oNode && oNode.tagName &&
1778 oNode.tagName.toUpperCase() == _LI) {
1781 this.addItem(new this.ITEM_TYPE(oNode,
1782 { parent: this }), i);
1787 while ((oNode = oNode.nextSibling));
1801 oNode = oSrcElement.firstChild;
1805 if (oNode && oNode.tagName) {
1807 switch (oNode.tagName.toUpperCase()) {
1827 while ((oNode = oNode.nextSibling));
1841 * @method _getFirstEnabledItem
1842 * @description Returns the first enabled item in the menu.
1843 * @return {YAHOO.widget.MenuItem}
1846 _getFirstEnabledItem: function () {
1848 var aItems = this.getItems(),
1849 nItems = aItems.length,
1854 for(var i=0; i<nItems; i++) {
1858 if (oItem && !oItem.cfg.getProperty(_DISABLED) && oItem.element.style.display != _NONE) {
1873 * @method _addItemToGroup
1874 * @description Adds a menu item to a group.
1876 * @param {Number} p_nGroupIndex Number indicating the group to which the
1878 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
1879 * instance to be added to the menu.
1880 * @param {String} p_oItem String specifying the text of the item to be added
1882 * @param {Object} p_oItem Object literal containing a set of menu item
1883 * configuration properties.
1884 * @param {Number} p_nItemIndex Optional. Number indicating the index at
1885 * which the menu item should be added.
1886 * @return {YAHOO.widget.MenuItem}
1888 _addItemToGroup: function (p_nGroupIndex, p_oItem, p_nItemIndex) {
1900 function getNextItemSibling(p_aArray, p_nStartIndex) {
1902 return (p_aArray[p_nStartIndex] || getNextItemSibling(p_aArray, (p_nStartIndex+1)));
1907 if (p_oItem instanceof this.ITEM_TYPE) {
1910 oItem.parent = this;
1913 else if (Lang.isString(p_oItem)) {
1915 oItem = new this.ITEM_TYPE(p_oItem, { parent: this });
1918 else if (Lang.isObject(p_oItem)) {
1920 p_oItem.parent = this;
1922 oItem = new this.ITEM_TYPE(p_oItem.text, p_oItem);
1929 if (oItem.cfg.getProperty(_SELECTED)) {
1931 this.activeItem = oItem;
1936 nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
1937 aGroup = this._getItemGroup(nGroupIndex);
1943 aGroup = this._createItemGroup(nGroupIndex);
1948 if (Lang.isNumber(p_nItemIndex)) {
1950 bAppend = (p_nItemIndex >= aGroup.length);
1953 if (aGroup[p_nItemIndex]) {
1955 aGroup.splice(p_nItemIndex, 0, oItem);
1960 aGroup[p_nItemIndex] = oItem;
1965 oGroupItem = aGroup[p_nItemIndex];
1969 if (bAppend && (!oGroupItem.element.parentNode ||
1970 oGroupItem.element.parentNode.nodeType == 11)) {
1972 this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
1977 oNextItemSibling = getNextItemSibling(aGroup, (p_nItemIndex+1));
1979 if (oNextItemSibling && (!oGroupItem.element.parentNode ||
1980 oGroupItem.element.parentNode.nodeType == 11)) {
1982 this._aListElements[nGroupIndex].insertBefore(
1983 oGroupItem.element, oNextItemSibling.element);
1990 oGroupItem.parent = this;
1992 this._subscribeToItemEvents(oGroupItem);
1994 this._configureSubmenu(oGroupItem);
1996 this._updateItemProperties(nGroupIndex);
1999 this.itemAddedEvent.fire(oGroupItem);
2000 this.changeContentEvent.fire();
2002 returnVal = oGroupItem;
2009 nItemIndex = aGroup.length;
2011 aGroup[nItemIndex] = oItem;
2013 oGroupItem = aGroup[nItemIndex];
2018 if (!Dom.isAncestor(this._aListElements[nGroupIndex], oGroupItem.element)) {
2020 this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
2024 oGroupItem.element.setAttribute(_GROUP_INDEX, nGroupIndex);
2025 oGroupItem.element.setAttribute(_INDEX, nItemIndex);
2027 oGroupItem.parent = this;
2029 oGroupItem.index = nItemIndex;
2030 oGroupItem.groupIndex = nGroupIndex;
2032 this._subscribeToItemEvents(oGroupItem);
2034 this._configureSubmenu(oGroupItem);
2036 if (nItemIndex === 0) {
2038 Dom.addClass(oGroupItem.element, _FIRST_OF_TYPE);
2044 this.itemAddedEvent.fire(oGroupItem);
2045 this.changeContentEvent.fire();
2047 returnVal = oGroupItem;
2061 * @method _removeItemFromGroupByIndex
2062 * @description Removes a menu item from a group by index. Returns the menu
2063 * item that was removed.
2065 * @param {Number} p_nGroupIndex Number indicating the group to which the menu
2067 * @param {Number} p_nItemIndex Number indicating the index of the menu item
2069 * @return {YAHOO.widget.MenuItem}
2071 _removeItemFromGroupByIndex: function (p_nGroupIndex, p_nItemIndex) {
2073 var nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0,
2074 aGroup = this._getItemGroup(nGroupIndex),
2081 aArray = aGroup.splice(p_nItemIndex, 1);
2086 // Update the index and className properties of each member
2088 this._updateItemProperties(nGroupIndex);
2090 if (aGroup.length === 0) {
2094 oUL = this._aListElements[nGroupIndex];
2096 if (this.body && oUL) {
2098 this.body.removeChild(oUL);
2102 // Remove the group from the array of items
2104 this._aItemGroups.splice(nGroupIndex, 1);
2107 // Remove the UL from the array of ULs
2109 this._aListElements.splice(nGroupIndex, 1);
2113 Assign the "first-of-type" class to the new first UL
2117 oUL = this._aListElements[0];
2121 Dom.addClass(oUL, _FIRST_OF_TYPE);
2128 this.itemRemovedEvent.fire(oItem);
2129 this.changeContentEvent.fire();
2135 // Return a reference to the item that was removed
2143 * @method _removeItemFromGroupByValue
2144 * @description Removes a menu item from a group by reference. Returns the
2145 * menu item that was removed.
2147 * @param {Number} p_nGroupIndex Number indicating the group to which the
2148 * menu item belongs.
2149 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2150 * instance to be removed.
2151 * @return {YAHOO.widget.MenuItem}
2153 _removeItemFromGroupByValue: function (p_nGroupIndex, p_oItem) {
2155 var aGroup = this._getItemGroup(p_nGroupIndex),
2163 nItems = aGroup.length;
2172 if (aGroup[i] == p_oItem) {
2182 if (nItemIndex > -1) {
2184 returnVal = this._removeItemFromGroupByIndex(p_nGroupIndex, nItemIndex);
2198 * @method _updateItemProperties
2199 * @description Updates the "index," "groupindex," and "className" properties
2200 * of the menu items in the specified group.
2202 * @param {Number} p_nGroupIndex Number indicating the group of items to update.
2204 _updateItemProperties: function (p_nGroupIndex) {
2206 var aGroup = this._getItemGroup(p_nGroupIndex),
2207 nItems = aGroup.length,
2217 // Update the index and className properties of each member
2225 oLI = oItem.element;
2228 oItem.groupIndex = p_nGroupIndex;
2230 oLI.setAttribute(_GROUP_INDEX, p_nGroupIndex);
2231 oLI.setAttribute(_INDEX, i);
2233 Dom.removeClass(oLI, _FIRST_OF_TYPE);
2243 Dom.addClass(oLI, _FIRST_OF_TYPE);
2253 * @method _createItemGroup
2254 * @description Creates a new menu item group (array) and its associated
2255 * <code><ul></code> element. Returns an aray of menu item groups.
2257 * @param {Number} p_nIndex Number indicating the group to create.
2260 _createItemGroup: function (p_nIndex) {
2265 if (!this._aItemGroups[p_nIndex]) {
2267 this._aItemGroups[p_nIndex] = [];
2269 oUL = document.createElement(_UL_LOWERCASE);
2271 this._aListElements[p_nIndex] = oUL;
2273 returnVal = this._aItemGroups[p_nIndex];
2283 * @method _getItemGroup
2284 * @description Returns the menu item group at the specified index.
2286 * @param {Number} p_nIndex Number indicating the index of the menu item group
2290 _getItemGroup: function (p_nIndex) {
2292 var nIndex = Lang.isNumber(p_nIndex) ? p_nIndex : 0,
2293 aGroups = this._aItemGroups,
2296 if (nIndex in aGroups) {
2298 returnVal = aGroups[nIndex];
2308 * @method _configureSubmenu
2309 * @description Subscribes the menu item's submenu to its parent menu's events.
2311 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2312 * instance with the submenu to be configured.
2314 _configureSubmenu: function (p_oItem) {
2316 var oSubmenu = p_oItem.cfg.getProperty(_SUBMENU);
2321 Listen for configuration changes to the parent menu
2322 so they they can be applied to the submenu.
2325 this.cfg.configChangedEvent.subscribe(this._onParentMenuConfigChange, oSubmenu, true);
2327 this.renderEvent.subscribe(this._onParentMenuRender, oSubmenu, true);
2337 * @method _subscribeToItemEvents
2338 * @description Subscribes a menu to a menu item's event.
2340 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2341 * instance whose events should be subscribed to.
2343 _subscribeToItemEvents: function (p_oItem) {
2345 p_oItem.destroyEvent.subscribe(this._onMenuItemDestroy, p_oItem, this);
2346 p_oItem.cfg.configChangedEvent.subscribe(this._onMenuItemConfigChange, p_oItem, this);
2352 * @method _onVisibleChange
2353 * @description Change event handler for the menu's "visible" configuration
2356 * @param {String} p_sType String representing the name of the event that
2358 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2360 _onVisibleChange: function (p_sType, p_aArgs) {
2362 var bVisible = p_aArgs[0];
2366 Dom.addClass(this.element, _VISIBLE);
2371 Dom.removeClass(this.element, _VISIBLE);
2379 * @method _cancelHideDelay
2380 * @description Cancels the call to "hideMenu."
2383 _cancelHideDelay: function () {
2385 var oTimer = this.getRoot()._hideDelayTimer;
2397 * @method _execHideDelay
2398 * @description Hides the menu after the number of milliseconds specified by
2399 * the "hidedelay" configuration property.
2402 _execHideDelay: function () {
2404 this._cancelHideDelay();
2406 var oRoot = this.getRoot();
2408 oRoot._hideDelayTimer = Lang.later(oRoot.cfg.getProperty(_HIDE_DELAY), this, function () {
2410 if (oRoot.activeItem) {
2412 if (oRoot.hasFocus()) {
2414 oRoot.activeItem.focus();
2418 oRoot.clearActiveItem();
2422 if (oRoot == this && !(this instanceof YAHOO.widget.MenuBar) &&
2423 this.cfg.getProperty(_POSITION) == _DYNAMIC) {
2435 * @method _cancelShowDelay
2436 * @description Cancels the call to the "showMenu."
2439 _cancelShowDelay: function () {
2441 var oTimer = this.getRoot()._showDelayTimer;
2453 * @method _execSubmenuHideDelay
2454 * @description Hides a submenu after the number of milliseconds specified by
2455 * the "submenuhidedelay" configuration property have ellapsed.
2457 * @param {YAHOO.widget.Menu} p_oSubmenu Object specifying the submenu that
2459 * @param {Number} p_nMouseX The x coordinate of the mouse when it left
2460 * the specified submenu's parent menu item.
2461 * @param {Number} p_nHideDelay The number of milliseconds that should ellapse
2462 * before the submenu is hidden.
2464 _execSubmenuHideDelay: function (p_oSubmenu, p_nMouseX, p_nHideDelay) {
2466 p_oSubmenu._submenuHideDelayTimer = Lang.later(50, this, function () {
2468 if (this._nCurrentMouseX > (p_nMouseX + 10)) {
2470 p_oSubmenu._submenuHideDelayTimer = Lang.later(p_nHideDelay, p_oSubmenu, function () {
2489 // Protected methods
2493 * @method _disableScrollHeader
2494 * @description Disables the header used for scrolling the body of the menu.
2497 _disableScrollHeader: function () {
2499 if (!this._bHeaderDisabled) {
2501 Dom.addClass(this.header, _TOP_SCROLLBAR_DISABLED);
2502 this._bHeaderDisabled = true;
2510 * @method _disableScrollFooter
2511 * @description Disables the footer used for scrolling the body of the menu.
2514 _disableScrollFooter: function () {
2516 if (!this._bFooterDisabled) {
2518 Dom.addClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2519 this._bFooterDisabled = true;
2527 * @method _enableScrollHeader
2528 * @description Enables the header used for scrolling the body of the menu.
2531 _enableScrollHeader: function () {
2533 if (this._bHeaderDisabled) {
2535 Dom.removeClass(this.header, _TOP_SCROLLBAR_DISABLED);
2536 this._bHeaderDisabled = false;
2544 * @method _enableScrollFooter
2545 * @description Enables the footer used for scrolling the body of the menu.
2548 _enableScrollFooter: function () {
2550 if (this._bFooterDisabled) {
2552 Dom.removeClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2553 this._bFooterDisabled = false;
2561 * @method _onMouseOver
2562 * @description "mouseover" event handler for the menu.
2564 * @param {String} p_sType String representing the name of the event that
2566 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2568 _onMouseOver: function (p_sType, p_aArgs) {
2570 var oEvent = p_aArgs[0],
2572 oTarget = Event.getTarget(oEvent),
2573 oRoot = this.getRoot(),
2574 oSubmenuHideDelayTimer = this._submenuHideDelayTimer,
2583 var showSubmenu = function () {
2585 if (this.parent.cfg.getProperty(_SELECTED)) {
2594 if (!this._bStopMouseEventHandlers) {
2596 if (!this._bHandledMouseOverEvent && (oTarget == this.element ||
2597 Dom.isAncestor(this.element, oTarget))) {
2599 // Menu mouseover logic
2601 if (this._useHideDelay) {
2602 this._cancelHideDelay();
2605 this._nCurrentMouseX = 0;
2607 Event.on(this.element, _MOUSEMOVE, this._onMouseMove, this, true);
2611 If the mouse is moving from the submenu back to its corresponding menu item,
2612 don't hide the submenu or clear the active MenuItem.
2615 if (!(oItem && Dom.isAncestor(oItem.element, Event.getRelatedTarget(oEvent)))) {
2617 this.clearActiveItem();
2622 if (this.parent && oSubmenuHideDelayTimer) {
2624 oSubmenuHideDelayTimer.cancel();
2626 this.parent.cfg.setProperty(_SELECTED, true);
2628 oParentMenu = this.parent.parent;
2630 oParentMenu._bHandledMouseOutEvent = true;
2631 oParentMenu._bHandledMouseOverEvent = false;
2636 this._bHandledMouseOverEvent = true;
2637 this._bHandledMouseOutEvent = false;
2642 if (oItem && !oItem.handledMouseOverEvent && !oItem.cfg.getProperty(_DISABLED) &&
2643 (oTarget == oItem.element || Dom.isAncestor(oItem.element, oTarget))) {
2645 // Menu Item mouseover logic
2647 nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2648 bShowDelay = (nShowDelay > 0);
2653 this._cancelShowDelay();
2658 oActiveItem = this.activeItem;
2662 oActiveItem.cfg.setProperty(_SELECTED, false);
2667 oItemCfg = oItem.cfg;
2669 // Select and focus the current menu item
2671 oItemCfg.setProperty(_SELECTED, true);
2674 if (this.hasFocus() || oRoot._hasFocus) {
2678 oRoot._hasFocus = false;
2683 if (this.cfg.getProperty(_AUTO_SUBMENU_DISPLAY)) {
2685 // Show the submenu this menu item
2687 oSubmenu = oItemCfg.getProperty(_SUBMENU);
2693 oRoot._showDelayTimer =
2694 Lang.later(oRoot.cfg.getProperty(_SHOW_DELAY), oSubmenu, showSubmenu);
2707 oItem.handledMouseOverEvent = true;
2708 oItem.handledMouseOutEvent = false;
2718 * @method _onMouseOut
2719 * @description "mouseout" event handler for the menu.
2721 * @param {String} p_sType String representing the name of the event that
2723 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2725 _onMouseOut: function (p_sType, p_aArgs) {
2727 var oEvent = p_aArgs[0],
2729 oRelatedTarget = Event.getRelatedTarget(oEvent),
2730 bMovingToSubmenu = false,
2737 if (!this._bStopMouseEventHandlers) {
2739 if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
2741 oItemCfg = oItem.cfg;
2742 oSubmenu = oItemCfg.getProperty(_SUBMENU);
2745 if (oSubmenu && (oRelatedTarget == oSubmenu.element ||
2746 Dom.isAncestor(oSubmenu.element, oRelatedTarget))) {
2748 bMovingToSubmenu = true;
2753 if (!oItem.handledMouseOutEvent && ((oRelatedTarget != oItem.element &&
2754 !Dom.isAncestor(oItem.element, oRelatedTarget)) || bMovingToSubmenu)) {
2756 // Menu Item mouseout logic
2758 if (!bMovingToSubmenu) {
2760 oItem.cfg.setProperty(_SELECTED, false);
2765 nSubmenuHideDelay = this.cfg.getProperty(_SUBMENU_HIDE_DELAY);
2767 nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2769 if (!(this instanceof YAHOO.widget.MenuBar) && nSubmenuHideDelay > 0 &&
2770 nShowDelay >= nSubmenuHideDelay) {
2772 this._execSubmenuHideDelay(oSubmenu, Event.getPageX(oEvent),
2787 oItem.handledMouseOutEvent = true;
2788 oItem.handledMouseOverEvent = false;
2795 if (!this._bHandledMouseOutEvent && ((oRelatedTarget != this.element &&
2796 !Dom.isAncestor(this.element, oRelatedTarget)) || bMovingToSubmenu)) {
2798 // Menu mouseout logic
2800 if (this._useHideDelay) {
2801 this._execHideDelay();
2804 Event.removeListener(this.element, _MOUSEMOVE, this._onMouseMove);
2806 this._nCurrentMouseX = Event.getPageX(oEvent);
2808 this._bHandledMouseOutEvent = true;
2809 this._bHandledMouseOverEvent = false;
2819 * @method _onMouseMove
2820 * @description "click" event handler for the menu.
2822 * @param {Event} p_oEvent Object representing the DOM event object passed
2823 * back by the event utility (YAHOO.util.Event).
2824 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
2827 _onMouseMove: function (p_oEvent, p_oMenu) {
2829 if (!this._bStopMouseEventHandlers) {
2831 this._nCurrentMouseX = Event.getPageX(p_oEvent);
2840 * @description "click" event handler for the menu.
2842 * @param {String} p_sType String representing the name of the event that
2844 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2846 _onClick: function (p_sType, p_aArgs) {
2848 var oEvent = p_aArgs[0],
2850 bInMenuAnchor = false,
2860 var hide = function () {
2862 oRoot = this.getRoot();
2864 if (oRoot instanceof YAHOO.widget.MenuBar ||
2865 oRoot.cfg.getProperty(_POSITION) == _STATIC) {
2867 oRoot.clearActiveItem();
2881 if (oItem.cfg.getProperty(_DISABLED)) {
2883 Event.preventDefault(oEvent);
2890 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
2894 Check if the URL of the anchor is pointing to an element that is
2895 a child of the menu.
2898 sURL = oItem.cfg.getProperty(_URL);
2903 nHashPos = sURL.indexOf(_HASH);
2908 if (nHashPos != -1) {
2910 sURL = sURL.substr(nHashPos, nLen);
2917 sId = sURL.substr(1, nLen);
2919 oMenu = YAHOO.widget.MenuManager.getMenu(sId);
2924 (this.getRoot() === oMenu.getRoot());
2929 else if (nLen === 1) {
2931 bInMenuAnchor = true;
2940 if (bInMenuAnchor && !oItem.cfg.getProperty(_TARGET)) {
2942 Event.preventDefault(oEvent);
2952 oItem.focusEvent.fire();
2959 if (!oSubmenu && !this.cfg.getProperty(_KEEP_OPEN)) {
2973 * @method _onKeyDown
2974 * @description "keydown" event handler for the menu.
2976 * @param {String} p_sType String representing the name of the event that
2978 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2980 _onKeyDown: function (p_sType, p_aArgs) {
2982 var oEvent = p_aArgs[0],
3000 if (this._useHideDelay) {
3001 this._cancelHideDelay();
3006 This function is called to prevent a bug in Firefox. In Firefox,
3007 moving a DOM element into a stationary mouse pointer will cause the
3008 browser to fire mouse events. This can result in the menu mouse
3009 event handlers being called uncessarily, especially when menus are
3010 moved into a stationary mouse pointer as a result of a
3013 function stopMouseEventHandlers() {
3015 this._bStopMouseEventHandlers = true;
3017 Lang.later(10, this, function () {
3019 this._bStopMouseEventHandlers = false;
3026 if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
3028 oItemCfg = oItem.cfg;
3029 oParentItem = this.parent;
3031 switch(oEvent.keyCode) {
3033 case 38: // Up arrow
3034 case 40: // Down arrow
3036 oNextItem = (oEvent.keyCode == 38) ?
3037 oItem.getPreviousEnabledSibling() :
3038 oItem.getNextEnabledSibling();
3042 this.clearActiveItem();
3044 oNextItem.cfg.setProperty(_SELECTED, true);
3048 if (this.cfg.getProperty(_MAX_HEIGHT) > 0) {
3051 nBodyScrollTop = oBody.scrollTop;
3052 nBodyOffsetHeight = oBody.offsetHeight;
3053 aItems = this.getItems();
3054 nItems = aItems.length - 1;
3055 nNextItemOffsetTop = oNextItem.element.offsetTop;
3058 if (oEvent.keyCode == 40 ) { // Down
3060 if (nNextItemOffsetTop >= (nBodyOffsetHeight + nBodyScrollTop)) {
3062 oBody.scrollTop = nNextItemOffsetTop - nBodyOffsetHeight;
3065 else if (nNextItemOffsetTop <= nBodyScrollTop) {
3067 oBody.scrollTop = 0;
3072 if (oNextItem == aItems[nItems]) {
3074 oBody.scrollTop = oNextItem.element.offsetTop;
3081 if (nNextItemOffsetTop <= nBodyScrollTop) {
3083 oBody.scrollTop = nNextItemOffsetTop - oNextItem.element.offsetHeight;
3086 else if (nNextItemOffsetTop >= (nBodyScrollTop + nBodyOffsetHeight)) {
3088 oBody.scrollTop = nNextItemOffsetTop;
3093 if (oNextItem == aItems[0]) {
3095 oBody.scrollTop = 0;
3102 nBodyScrollTop = oBody.scrollTop;
3103 nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3105 if (nBodyScrollTop === 0) {
3107 this._disableScrollHeader();
3108 this._enableScrollFooter();
3111 else if (nBodyScrollTop == nScrollTarget) {
3113 this._enableScrollHeader();
3114 this._disableScrollFooter();
3119 this._enableScrollHeader();
3120 this._enableScrollFooter();
3129 Event.preventDefault(oEvent);
3131 stopMouseEventHandlers();
3136 case 39: // Right arrow
3138 oSubmenu = oItemCfg.getProperty(_SUBMENU);
3142 if (!oItemCfg.getProperty(_SELECTED)) {
3144 oItemCfg.setProperty(_SELECTED, true);
3149 oSubmenu.setInitialFocus();
3150 oSubmenu.setInitialSelection();
3155 oRoot = this.getRoot();
3157 if (oRoot instanceof YAHOO.widget.MenuBar) {
3159 oNextItem = oRoot.activeItem.getNextEnabledSibling();
3163 oRoot.clearActiveItem();
3165 oNextItem.cfg.setProperty(_SELECTED, true);
3167 oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3172 oSubmenu.setInitialFocus();
3188 Event.preventDefault(oEvent);
3190 stopMouseEventHandlers();
3195 case 37: // Left arrow
3199 oParentMenu = oParentItem.parent;
3201 if (oParentMenu instanceof YAHOO.widget.MenuBar) {
3204 oParentMenu.activeItem.getPreviousEnabledSibling();
3208 oParentMenu.clearActiveItem();
3210 oNextItem.cfg.setProperty(_SELECTED, true);
3212 oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3217 oSubmenu.setInitialFocus();
3233 oParentItem.focus();
3239 Event.preventDefault(oEvent);
3241 stopMouseEventHandlers();
3251 if (oEvent.keyCode == 27) { // Esc key
3253 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3259 this.parent.focus();
3263 // Focus the element that previously had focus
3265 oFocusedEl = this._focusedElement;
3267 if (oFocusedEl && oFocusedEl.focus) {
3280 else if (this.activeItem) {
3282 oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
3284 if (oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
3287 this.activeItem.focus();
3292 this.activeItem.blur();
3293 this.activeItem.cfg.setProperty(_SELECTED, false);
3300 Event.preventDefault(oEvent);
3308 * @method _onKeyPress
3309 * @description "keypress" event handler for a Menu instance.
3311 * @param {String} p_sType The name of the event that was fired.
3312 * @param {Array} p_aArgs Collection of arguments sent when the event
3315 _onKeyPress: function (p_sType, p_aArgs) {
3317 var oEvent = p_aArgs[0];
3320 if (oEvent.keyCode == 40 || oEvent.keyCode == 38) {
3322 Event.preventDefault(oEvent);
3331 * @description "blur" event handler for a Menu instance.
3333 * @param {String} p_sType The name of the event that was fired.
3334 * @param {Array} p_aArgs Collection of arguments sent when the event
3337 _onBlur: function (p_sType, p_aArgs) {
3339 if (this._hasFocus) {
3340 this._hasFocus = false;
3346 * @method _onYChange
3347 * @description "y" event handler for a Menu instance.
3349 * @param {String} p_sType The name of the event that was fired.
3350 * @param {Array} p_aArgs Collection of arguments sent when the event
3353 _onYChange: function (p_sType, p_aArgs) {
3355 var oParent = this.parent,
3363 nScrollTop = oParent.parent.body.scrollTop;
3366 if (nScrollTop > 0) {
3368 nY = (this.cfg.getProperty(_Y) - nScrollTop);
3370 Dom.setY(this.element, nY);
3372 oIFrame = this.iframe;
3377 Dom.setY(oIFrame, nY);
3381 this.cfg.setProperty(_Y, nY, true);
3391 * @method _onScrollTargetMouseOver
3392 * @description "mouseover" event handler for the menu's "header" and "footer"
3393 * elements. Used to scroll the body of the menu up and down when the
3394 * menu's "maxheight" configuration property is set to a value greater than 0.
3396 * @param {Event} p_oEvent Object representing the DOM event object passed
3397 * back by the event utility (YAHOO.util.Event).
3398 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
3401 _onScrollTargetMouseOver: function (p_oEvent, p_oMenu) {
3403 var oBodyScrollTimer = this._bodyScrollTimer;
3406 if (oBodyScrollTimer) {
3408 oBodyScrollTimer.cancel();
3413 this._cancelHideDelay();
3416 var oTarget = Event.getTarget(p_oEvent),
3418 nScrollIncrement = this.cfg.getProperty(_SCROLL_INCREMENT),
3423 function scrollBodyDown() {
3425 var nScrollTop = oBody.scrollTop;
3428 if (nScrollTop < nScrollTarget) {
3430 oBody.scrollTop = (nScrollTop + nScrollIncrement);
3432 this._enableScrollHeader();
3437 oBody.scrollTop = nScrollTarget;
3439 this._bodyScrollTimer.cancel();
3441 this._disableScrollFooter();
3448 function scrollBodyUp() {
3450 var nScrollTop = oBody.scrollTop;
3453 if (nScrollTop > 0) {
3455 oBody.scrollTop = (nScrollTop - nScrollIncrement);
3457 this._enableScrollFooter();
3462 oBody.scrollTop = 0;
3464 this._bodyScrollTimer.cancel();
3466 this._disableScrollHeader();
3473 if (Dom.hasClass(oTarget, _HD)) {
3475 fnScrollFunction = scrollBodyUp;
3480 nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3482 fnScrollFunction = scrollBodyDown;
3487 this._bodyScrollTimer = Lang.later(10, this, fnScrollFunction, null, true);
3493 * @method _onScrollTargetMouseOut
3494 * @description "mouseout" event handler for the menu's "header" and "footer"
3495 * elements. Used to stop scrolling the body of the menu up and down when the
3496 * menu's "maxheight" configuration property is set to a value greater than 0.
3498 * @param {Event} p_oEvent Object representing the DOM event object passed
3499 * back by the event utility (YAHOO.util.Event).
3500 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
3503 _onScrollTargetMouseOut: function (p_oEvent, p_oMenu) {
3505 var oBodyScrollTimer = this._bodyScrollTimer;
3507 if (oBodyScrollTimer) {
3509 oBodyScrollTimer.cancel();
3513 this._cancelHideDelay();
3524 * @description "init" event handler for the menu.
3526 * @param {String} p_sType String representing the name of the event that
3528 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3530 _onInit: function (p_sType, p_aArgs) {
3532 this.cfg.subscribeToConfigEvent(_VISIBLE, this._onVisibleChange);
3534 var bRootMenu = !this.parent,
3535 bLazyLoad = this.lazyLoad;
3539 Automatically initialize a menu's subtree if:
3541 1) This is the root menu and lazyload is off
3543 2) This is the root menu, lazyload is on, but the menu is
3546 3) This menu is a submenu and lazyload is off
3551 if (((bRootMenu && !bLazyLoad) ||
3552 (bRootMenu && (this.cfg.getProperty(_VISIBLE) ||
3553 this.cfg.getProperty(_POSITION) == _STATIC)) ||
3554 (!bRootMenu && !bLazyLoad)) && this.getItemGroups().length === 0) {
3556 if (this.srcElement) {
3558 this._initSubTree();
3563 if (this.itemData) {
3565 this.addItems(this.itemData);
3570 else if (bLazyLoad) {
3572 this.cfg.fireQueue();
3580 * @method _onBeforeRender
3581 * @description "beforerender" event handler for the menu. Appends all of the
3582 * <code><ul></code>, <code><li></code> and their accompanying
3583 * title elements to the body element of the menu.
3585 * @param {String} p_sType String representing the name of the event that
3587 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3589 _onBeforeRender: function (p_sType, p_aArgs) {
3591 var oEl = this.element,
3592 nListElements = this._aListElements.length,
3598 if (nListElements > 0) {
3602 oUL = this._aListElements[i];
3608 Dom.addClass(oUL, _FIRST_OF_TYPE);
3614 if (!Dom.isAncestor(oEl, oUL)) {
3616 this.appendToBody(oUL);
3621 oGroupTitle = this._aGroupTitleElements[i];
3625 if (!Dom.isAncestor(oEl, oGroupTitle)) {
3627 oUL.parentNode.insertBefore(oGroupTitle, oUL);
3632 Dom.addClass(oUL, _HAS_TITLE);
3641 while (i < nListElements);
3650 * @description "render" event handler for the menu.
3652 * @param {String} p_sType String representing the name of the event that
3654 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3656 _onRender: function (p_sType, p_aArgs) {
3658 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3660 if (!this.cfg.getProperty(_VISIBLE)) {
3662 this.positionOffScreen();
3675 * @method _onBeforeShow
3676 * @description "beforeshow" event handler for the menu.
3678 * @param {String} p_sType String representing the name of the event that
3680 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3682 _onBeforeShow: function (p_sType, p_aArgs) {
3687 oContainer = this.cfg.getProperty(_CONTAINER);
3690 if (this.lazyLoad && this.getItemGroups().length === 0) {
3692 if (this.srcElement) {
3694 this._initSubTree();
3699 if (this.itemData) {
3701 if (this.parent && this.parent.parent &&
3702 this.parent.parent.srcElement &&
3703 this.parent.parent.srcElement.tagName.toUpperCase() ==
3706 nOptions = this.itemData.length;
3708 for(n=0; n<nOptions; n++) {
3710 if (this.itemData[n].tagName) {
3712 this.addItem((new this.ITEM_TYPE(this.itemData[n])));
3721 this.addItems(this.itemData);
3728 oSrcElement = this.srcElement;
3732 if (oSrcElement.tagName.toUpperCase() == _SELECT) {
3734 if (Dom.inDocument(oSrcElement)) {
3736 this.render(oSrcElement.parentNode);
3741 this.render(oContainer);
3757 this.render(this.parent.element);
3762 this.render(oContainer);
3772 var oParent = this.parent,
3776 if (!oParent && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3778 this.cfg.refireEvent(_XY);
3785 aAlignment = oParent.parent.cfg.getProperty(_SUBMENU_ALIGNMENT);
3787 this.cfg.setProperty(_CONTEXT, [oParent.element, aAlignment[0], aAlignment[1]]);
3795 getConstrainedY: function (y) {
3799 aContext = oMenu.cfg.getProperty(_CONTEXT),
3800 nInitialMaxHeight = oMenu.cfg.getProperty(_MAX_HEIGHT),
3804 oOverlapPositions = {
3813 bPotentialContextOverlap = (aContext && oOverlapPositions[aContext[1] + aContext[2]]),
3815 oMenuEl = oMenu.element,
3816 nMenuOffsetHeight = oMenuEl.offsetHeight,
3818 nViewportOffset = Overlay.VIEWPORT_OFFSET,
3819 viewPortHeight = Dom.getViewportHeight(),
3820 scrollY = Dom.getDocumentScrollTop(),
3823 (oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) + nViewportOffset < viewPortHeight),
3834 nBottomRegionHeight,
3836 topConstraint = scrollY + nViewportOffset,
3837 bottomConstraint = scrollY + viewPortHeight - nMenuOffsetHeight - nViewportOffset,
3842 var flipVertical = function () {
3846 // The Menu is below the context element, flip it above
3847 if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3848 nNewY = (nContextElY - nMenuOffsetHeight);
3850 else { // The Menu is above the context element, flip it below
3851 nNewY = (nContextElY + nContextElHeight);
3854 oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3862 Uses the context element's position to calculate the availble height
3863 above and below it to display its corresponding Menu.
3866 var getDisplayRegionHeight = function () {
3868 // The Menu is below the context element
3869 if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3870 return (nBottomRegionHeight - nViewportOffset);
3872 else { // The Menu is above the context element
3873 return (nTopRegionHeight - nViewportOffset);
3880 Sets the Menu's "y" configuration property to the correct value based on its
3881 current orientation.
3884 var alignY = function () {
3888 if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3889 nNewY = (nContextElY + nContextElHeight);
3892 nNewY = (nContextElY - oMenuEl.offsetHeight);
3895 oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3900 // Resets the maxheight of the Menu to the value set by the user
3902 var resetMaxHeight = function () {
3904 oMenu._setScrollHeight(this.cfg.getProperty(_MAX_HEIGHT));
3906 oMenu.hideEvent.unsubscribe(resetMaxHeight);
3912 Trys to place the Menu in the best possible position (either above or
3913 below its corresponding context element).
3916 var setVerticalPosition = function () {
3918 var nDisplayRegionHeight = getDisplayRegionHeight(),
3919 bMenuHasItems = (oMenu.getItems().length > 0),
3920 nMenuMinScrollHeight,
3924 if (nMenuOffsetHeight > nDisplayRegionHeight) {
3926 nMenuMinScrollHeight =
3927 bMenuHasItems ? oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) : nMenuOffsetHeight;
3930 if ((nDisplayRegionHeight > nMenuMinScrollHeight) && bMenuHasItems) {
3931 nMaxHeight = nDisplayRegionHeight;
3934 nMaxHeight = nInitialMaxHeight;
3938 oMenu._setScrollHeight(nMaxHeight);
3939 oMenu.hideEvent.subscribe(resetMaxHeight);
3942 // Re-align the Menu since its height has just changed
3943 // as a result of the setting of the maxheight property.
3948 if (nDisplayRegionHeight < nMenuMinScrollHeight) {
3953 All possible positions and values for the "maxheight"
3954 configuration property have been tried, but none were
3955 successful, so fall back to the original size and position.
3967 fnReturnVal = setVerticalPosition();
3974 else if (nMaxHeight && (nMaxHeight !== nInitialMaxHeight)) {
3976 oMenu._setScrollHeight(nInitialMaxHeight);
3977 oMenu.hideEvent.subscribe(resetMaxHeight);
3979 // Re-align the Menu since its height has just changed
3980 // as a result of the setting of the maxheight property.
3991 // Determine if the current value for the Menu's "y" configuration property will
3992 // result in the Menu being positioned outside the boundaries of the viewport
3994 if (y < topConstraint || y > bottomConstraint) {
3996 // The current value for the Menu's "y" configuration property WILL
3997 // result in the Menu being positioned outside the boundaries of the viewport
3999 if (bCanConstrain) {
4001 if (oMenu.cfg.getProperty(_PREVENT_CONTEXT_OVERLAP) && bPotentialContextOverlap) {
4004 // If the "preventcontextoverlap" configuration property is set to "true",
4005 // try to flip and/or scroll the Menu to both keep it inside the boundaries of the
4006 // viewport AND from overlaping its context element (MenuItem or MenuBarItem).
4008 oContextEl = aContext[0];
4009 nContextElHeight = oContextEl.offsetHeight;
4010 nContextElY = (Dom.getY(oContextEl) - scrollY);
4012 nTopRegionHeight = nContextElY;
4013 nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
4015 setVerticalPosition();
4017 yNew = oMenu.cfg.getProperty(_Y);
4020 else if (!(oMenu instanceof YAHOO.widget.MenuBar) &&
4021 nMenuOffsetHeight >= viewPortHeight) {
4024 // If the Menu exceeds the height of the viewport, introduce scroll bars
4025 // to keep the Menu inside the boundaries of the viewport
4027 nAvailableHeight = (viewPortHeight - (nViewportOffset * 2));
4029 if (nAvailableHeight > oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT)) {
4031 oMenu._setScrollHeight(nAvailableHeight);
4032 oMenu.hideEvent.subscribe(resetMaxHeight);
4036 yNew = oMenu.cfg.getProperty(_Y);
4045 if (y < topConstraint) {
4046 yNew = topConstraint;
4047 } else if (y > bottomConstraint) {
4048 yNew = bottomConstraint;
4055 // The "y" configuration property cannot be set to a value that will keep
4056 // entire Menu inside the boundary of the viewport. Therefore, set
4057 // the "y" configuration property to scrollY to keep as much of the
4058 // Menu inside the viewport as possible.
4059 yNew = nViewportOffset + scrollY;
4071 * @description "hide" event handler for the menu.
4073 * @param {String} p_sType String representing the name of the event that
4075 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4077 _onHide: function (p_sType, p_aArgs) {
4079 if (this.cfg.getProperty(_POSITION) === _DYNAMIC) {
4081 this.positionOffScreen();
4090 * @description "show" event handler for the menu.
4092 * @param {String} p_sType String representing the name of the event that
4094 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4096 _onShow: function (p_sType, p_aArgs) {
4098 var oParent = this.parent,
4105 function disableAutoSubmenuDisplay(p_oEvent) {
4109 if (p_oEvent.type == _MOUSEDOWN || (p_oEvent.type == _KEYDOWN && p_oEvent.keyCode == 27)) {
4112 Set the "autosubmenudisplay" to "false" if the user
4113 clicks outside the menu bar.
4116 oTarget = Event.getTarget(p_oEvent);
4118 if (oTarget != oParentMenu.element || !Dom.isAncestor(oParentMenu.element, oTarget)) {
4120 oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
4122 Event.removeListener(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
4123 Event.removeListener(document, _KEYDOWN, disableAutoSubmenuDisplay);
4132 function onSubmenuHide(p_sType, p_aArgs, p_sWidth) {
4134 this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4135 this.hideEvent.unsubscribe(onSubmenuHide, p_sWidth);
4142 oParentMenu = oParent.parent;
4145 if (!oParentMenu.cfg.getProperty(_AUTO_SUBMENU_DISPLAY) &&
4146 (oParentMenu instanceof YAHOO.widget.MenuBar ||
4147 oParentMenu.cfg.getProperty(_POSITION) == _STATIC)) {
4149 oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, true);
4151 Event.on(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
4152 Event.on(document, _KEYDOWN, disableAutoSubmenuDisplay);
4157 // The following fixes an issue with the selected state of a MenuItem
4158 // not rendering correctly when a submenu is aligned to the left of
4159 // its parent Menu instance.
4161 if ((this.cfg.getProperty("x") < oParentMenu.cfg.getProperty("x")) &&
4162 (UA.gecko && UA.gecko < 1.9) && !this.cfg.getProperty(_WIDTH)) {
4164 oElement = this.element;
4165 nOffsetWidth = oElement.offsetWidth;
4168 Measuring the difference of the offsetWidth before and after
4169 setting the "width" style attribute allows us to compute the
4170 about of padding and borders applied to the element, which in
4171 turn allows us to set the "width" property correctly.
4174 oElement.style.width = nOffsetWidth + _PX;
4176 sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4178 this.cfg.setProperty(_WIDTH, sWidth);
4180 this.hideEvent.subscribe(onSubmenuHide, sWidth);
4188 Dynamically positioned, root Menus focus themselves when visible, and
4189 will then, when hidden, restore focus to the UI control that had focus
4190 before the Menu was made visible.
4193 if (this === this.getRoot() && this.cfg.getProperty(_POSITION) === _DYNAMIC) {
4195 this._focusedElement = oFocusedElement;
4206 * @method _onBeforeHide
4207 * @description "beforehide" event handler for the menu.
4209 * @param {String} p_sType String representing the name of the event that
4211 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4213 _onBeforeHide: function (p_sType, p_aArgs) {
4215 var oActiveItem = this.activeItem,
4216 oRoot = this.getRoot(),
4223 oConfig = oActiveItem.cfg;
4225 oConfig.setProperty(_SELECTED, false);
4227 oSubmenu = oConfig.getProperty(_SUBMENU);
4239 Focus can get lost in IE when the mouse is moving from a submenu back to its parent Menu.
4240 For this reason, it is necessary to maintain the focused state in a private property
4241 so that the _onMouseOver event handler is able to determined whether or not to set focus
4242 to MenuItems as the user is moving the mouse.
4245 if (UA.ie && this.cfg.getProperty(_POSITION) === _DYNAMIC && this.parent) {
4247 oRoot._hasFocus = this.hasFocus();
4252 if (oRoot == this) {
4262 * @method _onParentMenuConfigChange
4263 * @description "configchange" event handler for a submenu.
4265 * @param {String} p_sType String representing the name of the event that
4267 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4268 * @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that
4269 * subscribed to the event.
4271 _onParentMenuConfigChange: function (p_sType, p_aArgs, p_oSubmenu) {
4273 var sPropertyName = p_aArgs[0][0],
4274 oPropertyValue = p_aArgs[0][1];
4276 switch(sPropertyName) {
4279 case _CONSTRAIN_TO_VIEWPORT:
4282 case _SUBMENU_HIDE_DELAY:
4283 case _CLICK_TO_HIDE:
4286 case _SCROLL_INCREMENT:
4288 case _MIN_SCROLL_HEIGHT:
4289 case _MONITOR_RESIZE:
4291 case _PREVENT_CONTEXT_OVERLAP:
4294 p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4298 case _SUBMENU_ALIGNMENT:
4300 if (!(this.parent.parent instanceof YAHOO.widget.MenuBar)) {
4302 p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4314 * @method _onParentMenuRender
4315 * @description "render" event handler for a submenu. Renders a
4316 * submenu in response to the firing of its parent's "render" event.
4318 * @param {String} p_sType String representing the name of the event that
4320 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4321 * @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that
4322 * subscribed to the event.
4324 _onParentMenuRender: function (p_sType, p_aArgs, p_oSubmenu) {
4326 var oParentMenu = p_oSubmenu.parent.parent,
4327 oParentCfg = oParentMenu.cfg,
4331 constraintoviewport: oParentCfg.getProperty(_CONSTRAIN_TO_VIEWPORT),
4335 clicktohide: oParentCfg.getProperty(_CLICK_TO_HIDE),
4337 effect: oParentCfg.getProperty(_EFFECT),
4339 showdelay: oParentCfg.getProperty(_SHOW_DELAY),
4341 hidedelay: oParentCfg.getProperty(_HIDE_DELAY),
4343 submenuhidedelay: oParentCfg.getProperty(_SUBMENU_HIDE_DELAY),
4345 classname: oParentCfg.getProperty(_CLASSNAME),
4347 scrollincrement: oParentCfg.getProperty(_SCROLL_INCREMENT),
4349 maxheight: oParentCfg.getProperty(_MAX_HEIGHT),
4351 minscrollheight: oParentCfg.getProperty(_MIN_SCROLL_HEIGHT),
4353 iframe: oParentCfg.getProperty(_IFRAME),
4355 shadow: oParentCfg.getProperty(_SHADOW),
4357 preventcontextoverlap: oParentCfg.getProperty(_PREVENT_CONTEXT_OVERLAP),
4359 monitorresize: oParentCfg.getProperty(_MONITOR_RESIZE),
4361 keepopen: oParentCfg.getProperty(_KEEP_OPEN)
4369 if (!(oParentMenu instanceof YAHOO.widget.MenuBar)) {
4371 oConfig[_SUBMENU_ALIGNMENT] = oParentCfg.getProperty(_SUBMENU_ALIGNMENT);
4376 p_oSubmenu.cfg.applyConfig(oConfig);
4379 if (!this.lazyLoad) {
4381 oLI = this.parent.element;
4383 if (this.element.parentNode == oLI) {
4400 * @method _onMenuItemDestroy
4401 * @description "destroy" event handler for the menu's items.
4403 * @param {String} p_sType String representing the name of the event
4405 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4406 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
4407 * that fired the event.
4409 _onMenuItemDestroy: function (p_sType, p_aArgs, p_oItem) {
4411 this._removeItemFromGroupByValue(p_oItem.groupIndex, p_oItem);
4417 * @method _onMenuItemConfigChange
4418 * @description "configchange" event handler for the menu's items.
4420 * @param {String} p_sType String representing the name of the event that
4422 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4423 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
4424 * that fired the event.
4426 _onMenuItemConfigChange: function (p_sType, p_aArgs, p_oItem) {
4428 var sPropertyName = p_aArgs[0][0],
4429 oPropertyValue = p_aArgs[0][1],
4433 switch(sPropertyName) {
4437 if (oPropertyValue === true) {
4439 this.activeItem = p_oItem;
4447 oSubmenu = p_aArgs[0][1];
4451 this._configureSubmenu(p_oItem);
4463 // Public event handlers for configuration properties
4467 * @method configVisible
4468 * @description Event handler for when the "visible" configuration property
4470 * @param {String} p_sType String representing the name of the event that
4472 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4473 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4476 configVisible: function (p_sType, p_aArgs, p_oMenu) {
4481 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4483 Menu.superclass.configVisible.call(this, p_sType, p_aArgs, p_oMenu);
4488 bVisible = p_aArgs[0];
4489 sDisplay = Dom.getStyle(this.element, _DISPLAY);
4491 Dom.setStyle(this.element, _VISIBILITY, _VISIBLE);
4495 if (sDisplay != _BLOCK) {
4496 this.beforeShowEvent.fire();
4497 Dom.setStyle(this.element, _DISPLAY, _BLOCK);
4498 this.showEvent.fire();
4504 if (sDisplay == _BLOCK) {
4505 this.beforeHideEvent.fire();
4506 Dom.setStyle(this.element, _DISPLAY, _NONE);
4507 this.hideEvent.fire();
4518 * @method configPosition
4519 * @description Event handler for when the "position" configuration property
4520 * of the menu changes.
4521 * @param {String} p_sType String representing the name of the event that
4523 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4524 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4527 configPosition: function (p_sType, p_aArgs, p_oMenu) {
4529 var oElement = this.element,
4530 sCSSPosition = p_aArgs[0] == _STATIC ? _STATIC : _ABSOLUTE,
4535 Dom.setStyle(oElement, _POSITION, sCSSPosition);
4538 if (sCSSPosition == _STATIC) {
4540 // Statically positioned menus are visible by default
4542 Dom.setStyle(oElement, _DISPLAY, _BLOCK);
4544 oCfg.setProperty(_VISIBLE, true);
4550 Even though the "visible" property is queued to
4551 "false" by default, we need to set the "visibility" property to
4552 "hidden" since Overlay's "configVisible" implementation checks the
4553 element's "visibility" style property before deciding whether
4554 or not to show an Overlay instance.
4557 Dom.setStyle(oElement, _VISIBILITY, _HIDDEN);
4562 if (sCSSPosition == _ABSOLUTE) {
4564 nZIndex = oCfg.getProperty(_ZINDEX);
4566 if (!nZIndex || nZIndex === 0) {
4568 oCfg.setProperty(_ZINDEX, 1);
4578 * @method configIframe
4579 * @description Event handler for when the "iframe" configuration property of
4581 * @param {String} p_sType String representing the name of the event that
4583 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4584 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4587 configIframe: function (p_sType, p_aArgs, p_oMenu) {
4589 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4591 Menu.superclass.configIframe.call(this, p_sType, p_aArgs, p_oMenu);
4599 * @method configHideDelay
4600 * @description Event handler for when the "hidedelay" configuration property
4601 * of the menu changes.
4602 * @param {String} p_sType String representing the name of the event that
4604 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4605 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4608 configHideDelay: function (p_sType, p_aArgs, p_oMenu) {
4610 var nHideDelay = p_aArgs[0];
4612 this._useHideDelay = (nHideDelay > 0);
4618 * @method configContainer
4619 * @description Event handler for when the "container" configuration property
4620 * of the menu changes.
4621 * @param {String} p_sType String representing the name of the event that
4623 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4624 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4627 configContainer: function (p_sType, p_aArgs, p_oMenu) {
4629 var oElement = p_aArgs[0];
4631 if (Lang.isString(oElement)) {
4633 this.cfg.setProperty(_CONTAINER, Dom.get(oElement), true);
4641 * @method _clearSetWidthFlag
4642 * @description Change event listener for the "width" configuration property. This listener is
4643 * added when a Menu's "width" configuration property is set by the "_setScrollHeight" method, and
4644 * is used to set the "_widthSetForScroll" property to "false" if the "width" configuration property
4645 * is changed after it was set by the "_setScrollHeight" method. If the "_widthSetForScroll"
4646 * property is set to "false", and the "_setScrollHeight" method is in the process of tearing down
4647 * scrolling functionality, it will maintain the Menu's new width rather than reseting it.
4650 _clearSetWidthFlag: function () {
4652 this._widthSetForScroll = false;
4654 this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4660 * @method _setScrollHeight
4662 * @param {String} p_nScrollHeight Number representing the scrolling height of the Menu.
4665 _setScrollHeight: function (p_nScrollHeight) {
4667 var nScrollHeight = p_nScrollHeight,
4668 bRefireIFrameAndShadow = false,
4682 if (this.getItems().length > 0) {
4684 oElement = this.element;
4686 oHeader = this.header;
4687 oFooter = this.footer;
4688 fnMouseOver = this._onScrollTargetMouseOver;
4689 fnMouseOut = this._onScrollTargetMouseOut;
4690 nMinScrollHeight = this.cfg.getProperty(_MIN_SCROLL_HEIGHT);
4693 if (nScrollHeight > 0 && nScrollHeight < nMinScrollHeight) {
4695 nScrollHeight = nMinScrollHeight;
4700 Dom.setStyle(oBody, _HEIGHT, _EMPTY_STRING);
4701 Dom.removeClass(oBody, _YUI_MENU_BODY_SCROLLED);
4702 oBody.scrollTop = 0;
4705 // Need to set a width for the Menu to fix the following problems in
4706 // Firefox 2 and IE:
4708 // #1) Scrolled Menus will render at 1px wide in Firefox 2
4710 // #2) There is a bug in gecko-based browsers where an element whose
4711 // "position" property is set to "absolute" and "overflow" property is
4712 // set to "hidden" will not render at the correct width when its
4713 // offsetParent's "position" property is also set to "absolute." It is
4714 // possible to work around this bug by specifying a value for the width
4715 // property in addition to overflow.
4717 // #3) In IE it is necessary to give the Menu a width before the
4718 // scrollbars are rendered to prevent the Menu from rendering with a
4719 // width that is 100% of the browser viewport.
4721 bSetWidth = ((UA.gecko && UA.gecko < 1.9) || UA.ie);
4723 if (nScrollHeight > 0 && bSetWidth && !this.cfg.getProperty(_WIDTH)) {
4725 nOffsetWidth = oElement.offsetWidth;
4728 Measuring the difference of the offsetWidth before and after
4729 setting the "width" style attribute allows us to compute the
4730 about of padding and borders applied to the element, which in
4731 turn allows us to set the "width" property correctly.
4734 oElement.style.width = nOffsetWidth + _PX;
4736 sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4739 this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4742 this.cfg.setProperty(_WIDTH, sWidth);
4746 Set a flag (_widthSetForScroll) to maintain some history regarding how the
4747 "width" configuration property was set. If the "width" configuration property
4748 is set by something other than the "_setScrollHeight" method, it will be
4749 necessary to maintain that new value and not clear the width if scrolling
4753 this._widthSetForScroll = true;
4755 this.cfg.subscribeToConfigEvent(_WIDTH, this._clearSetWidthFlag);
4760 if (nScrollHeight > 0 && (!oHeader && !oFooter)) {
4763 this.setHeader(_NON_BREAKING_SPACE);
4764 this.setFooter(_NON_BREAKING_SPACE);
4766 oHeader = this.header;
4767 oFooter = this.footer;
4769 Dom.addClass(oHeader, _TOP_SCROLLBAR);
4770 Dom.addClass(oFooter, _BOTTOM_SCROLLBAR);
4772 oElement.insertBefore(oHeader, oBody);
4773 oElement.appendChild(oFooter);
4778 nHeight = nScrollHeight;
4781 if (oHeader && oFooter) {
4782 nHeight = (nHeight - (oHeader.offsetHeight + oFooter.offsetHeight));
4786 if ((nHeight > 0) && (oBody.offsetHeight > nScrollHeight)) {
4789 Dom.addClass(oBody, _YUI_MENU_BODY_SCROLLED);
4790 Dom.setStyle(oBody, _HEIGHT, (nHeight + _PX));
4792 if (!this._hasScrollEventHandlers) {
4794 Event.on(oHeader, _MOUSEOVER, fnMouseOver, this, true);
4795 Event.on(oHeader, _MOUSEOUT, fnMouseOut, this, true);
4796 Event.on(oFooter, _MOUSEOVER, fnMouseOver, this, true);
4797 Event.on(oFooter, _MOUSEOUT, fnMouseOut, this, true);
4799 this._hasScrollEventHandlers = true;
4803 this._disableScrollHeader();
4804 this._enableScrollFooter();
4806 bRefireIFrameAndShadow = true;
4809 else if (oHeader && oFooter) {
4814 Only clear the "width" configuration property if it was set the
4815 "_setScrollHeight" method and wasn't changed by some other means after it was set.
4818 if (this._widthSetForScroll) {
4821 this._widthSetForScroll = false;
4823 this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4825 this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4830 this._enableScrollHeader();
4831 this._enableScrollFooter();
4833 if (this._hasScrollEventHandlers) {
4835 Event.removeListener(oHeader, _MOUSEOVER, fnMouseOver);
4836 Event.removeListener(oHeader, _MOUSEOUT, fnMouseOut);
4837 Event.removeListener(oFooter, _MOUSEOVER, fnMouseOver);
4838 Event.removeListener(oFooter, _MOUSEOUT, fnMouseOut);
4840 this._hasScrollEventHandlers = false;
4844 oElement.removeChild(oHeader);
4845 oElement.removeChild(oFooter);
4850 bRefireIFrameAndShadow = true;
4855 if (bRefireIFrameAndShadow) {
4857 this.cfg.refireEvent(_IFRAME);
4858 this.cfg.refireEvent(_SHADOW);
4868 * @method _setMaxHeight
4869 * @description "renderEvent" handler used to defer the setting of the
4870 * "maxheight" configuration property until the menu is rendered in lazy
4872 * @param {String} p_sType The name of the event that was fired.
4873 * @param {Array} p_aArgs Collection of arguments sent when the event
4875 * @param {Number} p_nMaxHeight Number representing the value to set for the
4876 * "maxheight" configuration property.
4879 _setMaxHeight: function (p_sType, p_aArgs, p_nMaxHeight) {
4881 this._setScrollHeight(p_nMaxHeight);
4882 this.renderEvent.unsubscribe(this._setMaxHeight);
4888 * @method configMaxHeight
4889 * @description Event handler for when the "maxheight" configuration property of
4891 * @param {String} p_sType The name of the event that was fired.
4892 * @param {Array} p_aArgs Collection of arguments sent when the event
4894 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired
4897 configMaxHeight: function (p_sType, p_aArgs, p_oMenu) {
4899 var nMaxHeight = p_aArgs[0];
4901 if (this.lazyLoad && !this.body && nMaxHeight > 0) {
4903 this.renderEvent.subscribe(this._setMaxHeight, nMaxHeight, this);
4908 this._setScrollHeight(nMaxHeight);
4916 * @method configClassName
4917 * @description Event handler for when the "classname" configuration property of
4919 * @param {String} p_sType The name of the event that was fired.
4920 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4921 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4923 configClassName: function (p_sType, p_aArgs, p_oMenu) {
4925 var sClassName = p_aArgs[0];
4927 if (this._sClassName) {
4929 Dom.removeClass(this.element, this._sClassName);
4933 Dom.addClass(this.element, sClassName);
4934 this._sClassName = sClassName;
4940 * @method _onItemAdded
4941 * @description "itemadded" event handler for a Menu instance.
4943 * @param {String} p_sType The name of the event that was fired.
4944 * @param {Array} p_aArgs Collection of arguments sent when the event
4947 _onItemAdded: function (p_sType, p_aArgs) {
4949 var oItem = p_aArgs[0];
4953 oItem.cfg.setProperty(_DISABLED, true);
4961 * @method configDisabled
4962 * @description Event handler for when the "disabled" configuration property of
4964 * @param {String} p_sType The name of the event that was fired.
4965 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4966 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4968 configDisabled: function (p_sType, p_aArgs, p_oMenu) {
4970 var bDisabled = p_aArgs[0],
4971 aItems = this.getItems(),
4975 if (Lang.isArray(aItems)) {
4977 nItems = aItems.length;
4985 aItems[i].cfg.setProperty(_DISABLED, bDisabled);
4995 this.clearActiveItem(true);
4997 Dom.addClass(this.element, _DISABLED);
4999 this.itemAddedEvent.subscribe(this._onItemAdded);
5004 Dom.removeClass(this.element, _DISABLED);
5006 this.itemAddedEvent.unsubscribe(this._onItemAdded);
5016 * @method configShadow
5017 * @description Event handler for when the "shadow" configuration property of
5019 * @param {String} p_sType The name of the event that was fired.
5020 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
5021 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
5023 configShadow: function (p_sType, p_aArgs, p_oMenu) {
5025 var sizeShadow = function () {
5027 var oElement = this.element,
5028 oShadow = this._shadow;
5030 if (oShadow && oElement) {
5032 // Clear the previous width
5034 if (oShadow.style.width && oShadow.style.height) {
5036 oShadow.style.width = _EMPTY_STRING;
5037 oShadow.style.height = _EMPTY_STRING;
5041 oShadow.style.width = (oElement.offsetWidth + 6) + _PX;
5042 oShadow.style.height = (oElement.offsetHeight + 1) + _PX;
5049 var replaceShadow = function () {
5051 this.element.appendChild(this._shadow);
5056 var addShadowVisibleClass = function () {
5058 Dom.addClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5063 var removeShadowVisibleClass = function () {
5065 Dom.removeClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5070 var createShadow = function () {
5072 var oShadow = this._shadow,
5077 oElement = this.element;
5080 if (!m_oShadowTemplate) {
5082 m_oShadowTemplate = document.createElement(_DIV_LOWERCASE);
5083 m_oShadowTemplate.className = _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE;
5087 oShadow = m_oShadowTemplate.cloneNode(false);
5089 oElement.appendChild(oShadow);
5091 this._shadow = oShadow;
5093 this.beforeShowEvent.subscribe(addShadowVisibleClass);
5094 this.beforeHideEvent.subscribe(removeShadowVisibleClass);
5100 Need to call sizeShadow & syncIframe via setTimeout for
5101 IE 7 Quirks Mode and IE 6 Standards Mode and Quirks Mode
5102 or the shadow and iframe shim will not be sized and
5103 positioned properly.
5106 Lang.later(0, this, function () {
5108 sizeShadow.call(this);
5114 this.cfg.subscribeToConfigEvent(_WIDTH, sizeShadow);
5115 this.cfg.subscribeToConfigEvent(_HEIGHT, sizeShadow);
5116 this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, sizeShadow);
5117 this.changeContentEvent.subscribe(sizeShadow);
5119 Module.textResizeEvent.subscribe(sizeShadow, this, true);
5121 this.destroyEvent.subscribe(function () {
5123 Module.textResizeEvent.unsubscribe(sizeShadow, this);
5129 this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, replaceShadow);
5136 var onBeforeShow = function () {
5140 // If called because the "shadow" event was refired - just append again and resize
5142 replaceShadow.call(this);
5145 sizeShadow.call(this);
5151 createShadow.call(this);
5155 this.beforeShowEvent.unsubscribe(onBeforeShow);
5160 var bShadow = p_aArgs[0];
5163 if (bShadow && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
5165 if (this.cfg.getProperty(_VISIBLE)) {
5169 // If the "shadow" event was refired - just append again and resize
5171 replaceShadow.call(this);
5174 sizeShadow.call(this);
5179 createShadow.call(this);
5185 this.beforeShowEvent.subscribe(onBeforeShow);
5199 * @method initEvents
5200 * @description Initializes the custom events for the menu.
5202 initEvents: function () {
5204 Menu.superclass.initEvents.call(this);
5206 // Create custom events
5208 var i = EVENT_TYPES.length - 1,
5215 aEventData = EVENT_TYPES[i];
5217 oCustomEvent = this.createEvent(aEventData[1]);
5218 oCustomEvent.signature = CustomEvent.LIST;
5220 this[aEventData[0]] = oCustomEvent;
5229 * @method positionOffScreen
5230 * @description Positions the menu outside of the boundaries of the browser's
5231 * viewport. Called automatically when a menu is hidden to ensure that
5232 * it doesn't force the browser to render uncessary scrollbars.
5234 positionOffScreen: function () {
5236 var oIFrame = this.iframe,
5237 oElement = this.element,
5238 sPos = this.OFF_SCREEN_POSITION;
5240 oElement.style.top = _EMPTY_STRING;
5241 oElement.style.left = _EMPTY_STRING;
5245 oIFrame.style.top = sPos;
5246 oIFrame.style.left = sPos;
5255 * @description Finds the menu's root menu.
5257 getRoot: function () {
5259 var oItem = this.parent,
5265 oParentMenu = oItem.parent;
5267 returnVal = oParentMenu ? oParentMenu.getRoot() : this;
5283 * @description Returns a string representing the menu.
5286 toString: function () {
5288 var sReturnVal = _MENU,
5293 sReturnVal += (_SPACE + sId);
5303 * @method setItemGroupTitle
5304 * @description Sets the title of a group of menu items.
5305 * @param {String} p_sGroupTitle String specifying the title of the group.
5306 * @param {Number} p_nGroupIndex Optional. Number specifying the group to which
5307 * the title belongs.
5309 setItemGroupTitle: function (p_sGroupTitle, p_nGroupIndex) {
5316 if (Lang.isString(p_sGroupTitle) && p_sGroupTitle.length > 0) {
5318 nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
5319 oTitle = this._aGroupTitleElements[nGroupIndex];
5324 oTitle.innerHTML = p_sGroupTitle;
5329 oTitle = document.createElement(this.GROUP_TITLE_TAG_NAME);
5331 oTitle.innerHTML = p_sGroupTitle;
5333 this._aGroupTitleElements[nGroupIndex] = oTitle;
5338 i = this._aGroupTitleElements.length - 1;
5342 if (this._aGroupTitleElements[i]) {
5344 Dom.removeClass(this._aGroupTitleElements[i], _FIRST_OF_TYPE);
5354 if (nFirstIndex !== null) {
5356 Dom.addClass(this._aGroupTitleElements[nFirstIndex],
5361 this.changeContentEvent.fire();
5371 * @description Appends an item to the menu.
5372 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
5373 * instance to be added to the menu.
5374 * @param {String} p_oItem String specifying the text of the item to be added
5376 * @param {Object} p_oItem Object literal containing a set of menu item
5377 * configuration properties.
5378 * @param {Number} p_nGroupIndex Optional. Number indicating the group to
5379 * which the item belongs.
5380 * @return {YAHOO.widget.MenuItem}
5382 addItem: function (p_oItem, p_nGroupIndex) {
5384 return this._addItemToGroup(p_nGroupIndex, p_oItem);
5391 * @description Adds an array of items to the menu.
5392 * @param {Array} p_aItems Array of items to be added to the menu. The array
5393 * can contain strings specifying the text for each item to be created, object
5394 * literals specifying each of the menu item configuration properties,
5395 * or MenuItem instances.
5396 * @param {Number} p_nGroupIndex Optional. Number specifying the group to
5397 * which the items belongs.
5400 addItems: function (p_aItems, p_nGroupIndex) {
5409 if (Lang.isArray(p_aItems)) {
5411 nItems = p_aItems.length;
5414 for(i=0; i<nItems; i++) {
5416 oItem = p_aItems[i];
5420 if (Lang.isArray(oItem)) {
5422 aItems[aItems.length] = this.addItems(oItem, i);
5427 aItems[aItems.length] = this._addItemToGroup(p_nGroupIndex, oItem);
5436 if (aItems.length) {
5450 * @method insertItem
5451 * @description Inserts an item into the menu at the specified index.
5452 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
5453 * instance to be added to the menu.
5454 * @param {String} p_oItem String specifying the text of the item to be added
5456 * @param {Object} p_oItem Object literal containing a set of menu item
5457 * configuration properties.
5458 * @param {Number} p_nItemIndex Number indicating the ordinal position at which
5459 * the item should be added.
5460 * @param {Number} p_nGroupIndex Optional. Number indicating the group to which
5462 * @return {YAHOO.widget.MenuItem}
5464 insertItem: function (p_oItem, p_nItemIndex, p_nGroupIndex) {
5466 return this._addItemToGroup(p_nGroupIndex, p_oItem, p_nItemIndex);
5472 * @method removeItem
5473 * @description Removes the specified item from the menu.
5474 * @param {YAHOO.widget.MenuItem} p_oObject Object reference for the MenuItem
5475 * instance to be removed from the menu.
5476 * @param {Number} p_oObject Number specifying the index of the item
5478 * @param {Number} p_nGroupIndex Optional. Number specifying the group to
5479 * which the item belongs.
5480 * @return {YAHOO.widget.MenuItem}
5482 removeItem: function (p_oObject, p_nGroupIndex) {
5487 if (!Lang.isUndefined(p_oObject)) {
5489 if (p_oObject instanceof YAHOO.widget.MenuItem) {
5491 oItem = this._removeItemFromGroupByValue(p_nGroupIndex, p_oObject);
5494 else if (Lang.isNumber(p_oObject)) {
5496 oItem = this._removeItemFromGroupByIndex(p_nGroupIndex, p_oObject);
5518 * @description Returns an array of all of the items in the menu.
5521 getItems: function () {
5523 var aGroups = this._aItemGroups,
5529 if (Lang.isArray(aGroups)) {
5531 nGroups = aGroups.length;
5533 returnVal = ((nGroups == 1) ? aGroups[0] : (Array.prototype.concat.apply(aItems, aGroups)));
5543 * @method getItemGroups
5544 * @description Multi-dimensional Array representing the menu items as they
5545 * are grouped in the menu.
5548 getItemGroups: function () {
5550 return this._aItemGroups;
5557 * @description Returns the item at the specified index.
5558 * @param {Number} p_nItemIndex Number indicating the ordinal position of the
5559 * item to be retrieved.
5560 * @param {Number} p_nGroupIndex Optional. Number indicating the group to which
5562 * @return {YAHOO.widget.MenuItem}
5564 getItem: function (p_nItemIndex, p_nGroupIndex) {
5569 if (Lang.isNumber(p_nItemIndex)) {
5571 aGroup = this._getItemGroup(p_nGroupIndex);
5575 returnVal = aGroup[p_nItemIndex];
5587 * @method getSubmenus
5588 * @description Returns an array of all of the submenus that are immediate
5589 * children of the menu.
5592 getSubmenus: function () {
5594 var aItems = this.getItems(),
5595 nItems = aItems.length,
5606 for(i=0; i<nItems; i++) {
5612 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5616 aSubmenus[aSubmenus.length] = oSubmenu;
5632 * @method clearContent
5633 * @description Removes all of the content from the menu, including the menu
5634 * items, group titles, header and footer.
5636 clearContent: function () {
5638 var aItems = this.getItems(),
5639 nItems = aItems.length,
5640 oElement = this.element,
5642 oHeader = this.header,
5643 oFooter = this.footer,
5659 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5663 this.cfg.configChangedEvent.unsubscribe(
5664 this._onParentMenuConfigChange, oSubmenu);
5666 this.renderEvent.unsubscribe(this._onParentMenuRender,
5671 this.removeItem(oItem, oItem.groupIndex);
5683 Event.purgeElement(oHeader);
5684 oElement.removeChild(oHeader);
5691 Event.purgeElement(oFooter);
5692 oElement.removeChild(oFooter);
5698 Event.purgeElement(oBody);
5700 oBody.innerHTML = _EMPTY_STRING;
5704 this.activeItem = null;
5706 this._aItemGroups = [];
5707 this._aListElements = [];
5708 this._aGroupTitleElements = [];
5710 this.cfg.setProperty(_WIDTH, null);
5717 * @description Removes the menu's <code><div></code> element
5718 * (and accompanying child nodes) from the document.
5720 destroy: function () {
5724 this.clearContent();
5726 this._aItemGroups = null;
5727 this._aListElements = null;
5728 this._aGroupTitleElements = null;
5731 // Continue with the superclass implementation of this method
5733 Menu.superclass.destroy.call(this);
5740 * @method setInitialFocus
5741 * @description Sets focus to the menu's first enabled item.
5743 setInitialFocus: function () {
5745 var oItem = this._getFirstEnabledItem();
5757 * @method setInitialSelection
5758 * @description Sets the "selected" configuration property of the menu's first
5759 * enabled item to "true."
5761 setInitialSelection: function () {
5763 var oItem = this._getFirstEnabledItem();
5767 oItem.cfg.setProperty(_SELECTED, true);
5774 * @method clearActiveItem
5775 * @description Sets the "selected" configuration property of the menu's active
5776 * item to "false" and hides the item's submenu.
5777 * @param {Boolean} p_bBlur Boolean indicating if the menu's active item
5778 * should be blurred.
5780 clearActiveItem: function (p_bBlur) {
5782 if (this.cfg.getProperty(_SHOW_DELAY) > 0) {
5784 this._cancelShowDelay();
5789 var oActiveItem = this.activeItem,
5795 oConfig = oActiveItem.cfg;
5801 this.getRoot()._hasFocus = true;
5805 oConfig.setProperty(_SELECTED, false);
5807 oSubmenu = oConfig.getProperty(_SUBMENU);
5816 this.activeItem = null;
5825 * @description Causes the menu to receive focus and fires the "focus" event.
5827 focus: function () {
5829 if (!this.hasFocus()) {
5831 this.setInitialFocus();
5840 * @description Causes the menu to lose focus and fires the "blur" event.
5846 if (this.hasFocus()) {
5848 oItem = MenuManager.getFocusedMenuItem();
5863 * @description Returns a boolean indicating whether or not the menu has focus.
5866 hasFocus: function () {
5868 return (MenuManager.getFocusedMenu() == this.getRoot());
5873 _doItemSubmenuSubscribe: function (p_sType, p_aArgs, p_oObject) {
5875 var oItem = p_aArgs[0],
5876 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5879 oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5885 _doSubmenuSubscribe: function (p_sType, p_aArgs, p_oObject) {
5887 var oSubmenu = this.cfg.getProperty(_SUBMENU);
5890 oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5897 * Adds the specified CustomEvent subscriber to the menu and each of
5900 * @param p_type {string} the type, or name of the event
5901 * @param p_fn {function} the function to exectute when the event fires
5902 * @param p_obj {Object} An object to be passed along when the event
5904 * @param p_override {boolean} If true, the obj passed in becomes the
5905 * execution scope of the listener
5907 subscribe: function () {
5909 // Subscribe to the event for this Menu instance
5910 Menu.superclass.subscribe.apply(this, arguments);
5912 // Subscribe to the "itemAdded" event so that all future submenus
5913 // also subscribe to this event
5914 Menu.superclass.subscribe.call(this, _ITEM_ADDED, this._doItemSubmenuSubscribe, arguments);
5917 var aItems = this.getItems(),
5926 nItems = aItems.length;
5935 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5938 oSubmenu.subscribe.apply(oSubmenu, arguments);
5941 oItem.cfg.subscribeToConfigEvent(_SUBMENU, this._doSubmenuSubscribe, arguments);
5954 unsubscribe: function () {
5956 // Remove the event for this Menu instance
5957 Menu.superclass.unsubscribe.apply(this, arguments);
5959 // Remove the "itemAdded" event so that all future submenus don't have
5960 // the event handler
5961 Menu.superclass.unsubscribe.call(this, _ITEM_ADDED, this._doItemSubmenuSubscribe, arguments);
5964 var aItems = this.getItems(),
5973 nItems = aItems.length;
5982 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5985 oSubmenu.unsubscribe.apply(oSubmenu, arguments);
5988 oItem.cfg.unsubscribeFromConfigEvent(_SUBMENU, this._doSubmenuSubscribe, arguments);
6002 * @description Initializes the class's configurable properties which can be
6003 * changed using the menu's Config object ("cfg").
6004 * @method initDefaultConfig
6006 initDefaultConfig: function () {
6008 Menu.superclass.initDefaultConfig.call(this);
6010 var oConfig = this.cfg;
6013 // Module documentation overrides
6017 * @description Object or array of objects representing the ContainerEffect
6018 * classes that are active for animating the container. When set this
6019 * property is automatically applied to all submenus.
6024 // Overlay documentation overrides
6029 * @description Number representing the absolute x-coordinate position of
6030 * the Menu. This property is only applied when the "position"
6031 * configuration property is set to dynamic.
6039 * @description Number representing the absolute y-coordinate position of
6040 * the Menu. This property is only applied when the "position"
6041 * configuration property is set to dynamic.
6048 * @description Array of the absolute x and y positions of the Menu. This
6049 * property is only applied when the "position" configuration property is
6059 * @description Array of context arguments for context-sensitive positioning.
6060 * The format is: [id or element, element corner, context corner].
6061 * For example, setting this property to ["img1", "tl", "bl"] would
6062 * align the Menu's top left corner to the context element's
6063 * bottom left corner. This property is only applied when the "position"
6064 * configuration property is set to dynamic.
6071 * @config fixedcenter
6072 * @description Boolean indicating if the Menu should be anchored to the
6073 * center of the viewport. This property is only applied when the
6074 * "position" configuration property is set to dynamic.
6082 * @description Boolean indicating whether or not the Menu should
6083 * have an IFRAME shim; used to prevent SELECT elements from
6084 * poking through an Overlay instance in IE6. When set to "true",
6085 * the iframe shim is created when the Menu instance is intially
6086 * made visible. This property is only applied when the "position"
6087 * configuration property is set to dynamic and is automatically applied
6090 * @default true for IE6 and below, false for all other browsers.
6094 // Add configuration attributes
6097 Change the default value for the "visible" configuration
6098 property to "false" by re-adding the property.
6103 * @description Boolean indicating whether or not the menu is visible. If
6104 * the menu's "position" configuration property is set to "dynamic" (the
6105 * default), this property toggles the menu's <code><div></code>
6106 * element's "visibility" style property between "visible" (true) or
6107 * "hidden" (false). If the menu's "position" configuration property is
6108 * set to "static" this property toggles the menu's
6109 * <code><div></code> element's "display" style property
6110 * between "block" (true) or "none" (false).
6114 oConfig.addProperty(
6117 handler: this.configVisible,
6118 value: VISIBLE_CONFIG.value,
6119 validator: VISIBLE_CONFIG.validator
6125 Change the default value for the "constraintoviewport" configuration
6126 property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6130 * @config constraintoviewport
6131 * @description Boolean indicating if the menu will try to remain inside
6132 * the boundaries of the size of viewport. This property is only applied
6133 * when the "position" configuration property is set to dynamic and is
6134 * automatically applied to all submenus.
6138 oConfig.addProperty(
6139 CONSTRAIN_TO_VIEWPORT_CONFIG.key,
6141 handler: this.configConstrainToViewport,
6142 value: CONSTRAIN_TO_VIEWPORT_CONFIG.value,
6143 validator: CONSTRAIN_TO_VIEWPORT_CONFIG.validator,
6144 supercedes: CONSTRAIN_TO_VIEWPORT_CONFIG.supercedes
6150 Change the default value for the "preventcontextoverlap" configuration
6151 property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6155 * @config preventcontextoverlap
6156 * @description Boolean indicating whether or not a submenu should overlap its parent MenuItem
6157 * when the "constraintoviewport" configuration property is set to "true".
6161 oConfig.addProperty(PREVENT_CONTEXT_OVERLAP_CONFIG.key, {
6163 value: PREVENT_CONTEXT_OVERLAP_CONFIG.value,
6164 validator: PREVENT_CONTEXT_OVERLAP_CONFIG.validator,
6165 supercedes: PREVENT_CONTEXT_OVERLAP_CONFIG.supercedes
6172 * @description String indicating how a menu should be positioned on the
6173 * screen. Possible values are "static" and "dynamic." Static menus are
6174 * visible by default and reside in the normal flow of the document
6175 * (CSS position: static). Dynamic menus are hidden by default, reside
6176 * out of the normal flow of the document (CSS position: absolute), and
6177 * can overlay other elements on the screen.
6181 oConfig.addProperty(
6182 POSITION_CONFIG.key,
6184 handler: this.configPosition,
6185 value: POSITION_CONFIG.value,
6186 validator: POSITION_CONFIG.validator,
6187 supercedes: POSITION_CONFIG.supercedes
6193 * @config submenualignment
6194 * @description Array defining how submenus should be aligned to their
6195 * parent menu item. The format is: [itemCorner, submenuCorner]. By default
6196 * a submenu's top left corner is aligned to its parent menu item's top
6198 * @default ["tl","tr"]
6201 oConfig.addProperty(
6202 SUBMENU_ALIGNMENT_CONFIG.key,
6204 value: SUBMENU_ALIGNMENT_CONFIG.value,
6205 suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
6211 * @config autosubmenudisplay
6212 * @description Boolean indicating if submenus are automatically made
6213 * visible when the user mouses over the menu's items.
6217 oConfig.addProperty(
6218 AUTO_SUBMENU_DISPLAY_CONFIG.key,
6220 value: AUTO_SUBMENU_DISPLAY_CONFIG.value,
6221 validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
6222 suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
6229 * @description Number indicating the time (in milliseconds) that should
6230 * expire before a submenu is made visible when the user mouses over
6231 * the menu's items. This property is only applied when the "position"
6232 * configuration property is set to dynamic and is automatically applied
6237 oConfig.addProperty(
6238 SHOW_DELAY_CONFIG.key,
6240 value: SHOW_DELAY_CONFIG.value,
6241 validator: SHOW_DELAY_CONFIG.validator,
6242 suppressEvent: SHOW_DELAY_CONFIG.suppressEvent
6249 * @description Number indicating the time (in milliseconds) that should
6250 * expire before the menu is hidden. This property is only applied when
6251 * the "position" configuration property is set to dynamic and is
6252 * automatically applied to all submenus.
6256 oConfig.addProperty(
6257 HIDE_DELAY_CONFIG.key,
6259 handler: this.configHideDelay,
6260 value: HIDE_DELAY_CONFIG.value,
6261 validator: HIDE_DELAY_CONFIG.validator,
6262 suppressEvent: HIDE_DELAY_CONFIG.suppressEvent
6268 * @config submenuhidedelay
6269 * @description Number indicating the time (in milliseconds) that should
6270 * expire before a submenu is hidden when the user mouses out of a menu item
6271 * heading in the direction of a submenu. The value must be greater than or
6272 * equal to the value specified for the "showdelay" configuration property.
6273 * This property is only applied when the "position" configuration property
6274 * is set to dynamic and is automatically applied to all submenus.
6278 oConfig.addProperty(
6279 SUBMENU_HIDE_DELAY_CONFIG.key,
6281 value: SUBMENU_HIDE_DELAY_CONFIG.value,
6282 validator: SUBMENU_HIDE_DELAY_CONFIG.validator,
6283 suppressEvent: SUBMENU_HIDE_DELAY_CONFIG.suppressEvent
6289 * @config clicktohide
6290 * @description Boolean indicating if the menu will automatically be
6291 * hidden if the user clicks outside of it. This property is only
6292 * applied when the "position" configuration property is set to dynamic
6293 * and is automatically applied to all submenus.
6297 oConfig.addProperty(
6298 CLICK_TO_HIDE_CONFIG.key,
6300 value: CLICK_TO_HIDE_CONFIG.value,
6301 validator: CLICK_TO_HIDE_CONFIG.validator,
6302 suppressEvent: CLICK_TO_HIDE_CONFIG.suppressEvent
6309 * @description HTML element reference or string specifying the id
6310 * attribute of the HTML element that the menu's markup should be
6312 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6313 * level-one-html.html#ID-58190037">HTMLElement</a>|String
6314 * @default document.body
6316 oConfig.addProperty(
6317 CONTAINER_CONFIG.key,
6319 handler: this.configContainer,
6320 value: document.body,
6321 suppressEvent: CONTAINER_CONFIG.suppressEvent
6327 * @config scrollincrement
6328 * @description Number used to control the scroll speed of a menu. Used to
6329 * increment the "scrollTop" property of the menu's body by when a menu's
6330 * content is scrolling. When set this property is automatically applied
6335 oConfig.addProperty(
6336 SCROLL_INCREMENT_CONFIG.key,
6338 value: SCROLL_INCREMENT_CONFIG.value,
6339 validator: SCROLL_INCREMENT_CONFIG.validator,
6340 supercedes: SCROLL_INCREMENT_CONFIG.supercedes,
6341 suppressEvent: SCROLL_INCREMENT_CONFIG.suppressEvent
6347 * @config minscrollheight
6348 * @description Number defining the minimum threshold for the "maxheight"
6349 * configuration property. When set this property is automatically applied
6354 oConfig.addProperty(
6355 MIN_SCROLL_HEIGHT_CONFIG.key,
6357 value: MIN_SCROLL_HEIGHT_CONFIG.value,
6358 validator: MIN_SCROLL_HEIGHT_CONFIG.validator,
6359 supercedes: MIN_SCROLL_HEIGHT_CONFIG.supercedes,
6360 suppressEvent: MIN_SCROLL_HEIGHT_CONFIG.suppressEvent
6367 * @description Number defining the maximum height (in pixels) for a menu's
6368 * body element (<code><div class="bd"></code>). Once a menu's body
6369 * exceeds this height, the contents of the body are scrolled to maintain
6370 * this value. This value cannot be set lower than the value of the
6371 * "minscrollheight" configuration property.
6375 oConfig.addProperty(
6376 MAX_HEIGHT_CONFIG.key,
6378 handler: this.configMaxHeight,
6379 value: MAX_HEIGHT_CONFIG.value,
6380 validator: MAX_HEIGHT_CONFIG.validator,
6381 suppressEvent: MAX_HEIGHT_CONFIG.suppressEvent,
6382 supercedes: MAX_HEIGHT_CONFIG.supercedes
6389 * @description String representing the CSS class to be applied to the
6390 * menu's root <code><div></code> element. The specified class(es)
6391 * are appended in addition to the default class as specified by the menu's
6392 * CSS_CLASS_NAME constant. When set this property is automatically
6393 * applied to all submenus.
6397 oConfig.addProperty(
6398 CLASS_NAME_CONFIG.key,
6400 handler: this.configClassName,
6401 value: CLASS_NAME_CONFIG.value,
6402 validator: CLASS_NAME_CONFIG.validator,
6403 supercedes: CLASS_NAME_CONFIG.supercedes
6410 * @description Boolean indicating if the menu should be disabled.
6411 * Disabling a menu disables each of its items. (Disabled menu items are
6412 * dimmed and will not respond to user input or fire events.) Disabled
6413 * menus have a corresponding "disabled" CSS class applied to their root
6414 * <code><div></code> element.
6418 oConfig.addProperty(
6419 DISABLED_CONFIG.key,
6421 handler: this.configDisabled,
6422 value: DISABLED_CONFIG.value,
6423 validator: DISABLED_CONFIG.validator,
6424 suppressEvent: DISABLED_CONFIG.suppressEvent
6431 * @description Boolean indicating if the menu should have a shadow.
6435 oConfig.addProperty(
6438 handler: this.configShadow,
6439 value: SHADOW_CONFIG.value,
6440 validator: SHADOW_CONFIG.validator
6447 * @description Boolean indicating if the menu should remain open when clicked.
6451 oConfig.addProperty(
6452 KEEP_OPEN_CONFIG.key,
6454 value: KEEP_OPEN_CONFIG.value,
6455 validator: KEEP_OPEN_CONFIG.validator
6461 }); // END YAHOO.lang.extend
6470 * Creates an item for a menu.
6472 * @param {String} p_oObject String specifying the text of the menu item.
6473 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6474 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying
6475 * the <code><li></code> element of the menu item.
6476 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6477 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
6478 * specifying the <code><optgroup></code> element of the menu item.
6479 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6480 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object
6481 * specifying the <code><option></code> element of the menu item.
6482 * @param {Object} p_oConfig Optional. Object literal specifying the
6483 * configuration for the menu item. See configuration class documentation
6488 YAHOO.widget.MenuItem = function (p_oObject, p_oConfig) {
6494 this.parent = p_oConfig.parent;
6495 this.value = p_oConfig.value;
6496 this.id = p_oConfig.id;
6500 this.init(p_oObject, p_oConfig);
6507 var Dom = YAHOO.util.Dom,
6508 Module = YAHOO.widget.Module,
6509 Menu = YAHOO.widget.Menu,
6510 MenuItem = YAHOO.widget.MenuItem,
6511 CustomEvent = YAHOO.util.CustomEvent,
6515 // Private string constants
6520 _HELP_TEXT = "helptext",
6523 _EMPHASIS = "emphasis",
6524 _STRONG_EMPHASIS = "strongemphasis",
6525 _CHECKED = "checked",
6526 _SUBMENU = "submenu",
6527 _DISABLED = "disabled",
6528 _SELECTED = "selected",
6529 _HAS_SUBMENU = "hassubmenu",
6530 _CHECKED_DISABLED = "checked-disabled",
6531 _HAS_SUBMENU_DISABLED = "hassubmenu-disabled",
6532 _HAS_SUBMENU_SELECTED = "hassubmenu-selected",
6533 _CHECKED_SELECTED = "checked-selected",
6534 _ONCLICK = "onclick",
6535 _CLASSNAME = "classname",
6538 _OPTGROUP = "OPTGROUP",
6539 _LI_UPPERCASE = "LI",
6543 _START_HELP_TEXT = "<em class=\"helptext\">",
6546 _START_STRONG = "<strong>",
6547 _END_STRONG = "</strong>",
6548 _PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
6552 _VISIBLE = "visible",
6554 _MENUITEM = "MenuItem",
6558 _LI_LOWERCASE = "li",
6559 _ANCHOR_TEMPLATE = "<a href=\"#\"></a>",
6563 ["mouseOverEvent", "mouseover"],
6564 ["mouseOutEvent", "mouseout"],
6565 ["mouseDownEvent", "mousedown"],
6566 ["mouseUpEvent", "mouseup"],
6567 ["clickEvent", _CLICK],
6568 ["keyPressEvent", "keypress"],
6569 ["keyDownEvent", "keydown"],
6570 ["keyUpEvent", "keyup"],
6571 ["focusEvent", "focus"],
6572 ["blurEvent", "blur"],
6573 ["destroyEvent", "destroy"]
6579 value: _EMPTY_STRING,
6580 validator: Lang.isString,
6584 HELP_TEXT_CONFIG = {
6586 supercedes: [_TEXT],
6604 validator: Lang.isBoolean,
6605 suppressEvent: true,
6609 STRONG_EMPHASIS_CONFIG = {
6610 key: _STRONG_EMPHASIS,
6612 validator: Lang.isBoolean,
6613 suppressEvent: true,
6620 validator: Lang.isBoolean,
6621 suppressEvent: true,
6622 supercedes: [_DISABLED, _SELECTED]
6627 suppressEvent: true,
6628 supercedes: [_DISABLED, _SELECTED]
6634 validator: Lang.isBoolean,
6635 suppressEvent: true,
6636 supercedes: [_TEXT, _SELECTED]
6642 validator: Lang.isBoolean,
6651 CLASS_NAME_CONFIG = {
6654 validator: Lang.isString,
6658 KEY_LISTENER_CONFIG = {
6664 m_oMenuItemTemplate = null,
6670 * @method getClassNameForState
6671 * @description Returns a class name for the specified prefix and state. If the class name does not
6672 * yet exist, it is created and stored in the CLASS_NAMES object to increase performance.
6674 * @param {String} prefix String representing the prefix for the class name
6675 * @param {String} state String representing a state - "disabled," "checked," etc.
6677 var getClassNameForState = function (prefix, state) {
6679 var oClassNames = CLASS_NAMES[prefix];
6682 CLASS_NAMES[prefix] = {};
6683 oClassNames = CLASS_NAMES[prefix];
6687 var sClassName = oClassNames[state];
6690 sClassName = prefix + _HYPHEN + state;
6691 oClassNames[state] = sClassName;
6700 * @method addClassNameForState
6701 * @description Applies a class name to a MenuItem instance's <LI> and <A> elements
6702 * that represents a MenuItem's state - "disabled," "checked," etc.
6704 * @param {String} state String representing a state - "disabled," "checked," etc.
6706 var addClassNameForState = function (state) {
6708 Dom.addClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6709 Dom.addClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6714 * @method removeClassNameForState
6715 * @description Removes a class name from a MenuItem instance's <LI> and <A> elements
6716 * that represents a MenuItem's state - "disabled," "checked," etc.
6718 * @param {String} state String representing a state - "disabled," "checked," etc.
6720 var removeClassNameForState = function (state) {
6722 Dom.removeClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6723 Dom.removeClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6728 MenuItem.prototype = {
6731 * @property CSS_CLASS_NAME
6732 * @description String representing the CSS class(es) to be applied to the
6733 * <code><li></code> element of the menu item.
6734 * @default "yuimenuitem"
6738 CSS_CLASS_NAME: "yuimenuitem",
6742 * @property CSS_LABEL_CLASS_NAME
6743 * @description String representing the CSS class(es) to be applied to the
6744 * menu item's <code><a></code> element.
6745 * @default "yuimenuitemlabel"
6749 CSS_LABEL_CLASS_NAME: "yuimenuitemlabel",
6753 * @property SUBMENU_TYPE
6754 * @description Object representing the type of menu to instantiate and
6755 * add when parsing the child nodes of the menu item's source HTML element.
6757 * @type YAHOO.widget.Menu
6763 // Private member variables
6767 * @property _oAnchor
6768 * @description Object reference to the menu item's
6769 * <code><a></code> element.
6772 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6773 * one-html.html#ID-48250443">HTMLAnchorElement</a>
6779 * @property _oHelpTextEM
6780 * @description Object reference to the menu item's help text
6781 * <code><em></code> element.
6784 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6785 * one-html.html#ID-58190037">HTMLElement</a>
6791 * @property _oSubmenu
6792 * @description Object reference to the menu item's submenu.
6795 * @type YAHOO.widget.Menu
6801 * @property _oOnclickAttributeValue
6802 * @description Object reference to the menu item's current value for the
6803 * "onclick" configuration attribute.
6808 _oOnclickAttributeValue: null,
6812 * @property _sClassName
6813 * @description The current value of the "classname" configuration attribute.
6822 // Public properties
6826 * @property constructor
6827 * @description Object reference to the menu item's constructor function.
6828 * @default YAHOO.widget.MenuItem
6829 * @type YAHOO.widget.MenuItem
6831 constructor: MenuItem,
6836 * @description Number indicating the ordinal position of the menu item in
6845 * @property groupIndex
6846 * @description Number indicating the index of the group to which the menu
6856 * @description Object reference to the menu item's parent menu.
6858 * @type YAHOO.widget.Menu
6865 * @description Object reference to the menu item's
6866 * <code><li></code> element.
6867 * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level
6868 * -one-html.html#ID-74680021">HTMLLIElement</a>
6869 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6870 * one-html.html#ID-74680021">HTMLLIElement</a>
6876 * @property srcElement
6877 * @description Object reference to the HTML element (either
6878 * <code><li></code>, <code><optgroup></code> or
6879 * <code><option></code>) used create the menu item.
6880 * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6881 * level-one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.
6882 * w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247"
6883 * >HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6884 * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6885 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6886 * one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.w3.
6887 * org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247">
6888 * HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6889 * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6896 * @description Object reference to the menu item's value.
6905 * @deprecated Use YAHOO.env.ua
6906 * @description String representing the browser.
6909 browser: Module.prototype.browser,
6914 * @description Id of the menu item's root <code><li></code>
6915 * element. This property should be set via the constructor using the
6916 * configuration object literal. If an id is not specified, then one will
6917 * be created using the "generateId" method of the Dom utility.
6929 * @event destroyEvent
6930 * @description Fires when the menu item's <code><li></code>
6931 * element is removed from its parent <code><ul></code> element.
6932 * @type YAHOO.util.CustomEvent
6937 * @event mouseOverEvent
6938 * @description Fires when the mouse has entered the menu item. Passes
6939 * back the DOM Event object as an argument.
6940 * @type YAHOO.util.CustomEvent
6945 * @event mouseOutEvent
6946 * @description Fires when the mouse has left the menu item. Passes back
6947 * the DOM Event object as an argument.
6948 * @type YAHOO.util.CustomEvent
6953 * @event mouseDownEvent
6954 * @description Fires when the user mouses down on the menu item. Passes
6955 * back the DOM Event object as an argument.
6956 * @type YAHOO.util.CustomEvent
6961 * @event mouseUpEvent
6962 * @description Fires when the user releases a mouse button while the mouse
6963 * is over the menu item. Passes back the DOM Event object as an argument.
6964 * @type YAHOO.util.CustomEvent
6970 * @description Fires when the user clicks the on the menu item. Passes
6971 * back the DOM Event object as an argument.
6972 * @type YAHOO.util.CustomEvent
6977 * @event keyPressEvent
6978 * @description Fires when the user presses an alphanumeric key when the
6979 * menu item has focus. Passes back the DOM Event object as an argument.
6980 * @type YAHOO.util.CustomEvent
6985 * @event keyDownEvent
6986 * @description Fires when the user presses a key when the menu item has
6987 * focus. Passes back the DOM Event object as an argument.
6988 * @type YAHOO.util.CustomEvent
6994 * @description Fires when the user releases a key when the menu item has
6995 * focus. Passes back the DOM Event object as an argument.
6996 * @type YAHOO.util.CustomEvent
7002 * @description Fires when the menu item receives focus.
7003 * @type YAHOO.util.CustomEvent
7009 * @description Fires when the menu item loses the input focus.
7010 * @type YAHOO.util.CustomEvent
7016 * @description The MenuItem class's initialization method. This method is
7017 * automatically called by the constructor, and sets up all DOM references
7018 * for pre-existing markup, and creates required markup if it is not
7020 * @param {String} p_oObject String specifying the text of the menu item.
7021 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7022 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying
7023 * the <code><li></code> element of the menu item.
7024 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7025 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
7026 * specifying the <code><optgroup></code> element of the menu item.
7027 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7028 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object
7029 * specifying the <code><option></code> element of the menu item.
7030 * @param {Object} p_oConfig Optional. Object literal specifying the
7031 * configuration for the menu item. See configuration class documentation
7034 init: function (p_oObject, p_oConfig) {
7037 if (!this.SUBMENU_TYPE) {
7039 this.SUBMENU_TYPE = Menu;
7044 // Create the config object
7046 this.cfg = new YAHOO.util.Config(this);
7048 this.initDefaultConfig();
7050 var oConfig = this.cfg,
7061 if (Lang.isString(p_oObject)) {
7063 this._createRootNodeStructure();
7065 oConfig.queueProperty(_TEXT, p_oObject);
7068 else if (p_oObject && p_oObject.tagName) {
7070 switch(p_oObject.tagName.toUpperCase()) {
7074 this._createRootNodeStructure();
7076 oConfig.queueProperty(_TEXT, p_oObject.text);
7077 oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7079 this.value = p_oObject.value;
7081 this.srcElement = p_oObject;
7087 this._createRootNodeStructure();
7089 oConfig.queueProperty(_TEXT, p_oObject.label);
7090 oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7092 this.srcElement = p_oObject;
7094 this._initSubTree();
7100 // Get the anchor node (if it exists)
7102 oAnchor = Dom.getFirstChild(p_oObject);
7105 // Capture the "text" and/or the "URL"
7109 sURL = oAnchor.getAttribute(_HREF, 2);
7110 sTarget = oAnchor.getAttribute(_TARGET);
7112 sText = oAnchor.innerHTML;
7116 this.srcElement = p_oObject;
7117 this.element = p_oObject;
7118 this._oAnchor = oAnchor;
7121 Set these properties silently to sync up the
7122 configuration object without making changes to the
7126 oConfig.setProperty(_TEXT, sText, true);
7127 oConfig.setProperty(_URL, sURL, true);
7128 oConfig.setProperty(_TARGET, sTarget, true);
7130 this._initSubTree();
7141 sId = (this.srcElement || this.element).id;
7145 sId = this.id || Dom.generateId();
7147 this.element.id = sId;
7154 Dom.addClass(this.element, this.CSS_CLASS_NAME);
7155 Dom.addClass(this._oAnchor, this.CSS_LABEL_CLASS_NAME);
7158 i = EVENT_TYPES.length - 1;
7162 aEventData = EVENT_TYPES[i];
7164 oCustomEvent = this.createEvent(aEventData[1]);
7165 oCustomEvent.signature = CustomEvent.LIST;
7167 this[aEventData[0]] = oCustomEvent;
7175 oConfig.applyConfig(p_oConfig);
7179 oConfig.fireQueue();
7190 * @method _createRootNodeStructure
7191 * @description Creates the core DOM structure for the menu item.
7194 _createRootNodeStructure: function () {
7199 if (!m_oMenuItemTemplate) {
7201 m_oMenuItemTemplate = document.createElement(_LI_LOWERCASE);
7202 m_oMenuItemTemplate.innerHTML = _ANCHOR_TEMPLATE;
7206 oElement = m_oMenuItemTemplate.cloneNode(true);
7207 oElement.className = this.CSS_CLASS_NAME;
7209 oAnchor = oElement.firstChild;
7210 oAnchor.className = this.CSS_LABEL_CLASS_NAME;
7212 this.element = oElement;
7213 this._oAnchor = oAnchor;
7219 * @method _initSubTree
7220 * @description Iterates the source element's childNodes collection and uses
7221 * the child nodes to instantiate other menus.
7224 _initSubTree: function () {
7226 var oSrcEl = this.srcElement,
7235 if (oSrcEl.childNodes.length > 0) {
7237 if (this.parent.lazyLoad && this.parent.srcElement &&
7238 this.parent.srcElement.tagName.toUpperCase() == _SELECT) {
7240 oConfig.setProperty(
7242 { id: Dom.generateId(), itemdata: oSrcEl.childNodes }
7248 oNode = oSrcEl.firstChild;
7253 if (oNode && oNode.tagName) {
7255 switch(oNode.tagName.toUpperCase()) {
7259 oConfig.setProperty(_SUBMENU, oNode);
7265 aOptions[aOptions.length] = oNode;
7274 while((oNode = oNode.nextSibling));
7277 nOptions = aOptions.length;
7281 oMenu = new this.SUBMENU_TYPE(Dom.generateId());
7283 oConfig.setProperty(_SUBMENU, oMenu);
7285 for(n=0; n<nOptions; n++) {
7287 oMenu.addItem((new oMenu.ITEM_TYPE(aOptions[n])));
7301 // Event handlers for configuration properties
7305 * @method configText
7306 * @description Event handler for when the "text" configuration property of
7307 * the menu item changes.
7308 * @param {String} p_sType String representing the name of the event that
7310 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7311 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7312 * that fired the event.
7314 configText: function (p_sType, p_aArgs, p_oItem) {
7316 var sText = p_aArgs[0],
7318 oAnchor = this._oAnchor,
7319 sHelpText = oConfig.getProperty(_HELP_TEXT),
7320 sHelpTextHTML = _EMPTY_STRING,
7321 sEmphasisStartTag = _EMPTY_STRING,
7322 sEmphasisEndTag = _EMPTY_STRING;
7330 sHelpTextHTML = _START_HELP_TEXT + sHelpText + _END_EM;
7335 if (oConfig.getProperty(_EMPHASIS)) {
7337 sEmphasisStartTag = _START_EM;
7338 sEmphasisEndTag = _END_EM;
7343 if (oConfig.getProperty(_STRONG_EMPHASIS)) {
7345 sEmphasisStartTag = _START_STRONG;
7346 sEmphasisEndTag = _END_STRONG;
7351 oAnchor.innerHTML = (sEmphasisStartTag + sText + sEmphasisEndTag + sHelpTextHTML);
7359 * @method configHelpText
7360 * @description Event handler for when the "helptext" configuration property
7361 * of the menu item changes.
7362 * @param {String} p_sType String representing the name of the event that
7364 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7365 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7366 * that fired the event.
7368 configHelpText: function (p_sType, p_aArgs, p_oItem) {
7370 this.cfg.refireEvent(_TEXT);
7377 * @description Event handler for when the "url" configuration property of
7378 * the menu item changes.
7379 * @param {String} p_sType String representing the name of the event that
7381 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7382 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7383 * that fired the event.
7385 configURL: function (p_sType, p_aArgs, p_oItem) {
7387 var sURL = p_aArgs[0];
7395 var oAnchor = this._oAnchor;
7399 oAnchor.removeAttribute(_HREF);
7403 oAnchor.setAttribute(_HREF, sURL);
7409 * @method configTarget
7410 * @description Event handler for when the "target" configuration property
7411 * of the menu item changes.
7412 * @param {String} p_sType String representing the name of the event that
7414 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7415 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7416 * that fired the event.
7418 configTarget: function (p_sType, p_aArgs, p_oItem) {
7420 var sTarget = p_aArgs[0],
7421 oAnchor = this._oAnchor;
7423 if (sTarget && sTarget.length > 0) {
7425 oAnchor.setAttribute(_TARGET, sTarget);
7430 oAnchor.removeAttribute(_TARGET);
7438 * @method configEmphasis
7439 * @description Event handler for when the "emphasis" configuration property
7440 * of the menu item changes.
7441 * @param {String} p_sType String representing the name of the event that
7443 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7444 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7445 * that fired the event.
7447 configEmphasis: function (p_sType, p_aArgs, p_oItem) {
7449 var bEmphasis = p_aArgs[0],
7453 if (bEmphasis && oConfig.getProperty(_STRONG_EMPHASIS)) {
7455 oConfig.setProperty(_STRONG_EMPHASIS, false);
7460 oConfig.refireEvent(_TEXT);
7466 * @method configStrongEmphasis
7467 * @description Event handler for when the "strongemphasis" configuration
7468 * property of the menu item changes.
7469 * @param {String} p_sType String representing the name of the event that
7471 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7472 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7473 * that fired the event.
7475 configStrongEmphasis: function (p_sType, p_aArgs, p_oItem) {
7477 var bStrongEmphasis = p_aArgs[0],
7481 if (bStrongEmphasis && oConfig.getProperty(_EMPHASIS)) {
7483 oConfig.setProperty(_EMPHASIS, false);
7487 oConfig.refireEvent(_TEXT);
7493 * @method configChecked
7494 * @description Event handler for when the "checked" configuration property
7495 * of the menu item changes.
7496 * @param {String} p_sType String representing the name of the event that
7498 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7499 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7500 * that fired the event.
7502 configChecked: function (p_sType, p_aArgs, p_oItem) {
7504 var bChecked = p_aArgs[0],
7510 addClassNameForState.call(this, _CHECKED);
7515 removeClassNameForState.call(this, _CHECKED);
7519 oConfig.refireEvent(_TEXT);
7522 if (oConfig.getProperty(_DISABLED)) {
7524 oConfig.refireEvent(_DISABLED);
7529 if (oConfig.getProperty(_SELECTED)) {
7531 oConfig.refireEvent(_SELECTED);
7540 * @method configDisabled
7541 * @description Event handler for when the "disabled" configuration property
7542 * of the menu item changes.
7543 * @param {String} p_sType String representing the name of the event that
7545 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7546 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7547 * that fired the event.
7549 configDisabled: function (p_sType, p_aArgs, p_oItem) {
7551 var bDisabled = p_aArgs[0],
7553 oSubmenu = oConfig.getProperty(_SUBMENU),
7554 bChecked = oConfig.getProperty(_CHECKED);
7559 if (oConfig.getProperty(_SELECTED)) {
7561 oConfig.setProperty(_SELECTED, false);
7566 addClassNameForState.call(this, _DISABLED);
7571 addClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7578 addClassNameForState.call(this, _CHECKED_DISABLED);
7585 removeClassNameForState.call(this, _DISABLED);
7590 removeClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7597 removeClassNameForState.call(this, _CHECKED_DISABLED);
7607 * @method configSelected
7608 * @description Event handler for when the "selected" configuration property
7609 * of the menu item changes.
7610 * @param {String} p_sType String representing the name of the event that
7612 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7613 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7614 * that fired the event.
7616 configSelected: function (p_sType, p_aArgs, p_oItem) {
7618 var oConfig = this.cfg,
7619 oAnchor = this._oAnchor,
7621 bSelected = p_aArgs[0],
7622 bChecked = oConfig.getProperty(_CHECKED),
7623 oSubmenu = oConfig.getProperty(_SUBMENU);
7633 if (bSelected && !oConfig.getProperty(_DISABLED)) {
7635 addClassNameForState.call(this, _SELECTED);
7640 addClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7647 addClassNameForState.call(this, _CHECKED_SELECTED);
7654 removeClassNameForState.call(this, _SELECTED);
7659 removeClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7666 removeClassNameForState.call(this, _CHECKED_SELECTED);
7673 if (this.hasFocus() && UA.opera) {
7683 * @method _onSubmenuBeforeHide
7684 * @description "beforehide" Custom Event handler for a submenu.
7686 * @param {String} p_sType String representing the name of the event that
7688 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7690 _onSubmenuBeforeHide: function (p_sType, p_aArgs) {
7692 var oItem = this.parent,
7697 oItem._oAnchor.blur();
7698 oMenu.beforeHideEvent.unsubscribe(onHide);
7703 if (oItem.hasFocus()) {
7705 oMenu = oItem.parent;
7707 oMenu.beforeHideEvent.subscribe(onHide);
7715 * @method configSubmenu
7716 * @description Event handler for when the "submenu" configuration property
7717 * of the menu item changes.
7718 * @param {String} p_sType String representing the name of the event that
7720 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7721 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7722 * that fired the event.
7724 configSubmenu: function (p_sType, p_aArgs, p_oItem) {
7726 var oSubmenu = p_aArgs[0],
7728 bLazyLoad = this.parent && this.parent.lazyLoad,
7736 if (oSubmenu instanceof Menu) {
7739 oMenu.parent = this;
7740 oMenu.lazyLoad = bLazyLoad;
7743 else if (Lang.isObject(oSubmenu) && oSubmenu.id && !oSubmenu.nodeType) {
7745 sSubmenuId = oSubmenu.id;
7746 oSubmenuConfig = oSubmenu;
7748 oSubmenuConfig.lazyload = bLazyLoad;
7749 oSubmenuConfig.parent = this;
7751 oMenu = new this.SUBMENU_TYPE(sSubmenuId, oSubmenuConfig);
7754 // Set the value of the property to the Menu instance
7756 oConfig.setProperty(_SUBMENU, oMenu, true);
7761 oMenu = new this.SUBMENU_TYPE(oSubmenu, { lazyload: bLazyLoad, parent: this });
7764 // Set the value of the property to the Menu instance
7766 oConfig.setProperty(_SUBMENU, oMenu, true);
7773 oMenu.cfg.setProperty(_PREVENT_CONTEXT_OVERLAP, true);
7775 addClassNameForState.call(this, _HAS_SUBMENU);
7778 if (oConfig.getProperty(_URL) === _HASH) {
7780 oConfig.setProperty(_URL, (_HASH + oMenu.id));
7785 this._oSubmenu = oMenu;
7790 oMenu.beforeHideEvent.subscribe(this._onSubmenuBeforeHide);
7799 removeClassNameForState.call(this, _HAS_SUBMENU);
7801 if (this._oSubmenu) {
7803 this._oSubmenu.destroy();
7810 if (oConfig.getProperty(_DISABLED)) {
7812 oConfig.refireEvent(_DISABLED);
7817 if (oConfig.getProperty(_SELECTED)) {
7819 oConfig.refireEvent(_SELECTED);
7827 * @method configOnClick
7828 * @description Event handler for when the "onclick" configuration property
7829 * of the menu item changes.
7830 * @param {String} p_sType String representing the name of the event that
7832 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7833 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7834 * that fired the event.
7836 configOnClick: function (p_sType, p_aArgs, p_oItem) {
7838 var oObject = p_aArgs[0];
7841 Remove any existing listeners if a "click" event handler has
7842 already been specified.
7845 if (this._oOnclickAttributeValue && (this._oOnclickAttributeValue != oObject)) {
7847 this.clickEvent.unsubscribe(this._oOnclickAttributeValue.fn,
7848 this._oOnclickAttributeValue.obj);
7850 this._oOnclickAttributeValue = null;
7855 if (!this._oOnclickAttributeValue && Lang.isObject(oObject) &&
7856 Lang.isFunction(oObject.fn)) {
7858 this.clickEvent.subscribe(oObject.fn,
7859 ((_OBJ in oObject) ? oObject.obj : this),
7860 ((_SCOPE in oObject) ? oObject.scope : null) );
7862 this._oOnclickAttributeValue = oObject;
7870 * @method configClassName
7871 * @description Event handler for when the "classname" configuration
7872 * property of a menu item changes.
7873 * @param {String} p_sType String representing the name of the event that
7875 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7876 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7877 * that fired the event.
7879 configClassName: function (p_sType, p_aArgs, p_oItem) {
7881 var sClassName = p_aArgs[0];
7883 if (this._sClassName) {
7885 Dom.removeClass(this.element, this._sClassName);
7889 Dom.addClass(this.element, sClassName);
7890 this._sClassName = sClassName;
7896 * @method _dispatchClickEvent
7897 * @description Dispatches a DOM "click" event to the anchor element of a
7898 * MenuItem instance.
7901 _dispatchClickEvent: function () {
7903 var oMenuItem = this,
7907 if (!oMenuItem.cfg.getProperty(_DISABLED)) {
7909 oAnchor = Dom.getFirstChild(oMenuItem.element);
7911 // Dispatch a "click" event to the MenuItem's anchor so that its
7912 // "click" event handlers will get called in response to the user
7913 // pressing the keyboard shortcut defined by the "keylistener"
7914 // configuration property.
7917 oAnchor.fireEvent(_ONCLICK);
7921 if ((UA.gecko && UA.gecko >= 1.9) || UA.opera || UA.webkit) {
7923 oEvent = document.createEvent("HTMLEvents");
7924 oEvent.initEvent(_CLICK, true, true);
7929 oEvent = document.createEvent("MouseEvents");
7930 oEvent.initMouseEvent(_CLICK, true, true, window, 0, 0, 0,
7931 0, 0, false, false, false, false, 0, null);
7935 oAnchor.dispatchEvent(oEvent);
7945 * @method _createKeyListener
7946 * @description "show" event handler for a Menu instance - responsible for
7947 * setting up the KeyListener instance for a MenuItem.
7949 * @param {String} type String representing the name of the event that
7951 * @param {Array} args Array of arguments sent when the event was fired.
7952 * @param {Array} keyData Array of arguments sent when the event was fired.
7954 _createKeyListener: function (type, args, keyData) {
7956 var oMenuItem = this,
7957 oMenu = oMenuItem.parent;
7959 var oKeyListener = new YAHOO.util.KeyListener(
7960 oMenu.element.ownerDocument,
7963 fn: oMenuItem._dispatchClickEvent,
7965 correctScope: true });
7968 if (oMenu.cfg.getProperty(_VISIBLE)) {
7969 oKeyListener.enable();
7973 oMenu.subscribe(_SHOW, oKeyListener.enable, null, oKeyListener);
7974 oMenu.subscribe(_HIDE, oKeyListener.disable, null, oKeyListener);
7976 oMenuItem._keyListener = oKeyListener;
7978 oMenu.unsubscribe(_SHOW, oMenuItem._createKeyListener, keyData);
7984 * @method configKeyListener
7985 * @description Event handler for when the "keylistener" configuration
7986 * property of a menu item changes.
7987 * @param {String} p_sType String representing the name of the event that
7989 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7991 configKeyListener: function (p_sType, p_aArgs) {
7993 var oKeyData = p_aArgs[0],
7995 oMenu = oMenuItem.parent;
7997 if (oMenuItem._keyData) {
7999 // Unsubscribe from the "show" event in case the keylistener
8000 // config was changed before the Menu was ever made visible.
8002 oMenu.unsubscribe(_SHOW,
8003 oMenuItem._createKeyListener, oMenuItem._keyData);
8005 oMenuItem._keyData = null;
8010 // Tear down for the previous value of the "keylistener" property
8012 if (oMenuItem._keyListener) {
8014 oMenu.unsubscribe(_SHOW, oMenuItem._keyListener.enable);
8015 oMenu.unsubscribe(_HIDE, oMenuItem._keyListener.disable);
8017 oMenuItem._keyListener.disable();
8018 oMenuItem._keyListener = null;
8025 oMenuItem._keyData = oKeyData;
8027 // Defer the creation of the KeyListener instance until the
8028 // parent Menu is visible. This is necessary since the
8029 // KeyListener instance needs to be bound to the document the
8030 // Menu has been rendered into. Deferring creation of the
8031 // KeyListener instance also improves performance.
8033 oMenu.subscribe(_SHOW, oMenuItem._createKeyListener,
8034 oKeyData, oMenuItem);
8044 * @method initDefaultConfig
8045 * @description Initializes an item's configurable properties.
8047 initDefaultConfig : function () {
8049 var oConfig = this.cfg;
8052 // Define the configuration attributes
8056 * @description String specifying the text label for the menu item.
8057 * When building a menu from existing HTML the value of this property
8058 * will be interpreted from the menu's markup.
8062 oConfig.addProperty(
8065 handler: this.configText,
8066 value: TEXT_CONFIG.value,
8067 validator: TEXT_CONFIG.validator,
8068 suppressEvent: TEXT_CONFIG.suppressEvent
8075 * @description String specifying additional instructional text to
8076 * accompany the text for the menu item.
8077 * @deprecated Use "text" configuration property to add help text markup.
8078 * For example: <code>oMenuItem.cfg.setProperty("text", "Copy <em
8079 * class=\"helptext\">Ctrl + C</em>");</code>
8081 * @type String|<a href="http://www.w3.org/TR/
8082 * 2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8085 oConfig.addProperty(
8086 HELP_TEXT_CONFIG.key,
8088 handler: this.configHelpText,
8089 supercedes: HELP_TEXT_CONFIG.supercedes,
8090 suppressEvent: HELP_TEXT_CONFIG.suppressEvent
8097 * @description String specifying the URL for the menu item's anchor's
8098 * "href" attribute. When building a menu from existing HTML the value
8099 * of this property will be interpreted from the menu's markup.
8103 oConfig.addProperty(
8106 handler: this.configURL,
8107 value: URL_CONFIG.value,
8108 suppressEvent: URL_CONFIG.suppressEvent
8115 * @description String specifying the value for the "target" attribute
8116 * of the menu item's anchor element. <strong>Specifying a target will
8117 * require the user to click directly on the menu item's anchor node in
8118 * order to cause the browser to navigate to the specified URL.</strong>
8119 * When building a menu from existing HTML the value of this property
8120 * will be interpreted from the menu's markup.
8124 oConfig.addProperty(
8127 handler: this.configTarget,
8128 suppressEvent: TARGET_CONFIG.suppressEvent
8135 * @description Boolean indicating if the text of the menu item will be
8136 * rendered with emphasis.
8137 * @deprecated Use the "text" configuration property to add emphasis.
8138 * For example: <code>oMenuItem.cfg.setProperty("text", "<em>Some
8139 * Text</em>");</code>
8143 oConfig.addProperty(
8144 EMPHASIS_CONFIG.key,
8146 handler: this.configEmphasis,
8147 value: EMPHASIS_CONFIG.value,
8148 validator: EMPHASIS_CONFIG.validator,
8149 suppressEvent: EMPHASIS_CONFIG.suppressEvent,
8150 supercedes: EMPHASIS_CONFIG.supercedes
8156 * @config strongemphasis
8157 * @description Boolean indicating if the text of the menu item will be
8158 * rendered with strong emphasis.
8159 * @deprecated Use the "text" configuration property to add strong emphasis.
8160 * For example: <code>oMenuItem.cfg.setProperty("text", "<strong>
8161 * Some Text</strong>");</code>
8165 oConfig.addProperty(
8166 STRONG_EMPHASIS_CONFIG.key,
8168 handler: this.configStrongEmphasis,
8169 value: STRONG_EMPHASIS_CONFIG.value,
8170 validator: STRONG_EMPHASIS_CONFIG.validator,
8171 suppressEvent: STRONG_EMPHASIS_CONFIG.suppressEvent,
8172 supercedes: STRONG_EMPHASIS_CONFIG.supercedes
8179 * @description Boolean indicating if the menu item should be rendered
8184 oConfig.addProperty(
8187 handler: this.configChecked,
8188 value: CHECKED_CONFIG.value,
8189 validator: CHECKED_CONFIG.validator,
8190 suppressEvent: CHECKED_CONFIG.suppressEvent,
8191 supercedes: CHECKED_CONFIG.supercedes
8198 * @description Boolean indicating if the menu item should be disabled.
8199 * (Disabled menu items are dimmed and will not respond to user input
8204 oConfig.addProperty(
8205 DISABLED_CONFIG.key,
8207 handler: this.configDisabled,
8208 value: DISABLED_CONFIG.value,
8209 validator: DISABLED_CONFIG.validator,
8210 suppressEvent: DISABLED_CONFIG.suppressEvent
8217 * @description Boolean indicating if the menu item should
8222 oConfig.addProperty(
8223 SELECTED_CONFIG.key,
8225 handler: this.configSelected,
8226 value: SELECTED_CONFIG.value,
8227 validator: SELECTED_CONFIG.validator,
8228 suppressEvent: SELECTED_CONFIG.suppressEvent
8235 * @description Object specifying the submenu to be appended to the
8236 * menu item. The value can be one of the following: <ul><li>Object
8237 * specifying a Menu instance.</li><li>Object literal specifying the
8238 * menu to be created. Format: <code>{ id: [menu id], itemdata:
8239 * [<a href="YAHOO.widget.Menu.html#itemData">array of values for
8240 * items</a>] }</code>.</li><li>String specifying the id attribute
8241 * of the <code><div></code> element of the menu.</li><li>
8242 * Object specifying the <code><div></code> element of the
8245 * @type Menu|String|Object|<a href="http://www.w3.org/TR/2000/
8246 * WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8249 oConfig.addProperty(
8252 handler: this.configSubmenu,
8253 supercedes: SUBMENU_CONFIG.supercedes,
8254 suppressEvent: SUBMENU_CONFIG.suppressEvent
8261 * @description Object literal representing the code to be executed when
8262 * the item is clicked. Format:<br> <code> {<br>
8263 * <strong>fn:</strong> Function, // The handler to call when
8264 * the event fires.<br> <strong>obj:</strong> Object, // An
8265 * object to pass back to the handler.<br> <strong>scope:</strong>
8266 * Object // The object to use for the scope of the handler.
8271 oConfig.addProperty(
8274 handler: this.configOnClick,
8275 suppressEvent: ONCLICK_CONFIG.suppressEvent
8282 * @description CSS class to be applied to the menu item's root
8283 * <code><li></code> element. The specified class(es) are
8284 * appended in addition to the default class as specified by the menu
8285 * item's CSS_CLASS_NAME constant.
8289 oConfig.addProperty(
8290 CLASS_NAME_CONFIG.key,
8292 handler: this.configClassName,
8293 value: CLASS_NAME_CONFIG.value,
8294 validator: CLASS_NAME_CONFIG.validator,
8295 suppressEvent: CLASS_NAME_CONFIG.suppressEvent
8301 * @config keylistener
8302 * @description Object literal representing the key(s) that can be used
8303 * to trigger the MenuItem's "click" event. Possible attributes are
8304 * shift (boolean), alt (boolean), ctrl (boolean) and keys (either an int
8305 * or an array of ints representing keycodes).
8309 oConfig.addProperty(
8310 KEY_LISTENER_CONFIG.key,
8312 handler: this.configKeyListener,
8313 value: KEY_LISTENER_CONFIG.value,
8314 suppressEvent: KEY_LISTENER_CONFIG.suppressEvent
8321 * @method getNextSibling
8322 * @description Finds the menu item's next sibling.
8323 * @return YAHOO.widget.MenuItem
8325 getNextSibling: function () {
8327 var isUL = function (el) {
8328 return (el.nodeName.toLowerCase() === "ul");
8331 menuitemEl = this.element,
8332 next = Dom.getNextSibling(menuitemEl),
8339 parent = menuitemEl.parentNode;
8340 sibling = Dom.getNextSiblingBy(parent, isUL);
8346 list = Dom.getFirstChildBy(parent.parentNode, isUL);
8349 next = Dom.getFirstChild(list);
8353 return YAHOO.widget.MenuManager.getMenuItem(next.id);
8358 * @method getNextEnabledSibling
8359 * @description Finds the menu item's next enabled sibling.
8360 * @return YAHOO.widget.MenuItem
8362 getNextEnabledSibling: function () {
8364 var next = this.getNextSibling();
8366 return (next.cfg.getProperty(_DISABLED) || next.element.style.display == _NONE) ? next.getNextEnabledSibling() : next;
8372 * @method getPreviousSibling
8373 * @description Finds the menu item's previous sibling.
8374 * @return {YAHOO.widget.MenuItem}
8376 getPreviousSibling: function () {
8378 var isUL = function (el) {
8379 return (el.nodeName.toLowerCase() === "ul");
8382 menuitemEl = this.element,
8383 next = Dom.getPreviousSibling(menuitemEl),
8390 parent = menuitemEl.parentNode;
8391 sibling = Dom.getPreviousSiblingBy(parent, isUL);
8397 list = Dom.getLastChildBy(parent.parentNode, isUL);
8400 next = Dom.getLastChild(list);
8404 return YAHOO.widget.MenuManager.getMenuItem(next.id);
8410 * @method getPreviousEnabledSibling
8411 * @description Finds the menu item's previous enabled sibling.
8412 * @return {YAHOO.widget.MenuItem}
8414 getPreviousEnabledSibling: function () {
8416 var next = this.getPreviousSibling();
8418 return (next.cfg.getProperty(_DISABLED) || next.element.style.display == _NONE) ? next.getPreviousEnabledSibling() : next;
8425 * @description Causes the menu item to receive the focus and fires the
8428 focus: function () {
8430 var oParent = this.parent,
8431 oAnchor = this._oAnchor,
8432 oActiveItem = oParent.activeItem;
8435 function setFocus() {
8439 if (!(UA.ie && !document.hasFocus())) {
8443 oActiveItem.blurEvent.fire();
8449 this.focusEvent.fire();
8461 if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE) &&
8462 this.element.style.display != _NONE) {
8466 Setting focus via a timer fixes a race condition in Firefox, IE
8467 and Opera where the browser viewport jumps as it trys to
8468 position and focus the menu.
8471 Lang.later(0, this, setFocus);
8480 * @description Causes the menu item to lose focus and fires the
8485 var oParent = this.parent;
8487 if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE)) {
8489 Lang.later(0, this, function () {
8493 this._oAnchor.blur();
8494 this.blurEvent.fire();
8510 * @description Returns a boolean indicating whether or not the menu item
8514 hasFocus: function () {
8516 return (YAHOO.widget.MenuManager.getFocusedMenuItem() == this);
8523 * @description Removes the menu item's <code><li></code> element
8524 * from its parent <code><ul></code> element.
8526 destroy: function () {
8528 var oEl = this.element,
8538 // If the item has a submenu, destroy it first
8540 oSubmenu = this.cfg.getProperty(_SUBMENU);
8549 // Remove the element from the parent node
8551 oParentNode = oEl.parentNode;
8555 oParentNode.removeChild(oEl);
8557 this.destroyEvent.fire();
8562 // Remove CustomEvent listeners
8564 i = EVENT_TYPES.length - 1;
8568 aEventData = EVENT_TYPES[i];
8570 this[aEventData[0]].unsubscribeAll();
8576 this.cfg.configChangedEvent.unsubscribeAll();
8585 * @description Returns a string representing the menu item.
8588 toString: function () {
8590 var sReturnVal = _MENUITEM,
8595 sReturnVal += (_SPACE + sId);
8605 Lang.augmentProto(MenuItem, YAHOO.util.EventProvider);
8611 _MOUSEDOWN = "mousedown",
8612 _CONTEXTMENU = "ContextMenu",
8616 * Creates a list of options or commands which are made visible in response to
8617 * an HTML element's "contextmenu" event ("mousedown" for Opera).
8619 * @param {String} p_oElement String specifying the id attribute of the
8620 * <code><div></code> element of the context menu.
8621 * @param {String} p_oElement String specifying the id attribute of the
8622 * <code><select></code> element to be used as the data source for the
8624 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8625 * html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the
8626 * <code><div></code> element of the context menu.
8627 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8628 * html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying
8629 * the <code><select></code> element to be used as the data source for
8631 * @param {Object} p_oConfig Optional. Object literal specifying the
8632 * configuration for the context menu. See configuration class documentation
8634 * @class ContextMenu
8636 * @extends YAHOO.widget.Menu
8637 * @namespace YAHOO.widget
8639 YAHOO.widget.ContextMenu = function(p_oElement, p_oConfig) {
8641 YAHOO.widget.ContextMenu.superclass.constructor.call(this, p_oElement, p_oConfig);
8646 var Event = YAHOO.util.Event,
8648 ContextMenu = YAHOO.widget.ContextMenu,
8653 * Constant representing the name of the ContextMenu's events
8654 * @property EVENT_TYPES
8661 "TRIGGER_CONTEXT_MENU": "triggerContextMenu",
8662 "CONTEXT_MENU": (UA.opera ? _MOUSEDOWN : "contextmenu"),
8669 * Constant representing the ContextMenu's configuration properties
8670 * @property DEFAULT_CONFIG
8683 * @description "beforeShow" event handler used to position the contextmenu.
8685 * @param {String} p_sType String representing the name of the event that
8687 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
8688 * @param {Array} p_aPos Array representing the xy position for the context menu.
8690 function position(p_sType, p_aArgs, p_aPos) {
8692 this.cfg.setProperty(_XY, p_aPos);
8694 this.beforeShowEvent.unsubscribe(position, p_aPos);
8699 YAHOO.lang.extend(ContextMenu, YAHOO.widget.Menu, {
8703 // Private properties
8707 * @property _oTrigger
8708 * @description Object reference to the current value of the "trigger"
8709 * configuration property.
8712 * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/leve
8713 * l-one-html.html#ID-58190037">HTMLElement</a>|Array
8719 * @property _bCancelled
8720 * @description Boolean indicating if the display of the context menu should
8730 // Public properties
8734 * @property contextEventTarget
8735 * @description Object reference for the HTML element that was the target of the
8736 * "contextmenu" DOM event ("mousedown" for Opera) that triggered the display of
8739 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8740 * html.html#ID-58190037">HTMLElement</a>
8742 contextEventTarget: null,
8750 * @event triggerContextMenuEvent
8751 * @description Custom Event wrapper for the "contextmenu" DOM event
8752 * ("mousedown" for Opera) fired by the element(s) that trigger the display of
8755 triggerContextMenuEvent: null,
8761 * @description The ContextMenu class's initialization method. This method is
8762 * automatically called by the constructor, and sets up all DOM references for
8763 * pre-existing markup, and creates required markup if it is not already present.
8764 * @param {String} p_oElement String specifying the id attribute of the
8765 * <code><div></code> element of the context menu.
8766 * @param {String} p_oElement String specifying the id attribute of the
8767 * <code><select></code> element to be used as the data source for
8769 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8770 * html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the
8771 * <code><div></code> element of the context menu.
8772 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8773 * html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying
8774 * the <code><select></code> element to be used as the data source for
8776 * @param {Object} p_oConfig Optional. Object literal specifying the
8777 * configuration for the context menu. See configuration class documentation
8780 init: function(p_oElement, p_oConfig) {
8783 // Call the init of the superclass (YAHOO.widget.Menu)
8785 ContextMenu.superclass.init.call(this, p_oElement);
8788 this.beforeInitEvent.fire(ContextMenu);
8793 this.cfg.applyConfig(p_oConfig, true);
8797 this.initEvent.fire(ContextMenu);
8803 * @method initEvents
8804 * @description Initializes the custom events for the context menu.
8806 initEvents: function() {
8808 ContextMenu.superclass.initEvents.call(this);
8810 // Create custom events
8812 this.triggerContextMenuEvent = this.createEvent(EVENT_TYPES.TRIGGER_CONTEXT_MENU);
8814 this.triggerContextMenuEvent.signature = YAHOO.util.CustomEvent.LIST;
8821 * @description Cancels the display of the context menu.
8823 cancel: function() {
8825 this._bCancelled = true;
8835 * @method _removeEventHandlers
8836 * @description Removes all of the DOM event handlers from the HTML element(s)
8837 * whose "context menu" event ("click" for Opera) trigger the display of
8841 _removeEventHandlers: function() {
8843 var oTrigger = this._oTrigger;
8846 // Remove the event handlers from the trigger(s)
8850 Event.removeListener(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu);
8854 Event.removeListener(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick);
8864 // Private event handlers
8869 * @method _onTriggerClick
8870 * @description "click" event handler for the HTML element(s) identified as the
8871 * "trigger" for the context menu. Used to cancel default behaviors in Opera.
8873 * @param {Event} p_oEvent Object representing the DOM event object passed back
8874 * by the event utility (YAHOO.util.Event).
8875 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8876 * menu that is handling the event.
8878 _onTriggerClick: function(p_oEvent, p_oMenu) {
8880 if (p_oEvent.ctrlKey) {
8882 Event.stopEvent(p_oEvent);
8890 * @method _onTriggerContextMenu
8891 * @description "contextmenu" event handler ("mousedown" for Opera) for the HTML
8892 * element(s) that trigger the display of the context menu.
8894 * @param {Event} p_oEvent Object representing the DOM event object passed back
8895 * by the event utility (YAHOO.util.Event).
8896 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8897 * menu that is handling the event.
8899 _onTriggerContextMenu: function(p_oEvent, p_oMenu) {
8903 if (!(p_oEvent.type == _MOUSEDOWN && !p_oEvent.ctrlKey)) {
8905 this.contextEventTarget = Event.getTarget(p_oEvent);
8907 this.triggerContextMenuEvent.fire(p_oEvent);
8910 if (!this._bCancelled) {
8913 Prevent the browser's default context menu from appearing and
8914 stop the propagation of the "contextmenu" event so that
8915 other ContextMenu instances are not displayed.
8918 Event.stopEvent(p_oEvent);
8921 // Hide any other Menu instances that might be visible
8923 YAHOO.widget.MenuManager.hideVisible();
8927 // Position and display the context menu
8929 aXY = Event.getXY(p_oEvent);
8932 if (!YAHOO.util.Dom.inDocument(this.element)) {
8934 this.beforeShowEvent.subscribe(position, aXY);
8939 this.cfg.setProperty(_XY, aXY);
8948 this._bCancelled = false;
8961 * @description Returns a string representing the context menu.
8964 toString: function() {
8966 var sReturnVal = _CONTEXTMENU,
8971 sReturnVal += (_SPACE + sId);
8981 * @method initDefaultConfig
8982 * @description Initializes the class's configurable properties which can be
8983 * changed using the context menu's Config object ("cfg").
8985 initDefaultConfig: function() {
8987 ContextMenu.superclass.initDefaultConfig.call(this);
8991 * @description The HTML element(s) whose "contextmenu" event ("mousedown"
8992 * for Opera) trigger the display of the context menu. Can be a string
8993 * representing the id attribute of the HTML element, an object reference
8994 * for the HTML element, or an array of strings or HTML element references.
8996 * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
8997 * level-one-html.html#ID-58190037">HTMLElement</a>|Array
8999 this.cfg.addProperty(TRIGGER_CONFIG.key,
9001 handler: this.configTrigger,
9002 suppressEvent: TRIGGER_CONFIG.suppressEvent
9011 * @description Removes the context menu's <code><div></code> element
9012 * (and accompanying child nodes) from the document.
9014 destroy: function() {
9016 // Remove the DOM event handlers from the current trigger(s)
9018 this._removeEventHandlers();
9021 // Continue with the superclass implementation of this method
9023 ContextMenu.superclass.destroy.call(this);
9029 // Public event handlers for configuration properties
9033 * @method configTrigger
9034 * @description Event handler for when the value of the "trigger" configuration
9036 * @param {String} p_sType String representing the name of the event that
9038 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
9039 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
9040 * menu that fired the event.
9042 configTrigger: function(p_sType, p_aArgs, p_oMenu) {
9044 var oTrigger = p_aArgs[0];
9049 If there is a current "trigger" - remove the event handlers
9050 from that element(s) before assigning new ones
9053 if (this._oTrigger) {
9055 this._removeEventHandlers();
9059 this._oTrigger = oTrigger;
9063 Listen for the "mousedown" event in Opera b/c it does not
9064 support the "contextmenu" event
9067 Event.on(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu, this, true);
9071 Assign a "click" event handler to the trigger element(s) for
9072 Opera to prevent default browser behaviors.
9077 Event.on(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick, this, true);
9084 this._removeEventHandlers();
9090 }); // END YAHOO.lang.extend
9097 * Creates an item for a context menu.
9099 * @param {String} p_oObject String specifying the text of the context menu item.
9100 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9101 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9102 * <code><li></code> element of the context menu item.
9103 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9104 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9105 * specifying the <code><optgroup></code> element of the context
9107 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9108 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9109 * the <code><option></code> element of the context menu item.
9110 * @param {Object} p_oConfig Optional. Object literal specifying the
9111 * configuration for the context menu item. See configuration class
9112 * documentation for more details.
9113 * @class ContextMenuItem
9115 * @extends YAHOO.widget.MenuItem
9116 * @deprecated As of version 2.4.0 items for YAHOO.widget.ContextMenu instances
9117 * are of type YAHOO.widget.MenuItem.
9119 YAHOO.widget.ContextMenuItem = YAHOO.widget.MenuItem;
9122 var Lang = YAHOO.lang,
9127 _DYNAMIC_STATIC = "dynamic," + _STATIC,
9128 _DISABLED = "disabled",
9129 _SELECTED = "selected",
9130 _AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
9131 _SUBMENU = "submenu",
9132 _VISIBLE = "visible",
9134 _SUBMENU_TOGGLE_REGION = "submenutoggleregion",
9135 _MENUBAR = "MenuBar";
9138 * Horizontal collection of items, each of which can contain a submenu.
9140 * @param {String} p_oElement String specifying the id attribute of the
9141 * <code><div></code> element of the menu bar.
9142 * @param {String} p_oElement String specifying the id attribute of the
9143 * <code><select></code> element to be used as the data source for the
9145 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9146 * one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying
9147 * the <code><div></code> element of the menu bar.
9148 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9149 * one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object
9150 * specifying the <code><select></code> element to be used as the data
9151 * source for the menu bar.
9152 * @param {Object} p_oConfig Optional. Object literal specifying the
9153 * configuration for the menu bar. See configuration class documentation for
9157 * @extends YAHOO.widget.Menu
9158 * @namespace YAHOO.widget
9160 YAHOO.widget.MenuBar = function(p_oElement, p_oConfig) {
9162 YAHOO.widget.MenuBar.superclass.constructor.call(this, p_oElement, p_oConfig);
9168 * @method checkPosition
9169 * @description Checks to make sure that the value of the "position" property
9170 * is one of the supported strings. Returns true if the position is supported.
9172 * @param {Object} p_sPosition String specifying the position of the menu.
9175 function checkPosition(p_sPosition) {
9177 var returnVal = false;
9179 if (Lang.isString(p_sPosition)) {
9181 returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
9190 var Event = YAHOO.util.Event,
9191 MenuBar = YAHOO.widget.MenuBar,
9196 validator: checkPosition,
9197 supercedes: [_VISIBLE]
9200 SUBMENU_ALIGNMENT_CONFIG = {
9201 key: "submenualignment",
9205 AUTO_SUBMENU_DISPLAY_CONFIG = {
9206 key: _AUTO_SUBMENU_DISPLAY,
9208 validator: Lang.isBoolean,
9212 SUBMENU_TOGGLE_REGION_CONFIG = {
9213 key: _SUBMENU_TOGGLE_REGION,
9215 validator: Lang.isBoolean
9220 Lang.extend(MenuBar, YAHOO.widget.Menu, {
9224 * @description The MenuBar class's initialization method. This method is
9225 * automatically called by the constructor, and sets up all DOM references for
9226 * pre-existing markup, and creates required markup if it is not already present.
9227 * @param {String} p_oElement String specifying the id attribute of the
9228 * <code><div></code> element of the menu bar.
9229 * @param {String} p_oElement String specifying the id attribute of the
9230 * <code><select></code> element to be used as the data source for the
9232 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9233 * one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying
9234 * the <code><div></code> element of the menu bar.
9235 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9236 * one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object
9237 * specifying the <code><select></code> element to be used as the data
9238 * source for the menu bar.
9239 * @param {Object} p_oConfig Optional. Object literal specifying the
9240 * configuration for the menu bar. See configuration class documentation for
9243 init: function(p_oElement, p_oConfig) {
9245 if(!this.ITEM_TYPE) {
9247 this.ITEM_TYPE = YAHOO.widget.MenuBarItem;
9252 // Call the init of the superclass (YAHOO.widget.Menu)
9254 MenuBar.superclass.init.call(this, p_oElement);
9257 this.beforeInitEvent.fire(MenuBar);
9262 this.cfg.applyConfig(p_oConfig, true);
9266 this.initEvent.fire(MenuBar);
9276 * @property CSS_CLASS_NAME
9277 * @description String representing the CSS class(es) to be applied to the menu
9278 * bar's <code><div></code> element.
9279 * @default "yuimenubar"
9283 CSS_CLASS_NAME: "yuimenubar",
9287 * @property SUBMENU_TOGGLE_REGION_WIDTH
9288 * @description Width (in pixels) of the area of a MenuBarItem that, when pressed, will toggle the
9289 * display of the MenuBarItem's submenu.
9294 SUBMENU_TOGGLE_REGION_WIDTH: 20,
9297 // Protected event handlers
9301 * @method _onKeyDown
9302 * @description "keydown" Custom Event handler for the menu bar.
9304 * @param {String} p_sType String representing the name of the event that
9306 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
9307 * @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar
9308 * that fired the event.
9310 _onKeyDown: function(p_sType, p_aArgs, p_oMenuBar) {
9312 var oEvent = p_aArgs[0],
9319 if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9321 oItemCfg = oItem.cfg;
9323 switch(oEvent.keyCode) {
9325 case 37: // Left arrow
9326 case 39: // Right arrow
9328 if(oItem == this.activeItem && !oItemCfg.getProperty(_SELECTED)) {
9330 oItemCfg.setProperty(_SELECTED, true);
9335 oNextItem = (oEvent.keyCode == 37) ?
9336 oItem.getPreviousEnabledSibling() :
9337 oItem.getNextEnabledSibling();
9341 this.clearActiveItem();
9343 oNextItem.cfg.setProperty(_SELECTED, true);
9345 oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
9350 oSubmenu.setInitialFocus();
9361 Event.preventDefault(oEvent);
9365 case 40: // Down arrow
9367 if(this.activeItem != oItem) {
9369 this.clearActiveItem();
9371 oItemCfg.setProperty(_SELECTED, true);
9376 oSubmenu = oItemCfg.getProperty(_SUBMENU);
9380 if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9382 oSubmenu.setInitialSelection();
9383 oSubmenu.setInitialFocus();
9389 oSubmenu.setInitialFocus();
9395 Event.preventDefault(oEvent);
9404 if(oEvent.keyCode == 27 && this.activeItem) { // Esc key
9406 oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
9408 if(oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
9411 this.activeItem.focus();
9416 this.activeItem.cfg.setProperty(_SELECTED, false);
9417 this.activeItem.blur();
9421 Event.preventDefault(oEvent);
9430 * @description "click" event handler for the menu bar.
9432 * @param {String} p_sType String representing the name of the event that
9434 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
9435 * @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar
9436 * that fired the event.
9438 _onClick: function(p_sType, p_aArgs, p_oMenuBar) {
9440 MenuBar.superclass._onClick.call(this, p_sType, p_aArgs, p_oMenuBar);
9442 var oItem = p_aArgs[1],
9454 var toggleSubmenuDisplay = function () {
9456 if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9470 if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9472 oEvent = p_aArgs[0];
9473 oTarget = Event.getTarget(oEvent);
9474 oActiveItem = this.activeItem;
9478 // Hide any other submenus that might be visible
9480 if(oActiveItem && oActiveItem != oItem) {
9482 this.clearActiveItem();
9487 oItem.cfg.setProperty(_SELECTED, true);
9490 // Show the submenu for the item
9492 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
9497 oItemEl = oItem.element;
9498 nMenuItemX = YAHOO.util.Dom.getX(oItemEl);
9499 nToggleRegion = nMenuItemX + (oItemEl.offsetWidth - this.SUBMENU_TOGGLE_REGION_WIDTH);
9501 if (oConfig.getProperty(_SUBMENU_TOGGLE_REGION)) {
9503 if (Event.getPageX(oEvent) > nToggleRegion) {
9505 toggleSubmenuDisplay();
9507 Event.preventDefault(oEvent);
9510 Return false so that other click event handlers are not called when the
9511 user clicks inside the toggle region.
9520 toggleSubmenuDisplay();
9538 * @method configSubmenuToggle
9539 * @description Event handler for when the "submenutoggleregion" configuration property of
9540 * a MenuBar changes.
9541 * @param {String} p_sType The name of the event that was fired.
9542 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
9544 configSubmenuToggle: function (p_sType, p_aArgs) {
9546 var bSubmenuToggle = p_aArgs[0];
9548 if (bSubmenuToggle) {
9550 this.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
9559 * @description Returns a string representing the menu bar.
9562 toString: function() {
9564 var sReturnVal = _MENUBAR,
9569 sReturnVal += (_SPACE + sId);
9579 * @description Initializes the class's configurable properties which can be
9580 * changed using the menu bar's Config object ("cfg").
9581 * @method initDefaultConfig
9583 initDefaultConfig: function() {
9585 MenuBar.superclass.initDefaultConfig.call(this);
9587 var oConfig = this.cfg;
9589 // Add configuration properties
9593 Set the default value for the "position" configuration property
9594 to "static" by re-adding the property.
9600 * @description String indicating how a menu bar should be positioned on the
9601 * screen. Possible values are "static" and "dynamic." Static menu bars
9602 * are visible by default and reside in the normal flow of the document
9603 * (CSS position: static). Dynamic menu bars are hidden by default, reside
9604 * out of the normal flow of the document (CSS position: absolute), and can
9605 * overlay other elements on the screen.
9609 oConfig.addProperty(
9610 POSITION_CONFIG.key,
9612 handler: this.configPosition,
9613 value: POSITION_CONFIG.value,
9614 validator: POSITION_CONFIG.validator,
9615 supercedes: POSITION_CONFIG.supercedes
9621 Set the default value for the "submenualignment" configuration property
9622 to ["tl","bl"] by re-adding the property.
9626 * @config submenualignment
9627 * @description Array defining how submenus should be aligned to their
9628 * parent menu bar item. The format is: [itemCorner, submenuCorner].
9629 * @default ["tl","bl"]
9632 oConfig.addProperty(
9633 SUBMENU_ALIGNMENT_CONFIG.key,
9635 value: SUBMENU_ALIGNMENT_CONFIG.value,
9636 suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
9642 Change the default value for the "autosubmenudisplay" configuration
9643 property to "false" by re-adding the property.
9647 * @config autosubmenudisplay
9648 * @description Boolean indicating if submenus are automatically made
9649 * visible when the user mouses over the menu bar's items.
9653 oConfig.addProperty(
9654 AUTO_SUBMENU_DISPLAY_CONFIG.key,
9656 value: AUTO_SUBMENU_DISPLAY_CONFIG.value,
9657 validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
9658 suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
9664 * @config submenutoggleregion
9665 * @description Boolean indicating if only a specific region of a MenuBarItem should toggle the
9666 * display of a submenu. The default width of the region is determined by the value of the
9667 * SUBMENU_TOGGLE_REGION_WIDTH property. If set to true, the autosubmenudisplay
9668 * configuration property will be set to false, and any click event listeners will not be
9669 * called when the user clicks inside the submenu toggle region of a MenuBarItem. If the
9670 * user clicks outside of the submenu toggle region, the MenuBarItem will maintain its
9671 * standard behavior.
9675 oConfig.addProperty(
9676 SUBMENU_TOGGLE_REGION_CONFIG.key,
9678 value: SUBMENU_TOGGLE_REGION_CONFIG.value,
9679 validator: SUBMENU_TOGGLE_REGION_CONFIG.validator,
9680 handler: this.configSubmenuToggle
9686 }); // END YAHOO.lang.extend
9693 * Creates an item for a menu bar.
9695 * @param {String} p_oObject String specifying the text of the menu bar item.
9696 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9697 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9698 * <code><li></code> element of the menu bar item.
9699 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9700 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9701 * specifying the <code><optgroup></code> element of the menu bar item.
9702 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9703 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9704 * the <code><option></code> element of the menu bar item.
9705 * @param {Object} p_oConfig Optional. Object literal specifying the
9706 * configuration for the menu bar item. See configuration class documentation
9708 * @class MenuBarItem
9710 * @extends YAHOO.widget.MenuItem
9712 YAHOO.widget.MenuBarItem = function(p_oObject, p_oConfig) {
9714 YAHOO.widget.MenuBarItem.superclass.constructor.call(this, p_oObject, p_oConfig);
9718 YAHOO.lang.extend(YAHOO.widget.MenuBarItem, YAHOO.widget.MenuItem, {
9724 * @description The MenuBarItem class's initialization method. This method is
9725 * automatically called by the constructor, and sets up all DOM references for
9726 * pre-existing markup, and creates required markup if it is not already present.
9727 * @param {String} p_oObject String specifying the text of the menu bar item.
9728 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9729 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9730 * <code><li></code> element of the menu bar item.
9731 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9732 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9733 * specifying the <code><optgroup></code> element of the menu bar item.
9734 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9735 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9736 * the <code><option></code> element of the menu bar item.
9737 * @param {Object} p_oConfig Optional. Object literal specifying the
9738 * configuration for the menu bar item. See configuration class documentation
9741 init: function(p_oObject, p_oConfig) {
9743 if(!this.SUBMENU_TYPE) {
9745 this.SUBMENU_TYPE = YAHOO.widget.Menu;
9751 Call the init of the superclass (YAHOO.widget.MenuItem)
9752 Note: We don't pass the user config in here yet
9753 because we only want it executed once, at the lowest
9757 YAHOO.widget.MenuBarItem.superclass.init.call(this, p_oObject);
9760 var oConfig = this.cfg;
9764 oConfig.applyConfig(p_oConfig, true);
9768 oConfig.fireQueue();
9778 * @property CSS_CLASS_NAME
9779 * @description String representing the CSS class(es) to be applied to the
9780 * <code><li></code> element of the menu bar item.
9781 * @default "yuimenubaritem"
9785 CSS_CLASS_NAME: "yuimenubaritem",
9789 * @property CSS_LABEL_CLASS_NAME
9790 * @description String representing the CSS class(es) to be applied to the
9791 * menu bar item's <code><a></code> element.
9792 * @default "yuimenubaritemlabel"
9796 CSS_LABEL_CLASS_NAME: "yuimenubaritemlabel",
9805 * @description Returns a string representing the menu bar item.
9808 toString: function() {
9810 var sReturnVal = "MenuBarItem";
9812 if(this.cfg && this.cfg.getProperty("text")) {
9814 sReturnVal += (": " + this.cfg.getProperty("text"));
9822 }); // END YAHOO.lang.extend
9823 YAHOO.register("menu", YAHOO.widget.Menu, {version: "2.8.0r4", build: "2449"});