2 Copyright (c) 2008, 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
36 _DISABLED = "disabled",
37 _MOUSEOVER = "mouseover",
38 _MOUSEOUT = "mouseout",
39 _MOUSEDOWN = "mousedown",
41 _FOCUS = YAHOO.env.ua.ie ? "focusin" : "focus",
45 _KEYPRESS = "keypress",
46 _CLICK_TO_HIDE = "clicktohide",
47 _POSITION = "position",
49 _SHOW_DELAY = "showdelay",
50 _SELECTED = "selected",
53 _MENUMANAGER = "MenuManager",
57 Event = YAHOO.util.Event,
62 * Singleton that manages a collection of all menus and menu items. Listens
63 * for DOM events at the document level and dispatches the events to the
64 * corresponding menu or menu item.
66 * @namespace YAHOO.widget
70 YAHOO.widget.MenuManager = function () {
72 // Private member variables
75 // Flag indicating if the DOM event handlers have been attached
77 var m_bInitializedEventHandlers = false,
80 // Collection of menus
85 // Collection of visible menus
90 // Collection of menu items
95 // Map of DOM event types to their equivalent CustomEvent types
98 "click": "clickEvent",
99 "mousedown": "mouseDownEvent",
100 "mouseup": "mouseUpEvent",
101 "mouseover": "mouseOverEvent",
102 "mouseout": "mouseOutEvent",
103 "keydown": "keyDownEvent",
104 "keyup": "keyUpEvent",
105 "keypress": "keyPressEvent",
106 "focus": "focusEvent",
107 "focusin": "focusEvent",
109 "focusout": "blurEvent"
113 // The element in the DOM that currently has focus
115 m_oFocusedElement = null,
118 m_oFocusedMenuItem = null;
126 * @method getMenuRootElement
127 * @description Finds the root DIV node of a menu or the root LI node of
130 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
131 * level-one-html.html#ID-58190037">HTMLElement</a>} p_oElement Object
132 * specifying an HTML element.
134 function getMenuRootElement(p_oElement) {
139 if (p_oElement && p_oElement.tagName) {
141 switch (p_oElement.tagName.toUpperCase()) {
145 oParentNode = p_oElement.parentNode;
147 // Check if the DIV is the inner "body" node of a menu
150 Dom.hasClass(p_oElement, _HD) ||
151 Dom.hasClass(p_oElement, _BD) ||
152 Dom.hasClass(p_oElement, _FT)
155 oParentNode.tagName &&
156 oParentNode.tagName.toUpperCase() == _DIV) {
158 returnVal = oParentNode;
163 returnVal = p_oElement;
171 returnVal = p_oElement;
177 oParentNode = p_oElement.parentNode;
181 returnVal = getMenuRootElement(oParentNode);
197 // Private event handlers
202 * @description Generic, global event handler for all of a menu's
203 * DOM-based events. This listens for events against the document
204 * object. If the target of a given event is a member of a menu or
205 * menu item's DOM, the instance's corresponding Custom Event is fired.
207 * @param {Event} p_oEvent Object representing the DOM event object
208 * passed back by the event utility (YAHOO.util.Event).
210 function onDOMEvent(p_oEvent) {
212 // Get the target node of the DOM event
214 var oTarget = Event.getTarget(p_oEvent),
216 // See if the target of the event was a menu, or a menu item
218 oElement = getMenuRootElement(oTarget),
228 sTagName = oElement.tagName.toUpperCase();
230 if (sTagName == _LI) {
234 if (sId && m_oItems[sId]) {
236 oMenuItem = m_oItems[sId];
237 oMenu = oMenuItem.parent;
242 else if (sTagName == _DIV) {
246 oMenu = m_oMenus[oElement.id];
257 sCustomEventType = m_oEventTypes[p_oEvent.type];
260 // Fire the Custom Event that corresponds the current DOM event
262 if (oMenuItem && !oMenuItem.cfg.getProperty(_DISABLED)) {
264 oMenuItem[sCustomEventType].fire(p_oEvent);
268 oMenu[sCustomEventType].fire(p_oEvent, oMenuItem);
271 else if (p_oEvent.type == _MOUSEDOWN) {
274 If the target of the event wasn't a menu, hide all
275 dynamically positioned menus
278 for (var i in m_oVisibleMenus) {
280 if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
282 oMenu = m_oVisibleMenus[i];
284 if (oMenu.cfg.getProperty(_CLICK_TO_HIDE) &&
285 !(oMenu instanceof YAHOO.widget.MenuBar) &&
286 oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
293 if (oMenu.cfg.getProperty(_SHOW_DELAY) > 0) {
295 oMenu._cancelShowDelay();
300 if (oMenu.activeItem) {
302 oMenu.activeItem.blur();
303 oMenu.activeItem.cfg.setProperty(_SELECTED, false);
305 oMenu.activeItem = null;
316 else if (p_oEvent.type == _FOCUS) {
318 m_oFocusedElement = oTarget;
326 * @method onMenuDestroy
327 * @description "destroy" event handler for a menu.
329 * @param {String} p_sType String representing the name of the event
331 * @param {Array} p_aArgs Array of arguments sent when the event
333 * @param {YAHOO.widget.Menu} p_oMenu The menu that fired the event.
335 function onMenuDestroy(p_sType, p_aArgs, p_oMenu) {
337 if (m_oMenus[p_oMenu.id]) {
339 this.removeMenu(p_oMenu);
347 * @method onMenuFocus
348 * @description "focus" event handler for a MenuItem instance.
350 * @param {String} p_sType String representing the name of the event
352 * @param {Array} p_aArgs Array of arguments sent when the event
355 function onMenuFocus(p_sType, p_aArgs) {
357 var oItem = p_aArgs[1];
361 m_oFocusedMenuItem = oItem;
370 * @description "blur" event handler for a MenuItem instance.
372 * @param {String} p_sType String representing the name of the event
374 * @param {Array} p_aArgs Array of arguments sent when the event
377 function onMenuBlur(p_sType, p_aArgs) {
379 m_oFocusedMenuItem = null;
386 * @description "hide" event handler for a Menu 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
392 * @param <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
393 * level-one-html.html#ID-58190037">p_oFocusedElement</a> The HTML element that had focus
394 * prior to the Menu being made visible
396 function onMenuHide(p_sType, p_aArgs, p_oFocusedElement) {
399 Restore focus to the element in the DOM that had focus prior to the Menu
403 if (p_oFocusedElement && p_oFocusedElement.focus) {
406 p_oFocusedElement.focus();
413 this.hideEvent.unsubscribe(onMenuHide, p_oFocusedElement);
420 * @description "show" event handler for a MenuItem instance.
422 * @param {String} p_sType String representing the name of the event
424 * @param {Array} p_aArgs Array of arguments sent when the event
427 function onMenuShow(p_sType, p_aArgs) {
430 Dynamically positioned, root Menus focus themselves when visible, and will then,
431 when hidden, restore focus to the UI control that had focus before the Menu was
435 if (this === this.getRoot() && this.cfg.getProperty(_POSITION) === _DYNAMIC) {
437 this.hideEvent.subscribe(onMenuHide, m_oFocusedElement);
446 * @method onMenuVisibleConfigChange
447 * @description Event handler for when the "visible" configuration
448 * property of a Menu instance changes.
450 * @param {String} p_sType String representing the name of the event
452 * @param {Array} p_aArgs Array of arguments sent when the event
455 function onMenuVisibleConfigChange(p_sType, p_aArgs) {
457 var bVisible = p_aArgs[0],
462 m_oVisibleMenus[sId] = this;
464 YAHOO.log(this + " added to the collection of visible menus.",
465 "info", _MENUMANAGER);
468 else if (m_oVisibleMenus[sId]) {
470 delete m_oVisibleMenus[sId];
472 YAHOO.log(this + " removed from the collection of visible menus.",
473 "info", _MENUMANAGER);
481 * @method onItemDestroy
482 * @description "destroy" event handler for a MenuItem instance.
484 * @param {String} p_sType String representing the name of the event
486 * @param {Array} p_aArgs Array of arguments sent when the event
489 function onItemDestroy(p_sType, p_aArgs) {
498 * @description Removes a MenuItem instance from the MenuManager's collection of MenuItems.
500 * @param {MenuItem} p_oMenuItem The MenuItem instance to be removed.
502 function removeItem(p_oMenuItem) {
504 var sId = p_oMenuItem.id;
506 if (sId && m_oItems[sId]) {
508 if (m_oFocusedMenuItem == p_oMenuItem) {
510 m_oFocusedMenuItem = null;
514 delete m_oItems[sId];
516 p_oMenuItem.destroyEvent.unsubscribe(onItemDestroy);
518 YAHOO.log(p_oMenuItem + " successfully unregistered.", "info", _MENUMANAGER);
526 * @method onItemAdded
527 * @description "itemadded" event handler for a Menu instance.
529 * @param {String} p_sType String representing the name of the event
531 * @param {Array} p_aArgs Array of arguments sent when the event
534 function onItemAdded(p_sType, p_aArgs) {
536 var oItem = p_aArgs[0],
539 if (oItem instanceof YAHOO.widget.MenuItem) {
543 if (!m_oItems[sId]) {
545 m_oItems[sId] = oItem;
547 oItem.destroyEvent.subscribe(onItemDestroy);
549 YAHOO.log(oItem + " successfully registered.", "info", _MENUMANAGER);
560 // Privileged methods
565 * @description Adds a menu to the collection of known menus.
566 * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
567 * instance to be added.
569 addMenu: function (p_oMenu) {
573 if (p_oMenu instanceof YAHOO.widget.Menu && p_oMenu.id &&
574 !m_oMenus[p_oMenu.id]) {
576 m_oMenus[p_oMenu.id] = p_oMenu;
579 if (!m_bInitializedEventHandlers) {
583 Event.on(oDoc, _MOUSEOVER, onDOMEvent, this, true);
584 Event.on(oDoc, _MOUSEOUT, onDOMEvent, this, true);
585 Event.on(oDoc, _MOUSEDOWN, onDOMEvent, this, true);
586 Event.on(oDoc, _MOUSEUP, onDOMEvent, this, true);
587 Event.on(oDoc, _CLICK, onDOMEvent, this, true);
588 Event.on(oDoc, _KEYDOWN, onDOMEvent, this, true);
589 Event.on(oDoc, _KEYUP, onDOMEvent, this, true);
590 Event.on(oDoc, _KEYPRESS, onDOMEvent, this, true);
592 Event.onFocus(oDoc, onDOMEvent, this, true);
593 Event.onBlur(oDoc, onDOMEvent, this, true);
595 m_bInitializedEventHandlers = true;
597 YAHOO.log("DOM event handlers initialized.", "info", _MENUMANAGER);
601 p_oMenu.cfg.subscribeToConfigEvent(_VISIBLE, onMenuVisibleConfigChange);
602 p_oMenu.destroyEvent.subscribe(onMenuDestroy, p_oMenu, this);
603 p_oMenu.itemAddedEvent.subscribe(onItemAdded);
604 p_oMenu.focusEvent.subscribe(onMenuFocus);
605 p_oMenu.blurEvent.subscribe(onMenuBlur);
606 p_oMenu.showEvent.subscribe(onMenuShow);
608 YAHOO.log(p_oMenu + " successfully registered.", "info", _MENUMANAGER);
617 * @description Removes a menu from the collection of known menus.
618 * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
619 * instance to be removed.
621 removeMenu: function (p_oMenu) {
631 if ((sId in m_oMenus) && (m_oMenus[sId] == p_oMenu)) {
633 // Unregister each menu item
635 aItems = p_oMenu.getItems();
637 if (aItems && aItems.length > 0) {
639 i = aItems.length - 1;
643 removeItem(aItems[i]);
651 // Unregister the menu
653 delete m_oMenus[sId];
655 YAHOO.log(p_oMenu + " successfully unregistered.", "info", _MENUMANAGER);
659 Unregister the menu from the collection of
663 if ((sId in m_oVisibleMenus) && (m_oVisibleMenus[sId] == p_oMenu)) {
665 delete m_oVisibleMenus[sId];
667 YAHOO.log(p_oMenu + " unregistered from the" +
668 " collection of visible menus.", "info", _MENUMANAGER);
673 // Unsubscribe event listeners
677 p_oMenu.cfg.unsubscribeFromConfigEvent(_VISIBLE,
678 onMenuVisibleConfigChange);
682 p_oMenu.destroyEvent.unsubscribe(onMenuDestroy,
685 p_oMenu.itemAddedEvent.unsubscribe(onItemAdded);
686 p_oMenu.focusEvent.unsubscribe(onMenuFocus);
687 p_oMenu.blurEvent.unsubscribe(onMenuBlur);
697 * @method hideVisible
698 * @description Hides all visible, dynamically positioned menus
699 * (excluding instances of YAHOO.widget.MenuBar).
701 hideVisible: function () {
705 for (var i in m_oVisibleMenus) {
707 if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
709 oMenu = m_oVisibleMenus[i];
711 if (!(oMenu instanceof YAHOO.widget.MenuBar) &&
712 oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
727 * @description Returns a collection of all visible menus registered
728 * with the menu manger.
731 getVisible: function () {
733 return m_oVisibleMenus;
740 * @description Returns a collection of all menus registered with the
744 getMenus: function () {
753 * @description Returns a menu with the specified id.
754 * @param {String} p_sId String specifying the id of the
755 * <code><div></code> element representing the menu to
757 * @return {YAHOO.widget.Menu}
759 getMenu: function (p_sId) {
763 if (p_sId in m_oMenus) {
765 returnVal = m_oMenus[p_sId];
775 * @method getMenuItem
776 * @description Returns a menu item with the specified id.
777 * @param {String} p_sId String specifying the id of the
778 * <code><li></code> element representing the menu item to
780 * @return {YAHOO.widget.MenuItem}
782 getMenuItem: function (p_sId) {
786 if (p_sId in m_oItems) {
788 returnVal = m_oItems[p_sId];
798 * @method getMenuItemGroup
799 * @description Returns an array of menu item instances whose
800 * corresponding <code><li></code> elements are child
801 * nodes of the <code><ul></code> element with the
803 * @param {String} p_sId String specifying the id of the
804 * <code><ul></code> element representing the group of
805 * menu items to be retrieved.
808 getMenuItemGroup: function (p_sId) {
810 var oUL = Dom.get(p_sId),
818 if (oUL && oUL.tagName && oUL.tagName.toUpperCase() == _UL) {
820 oNode = oUL.firstChild;
832 oItem = this.getMenuItem(sId);
836 aItems[aItems.length] = oItem;
843 while ((oNode = oNode.nextSibling));
846 if (aItems.length > 0) {
862 * @method getFocusedMenuItem
863 * @description Returns a reference to the menu item that currently
865 * @return {YAHOO.widget.MenuItem}
867 getFocusedMenuItem: function () {
869 return m_oFocusedMenuItem;
875 * @method getFocusedMenu
876 * @description Returns a reference to the menu that currently
878 * @return {YAHOO.widget.Menu}
880 getFocusedMenu: function () {
884 if (m_oFocusedMenuItem) {
886 returnVal = m_oFocusedMenuItem.parent.getRoot();
897 * @description Returns a string representing the menu manager.
900 toString: function () {
916 var Lang = YAHOO.lang,
921 _DIV_UPPERCASE = "DIV",
922 _DIV_LOWERCASE = "div",
927 _UL_UPPERCASE = "UL",
928 _UL_LOWERCASE = "ul",
929 _FIRST_OF_TYPE = "first-of-type",
931 _OPTGROUP = "OPTGROUP",
933 _DISABLED = "disabled",
935 _SELECTED = "selected",
936 _GROUP_INDEX = "groupindex",
938 _SUBMENU = "submenu",
939 _VISIBLE = "visible",
940 _HIDE_DELAY = "hidedelay",
941 _POSITION = "position",
942 _DYNAMIC = "dynamic",
944 _DYNAMIC_STATIC = _DYNAMIC + "," + _STATIC,
945 _WINDOWS = "windows",
949 _MAX_HEIGHT = "maxheight",
950 _TOP_SCROLLBAR = "topscrollbar",
951 _BOTTOM_SCROLLBAR = "bottomscrollbar",
953 _TOP_SCROLLBAR_DISABLED = _TOP_SCROLLBAR + _UNDERSCORE + _DISABLED,
954 _BOTTOM_SCROLLBAR_DISABLED = _BOTTOM_SCROLLBAR + _UNDERSCORE + _DISABLED,
955 _MOUSEMOVE = "mousemove",
956 _SHOW_DELAY = "showdelay",
957 _SUBMENU_HIDE_DELAY = "submenuhidedelay",
959 _CONSTRAIN_TO_VIEWPORT = "constraintoviewport",
960 _PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
961 _SUBMENU_ALIGNMENT = "submenualignment",
962 _AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
963 _CLICK_TO_HIDE = "clicktohide",
964 _CONTAINER = "container",
965 _SCROLL_INCREMENT = "scrollincrement",
966 _MIN_SCROLL_HEIGHT = "minscrollheight",
967 _CLASSNAME = "classname",
969 _KEEP_OPEN = "keepopen",
971 _HAS_TITLE = "hastitle",
972 _CONTEXT = "context",
974 _MOUSEDOWN = "mousedown",
975 _KEYDOWN = "keydown",
980 _MONITOR_RESIZE = "monitorresize",
981 _DISPLAY = "display",
983 _VISIBILITY = "visibility",
984 _ABSOLUTE = "absolute",
986 _YUI_MENU_BODY_SCROLLED = "yui-menu-body-scrolled",
987 _NON_BREAKING_SPACE = " ",
989 _MOUSEOVER = "mouseover",
990 _MOUSEOUT = "mouseout",
991 _ITEM_ADDED = "itemAdded",
992 _ITEM_REMOVED = "itemRemoved",
994 _YUI_MENU_SHADOW = "yui-menu-shadow",
995 _YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + "-visible",
996 _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + _SPACE + _YUI_MENU_SHADOW_VISIBLE;
1000 * The Menu class creates a container that holds a vertical list representing
1001 * a set of options or commands. Menu is the base class for all
1003 * @param {String} p_oElement String specifying the id attribute of the
1004 * <code><div></code> element of the menu.
1005 * @param {String} p_oElement String specifying the id attribute of the
1006 * <code><select></code> element to be used as the data source
1008 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1009 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
1010 * specifying the <code><div></code> element of the menu.
1011 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1012 * level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
1013 * Object specifying the <code><select></code> element to be used as
1014 * the data source for the menu.
1015 * @param {Object} p_oConfig Optional. Object literal specifying the
1016 * configuration for the menu. See configuration class documentation for
1018 * @namespace YAHOO.widget
1021 * @extends YAHOO.widget.Overlay
1023 YAHOO.widget.Menu = function (p_oElement, p_oConfig) {
1027 this.parent = p_oConfig.parent;
1028 this.lazyLoad = p_oConfig.lazyLoad || p_oConfig.lazyload;
1029 this.itemData = p_oConfig.itemData || p_oConfig.itemdata;
1034 YAHOO.widget.Menu.superclass.constructor.call(this, p_oElement, p_oConfig);
1041 * @method checkPosition
1042 * @description Checks to make sure that the value of the "position" property
1043 * is one of the supported strings. Returns true if the position is supported.
1045 * @param {Object} p_sPosition String specifying the position of the menu.
1048 function checkPosition(p_sPosition) {
1050 var returnVal = false;
1052 if (Lang.isString(p_sPosition)) {
1054 returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
1063 var Dom = YAHOO.util.Dom,
1064 Event = YAHOO.util.Event,
1065 Module = YAHOO.widget.Module,
1066 Overlay = YAHOO.widget.Overlay,
1067 Menu = YAHOO.widget.Menu,
1068 MenuManager = YAHOO.widget.MenuManager,
1069 CustomEvent = YAHOO.util.CustomEvent,
1076 ["mouseOverEvent", _MOUSEOVER],
1077 ["mouseOutEvent", _MOUSEOUT],
1078 ["mouseDownEvent", _MOUSEDOWN],
1079 ["mouseUpEvent", "mouseup"],
1080 ["clickEvent", "click"],
1081 ["keyPressEvent", "keypress"],
1082 ["keyDownEvent", _KEYDOWN],
1083 ["keyUpEvent", "keyup"],
1084 ["focusEvent", "focus"],
1085 ["blurEvent", "blur"],
1086 ["itemAddedEvent", _ITEM_ADDED],
1087 ["itemRemovedEvent", _ITEM_REMOVED]
1094 validator: Lang.isBoolean
1097 CONSTRAIN_TO_VIEWPORT_CONFIG = {
1098 key: _CONSTRAIN_TO_VIEWPORT,
1100 validator: Lang.isBoolean,
1101 supercedes: [_IFRAME,"x",_Y,_XY]
1104 PREVENT_CONTEXT_OVERLAP_CONFIG = {
1105 key: _PREVENT_CONTEXT_OVERLAP,
1107 validator: Lang.isBoolean,
1108 supercedes: [_CONSTRAIN_TO_VIEWPORT]
1114 validator: checkPosition,
1115 supercedes: [_VISIBLE, _IFRAME]
1118 SUBMENU_ALIGNMENT_CONFIG = {
1119 key: _SUBMENU_ALIGNMENT,
1123 AUTO_SUBMENU_DISPLAY_CONFIG = {
1124 key: _AUTO_SUBMENU_DISPLAY,
1126 validator: Lang.isBoolean,
1130 SHOW_DELAY_CONFIG = {
1133 validator: Lang.isNumber,
1137 HIDE_DELAY_CONFIG = {
1140 validator: Lang.isNumber,
1144 SUBMENU_HIDE_DELAY_CONFIG = {
1145 key: _SUBMENU_HIDE_DELAY,
1147 validator: Lang.isNumber,
1151 CLICK_TO_HIDE_CONFIG = {
1152 key: _CLICK_TO_HIDE,
1154 validator: Lang.isBoolean,
1158 CONTAINER_CONFIG = {
1163 SCROLL_INCREMENT_CONFIG = {
1164 key: _SCROLL_INCREMENT,
1166 validator: Lang.isNumber,
1167 supercedes: [_MAX_HEIGHT],
1171 MIN_SCROLL_HEIGHT_CONFIG = {
1172 key: _MIN_SCROLL_HEIGHT,
1174 validator: Lang.isNumber,
1175 supercedes: [_MAX_HEIGHT],
1179 MAX_HEIGHT_CONFIG = {
1182 validator: Lang.isNumber,
1183 supercedes: [_IFRAME],
1187 CLASS_NAME_CONFIG = {
1190 validator: Lang.isString,
1197 validator: Lang.isBoolean,
1204 validator: Lang.isBoolean,
1205 suppressEvent: true,
1206 supercedes: [_VISIBLE]
1209 KEEP_OPEN_CONFIG = {
1212 validator: Lang.isBoolean
1217 YAHOO.lang.extend(Menu, Overlay, {
1224 * @property CSS_CLASS_NAME
1225 * @description String representing the CSS class(es) to be applied to the
1226 * menu's <code><div></code> element.
1227 * @default "yuimenu"
1231 CSS_CLASS_NAME: "yuimenu",
1235 * @property ITEM_TYPE
1236 * @description Object representing the type of menu item to instantiate and
1237 * add when parsing the child nodes (either <code><li></code> element,
1238 * <code><optgroup></code> element or <code><option></code>)
1239 * of the menu's source HTML element.
1240 * @default YAHOO.widget.MenuItem
1242 * @type YAHOO.widget.MenuItem
1248 * @property GROUP_TITLE_TAG_NAME
1249 * @description String representing the tagname of the HTML element used to
1250 * title the menu's item groups.
1255 GROUP_TITLE_TAG_NAME: "h6",
1259 * @property OFF_SCREEN_POSITION
1260 * @description Array representing the default x and y position that a menu
1261 * should have when it is positioned outside the viewport by the
1262 * "poistionOffScreen" method.
1267 OFF_SCREEN_POSITION: "-999em",
1270 // Private properties
1274 * @property _bHideDelayEventHandlersAssigned
1275 * @description Boolean indicating if the "mouseover" and "mouseout" event
1276 * handlers used for hiding the menu via a call to "YAHOO.lang.later" have
1277 * already been assigned.
1282 _bHideDelayEventHandlersAssigned: false,
1286 * @property _bHandledMouseOverEvent
1287 * @description Boolean indicating the current state of the menu's
1288 * "mouseover" event.
1293 _bHandledMouseOverEvent: false,
1297 * @property _bHandledMouseOutEvent
1298 * @description Boolean indicating the current state of the menu's
1304 _bHandledMouseOutEvent: false,
1308 * @property _aGroupTitleElements
1309 * @description Array of HTML element used to title groups of menu items.
1314 _aGroupTitleElements: null,
1318 * @property _aItemGroups
1319 * @description Multi-dimensional Array representing the menu items as they
1320 * are grouped in the menu.
1329 * @property _aListElements
1330 * @description Array of <code><ul></code> elements, each of which is
1331 * the parent node for each item's <code><li></code> element.
1336 _aListElements: null,
1340 * @property _nCurrentMouseX
1341 * @description The current x coordinate of the mouse inside the area of
1351 * @property _bStopMouseEventHandlers
1352 * @description Stops "mouseover," "mouseout," and "mousemove" event handlers
1358 _bStopMouseEventHandlers: false,
1362 * @property _sClassName
1363 * @description The current value of the "classname" configuration attribute.
1372 // Public properties
1376 * @property lazyLoad
1377 * @description Boolean indicating if the menu's "lazy load" feature is
1378 * enabled. If set to "true," initialization and rendering of the menu's
1379 * items will be deferred until the first time it is made visible. This
1380 * property should be set via the constructor using the configuration
1389 * @property itemData
1390 * @description Array of items to be added to the menu. The array can contain
1391 * strings representing the text for each item to be created, object literals
1392 * representing the menu item configuration properties, or MenuItem instances.
1393 * This property should be set via the constructor using the configuration
1402 * @property activeItem
1403 * @description Object reference to the item in the menu that has is selected.
1405 * @type YAHOO.widget.MenuItem
1412 * @description Object reference to the menu's parent menu or menu item.
1413 * This property can be set via the constructor using the configuration
1416 * @type YAHOO.widget.MenuItem
1422 * @property srcElement
1423 * @description Object reference to the HTML element (either
1424 * <code><select></code> or <code><div></code>) used to
1427 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1428 * level-one-html.html#ID-94282980">HTMLSelectElement</a>|<a
1429 * href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.
1430 * html#ID-22445964">HTMLDivElement</a>
1440 * @event mouseOverEvent
1441 * @description Fires when the mouse has entered the menu. Passes back
1442 * the DOM Event object as an argument.
1447 * @event mouseOutEvent
1448 * @description Fires when the mouse has left the menu. Passes back the DOM
1449 * Event object as an argument.
1450 * @type YAHOO.util.CustomEvent
1455 * @event mouseDownEvent
1456 * @description Fires when the user mouses down on the menu. Passes back the
1457 * DOM Event object as an argument.
1458 * @type YAHOO.util.CustomEvent
1463 * @event mouseUpEvent
1464 * @description Fires when the user releases a mouse button while the mouse is
1465 * over the menu. Passes back the DOM Event object as an argument.
1466 * @type YAHOO.util.CustomEvent
1472 * @description Fires when the user clicks the on the menu. Passes back the
1473 * DOM Event object as an argument.
1474 * @type YAHOO.util.CustomEvent
1479 * @event keyPressEvent
1480 * @description Fires when the user presses an alphanumeric key when one of the
1481 * menu's items has focus. Passes back the DOM Event object as an argument.
1482 * @type YAHOO.util.CustomEvent
1487 * @event keyDownEvent
1488 * @description Fires when the user presses a key when one of the menu's items
1489 * has focus. Passes back the DOM Event object as an argument.
1490 * @type YAHOO.util.CustomEvent
1496 * @description Fires when the user releases a key when one of the menu's items
1497 * has focus. Passes back the DOM Event object as an argument.
1498 * @type YAHOO.util.CustomEvent
1503 * @event itemAddedEvent
1504 * @description Fires when an item is added to the menu.
1505 * @type YAHOO.util.CustomEvent
1510 * @event itemRemovedEvent
1511 * @description Fires when an item is removed to the menu.
1512 * @type YAHOO.util.CustomEvent
1518 * @description The Menu class's initialization method. This method is
1519 * automatically called by the constructor, and sets up all DOM references
1520 * for pre-existing markup, and creates required markup if it is not
1522 * @param {String} p_oElement String specifying the id attribute of the
1523 * <code><div></code> element of the menu.
1524 * @param {String} p_oElement String specifying the id attribute of the
1525 * <code><select></code> element to be used as the data source
1527 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1528 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
1529 * specifying the <code><div></code> element of the menu.
1530 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1531 * level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
1532 * Object specifying the <code><select></code> element to be used as
1533 * the data source for the menu.
1534 * @param {Object} p_oConfig Optional. Object literal specifying the
1535 * configuration for the menu. See configuration class documentation for
1538 init: function (p_oElement, p_oConfig) {
1540 this._aItemGroups = [];
1541 this._aListElements = [];
1542 this._aGroupTitleElements = [];
1544 if (!this.ITEM_TYPE) {
1546 this.ITEM_TYPE = YAHOO.widget.MenuItem;
1553 if (Lang.isString(p_oElement)) {
1555 oElement = Dom.get(p_oElement);
1558 else if (p_oElement.tagName) {
1560 oElement = p_oElement;
1565 if (oElement && oElement.tagName) {
1567 switch(oElement.tagName.toUpperCase()) {
1569 case _DIV_UPPERCASE:
1571 this.srcElement = oElement;
1575 oElement.setAttribute(_ID, Dom.generateId());
1581 Note: we don't pass the user config in here yet
1582 because we only want it executed once, at the lowest
1586 Menu.superclass.init.call(this, oElement);
1588 this.beforeInitEvent.fire(Menu);
1590 YAHOO.log("Source element: " + this.srcElement.tagName, "info", this.toString());
1596 this.srcElement = oElement;
1600 The source element is not something that we can use
1601 outright, so we need to create a new Overlay
1603 Note: we don't pass the user config in here yet
1604 because we only want it executed once, at the lowest
1608 Menu.superclass.init.call(this, Dom.generateId());
1610 this.beforeInitEvent.fire(Menu);
1612 YAHOO.log("Source element: " + this.srcElement.tagName, "info", this.toString());
1622 Note: we don't pass the user config in here yet
1623 because we only want it executed once, at the lowest
1627 Menu.superclass.init.call(this, p_oElement);
1629 this.beforeInitEvent.fire(Menu);
1631 YAHOO.log("No source element found. Created element with id: " + this.id, "info", this.toString());
1638 Dom.addClass(this.element, this.CSS_CLASS_NAME);
1641 // Subscribe to Custom Events
1643 this.initEvent.subscribe(this._onInit);
1644 this.beforeRenderEvent.subscribe(this._onBeforeRender);
1645 this.renderEvent.subscribe(this._onRender);
1646 this.beforeShowEvent.subscribe(this._onBeforeShow);
1647 this.hideEvent.subscribe(this._onHide);
1648 this.showEvent.subscribe(this._onShow);
1649 this.beforeHideEvent.subscribe(this._onBeforeHide);
1650 this.mouseOverEvent.subscribe(this._onMouseOver);
1651 this.mouseOutEvent.subscribe(this._onMouseOut);
1652 this.clickEvent.subscribe(this._onClick);
1653 this.keyDownEvent.subscribe(this._onKeyDown);
1654 this.keyPressEvent.subscribe(this._onKeyPress);
1655 this.blurEvent.subscribe(this._onBlur);
1658 if (UA.gecko || UA.webkit) {
1660 this.cfg.subscribeToConfigEvent(_Y, this._onYChange);
1667 this.cfg.applyConfig(p_oConfig, true);
1672 // Register the Menu instance with the MenuManager
1674 MenuManager.addMenu(this);
1677 this.initEvent.fire(Menu);
1689 * @method _initSubTree
1690 * @description Iterates the childNodes of the source element to find nodes
1691 * used to instantiate menu and menu items.
1694 _initSubTree: function () {
1696 var oSrcElement = this.srcElement,
1708 sSrcElementTagName =
1709 (oSrcElement.tagName && oSrcElement.tagName.toUpperCase());
1712 if (sSrcElementTagName == _DIV_UPPERCASE) {
1714 // Populate the collection of item groups and item group titles
1716 oNode = this.body.firstChild;
1722 sGroupTitleTagName = this.GROUP_TITLE_TAG_NAME.toUpperCase();
1727 if (oNode && oNode.tagName) {
1729 switch (oNode.tagName.toUpperCase()) {
1731 case sGroupTitleTagName:
1733 this._aGroupTitleElements[nGroup] = oNode;
1739 this._aListElements[nGroup] = oNode;
1740 this._aItemGroups[nGroup] = [];
1750 while ((oNode = oNode.nextSibling));
1754 Apply the "first-of-type" class to the first UL to mimic
1755 the ":first-of-type" CSS3 psuedo class.
1758 if (this._aListElements[0]) {
1760 Dom.addClass(this._aListElements[0], _FIRST_OF_TYPE);
1771 YAHOO.log("Searching DOM for items to initialize.", "info", this.toString());
1774 if (sSrcElementTagName) {
1776 switch (sSrcElementTagName) {
1778 case _DIV_UPPERCASE:
1780 aListElements = this._aListElements;
1781 nListElements = aListElements.length;
1783 if (nListElements > 0) {
1785 YAHOO.log("Found " + nListElements + " item groups to initialize.",
1786 "info", this.toString());
1788 i = nListElements - 1;
1792 oNode = aListElements[i].firstChild;
1796 YAHOO.log("Scanning " +
1797 aListElements[i].childNodes.length +
1798 " child nodes for items to initialize.", "info", this.toString());
1802 if (oNode && oNode.tagName &&
1803 oNode.tagName.toUpperCase() == _LI) {
1805 YAHOO.log("Initializing " +
1806 oNode.tagName + " node.", "info", this.toString());
1808 this.addItem(new this.ITEM_TYPE(oNode,
1809 { parent: this }), i);
1814 while ((oNode = oNode.nextSibling));
1827 YAHOO.log("Scanning " +
1828 oSrcElement.childNodes.length +
1829 " child nodes for items to initialize.", "info", this.toString());
1831 oNode = oSrcElement.firstChild;
1835 if (oNode && oNode.tagName) {
1837 switch (oNode.tagName.toUpperCase()) {
1842 YAHOO.log("Initializing " +
1843 oNode.tagName + " node.", "info", this.toString());
1859 while ((oNode = oNode.nextSibling));
1873 * @method _getFirstEnabledItem
1874 * @description Returns the first enabled item in the menu.
1875 * @return {YAHOO.widget.MenuItem}
1878 _getFirstEnabledItem: function () {
1880 var aItems = this.getItems(),
1881 nItems = aItems.length,
1886 for(var i=0; i<nItems; i++) {
1890 if (oItem && !oItem.cfg.getProperty(_DISABLED) && oItem.element.style.display != _NONE) {
1905 * @method _addItemToGroup
1906 * @description Adds a menu item to a group.
1908 * @param {Number} p_nGroupIndex Number indicating the group to which the
1910 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
1911 * instance to be added to the menu.
1912 * @param {String} p_oItem String specifying the text of the item to be added
1914 * @param {Object} p_oItem Object literal containing a set of menu item
1915 * configuration properties.
1916 * @param {Number} p_nItemIndex Optional. Number indicating the index at
1917 * which the menu item should be added.
1918 * @return {YAHOO.widget.MenuItem}
1920 _addItemToGroup: function (p_nGroupIndex, p_oItem, p_nItemIndex) {
1932 function getNextItemSibling(p_aArray, p_nStartIndex) {
1934 return (p_aArray[p_nStartIndex] || getNextItemSibling(p_aArray, (p_nStartIndex+1)));
1939 if (p_oItem instanceof this.ITEM_TYPE) {
1942 oItem.parent = this;
1945 else if (Lang.isString(p_oItem)) {
1947 oItem = new this.ITEM_TYPE(p_oItem, { parent: this });
1950 else if (Lang.isObject(p_oItem)) {
1952 p_oItem.parent = this;
1954 oItem = new this.ITEM_TYPE(p_oItem.text, p_oItem);
1961 if (oItem.cfg.getProperty(_SELECTED)) {
1963 this.activeItem = oItem;
1968 nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
1969 aGroup = this._getItemGroup(nGroupIndex);
1975 aGroup = this._createItemGroup(nGroupIndex);
1980 if (Lang.isNumber(p_nItemIndex)) {
1982 bAppend = (p_nItemIndex >= aGroup.length);
1985 if (aGroup[p_nItemIndex]) {
1987 aGroup.splice(p_nItemIndex, 0, oItem);
1992 aGroup[p_nItemIndex] = oItem;
1997 oGroupItem = aGroup[p_nItemIndex];
2001 if (bAppend && (!oGroupItem.element.parentNode ||
2002 oGroupItem.element.parentNode.nodeType == 11)) {
2004 this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
2009 oNextItemSibling = getNextItemSibling(aGroup, (p_nItemIndex+1));
2011 if (oNextItemSibling && (!oGroupItem.element.parentNode ||
2012 oGroupItem.element.parentNode.nodeType == 11)) {
2014 this._aListElements[nGroupIndex].insertBefore(
2015 oGroupItem.element, oNextItemSibling.element);
2022 oGroupItem.parent = this;
2024 this._subscribeToItemEvents(oGroupItem);
2026 this._configureSubmenu(oGroupItem);
2028 this._updateItemProperties(nGroupIndex);
2030 YAHOO.log("Item inserted." +
2031 " Text: " + oGroupItem.cfg.getProperty("text") + ", " +
2032 " Index: " + oGroupItem.index + ", " +
2033 " Group Index: " + oGroupItem.groupIndex, "info", this.toString());
2035 this.itemAddedEvent.fire(oGroupItem);
2036 this.changeContentEvent.fire();
2038 returnVal = oGroupItem;
2045 nItemIndex = aGroup.length;
2047 aGroup[nItemIndex] = oItem;
2049 oGroupItem = aGroup[nItemIndex];
2054 if (!Dom.isAncestor(this._aListElements[nGroupIndex], oGroupItem.element)) {
2056 this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
2060 oGroupItem.element.setAttribute(_GROUP_INDEX, nGroupIndex);
2061 oGroupItem.element.setAttribute(_INDEX, nItemIndex);
2063 oGroupItem.parent = this;
2065 oGroupItem.index = nItemIndex;
2066 oGroupItem.groupIndex = nGroupIndex;
2068 this._subscribeToItemEvents(oGroupItem);
2070 this._configureSubmenu(oGroupItem);
2072 if (nItemIndex === 0) {
2074 Dom.addClass(oGroupItem.element, _FIRST_OF_TYPE);
2078 YAHOO.log("Item added." +
2079 " Text: " + oGroupItem.cfg.getProperty("text") + ", " +
2080 " Index: " + oGroupItem.index + ", " +
2081 " Group Index: " + oGroupItem.groupIndex, "info", this.toString());
2084 this.itemAddedEvent.fire(oGroupItem);
2085 this.changeContentEvent.fire();
2087 returnVal = oGroupItem;
2101 * @method _removeItemFromGroupByIndex
2102 * @description Removes a menu item from a group by index. Returns the menu
2103 * item that was removed.
2105 * @param {Number} p_nGroupIndex Number indicating the group to which the menu
2107 * @param {Number} p_nItemIndex Number indicating the index of the menu item
2109 * @return {YAHOO.widget.MenuItem}
2111 _removeItemFromGroupByIndex: function (p_nGroupIndex, p_nItemIndex) {
2113 var nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0,
2114 aGroup = this._getItemGroup(nGroupIndex),
2121 aArray = aGroup.splice(p_nItemIndex, 1);
2126 // Update the index and className properties of each member
2128 this._updateItemProperties(nGroupIndex);
2130 if (aGroup.length === 0) {
2134 oUL = this._aListElements[nGroupIndex];
2136 if (this.body && oUL) {
2138 this.body.removeChild(oUL);
2142 // Remove the group from the array of items
2144 this._aItemGroups.splice(nGroupIndex, 1);
2147 // Remove the UL from the array of ULs
2149 this._aListElements.splice(nGroupIndex, 1);
2153 Assign the "first-of-type" class to the new first UL
2157 oUL = this._aListElements[0];
2161 Dom.addClass(oUL, _FIRST_OF_TYPE);
2168 this.itemRemovedEvent.fire(oItem);
2169 this.changeContentEvent.fire();
2175 // Return a reference to the item that was removed
2183 * @method _removeItemFromGroupByValue
2184 * @description Removes a menu item from a group by reference. Returns the
2185 * menu item that was removed.
2187 * @param {Number} p_nGroupIndex Number indicating the group to which the
2188 * menu item belongs.
2189 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2190 * instance to be removed.
2191 * @return {YAHOO.widget.MenuItem}
2193 _removeItemFromGroupByValue: function (p_nGroupIndex, p_oItem) {
2195 var aGroup = this._getItemGroup(p_nGroupIndex),
2203 nItems = aGroup.length;
2212 if (aGroup[i] == p_oItem) {
2222 if (nItemIndex > -1) {
2224 returnVal = this._removeItemFromGroupByIndex(p_nGroupIndex, nItemIndex);
2238 * @method _updateItemProperties
2239 * @description Updates the "index," "groupindex," and "className" properties
2240 * of the menu items in the specified group.
2242 * @param {Number} p_nGroupIndex Number indicating the group of items to update.
2244 _updateItemProperties: function (p_nGroupIndex) {
2246 var aGroup = this._getItemGroup(p_nGroupIndex),
2247 nItems = aGroup.length,
2257 // Update the index and className properties of each member
2265 oLI = oItem.element;
2268 oItem.groupIndex = p_nGroupIndex;
2270 oLI.setAttribute(_GROUP_INDEX, p_nGroupIndex);
2271 oLI.setAttribute(_INDEX, i);
2273 Dom.removeClass(oLI, _FIRST_OF_TYPE);
2283 Dom.addClass(oLI, _FIRST_OF_TYPE);
2293 * @method _createItemGroup
2294 * @description Creates a new menu item group (array) and its associated
2295 * <code><ul></code> element. Returns an aray of menu item groups.
2297 * @param {Number} p_nIndex Number indicating the group to create.
2300 _createItemGroup: function (p_nIndex) {
2305 if (!this._aItemGroups[p_nIndex]) {
2307 this._aItemGroups[p_nIndex] = [];
2309 oUL = document.createElement(_UL_LOWERCASE);
2311 this._aListElements[p_nIndex] = oUL;
2313 returnVal = this._aItemGroups[p_nIndex];
2323 * @method _getItemGroup
2324 * @description Returns the menu item group at the specified index.
2326 * @param {Number} p_nIndex Number indicating the index of the menu item group
2330 _getItemGroup: function (p_nIndex) {
2332 var nIndex = Lang.isNumber(p_nIndex) ? p_nIndex : 0,
2333 aGroups = this._aItemGroups,
2336 if (nIndex in aGroups) {
2338 returnVal = aGroups[nIndex];
2348 * @method _configureSubmenu
2349 * @description Subscribes the menu item's submenu to its parent menu's events.
2351 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2352 * instance with the submenu to be configured.
2354 _configureSubmenu: function (p_oItem) {
2356 var oSubmenu = p_oItem.cfg.getProperty(_SUBMENU);
2361 Listen for configuration changes to the parent menu
2362 so they they can be applied to the submenu.
2365 this.cfg.configChangedEvent.subscribe(this._onParentMenuConfigChange, oSubmenu, true);
2367 this.renderEvent.subscribe(this._onParentMenuRender, oSubmenu, true);
2377 * @method _subscribeToItemEvents
2378 * @description Subscribes a menu to a menu item's event.
2380 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2381 * instance whose events should be subscribed to.
2383 _subscribeToItemEvents: function (p_oItem) {
2385 p_oItem.destroyEvent.subscribe(this._onMenuItemDestroy, p_oItem, this);
2386 p_oItem.cfg.configChangedEvent.subscribe(this._onMenuItemConfigChange, p_oItem, this);
2392 * @method _onVisibleChange
2393 * @description Change event handler for the the menu's "visible" configuration
2396 * @param {String} p_sType String representing the name of the event that
2398 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2400 _onVisibleChange: function (p_sType, p_aArgs) {
2402 var bVisible = p_aArgs[0];
2406 Dom.addClass(this.element, _VISIBLE);
2411 Dom.removeClass(this.element, _VISIBLE);
2419 * @method _cancelHideDelay
2420 * @description Cancels the call to "hideMenu."
2423 _cancelHideDelay: function () {
2425 var oTimer = this.getRoot()._hideDelayTimer;
2437 * @method _execHideDelay
2438 * @description Hides the menu after the number of milliseconds specified by
2439 * the "hidedelay" configuration property.
2442 _execHideDelay: function () {
2444 this._cancelHideDelay();
2446 var oRoot = this.getRoot();
2448 oRoot._hideDelayTimer = Lang.later(oRoot.cfg.getProperty(_HIDE_DELAY), this, function () {
2450 if (oRoot.activeItem) {
2452 if (oRoot.hasFocus()) {
2454 oRoot.activeItem.focus();
2458 oRoot.clearActiveItem();
2462 if (oRoot == this && !(this instanceof YAHOO.widget.MenuBar) &&
2463 this.cfg.getProperty(_POSITION) == _DYNAMIC) {
2475 * @method _cancelShowDelay
2476 * @description Cancels the call to the "showMenu."
2479 _cancelShowDelay: function () {
2481 var oTimer = this.getRoot()._showDelayTimer;
2493 * @method _execSubmenuHideDelay
2494 * @description Hides a submenu after the number of milliseconds specified by
2495 * the "submenuhidedelay" configuration property have ellapsed.
2497 * @param {YAHOO.widget.Menu} p_oSubmenu Object specifying the submenu that
2499 * @param {Number} p_nMouseX The x coordinate of the mouse when it left
2500 * the specified submenu's parent menu item.
2501 * @param {Number} p_nHideDelay The number of milliseconds that should ellapse
2502 * before the submenu is hidden.
2504 _execSubmenuHideDelay: function (p_oSubmenu, p_nMouseX, p_nHideDelay) {
2506 p_oSubmenu._submenuHideDelayTimer = Lang.later(50, this, function () {
2508 if (this._nCurrentMouseX > (p_nMouseX + 10)) {
2510 p_oSubmenu._submenuHideDelayTimer = Lang.later(p_nHideDelay, p_oSubmenu, function () {
2529 // Protected methods
2533 * @method _disableScrollHeader
2534 * @description Disables the header used for scrolling the body of the menu.
2537 _disableScrollHeader: function () {
2539 if (!this._bHeaderDisabled) {
2541 Dom.addClass(this.header, _TOP_SCROLLBAR_DISABLED);
2542 this._bHeaderDisabled = true;
2550 * @method _disableScrollFooter
2551 * @description Disables the footer used for scrolling the body of the menu.
2554 _disableScrollFooter: function () {
2556 if (!this._bFooterDisabled) {
2558 Dom.addClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2559 this._bFooterDisabled = true;
2567 * @method _enableScrollHeader
2568 * @description Enables the header used for scrolling the body of the menu.
2571 _enableScrollHeader: function () {
2573 if (this._bHeaderDisabled) {
2575 Dom.removeClass(this.header, _TOP_SCROLLBAR_DISABLED);
2576 this._bHeaderDisabled = false;
2584 * @method _enableScrollFooter
2585 * @description Enables the footer used for scrolling the body of the menu.
2588 _enableScrollFooter: function () {
2590 if (this._bFooterDisabled) {
2592 Dom.removeClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2593 this._bFooterDisabled = false;
2601 * @method _onMouseOver
2602 * @description "mouseover" event handler for the menu.
2604 * @param {String} p_sType String representing the name of the event that
2606 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2608 _onMouseOver: function (p_sType, p_aArgs) {
2610 var oEvent = p_aArgs[0],
2612 oTarget = Event.getTarget(oEvent),
2613 oRoot = this.getRoot(),
2614 oSubmenuHideDelayTimer = this._submenuHideDelayTimer,
2623 var showSubmenu = function () {
2625 if (this.parent.cfg.getProperty(_SELECTED)) {
2634 if (!this._bStopMouseEventHandlers) {
2636 if (!this._bHandledMouseOverEvent && (oTarget == this.element ||
2637 Dom.isAncestor(this.element, oTarget))) {
2639 // Menu mouseover logic
2641 this._nCurrentMouseX = 0;
2643 Event.on(this.element, _MOUSEMOVE, this._onMouseMove, this, true);
2647 If the mouse is moving from the submenu back to its corresponding menu item,
2648 don't hide the submenu or clear the active MenuItem.
2651 if (!(oItem && Dom.isAncestor(oItem.element, Event.getRelatedTarget(oEvent)))) {
2653 this.clearActiveItem();
2658 if (this.parent && oSubmenuHideDelayTimer) {
2660 oSubmenuHideDelayTimer.cancel();
2662 this.parent.cfg.setProperty(_SELECTED, true);
2664 oParentMenu = this.parent.parent;
2666 oParentMenu._bHandledMouseOutEvent = true;
2667 oParentMenu._bHandledMouseOverEvent = false;
2672 this._bHandledMouseOverEvent = true;
2673 this._bHandledMouseOutEvent = false;
2678 if (oItem && !oItem.handledMouseOverEvent && !oItem.cfg.getProperty(_DISABLED) &&
2679 (oTarget == oItem.element || Dom.isAncestor(oItem.element, oTarget))) {
2681 // Menu Item mouseover logic
2683 nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2684 bShowDelay = (nShowDelay > 0);
2689 this._cancelShowDelay();
2694 oActiveItem = this.activeItem;
2698 oActiveItem.cfg.setProperty(_SELECTED, false);
2703 oItemCfg = oItem.cfg;
2705 // Select and focus the current menu item
2707 oItemCfg.setProperty(_SELECTED, true);
2710 if (this.hasFocus() || oRoot._hasFocus) {
2714 oRoot._hasFocus = false;
2719 if (this.cfg.getProperty(_AUTO_SUBMENU_DISPLAY)) {
2721 // Show the submenu this menu item
2723 oSubmenu = oItemCfg.getProperty(_SUBMENU);
2729 oRoot._showDelayTimer =
2730 Lang.later(oRoot.cfg.getProperty(_SHOW_DELAY), oSubmenu, showSubmenu);
2743 oItem.handledMouseOverEvent = true;
2744 oItem.handledMouseOutEvent = false;
2754 * @method _onMouseOut
2755 * @description "mouseout" event handler for the menu.
2757 * @param {String} p_sType String representing the name of the event that
2759 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2761 _onMouseOut: function (p_sType, p_aArgs) {
2763 var oEvent = p_aArgs[0],
2765 oRelatedTarget = Event.getRelatedTarget(oEvent),
2766 bMovingToSubmenu = false,
2773 if (!this._bStopMouseEventHandlers) {
2775 if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
2777 oItemCfg = oItem.cfg;
2778 oSubmenu = oItemCfg.getProperty(_SUBMENU);
2781 if (oSubmenu && (oRelatedTarget == oSubmenu.element ||
2782 Dom.isAncestor(oSubmenu.element, oRelatedTarget))) {
2784 bMovingToSubmenu = true;
2789 if (!oItem.handledMouseOutEvent && ((oRelatedTarget != oItem.element &&
2790 !Dom.isAncestor(oItem.element, oRelatedTarget)) || bMovingToSubmenu)) {
2792 // Menu Item mouseout logic
2794 if (!bMovingToSubmenu) {
2796 oItem.cfg.setProperty(_SELECTED, false);
2801 nSubmenuHideDelay = this.cfg.getProperty(_SUBMENU_HIDE_DELAY);
2803 nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2805 if (!(this instanceof YAHOO.widget.MenuBar) && nSubmenuHideDelay > 0 &&
2806 nShowDelay >= nSubmenuHideDelay) {
2808 this._execSubmenuHideDelay(oSubmenu, Event.getPageX(oEvent),
2823 oItem.handledMouseOutEvent = true;
2824 oItem.handledMouseOverEvent = false;
2831 if (!this._bHandledMouseOutEvent && ((oRelatedTarget != this.element &&
2832 !Dom.isAncestor(this.element, oRelatedTarget)) || bMovingToSubmenu)) {
2834 // Menu mouseout logic
2836 Event.removeListener(this.element, _MOUSEMOVE, this._onMouseMove);
2838 this._nCurrentMouseX = Event.getPageX(oEvent);
2840 this._bHandledMouseOutEvent = true;
2841 this._bHandledMouseOverEvent = false;
2851 * @method _onMouseMove
2852 * @description "click" event handler for the menu.
2854 * @param {Event} p_oEvent Object representing the DOM event object passed
2855 * back by the event utility (YAHOO.util.Event).
2856 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
2859 _onMouseMove: function (p_oEvent, p_oMenu) {
2861 if (!this._bStopMouseEventHandlers) {
2863 this._nCurrentMouseX = Event.getPageX(p_oEvent);
2872 * @description "click" event handler for the menu.
2874 * @param {String} p_sType String representing the name of the event that
2876 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2878 _onClick: function (p_sType, p_aArgs) {
2880 var oEvent = p_aArgs[0],
2882 bInMenuAnchor = false,
2891 var hide = function () {
2894 There is an inconsistency between Firefox 2 for Mac OS X and Firefox 2 Windows
2895 regarding the triggering of the display of the browser's context menu and the
2896 subsequent firing of the "click" event. In Firefox for Windows, when the user
2897 triggers the display of the browser's context menu the "click" event also fires
2898 for the document object, even though the "click" event did not fire for the
2899 element that was the original target of the "contextmenu" event. This is unique
2900 to Firefox on Windows. For all other A-Grade browsers, including Firefox 2 for
2901 Mac OS X, the "click" event doesn't fire for the document object.
2903 This bug in Firefox 2 for Windows affects Menu as Menu instances listen for
2904 events at the document level and have an internal "click" event handler they
2905 use to hide themselves when clicked. As a result, in Firefox for Windows a
2906 Menu will hide when the user right clicks on a MenuItem to raise the browser's
2907 default context menu, because its internal "click" event handler ends up
2908 getting called. The following line fixes this bug.
2911 if (!((UA.gecko && this.platform == _WINDOWS) && oEvent.button > 0)) {
2913 oRoot = this.getRoot();
2915 if (oRoot instanceof YAHOO.widget.MenuBar ||
2916 oRoot.cfg.getProperty(_POSITION) == _STATIC) {
2918 oRoot.clearActiveItem();
2934 if (oItem.cfg.getProperty(_DISABLED)) {
2936 Event.preventDefault(oEvent);
2943 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
2947 Check if the URL of the anchor is pointing to an element that is
2948 a child of the menu.
2951 sURL = oItem.cfg.getProperty(_URL);
2956 nHashPos = sURL.indexOf(_HASH);
2961 if (nHashPos != -1) {
2963 sURL = sURL.substr(nHashPos, nLen);
2970 sId = sURL.substr(1, nLen);
2972 bInMenuAnchor = Dom.isAncestor(this.element, sId);
2975 else if (nLen === 1) {
2977 bInMenuAnchor = true;
2987 if (bInMenuAnchor && !oItem.cfg.getProperty(_TARGET)) {
2989 Event.preventDefault(oEvent);
2999 oItem.focusEvent.fire();
3006 if (!oSubmenu && !this.cfg.getProperty(_KEEP_OPEN)) {
3020 * @method _onKeyDown
3021 * @description "keydown" event handler for the menu.
3023 * @param {String} p_sType String representing the name of the event that
3025 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3027 _onKeyDown: function (p_sType, p_aArgs) {
3029 var oEvent = p_aArgs[0],
3047 This function is called to prevent a bug in Firefox. In Firefox,
3048 moving a DOM element into a stationary mouse pointer will cause the
3049 browser to fire mouse events. This can result in the menu mouse
3050 event handlers being called uncessarily, especially when menus are
3051 moved into a stationary mouse pointer as a result of a
3054 function stopMouseEventHandlers() {
3056 this._bStopMouseEventHandlers = true;
3058 Lang.later(10, this, function () {
3060 this._bStopMouseEventHandlers = false;
3067 if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
3069 oItemCfg = oItem.cfg;
3070 oParentItem = this.parent;
3072 switch(oEvent.keyCode) {
3074 case 38: // Up arrow
3075 case 40: // Down arrow
3077 oNextItem = (oEvent.keyCode == 38) ?
3078 oItem.getPreviousEnabledSibling() :
3079 oItem.getNextEnabledSibling();
3083 this.clearActiveItem();
3085 oNextItem.cfg.setProperty(_SELECTED, true);
3089 if (this.cfg.getProperty(_MAX_HEIGHT) > 0) {
3092 nBodyScrollTop = oBody.scrollTop;
3093 nBodyOffsetHeight = oBody.offsetHeight;
3094 aItems = this.getItems();
3095 nItems = aItems.length - 1;
3096 nNextItemOffsetTop = oNextItem.element.offsetTop;
3099 if (oEvent.keyCode == 40 ) { // Down
3101 if (nNextItemOffsetTop >= (nBodyOffsetHeight + nBodyScrollTop)) {
3103 oBody.scrollTop = nNextItemOffsetTop - nBodyOffsetHeight;
3106 else if (nNextItemOffsetTop <= nBodyScrollTop) {
3108 oBody.scrollTop = 0;
3113 if (oNextItem == aItems[nItems]) {
3115 oBody.scrollTop = oNextItem.element.offsetTop;
3122 if (nNextItemOffsetTop <= nBodyScrollTop) {
3124 oBody.scrollTop = nNextItemOffsetTop - oNextItem.element.offsetHeight;
3127 else if (nNextItemOffsetTop >= (nBodyScrollTop + nBodyOffsetHeight)) {
3129 oBody.scrollTop = nNextItemOffsetTop;
3134 if (oNextItem == aItems[0]) {
3136 oBody.scrollTop = 0;
3143 nBodyScrollTop = oBody.scrollTop;
3144 nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3146 if (nBodyScrollTop === 0) {
3148 this._disableScrollHeader();
3149 this._enableScrollFooter();
3152 else if (nBodyScrollTop == nScrollTarget) {
3154 this._enableScrollHeader();
3155 this._disableScrollFooter();
3160 this._enableScrollHeader();
3161 this._enableScrollFooter();
3170 Event.preventDefault(oEvent);
3172 stopMouseEventHandlers();
3177 case 39: // Right arrow
3179 oSubmenu = oItemCfg.getProperty(_SUBMENU);
3183 if (!oItemCfg.getProperty(_SELECTED)) {
3185 oItemCfg.setProperty(_SELECTED, true);
3190 oSubmenu.setInitialFocus();
3191 oSubmenu.setInitialSelection();
3196 oRoot = this.getRoot();
3198 if (oRoot instanceof YAHOO.widget.MenuBar) {
3200 oNextItem = oRoot.activeItem.getNextEnabledSibling();
3204 oRoot.clearActiveItem();
3206 oNextItem.cfg.setProperty(_SELECTED, true);
3208 oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3213 oSubmenu.setInitialFocus();
3229 Event.preventDefault(oEvent);
3231 stopMouseEventHandlers();
3236 case 37: // Left arrow
3240 oParentMenu = oParentItem.parent;
3242 if (oParentMenu instanceof YAHOO.widget.MenuBar) {
3245 oParentMenu.activeItem.getPreviousEnabledSibling();
3249 oParentMenu.clearActiveItem();
3251 oNextItem.cfg.setProperty(_SELECTED, true);
3253 oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3258 oSubmenu.setInitialFocus();
3274 oParentItem.focus();
3280 Event.preventDefault(oEvent);
3282 stopMouseEventHandlers();
3292 if (oEvent.keyCode == 27) { // Esc key
3294 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3300 this.parent.focus();
3305 else if (this.activeItem) {
3307 oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
3309 if (oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
3312 this.activeItem.focus();
3317 this.activeItem.blur();
3318 this.activeItem.cfg.setProperty(_SELECTED, false);
3325 Event.preventDefault(oEvent);
3333 * @method _onKeyPress
3334 * @description "keypress" event handler for a Menu instance.
3336 * @param {String} p_sType The name of the event that was fired.
3337 * @param {Array} p_aArgs Collection of arguments sent when the event
3340 _onKeyPress: function (p_sType, p_aArgs) {
3342 var oEvent = p_aArgs[0];
3345 if (oEvent.keyCode == 40 || oEvent.keyCode == 38) {
3347 Event.preventDefault(oEvent);
3356 * @description "blur" event handler for a Menu instance.
3358 * @param {String} p_sType The name of the event that was fired.
3359 * @param {Array} p_aArgs Collection of arguments sent when the event
3362 _onBlur: function (p_sType, p_aArgs) {
3364 if (this._hasFocus) {
3365 this._hasFocus = false;
3371 * @method _onYChange
3372 * @description "y" event handler for a Menu instance.
3374 * @param {String} p_sType The name of the event that was fired.
3375 * @param {Array} p_aArgs Collection of arguments sent when the event
3378 _onYChange: function (p_sType, p_aArgs) {
3380 var oParent = this.parent,
3388 nScrollTop = oParent.parent.body.scrollTop;
3391 if (nScrollTop > 0) {
3393 nY = (this.cfg.getProperty(_Y) - nScrollTop);
3395 Dom.setY(this.element, nY);
3397 oIFrame = this.iframe;
3402 Dom.setY(oIFrame, nY);
3406 this.cfg.setProperty(_Y, nY, true);
3416 * @method _onScrollTargetMouseOver
3417 * @description "mouseover" event handler for the menu's "header" and "footer"
3418 * elements. Used to scroll the body of the menu up and down when the
3419 * menu's "maxheight" configuration property is set to a value greater than 0.
3421 * @param {Event} p_oEvent Object representing the DOM event object passed
3422 * back by the event utility (YAHOO.util.Event).
3423 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
3426 _onScrollTargetMouseOver: function (p_oEvent, p_oMenu) {
3428 var oBodyScrollTimer = this._bodyScrollTimer;
3431 if (oBodyScrollTimer) {
3433 oBodyScrollTimer.cancel();
3438 this._cancelHideDelay();
3441 var oTarget = Event.getTarget(p_oEvent),
3443 nScrollIncrement = this.cfg.getProperty(_SCROLL_INCREMENT),
3448 function scrollBodyDown() {
3450 var nScrollTop = oBody.scrollTop;
3453 if (nScrollTop < nScrollTarget) {
3455 oBody.scrollTop = (nScrollTop + nScrollIncrement);
3457 this._enableScrollHeader();
3462 oBody.scrollTop = nScrollTarget;
3464 this._bodyScrollTimer.cancel();
3466 this._disableScrollFooter();
3473 function scrollBodyUp() {
3475 var nScrollTop = oBody.scrollTop;
3478 if (nScrollTop > 0) {
3480 oBody.scrollTop = (nScrollTop - nScrollIncrement);
3482 this._enableScrollFooter();
3487 oBody.scrollTop = 0;
3489 this._bodyScrollTimer.cancel();
3491 this._disableScrollHeader();
3498 if (Dom.hasClass(oTarget, _HD)) {
3500 fnScrollFunction = scrollBodyUp;
3505 nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3507 fnScrollFunction = scrollBodyDown;
3512 this._bodyScrollTimer = Lang.later(10, this, fnScrollFunction, null, true);
3518 * @method _onScrollTargetMouseOut
3519 * @description "mouseout" event handler for the menu's "header" and "footer"
3520 * elements. Used to stop scrolling the body of the menu up and down when the
3521 * menu's "maxheight" configuration property is set to a value greater than 0.
3523 * @param {Event} p_oEvent Object representing the DOM event object passed
3524 * back by the event utility (YAHOO.util.Event).
3525 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
3528 _onScrollTargetMouseOut: function (p_oEvent, p_oMenu) {
3530 var oBodyScrollTimer = this._bodyScrollTimer;
3532 if (oBodyScrollTimer) {
3534 oBodyScrollTimer.cancel();
3538 this._cancelHideDelay();
3549 * @description "init" event handler for the menu.
3551 * @param {String} p_sType String representing the name of the event that
3553 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3555 _onInit: function (p_sType, p_aArgs) {
3557 this.cfg.subscribeToConfigEvent(_VISIBLE, this._onVisibleChange);
3559 var bRootMenu = !this.parent,
3560 bLazyLoad = this.lazyLoad;
3564 Automatically initialize a menu's subtree if:
3566 1) This is the root menu and lazyload is off
3568 2) This is the root menu, lazyload is on, but the menu is
3571 3) This menu is a submenu and lazyload is off
3576 if (((bRootMenu && !bLazyLoad) ||
3577 (bRootMenu && (this.cfg.getProperty(_VISIBLE) ||
3578 this.cfg.getProperty(_POSITION) == _STATIC)) ||
3579 (!bRootMenu && !bLazyLoad)) && this.getItemGroups().length === 0) {
3581 if (this.srcElement) {
3583 this._initSubTree();
3588 if (this.itemData) {
3590 this.addItems(this.itemData);
3595 else if (bLazyLoad) {
3597 this.cfg.fireQueue();
3605 * @method _onBeforeRender
3606 * @description "beforerender" event handler for the menu. Appends all of the
3607 * <code><ul></code>, <code><li></code> and their accompanying
3608 * title elements to the body element of the menu.
3610 * @param {String} p_sType String representing the name of the event that
3612 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3614 _onBeforeRender: function (p_sType, p_aArgs) {
3616 var oEl = this.element,
3617 nListElements = this._aListElements.length,
3623 if (nListElements > 0) {
3627 oUL = this._aListElements[i];
3633 Dom.addClass(oUL, _FIRST_OF_TYPE);
3639 if (!Dom.isAncestor(oEl, oUL)) {
3641 this.appendToBody(oUL);
3646 oGroupTitle = this._aGroupTitleElements[i];
3650 if (!Dom.isAncestor(oEl, oGroupTitle)) {
3652 oUL.parentNode.insertBefore(oGroupTitle, oUL);
3657 Dom.addClass(oUL, _HAS_TITLE);
3666 while (i < nListElements);
3675 * @description "render" event handler for the menu.
3677 * @param {String} p_sType String representing the name of the event that
3679 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3681 _onRender: function (p_sType, p_aArgs) {
3683 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3685 if (!this.cfg.getProperty(_VISIBLE)) {
3687 this.positionOffScreen();
3700 * @method _onBeforeShow
3701 * @description "beforeshow" event handler for the menu.
3703 * @param {String} p_sType String representing the name of the event that
3705 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3707 _onBeforeShow: function (p_sType, p_aArgs) {
3712 oContainer = this.cfg.getProperty(_CONTAINER);
3715 if (this.lazyLoad && this.getItemGroups().length === 0) {
3717 if (this.srcElement) {
3719 this._initSubTree();
3724 if (this.itemData) {
3726 if (this.parent && this.parent.parent &&
3727 this.parent.parent.srcElement &&
3728 this.parent.parent.srcElement.tagName.toUpperCase() ==
3731 nOptions = this.itemData.length;
3733 for(n=0; n<nOptions; n++) {
3735 if (this.itemData[n].tagName) {
3737 this.addItem((new this.ITEM_TYPE(this.itemData[n])));
3746 this.addItems(this.itemData);
3753 oSrcElement = this.srcElement;
3757 if (oSrcElement.tagName.toUpperCase() == _SELECT) {
3759 if (Dom.inDocument(oSrcElement)) {
3761 this.render(oSrcElement.parentNode);
3766 this.render(oContainer);
3782 this.render(this.parent.element);
3787 this.render(oContainer);
3797 var oParent = this.parent,
3801 if (!oParent && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3803 this.cfg.refireEvent(_XY);
3810 aAlignment = oParent.parent.cfg.getProperty(_SUBMENU_ALIGNMENT);
3812 this.cfg.setProperty(_CONTEXT, [oParent.element, aAlignment[0], aAlignment[1]]);
3820 getConstrainedY: function (y) {
3824 aContext = oMenu.cfg.getProperty(_CONTEXT),
3825 nInitialMaxHeight = oMenu.cfg.getProperty(_MAX_HEIGHT),
3829 oOverlapPositions = {
3838 bPotentialContextOverlap = (aContext && oOverlapPositions[aContext[1] + aContext[2]]),
3840 oMenuEl = oMenu.element,
3841 nMenuOffsetHeight = oMenuEl.offsetHeight,
3843 nViewportOffset = Overlay.VIEWPORT_OFFSET,
3844 viewPortHeight = Dom.getViewportHeight(),
3845 scrollY = Dom.getDocumentScrollTop(),
3848 (oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) + nViewportOffset < viewPortHeight),
3859 nBottomRegionHeight,
3867 var flipVertical = function () {
3871 // The Menu is below the context element, flip it above
3872 if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3873 nNewY = (nContextElY - nMenuOffsetHeight);
3875 else { // The Menu is above the context element, flip it below
3876 nNewY = (nContextElY + nContextElHeight);
3879 oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3887 Uses the context element's position to calculate the availble height
3888 above and below it to display its corresponding Menu.
3891 var getDisplayRegionHeight = function () {
3893 // The Menu is below the context element
3894 if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3895 return (nBottomRegionHeight - nViewportOffset);
3897 else { // The Menu is above the context element
3898 return (nTopRegionHeight - nViewportOffset);
3905 Sets the Menu's "y" configuration property to the correct value based on its
3906 current orientation.
3909 var alignY = function () {
3913 if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3914 nNewY = (nContextElY + nContextElHeight);
3917 nNewY = (nContextElY - oMenuEl.offsetHeight);
3920 oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3925 // Resets the maxheight of the Menu to the value set by the user
3927 var resetMaxHeight = function () {
3929 oMenu._setScrollHeight(this.cfg.getProperty(_MAX_HEIGHT));
3931 oMenu.hideEvent.unsubscribe(resetMaxHeight);
3937 Trys to place the Menu in the best possible position (either above or
3938 below its corresponding context element).
3941 var setVerticalPosition = function () {
3943 var nDisplayRegionHeight = getDisplayRegionHeight(),
3944 bMenuHasItems = (oMenu.getItems().length > 0),
3945 nMenuMinScrollHeight,
3950 if (nMenuOffsetHeight > nDisplayRegionHeight) {
3952 nMenuMinScrollHeight =
3953 bMenuHasItems ? oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) : nMenuOffsetHeight;
3956 if ((nDisplayRegionHeight > nMenuMinScrollHeight) && bMenuHasItems) {
3957 nMaxHeight = nDisplayRegionHeight;
3960 nMaxHeight = nInitialMaxHeight;
3964 oMenu._setScrollHeight(nMaxHeight);
3965 oMenu.hideEvent.subscribe(resetMaxHeight);
3968 // Re-align the Menu since its height has just changed
3969 // as a result of the setting of the maxheight property.
3974 if (nDisplayRegionHeight < nMenuMinScrollHeight) {
3979 All possible positions and values for the "maxheight"
3980 configuration property have been tried, but none were
3981 successful, so fall back to the original size and position.
3993 fnReturnVal = setVerticalPosition();
4000 else if (nMaxHeight && (nMaxHeight != nInitialMaxHeight)) {
4002 oMenu._setScrollHeight(nInitialMaxHeight);
4003 oMenu.hideEvent.subscribe(resetMaxHeight);
4005 // Re-align the Menu since its height has just changed
4006 // as a result of the setting of the maxheight property.
4017 if (oMenu.cfg.getProperty(_PREVENT_CONTEXT_OVERLAP) && bPotentialContextOverlap) {
4019 if (bCanConstrain) {
4021 oContextEl = aContext[0];
4022 nContextElHeight = oContextEl.offsetHeight;
4023 nContextElY = (Dom.getY(oContextEl) - scrollY);
4025 nTopRegionHeight = nContextElY;
4026 nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
4028 setVerticalPosition();
4032 yNew = oMenu.cfg.getProperty(_Y);
4035 else if (!(oMenu instanceof YAHOO.widget.MenuBar) && nMenuOffsetHeight >= viewPortHeight) {
4037 nAvailableHeight = (viewPortHeight - (nViewportOffset * 2));
4039 if (nAvailableHeight > oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT)) {
4041 oMenu._setScrollHeight(nAvailableHeight);
4042 oMenu.hideEvent.subscribe(resetMaxHeight);
4046 yNew = oMenu.cfg.getProperty(_Y);
4053 if (bCanConstrain) {
4055 topConstraint = scrollY + nViewportOffset;
4056 bottomConstraint = scrollY + viewPortHeight - nMenuOffsetHeight - nViewportOffset;
4058 if (y < topConstraint) {
4059 yNew = topConstraint;
4060 } else if (y > bottomConstraint) {
4061 yNew = bottomConstraint;
4064 yNew = nViewportOffset + scrollY;
4076 * @description "hide" event handler for the menu.
4078 * @param {String} p_sType String representing the name of the event that
4080 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4082 _onHide: function (p_sType, p_aArgs) {
4084 if (this.cfg.getProperty(_POSITION) === _DYNAMIC) {
4086 this.positionOffScreen();
4095 * @description "show" event handler for the menu.
4097 * @param {String} p_sType String representing the name of the event that
4099 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4101 _onShow: function (p_sType, p_aArgs) {
4103 var oParent = this.parent,
4110 function disableAutoSubmenuDisplay(p_oEvent) {
4114 if (p_oEvent.type == _MOUSEDOWN || (p_oEvent.type == _KEYDOWN && p_oEvent.keyCode == 27)) {
4117 Set the "autosubmenudisplay" to "false" if the user
4118 clicks outside the menu bar.
4121 oTarget = Event.getTarget(p_oEvent);
4123 if (oTarget != oParentMenu.element || !Dom.isAncestor(oParentMenu.element, oTarget)) {
4125 oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
4127 Event.removeListener(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
4128 Event.removeListener(document, _KEYDOWN, disableAutoSubmenuDisplay);
4137 function onSubmenuHide(p_sType, p_aArgs, p_sWidth) {
4139 this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4140 this.hideEvent.unsubscribe(onSubmenuHide, p_sWidth);
4147 oParentMenu = oParent.parent;
4150 if (!oParentMenu.cfg.getProperty(_AUTO_SUBMENU_DISPLAY) &&
4151 (oParentMenu instanceof YAHOO.widget.MenuBar ||
4152 oParentMenu.cfg.getProperty(_POSITION) == _STATIC)) {
4154 oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, true);
4156 Event.on(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
4157 Event.on(document, _KEYDOWN, disableAutoSubmenuDisplay);
4162 // The following fixes an issue with the selected state of a MenuItem not rendering
4163 // correctly when a submenu is aligned to the left of its parent Menu instance.
4165 if ((this.cfg.getProperty("x") < oParentMenu.cfg.getProperty("x")) &&
4167 !this.cfg.getProperty(_WIDTH)) {
4169 oElement = this.element;
4170 nOffsetWidth = oElement.offsetWidth;
4173 Measuring the difference of the offsetWidth before and after
4174 setting the "width" style attribute allows us to compute the
4175 about of padding and borders applied to the element, which in
4176 turn allows us to set the "width" property correctly.
4179 oElement.style.width = nOffsetWidth + _PX;
4181 sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4183 this.cfg.setProperty(_WIDTH, sWidth);
4185 this.hideEvent.subscribe(onSubmenuHide, sWidth);
4195 * @method _onBeforeHide
4196 * @description "beforehide" event handler for the menu.
4198 * @param {String} p_sType String representing the name of the event that
4200 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4202 _onBeforeHide: function (p_sType, p_aArgs) {
4204 var oActiveItem = this.activeItem,
4205 oRoot = this.getRoot(),
4212 oConfig = oActiveItem.cfg;
4214 oConfig.setProperty(_SELECTED, false);
4216 oSubmenu = oConfig.getProperty(_SUBMENU);
4228 Focus can get lost in IE when the mouse is moving from a submenu back to its parent Menu.
4229 For this reason, it is necessary to maintain the focused state in a private property
4230 so that the _onMouseOver event handler is able to determined whether or not to set focus
4231 to MenuItems as the user is moving the mouse.
4234 if (UA.ie && this.cfg.getProperty(_POSITION) === _DYNAMIC && this.parent) {
4236 oRoot._hasFocus = this.hasFocus();
4241 if (oRoot == this) {
4251 * @method _onParentMenuConfigChange
4252 * @description "configchange" event handler for a submenu.
4254 * @param {String} p_sType String representing the name of the event that
4256 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4257 * @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that
4258 * subscribed to the event.
4260 _onParentMenuConfigChange: function (p_sType, p_aArgs, p_oSubmenu) {
4262 var sPropertyName = p_aArgs[0][0],
4263 oPropertyValue = p_aArgs[0][1];
4265 switch(sPropertyName) {
4268 case _CONSTRAIN_TO_VIEWPORT:
4271 case _SUBMENU_HIDE_DELAY:
4272 case _CLICK_TO_HIDE:
4275 case _SCROLL_INCREMENT:
4276 case _MIN_SCROLL_HEIGHT:
4277 case _MONITOR_RESIZE:
4279 case _PREVENT_CONTEXT_OVERLAP:
4281 p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4285 case _SUBMENU_ALIGNMENT:
4287 if (!(this.parent.parent instanceof YAHOO.widget.MenuBar)) {
4289 p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4301 * @method _onParentMenuRender
4302 * @description "render" event handler for a submenu. Renders a
4303 * submenu in response to the firing of its parent's "render" event.
4305 * @param {String} p_sType String representing the name of the event that
4307 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4308 * @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that
4309 * subscribed to the event.
4311 _onParentMenuRender: function (p_sType, p_aArgs, p_oSubmenu) {
4313 var oParentMenu = p_oSubmenu.parent.parent,
4314 oParentCfg = oParentMenu.cfg,
4318 constraintoviewport: oParentCfg.getProperty(_CONSTRAIN_TO_VIEWPORT),
4322 clicktohide: oParentCfg.getProperty(_CLICK_TO_HIDE),
4324 effect: oParentCfg.getProperty(_EFFECT),
4326 showdelay: oParentCfg.getProperty(_SHOW_DELAY),
4328 hidedelay: oParentCfg.getProperty(_HIDE_DELAY),
4330 submenuhidedelay: oParentCfg.getProperty(_SUBMENU_HIDE_DELAY),
4332 classname: oParentCfg.getProperty(_CLASSNAME),
4334 scrollincrement: oParentCfg.getProperty(_SCROLL_INCREMENT),
4336 minscrollheight: oParentCfg.getProperty(_MIN_SCROLL_HEIGHT),
4338 iframe: oParentCfg.getProperty(_IFRAME),
4340 shadow: oParentCfg.getProperty(_SHADOW),
4342 preventcontextoverlap: oParentCfg.getProperty(_PREVENT_CONTEXT_OVERLAP),
4344 monitorresize: oParentCfg.getProperty(_MONITOR_RESIZE)
4352 if (!(oParentMenu instanceof YAHOO.widget.MenuBar)) {
4354 oConfig[_SUBMENU_ALIGNMENT] = oParentCfg.getProperty(_SUBMENU_ALIGNMENT);
4359 p_oSubmenu.cfg.applyConfig(oConfig);
4362 if (!this.lazyLoad) {
4364 oLI = this.parent.element;
4366 if (this.element.parentNode == oLI) {
4383 * @method _onMenuItemDestroy
4384 * @description "destroy" event handler for the menu's items.
4386 * @param {String} p_sType String representing the name of the event
4388 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4389 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
4390 * that fired the event.
4392 _onMenuItemDestroy: function (p_sType, p_aArgs, p_oItem) {
4394 this._removeItemFromGroupByValue(p_oItem.groupIndex, p_oItem);
4400 * @method _onMenuItemConfigChange
4401 * @description "configchange" event handler for the menu's items.
4403 * @param {String} p_sType String representing the name of the event that
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 _onMenuItemConfigChange: function (p_sType, p_aArgs, p_oItem) {
4411 var sPropertyName = p_aArgs[0][0],
4412 oPropertyValue = p_aArgs[0][1],
4416 switch(sPropertyName) {
4420 if (oPropertyValue === true) {
4422 this.activeItem = p_oItem;
4430 oSubmenu = p_aArgs[0][1];
4434 this._configureSubmenu(p_oItem);
4446 // Public event handlers for configuration properties
4450 * @method configVisible
4451 * @description Event handler for when the "visible" configuration property
4453 * @param {String} p_sType String representing the name of the event that
4455 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4456 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4459 configVisible: function (p_sType, p_aArgs, p_oMenu) {
4464 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4466 Menu.superclass.configVisible.call(this, p_sType, p_aArgs, p_oMenu);
4471 bVisible = p_aArgs[0];
4472 sDisplay = Dom.getStyle(this.element, _DISPLAY);
4474 Dom.setStyle(this.element, _VISIBILITY, _VISIBLE);
4478 if (sDisplay != _BLOCK) {
4479 this.beforeShowEvent.fire();
4480 Dom.setStyle(this.element, _DISPLAY, _BLOCK);
4481 this.showEvent.fire();
4487 if (sDisplay == _BLOCK) {
4488 this.beforeHideEvent.fire();
4489 Dom.setStyle(this.element, _DISPLAY, _NONE);
4490 this.hideEvent.fire();
4501 * @method configPosition
4502 * @description Event handler for when the "position" configuration property
4503 * of the menu changes.
4504 * @param {String} p_sType String representing the name of the event that
4506 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4507 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4510 configPosition: function (p_sType, p_aArgs, p_oMenu) {
4512 var oElement = this.element,
4513 sCSSPosition = p_aArgs[0] == _STATIC ? _STATIC : _ABSOLUTE,
4518 Dom.setStyle(oElement, _POSITION, sCSSPosition);
4521 if (sCSSPosition == _STATIC) {
4523 // Statically positioned menus are visible by default
4525 Dom.setStyle(oElement, _DISPLAY, _BLOCK);
4527 oCfg.setProperty(_VISIBLE, true);
4533 Even though the "visible" property is queued to
4534 "false" by default, we need to set the "visibility" property to
4535 "hidden" since Overlay's "configVisible" implementation checks the
4536 element's "visibility" style property before deciding whether
4537 or not to show an Overlay instance.
4540 Dom.setStyle(oElement, _VISIBILITY, _HIDDEN);
4545 if (sCSSPosition == _ABSOLUTE) {
4547 nZIndex = oCfg.getProperty(_ZINDEX);
4549 if (!nZIndex || nZIndex === 0) {
4551 oCfg.setProperty(_ZINDEX, 1);
4561 * @method configIframe
4562 * @description Event handler for when the "iframe" configuration property of
4564 * @param {String} p_sType String representing the name of the event that
4566 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4567 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4570 configIframe: function (p_sType, p_aArgs, p_oMenu) {
4572 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4574 Menu.superclass.configIframe.call(this, p_sType, p_aArgs, p_oMenu);
4582 * @method configHideDelay
4583 * @description Event handler for when the "hidedelay" configuration property
4584 * of the menu changes.
4585 * @param {String} p_sType String representing the name of the event that
4587 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4588 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4591 configHideDelay: function (p_sType, p_aArgs, p_oMenu) {
4593 var nHideDelay = p_aArgs[0],
4594 oMouseOutEvent = this.mouseOutEvent,
4595 oMouseOverEvent = this.mouseOverEvent,
4596 oKeyDownEvent = this.keyDownEvent;
4598 if (nHideDelay > 0) {
4601 Only assign event handlers once. This way the user change
4602 the value for the hidedelay as many times as they want.
4605 if (!this._bHideDelayEventHandlersAssigned) {
4607 oMouseOutEvent.subscribe(this._execHideDelay);
4608 oMouseOverEvent.subscribe(this._cancelHideDelay);
4609 oKeyDownEvent.subscribe(this._cancelHideDelay);
4611 this._bHideDelayEventHandlersAssigned = true;
4618 oMouseOutEvent.unsubscribe(this._execHideDelay);
4619 oMouseOverEvent.unsubscribe(this._cancelHideDelay);
4620 oKeyDownEvent.unsubscribe(this._cancelHideDelay);
4622 this._bHideDelayEventHandlersAssigned = false;
4630 * @method configContainer
4631 * @description Event handler for when the "container" configuration property
4632 * of the menu changes.
4633 * @param {String} p_sType String representing the name of the event that
4635 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4636 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4639 configContainer: function (p_sType, p_aArgs, p_oMenu) {
4641 var oElement = p_aArgs[0];
4643 if (Lang.isString(oElement)) {
4645 this.cfg.setProperty(_CONTAINER, Dom.get(oElement), true);
4653 * @method _clearSetWidthFlag
4654 * @description Change event listener for the "width" configuration property. This listener is
4655 * added when a Menu's "width" configuration property is set by the "_setScrollHeight" method, and
4656 * is used to set the "_widthSetForScroll" property to "false" if the "width" configuration property
4657 * is changed after it was set by the "_setScrollHeight" method. If the "_widthSetForScroll"
4658 * property is set to "false", and the "_setScrollHeight" method is in the process of tearing down
4659 * scrolling functionality, it will maintain the Menu's new width rather than reseting it.
4662 _clearSetWidthFlag: function () {
4664 this._widthSetForScroll = false;
4666 this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4672 * @method _setScrollHeight
4674 * @param {String} p_nScrollHeight Number representing the scrolling height of the Menu.
4677 _setScrollHeight: function (p_nScrollHeight) {
4679 var nScrollHeight = p_nScrollHeight,
4680 bRefireIFrameAndShadow = false,
4695 if (this.getItems().length > 0) {
4697 oElement = this.element;
4699 oHeader = this.header;
4700 oFooter = this.footer;
4701 fnMouseOver = this._onScrollTargetMouseOver;
4702 fnMouseOut = this._onScrollTargetMouseOut;
4703 nMinScrollHeight = this.cfg.getProperty(_MIN_SCROLL_HEIGHT);
4704 oParent = this.parent;
4707 if (nScrollHeight > 0 && nScrollHeight < nMinScrollHeight) {
4709 nScrollHeight = nMinScrollHeight;
4714 Dom.setStyle(oBody, _HEIGHT, _EMPTY_STRING);
4715 Dom.removeClass(oBody, _YUI_MENU_BODY_SCROLLED);
4716 oBody.scrollTop = 0;
4720 There is a bug in gecko-based browsers where an element whose
4721 "position" property is set to "absolute" and "overflow" property is set
4722 to "hidden" will not render at the correct width when its
4723 offsetParent's "position" property is also set to "absolute." It is
4724 possible to work around this bug by specifying a value for the width
4725 property in addition to overflow.
4727 In IE it is also necessary to give the Menu a width before the scrollbars are
4728 rendered to prevent the Menu from rendering with a width that is 100% of
4729 the browser viewport.
4732 bSetWidth = ((UA.gecko && oParent && oParent.parent &&
4733 oParent.parent.cfg.getProperty(_POSITION) == _DYNAMIC) || UA.ie);
4735 if (nScrollHeight > 0 && bSetWidth && !this.cfg.getProperty(_WIDTH)) {
4737 nOffsetWidth = oElement.offsetWidth;
4740 Measuring the difference of the offsetWidth before and after
4741 setting the "width" style attribute allows us to compute the
4742 about of padding and borders applied to the element, which in
4743 turn allows us to set the "width" property correctly.
4746 oElement.style.width = nOffsetWidth + _PX;
4748 sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4751 this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4753 YAHOO.log("Setting the \"width\" configuration property to " + sWidth + " for srolling.",
4754 "info", this.toString());
4756 this.cfg.setProperty(_WIDTH, sWidth);
4760 Set a flag (_widthSetForScroll) to maintain some history regarding how the
4761 "width" configuration property was set. If the "width" configuration property
4762 is set by something other than the "_setScrollHeight" method, it will be
4763 necessary to maintain that new value and not clear the width if scrolling
4767 this._widthSetForScroll = true;
4769 this.cfg.subscribeToConfigEvent(_WIDTH, this._clearSetWidthFlag);
4774 if (nScrollHeight > 0 && (!oHeader && !oFooter)) {
4776 YAHOO.log("Creating header and footer for scrolling.", "info", this.toString());
4778 this.setHeader(_NON_BREAKING_SPACE);
4779 this.setFooter(_NON_BREAKING_SPACE);
4781 oHeader = this.header;
4782 oFooter = this.footer;
4784 Dom.addClass(oHeader, _TOP_SCROLLBAR);
4785 Dom.addClass(oFooter, _BOTTOM_SCROLLBAR);
4787 oElement.insertBefore(oHeader, oBody);
4788 oElement.appendChild(oFooter);
4793 nHeight = nScrollHeight;
4796 if (oHeader && oFooter) {
4797 nHeight = (nHeight - (oHeader.offsetHeight + oFooter.offsetHeight));
4801 if ((nHeight > 0) && (oBody.offsetHeight > nScrollHeight)) {
4803 YAHOO.log("Setting up styles and event handlers for scrolling.",
4804 "info", this.toString());
4806 Dom.addClass(oBody, _YUI_MENU_BODY_SCROLLED);
4807 Dom.setStyle(oBody, _HEIGHT, (nHeight + _PX));
4809 if (!this._hasScrollEventHandlers) {
4811 Event.on(oHeader, _MOUSEOVER, fnMouseOver, this, true);
4812 Event.on(oHeader, _MOUSEOUT, fnMouseOut, this, true);
4813 Event.on(oFooter, _MOUSEOVER, fnMouseOver, this, true);
4814 Event.on(oFooter, _MOUSEOUT, fnMouseOut, this, true);
4816 this._hasScrollEventHandlers = true;
4820 this._disableScrollHeader();
4821 this._enableScrollFooter();
4823 bRefireIFrameAndShadow = true;
4826 else if (oHeader && oFooter) {
4828 YAHOO.log("Removing styles and event handlers for scrolling.", "info", this.toString());
4832 Only clear the the "width" configuration property if it was set the
4833 "_setScrollHeight" method and wasn't changed by some other means after it was set.
4836 if (this._widthSetForScroll) {
4838 YAHOO.log("Clearing width used for scrolling.", "info", this.toString());
4840 this._widthSetForScroll = false;
4842 this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4844 this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4849 this._enableScrollHeader();
4850 this._enableScrollFooter();
4852 if (this._hasScrollEventHandlers) {
4854 Event.removeListener(oHeader, _MOUSEOVER, fnMouseOver);
4855 Event.removeListener(oHeader, _MOUSEOUT, fnMouseOut);
4856 Event.removeListener(oFooter, _MOUSEOVER, fnMouseOver);
4857 Event.removeListener(oFooter, _MOUSEOUT, fnMouseOut);
4859 this._hasScrollEventHandlers = false;
4863 oElement.removeChild(oHeader);
4864 oElement.removeChild(oFooter);
4869 bRefireIFrameAndShadow = true;
4874 if (bRefireIFrameAndShadow) {
4876 this.cfg.refireEvent(_IFRAME);
4877 this.cfg.refireEvent(_SHADOW);
4887 * @method _setMaxHeight
4888 * @description "renderEvent" handler used to defer the setting of the
4889 * "maxheight" configuration property until the menu is rendered in lazy
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 {Number} p_nMaxHeight Number representing the value to set for the
4895 * "maxheight" configuration property.
4898 _setMaxHeight: function (p_sType, p_aArgs, p_nMaxHeight) {
4900 this._setScrollHeight(p_nMaxHeight);
4901 this.renderEvent.unsubscribe(this._setMaxHeight);
4907 * @method configMaxHeight
4908 * @description Event handler for when the "maxheight" configuration property of
4910 * @param {String} p_sType The name of the event that was fired.
4911 * @param {Array} p_aArgs Collection of arguments sent when the event
4913 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired
4916 configMaxHeight: function (p_sType, p_aArgs, p_oMenu) {
4918 var nMaxHeight = p_aArgs[0];
4920 if (this.lazyLoad && !this.body && nMaxHeight > 0) {
4922 this.renderEvent.subscribe(this._setMaxHeight, nMaxHeight, this);
4927 this._setScrollHeight(nMaxHeight);
4935 * @method configClassName
4936 * @description Event handler for when the "classname" configuration property of
4938 * @param {String} p_sType The name of the event that was fired.
4939 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4940 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4942 configClassName: function (p_sType, p_aArgs, p_oMenu) {
4944 var sClassName = p_aArgs[0];
4946 if (this._sClassName) {
4948 Dom.removeClass(this.element, this._sClassName);
4952 Dom.addClass(this.element, sClassName);
4953 this._sClassName = sClassName;
4959 * @method _onItemAdded
4960 * @description "itemadded" event handler for a Menu instance.
4962 * @param {String} p_sType The name of the event that was fired.
4963 * @param {Array} p_aArgs Collection of arguments sent when the event
4966 _onItemAdded: function (p_sType, p_aArgs) {
4968 var oItem = p_aArgs[0];
4972 oItem.cfg.setProperty(_DISABLED, true);
4980 * @method configDisabled
4981 * @description Event handler for when the "disabled" configuration property of
4983 * @param {String} p_sType The name of the event that was fired.
4984 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4985 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4987 configDisabled: function (p_sType, p_aArgs, p_oMenu) {
4989 var bDisabled = p_aArgs[0],
4990 aItems = this.getItems(),
4994 if (Lang.isArray(aItems)) {
4996 nItems = aItems.length;
5004 aItems[i].cfg.setProperty(_DISABLED, bDisabled);
5014 this.clearActiveItem(true);
5016 Dom.addClass(this.element, _DISABLED);
5018 this.itemAddedEvent.subscribe(this._onItemAdded);
5023 Dom.removeClass(this.element, _DISABLED);
5025 this.itemAddedEvent.unsubscribe(this._onItemAdded);
5035 * @method configShadow
5036 * @description Event handler for when the "shadow" configuration property of
5038 * @param {String} p_sType The name of the event that was fired.
5039 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
5040 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
5042 configShadow: function (p_sType, p_aArgs, p_oMenu) {
5044 var sizeShadow = function () {
5046 var oElement = this.element,
5047 oShadow = this._shadow;
5049 if (oShadow && oElement) {
5051 // Clear the previous width
5053 if (oShadow.style.width && oShadow.style.height) {
5055 oShadow.style.width = _EMPTY_STRING;
5056 oShadow.style.height = _EMPTY_STRING;
5060 oShadow.style.width = (oElement.offsetWidth + 6) + _PX;
5061 oShadow.style.height = (oElement.offsetHeight + 1) + _PX;
5068 var replaceShadow = function () {
5070 this.element.appendChild(this._shadow);
5075 var addShadowVisibleClass = function () {
5077 Dom.addClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5082 var removeShadowVisibleClass = function () {
5084 Dom.removeClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5089 var createShadow = function () {
5091 var oShadow = this._shadow,
5096 oElement = this.element;
5099 if (!m_oShadowTemplate) {
5101 m_oShadowTemplate = document.createElement(_DIV_LOWERCASE);
5102 m_oShadowTemplate.className = _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE;
5106 oShadow = m_oShadowTemplate.cloneNode(false);
5108 oElement.appendChild(oShadow);
5110 this._shadow = oShadow;
5112 this.beforeShowEvent.subscribe(addShadowVisibleClass);
5113 this.beforeHideEvent.subscribe(removeShadowVisibleClass);
5119 Need to call sizeShadow & syncIframe via setTimeout for
5120 IE 7 Quirks Mode and IE 6 Standards Mode and Quirks Mode
5121 or the shadow and iframe shim will not be sized and
5122 positioned properly.
5125 Lang.later(0, this, function () {
5127 sizeShadow.call(this);
5133 this.cfg.subscribeToConfigEvent(_WIDTH, sizeShadow);
5134 this.cfg.subscribeToConfigEvent(_HEIGHT, sizeShadow);
5135 this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, sizeShadow);
5136 this.changeContentEvent.subscribe(sizeShadow);
5138 Module.textResizeEvent.subscribe(sizeShadow, this, true);
5140 this.destroyEvent.subscribe(function () {
5142 Module.textResizeEvent.unsubscribe(sizeShadow, this);
5148 this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, replaceShadow);
5155 var onBeforeShow = function () {
5159 // If called because the "shadow" event was refired - just append again and resize
5161 replaceShadow.call(this);
5164 sizeShadow.call(this);
5170 createShadow.call(this);
5174 this.beforeShowEvent.unsubscribe(onBeforeShow);
5179 var bShadow = p_aArgs[0];
5182 if (bShadow && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
5184 if (this.cfg.getProperty(_VISIBLE)) {
5188 // If the "shadow" event was refired - just append again and resize
5190 replaceShadow.call(this);
5193 sizeShadow.call(this);
5198 createShadow.call(this);
5204 this.beforeShowEvent.subscribe(onBeforeShow);
5218 * @method initEvents
5219 * @description Initializes the custom events for the menu.
5221 initEvents: function () {
5223 Menu.superclass.initEvents.call(this);
5225 // Create custom events
5227 var i = EVENT_TYPES.length - 1,
5234 aEventData = EVENT_TYPES[i];
5236 oCustomEvent = this.createEvent(aEventData[1]);
5237 oCustomEvent.signature = CustomEvent.LIST;
5239 this[aEventData[0]] = oCustomEvent;
5248 * @method positionOffScreen
5249 * @description Positions the menu outside of the boundaries of the browser's
5250 * viewport. Called automatically when a menu is hidden to ensure that
5251 * it doesn't force the browser to render uncessary scrollbars.
5253 positionOffScreen: function () {
5255 var oIFrame = this.iframe,
5256 oElement = this.element,
5257 sPos = this.OFF_SCREEN_POSITION;
5259 oElement.style.top = _EMPTY_STRING;
5260 oElement.style.left = _EMPTY_STRING;
5264 oIFrame.style.top = sPos;
5265 oIFrame.style.left = sPos;
5274 * @description Finds the menu's root menu.
5276 getRoot: function () {
5278 var oItem = this.parent,
5284 oParentMenu = oItem.parent;
5286 returnVal = oParentMenu ? oParentMenu.getRoot() : this;
5302 * @description Returns a string representing the menu.
5305 toString: function () {
5307 var sReturnVal = _MENU,
5312 sReturnVal += (_SPACE + sId);
5322 * @method setItemGroupTitle
5323 * @description Sets the title of a group of menu items.
5324 * @param {String} p_sGroupTitle String specifying the title of the group.
5325 * @param {Number} p_nGroupIndex Optional. Number specifying the group to which
5326 * the title belongs.
5328 setItemGroupTitle: function (p_sGroupTitle, p_nGroupIndex) {
5335 if (Lang.isString(p_sGroupTitle) && p_sGroupTitle.length > 0) {
5337 nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
5338 oTitle = this._aGroupTitleElements[nGroupIndex];
5343 oTitle.innerHTML = p_sGroupTitle;
5348 oTitle = document.createElement(this.GROUP_TITLE_TAG_NAME);
5350 oTitle.innerHTML = p_sGroupTitle;
5352 this._aGroupTitleElements[nGroupIndex] = oTitle;
5357 i = this._aGroupTitleElements.length - 1;
5361 if (this._aGroupTitleElements[i]) {
5363 Dom.removeClass(this._aGroupTitleElements[i], _FIRST_OF_TYPE);
5373 if (nFirstIndex !== null) {
5375 Dom.addClass(this._aGroupTitleElements[nFirstIndex],
5380 this.changeContentEvent.fire();
5390 * @description Appends an item to the menu.
5391 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
5392 * instance to be added to the menu.
5393 * @param {String} p_oItem String specifying the text of the item to be added
5395 * @param {Object} p_oItem Object literal containing a set of menu item
5396 * configuration properties.
5397 * @param {Number} p_nGroupIndex Optional. Number indicating the group to
5398 * which the item belongs.
5399 * @return {YAHOO.widget.MenuItem}
5401 addItem: function (p_oItem, p_nGroupIndex) {
5403 return this._addItemToGroup(p_nGroupIndex, p_oItem);
5410 * @description Adds an array of items to the menu.
5411 * @param {Array} p_aItems Array of items to be added to the menu. The array
5412 * can contain strings specifying the text for each item to be created, object
5413 * literals specifying each of the menu item configuration properties,
5414 * or MenuItem instances.
5415 * @param {Number} p_nGroupIndex Optional. Number specifying the group to
5416 * which the items belongs.
5419 addItems: function (p_aItems, p_nGroupIndex) {
5428 if (Lang.isArray(p_aItems)) {
5430 nItems = p_aItems.length;
5433 for(i=0; i<nItems; i++) {
5435 oItem = p_aItems[i];
5439 if (Lang.isArray(oItem)) {
5441 aItems[aItems.length] = this.addItems(oItem, i);
5446 aItems[aItems.length] = this._addItemToGroup(p_nGroupIndex, oItem);
5455 if (aItems.length) {
5469 * @method insertItem
5470 * @description Inserts an item into the menu at the specified index.
5471 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
5472 * instance to be added to the menu.
5473 * @param {String} p_oItem String specifying the text of the item to be added
5475 * @param {Object} p_oItem Object literal containing a set of menu item
5476 * configuration properties.
5477 * @param {Number} p_nItemIndex Number indicating the ordinal position at which
5478 * the item should be added.
5479 * @param {Number} p_nGroupIndex Optional. Number indicating the group to which
5481 * @return {YAHOO.widget.MenuItem}
5483 insertItem: function (p_oItem, p_nItemIndex, p_nGroupIndex) {
5485 return this._addItemToGroup(p_nGroupIndex, p_oItem, p_nItemIndex);
5491 * @method removeItem
5492 * @description Removes the specified item from the menu.
5493 * @param {YAHOO.widget.MenuItem} p_oObject Object reference for the MenuItem
5494 * instance to be removed from the menu.
5495 * @param {Number} p_oObject Number specifying the index of the item
5497 * @param {Number} p_nGroupIndex Optional. Number specifying the group to
5498 * which the item belongs.
5499 * @return {YAHOO.widget.MenuItem}
5501 removeItem: function (p_oObject, p_nGroupIndex) {
5506 if (!Lang.isUndefined(p_oObject)) {
5508 if (p_oObject instanceof YAHOO.widget.MenuItem) {
5510 oItem = this._removeItemFromGroupByValue(p_nGroupIndex, p_oObject);
5513 else if (Lang.isNumber(p_oObject)) {
5515 oItem = this._removeItemFromGroupByIndex(p_nGroupIndex, p_oObject);
5523 YAHOO.log("Item removed." +
5524 " Text: " + oItem.cfg.getProperty("text") + ", " +
5525 " Index: " + oItem.index + ", " +
5526 " Group Index: " + oItem.groupIndex, "info", this.toString());
5541 * @description Returns an array of all of the items in the menu.
5544 getItems: function () {
5546 var aGroups = this._aItemGroups,
5552 if (Lang.isArray(aGroups)) {
5554 nGroups = aGroups.length;
5556 returnVal = ((nGroups == 1) ? aGroups[0] : (Array.prototype.concat.apply(aItems, aGroups)));
5566 * @method getItemGroups
5567 * @description Multi-dimensional Array representing the menu items as they
5568 * are grouped in the menu.
5571 getItemGroups: function () {
5573 return this._aItemGroups;
5580 * @description Returns the item at the specified index.
5581 * @param {Number} p_nItemIndex Number indicating the ordinal position of the
5582 * item to be retrieved.
5583 * @param {Number} p_nGroupIndex Optional. Number indicating the group to which
5585 * @return {YAHOO.widget.MenuItem}
5587 getItem: function (p_nItemIndex, p_nGroupIndex) {
5592 if (Lang.isNumber(p_nItemIndex)) {
5594 aGroup = this._getItemGroup(p_nGroupIndex);
5598 returnVal = aGroup[p_nItemIndex];
5610 * @method getSubmenus
5611 * @description Returns an array of all of the submenus that are immediate
5612 * children of the menu.
5615 getSubmenus: function () {
5617 var aItems = this.getItems(),
5618 nItems = aItems.length,
5629 for(i=0; i<nItems; i++) {
5635 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5639 aSubmenus[aSubmenus.length] = oSubmenu;
5655 * @method clearContent
5656 * @description Removes all of the content from the menu, including the menu
5657 * items, group titles, header and footer.
5659 clearContent: function () {
5661 var aItems = this.getItems(),
5662 nItems = aItems.length,
5663 oElement = this.element,
5665 oHeader = this.header,
5666 oFooter = this.footer,
5682 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5686 this.cfg.configChangedEvent.unsubscribe(
5687 this._onParentMenuConfigChange, oSubmenu);
5689 this.renderEvent.unsubscribe(this._onParentMenuRender,
5694 this.removeItem(oItem, oItem.groupIndex);
5706 Event.purgeElement(oHeader);
5707 oElement.removeChild(oHeader);
5714 Event.purgeElement(oFooter);
5715 oElement.removeChild(oFooter);
5721 Event.purgeElement(oBody);
5723 oBody.innerHTML = _EMPTY_STRING;
5727 this.activeItem = null;
5729 this._aItemGroups = [];
5730 this._aListElements = [];
5731 this._aGroupTitleElements = [];
5733 this.cfg.setProperty(_WIDTH, null);
5740 * @description Removes the menu's <code><div></code> element
5741 * (and accompanying child nodes) from the document.
5743 destroy: function () {
5747 this.clearContent();
5749 this._aItemGroups = null;
5750 this._aListElements = null;
5751 this._aGroupTitleElements = null;
5754 // Continue with the superclass implementation of this method
5756 Menu.superclass.destroy.call(this);
5758 YAHOO.log("Destroyed.", "info", this.toString());
5764 * @method setInitialFocus
5765 * @description Sets focus to the menu's first enabled item.
5767 setInitialFocus: function () {
5769 var oItem = this._getFirstEnabledItem();
5781 * @method setInitialSelection
5782 * @description Sets the "selected" configuration property of the menu's first
5783 * enabled item to "true."
5785 setInitialSelection: function () {
5787 var oItem = this._getFirstEnabledItem();
5791 oItem.cfg.setProperty(_SELECTED, true);
5798 * @method clearActiveItem
5799 * @description Sets the "selected" configuration property of the menu's active
5800 * item to "false" and hides the item's submenu.
5801 * @param {Boolean} p_bBlur Boolean indicating if the menu's active item
5802 * should be blurred.
5804 clearActiveItem: function (p_bBlur) {
5806 if (this.cfg.getProperty(_SHOW_DELAY) > 0) {
5808 this._cancelShowDelay();
5813 var oActiveItem = this.activeItem,
5819 oConfig = oActiveItem.cfg;
5825 this.getRoot()._hasFocus = true;
5829 oConfig.setProperty(_SELECTED, false);
5831 oSubmenu = oConfig.getProperty(_SUBMENU);
5840 this.activeItem = null;
5849 * @description Causes the menu to receive focus and fires the "focus" event.
5851 focus: function () {
5853 if (!this.hasFocus()) {
5855 this.setInitialFocus();
5864 * @description Causes the menu to lose focus and fires the "blur" event.
5870 if (this.hasFocus()) {
5872 oItem = MenuManager.getFocusedMenuItem();
5887 * @description Returns a boolean indicating whether or not the menu has focus.
5890 hasFocus: function () {
5892 return (MenuManager.getFocusedMenu() == this.getRoot());
5898 * Adds the specified CustomEvent subscriber to the menu and each of
5901 * @param p_type {string} the type, or name of the event
5902 * @param p_fn {function} the function to exectute when the event fires
5903 * @param p_obj {Object} An object to be passed along when the event
5905 * @param p_override {boolean} If true, the obj passed in becomes the
5906 * execution scope of the listener
5908 subscribe: function () {
5910 function onItemAdded(p_sType, p_aArgs, p_oObject) {
5912 var oItem = p_aArgs[0],
5913 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5917 oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5924 function onSubmenuAdded(p_sType, p_aArgs, p_oObject) {
5926 var oSubmenu = this.cfg.getProperty(_SUBMENU);
5930 oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5937 Menu.superclass.subscribe.apply(this, arguments);
5938 Menu.superclass.subscribe.call(this, _ITEM_ADDED, onItemAdded, arguments);
5941 var aItems = this.getItems(),
5950 nItems = aItems.length;
5960 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5964 oSubmenu.subscribe.apply(oSubmenu, arguments);
5969 oItem.cfg.subscribeToConfigEvent(_SUBMENU, onSubmenuAdded, arguments);
5984 * @description Initializes the class's configurable properties which can be
5985 * changed using the menu's Config object ("cfg").
5986 * @method initDefaultConfig
5988 initDefaultConfig: function () {
5990 Menu.superclass.initDefaultConfig.call(this);
5992 var oConfig = this.cfg;
5995 // Module documentation overrides
5999 * @description Object or array of objects representing the ContainerEffect
6000 * classes that are active for animating the container. When set this
6001 * property is automatically applied to all submenus.
6006 // Overlay documentation overrides
6011 * @description Number representing the absolute x-coordinate position of
6012 * the Menu. This property is only applied when the "position"
6013 * configuration property is set to dynamic.
6021 * @description Number representing the absolute y-coordinate position of
6022 * the Menu. This property is only applied when the "position"
6023 * configuration property is set to dynamic.
6030 * @description Array of the absolute x and y positions of the Menu. This
6031 * property is only applied when the "position" configuration property is
6041 * @description Array of context arguments for context-sensitive positioning.
6042 * The format is: [id or element, element corner, context corner].
6043 * For example, setting this property to ["img1", "tl", "bl"] would
6044 * align the Mnu's top left corner to the context element's
6045 * bottom left corner. This property is only applied when the "position"
6046 * configuration property is set to dynamic.
6053 * @config fixedcenter
6054 * @description Boolean indicating if the Menu should be anchored to the
6055 * center of the viewport. This property is only applied when the
6056 * "position" configuration property is set to dynamic.
6064 * @description Boolean indicating whether or not the Menu should
6065 * have an IFRAME shim; used to prevent SELECT elements from
6066 * poking through an Overlay instance in IE6. When set to "true",
6067 * the iframe shim is created when the Menu instance is intially
6068 * made visible. This property is only applied when the "position"
6069 * configuration property is set to dynamic and is automatically applied
6072 * @default true for IE6 and below, false for all other browsers.
6076 // Add configuration attributes
6079 Change the default value for the "visible" configuration
6080 property to "false" by re-adding the property.
6085 * @description Boolean indicating whether or not the menu is visible. If
6086 * the menu's "position" configuration property is set to "dynamic" (the
6087 * default), this property toggles the menu's <code><div></code>
6088 * element's "visibility" style property between "visible" (true) or
6089 * "hidden" (false). If the menu's "position" configuration property is
6090 * set to "static" this property toggles the menu's
6091 * <code><div></code> element's "display" style property
6092 * between "block" (true) or "none" (false).
6096 oConfig.addProperty(
6099 handler: this.configVisible,
6100 value: VISIBLE_CONFIG.value,
6101 validator: VISIBLE_CONFIG.validator
6107 Change the default value for the "constraintoviewport" configuration
6108 property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6112 * @config constraintoviewport
6113 * @description Boolean indicating if the menu will try to remain inside
6114 * the boundaries of the size of viewport. This property is only applied
6115 * when the "position" configuration property is set to dynamic and is
6116 * automatically applied to all submenus.
6120 oConfig.addProperty(
6121 CONSTRAIN_TO_VIEWPORT_CONFIG.key,
6123 handler: this.configConstrainToViewport,
6124 value: CONSTRAIN_TO_VIEWPORT_CONFIG.value,
6125 validator: CONSTRAIN_TO_VIEWPORT_CONFIG.validator,
6126 supercedes: CONSTRAIN_TO_VIEWPORT_CONFIG.supercedes
6132 Change the default value for the "preventcontextoverlap" configuration
6133 property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6137 * @config preventcontextoverlap
6138 * @description Boolean indicating whether or not a submenu should overlap its parent MenuItem
6139 * when the "constraintoviewport" configuration property is set to "true".
6143 oConfig.addProperty(PREVENT_CONTEXT_OVERLAP_CONFIG.key, {
6145 value: PREVENT_CONTEXT_OVERLAP_CONFIG.value,
6146 validator: PREVENT_CONTEXT_OVERLAP_CONFIG.validator,
6147 supercedes: PREVENT_CONTEXT_OVERLAP_CONFIG.supercedes
6154 * @description String indicating how a menu should be positioned on the
6155 * screen. Possible values are "static" and "dynamic." Static menus are
6156 * visible by default and reside in the normal flow of the document
6157 * (CSS position: static). Dynamic menus are hidden by default, reside
6158 * out of the normal flow of the document (CSS position: absolute), and
6159 * can overlay other elements on the screen.
6163 oConfig.addProperty(
6164 POSITION_CONFIG.key,
6166 handler: this.configPosition,
6167 value: POSITION_CONFIG.value,
6168 validator: POSITION_CONFIG.validator,
6169 supercedes: POSITION_CONFIG.supercedes
6175 * @config submenualignment
6176 * @description Array defining how submenus should be aligned to their
6177 * parent menu item. The format is: [itemCorner, submenuCorner]. By default
6178 * a submenu's top left corner is aligned to its parent menu item's top
6180 * @default ["tl","tr"]
6183 oConfig.addProperty(
6184 SUBMENU_ALIGNMENT_CONFIG.key,
6186 value: SUBMENU_ALIGNMENT_CONFIG.value,
6187 suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
6193 * @config autosubmenudisplay
6194 * @description Boolean indicating if submenus are automatically made
6195 * visible when the user mouses over the menu's items.
6199 oConfig.addProperty(
6200 AUTO_SUBMENU_DISPLAY_CONFIG.key,
6202 value: AUTO_SUBMENU_DISPLAY_CONFIG.value,
6203 validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
6204 suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
6211 * @description Number indicating the time (in milliseconds) that should
6212 * expire before a submenu is made visible when the user mouses over
6213 * the menu's items. This property is only applied when the "position"
6214 * configuration property is set to dynamic and is automatically applied
6219 oConfig.addProperty(
6220 SHOW_DELAY_CONFIG.key,
6222 value: SHOW_DELAY_CONFIG.value,
6223 validator: SHOW_DELAY_CONFIG.validator,
6224 suppressEvent: SHOW_DELAY_CONFIG.suppressEvent
6231 * @description Number indicating the time (in milliseconds) that should
6232 * expire before the menu is hidden. This property is only applied when
6233 * the "position" configuration property is set to dynamic and is
6234 * automatically applied to all submenus.
6238 oConfig.addProperty(
6239 HIDE_DELAY_CONFIG.key,
6241 handler: this.configHideDelay,
6242 value: HIDE_DELAY_CONFIG.value,
6243 validator: HIDE_DELAY_CONFIG.validator,
6244 suppressEvent: HIDE_DELAY_CONFIG.suppressEvent
6250 * @config submenuhidedelay
6251 * @description Number indicating the time (in milliseconds) that should
6252 * expire before a submenu is hidden when the user mouses out of a menu item
6253 * heading in the direction of a submenu. The value must be greater than or
6254 * equal to the value specified for the "showdelay" configuration property.
6255 * This property is only applied when the "position" configuration property
6256 * is set to dynamic and is automatically applied to all submenus.
6260 oConfig.addProperty(
6261 SUBMENU_HIDE_DELAY_CONFIG.key,
6263 value: SUBMENU_HIDE_DELAY_CONFIG.value,
6264 validator: SUBMENU_HIDE_DELAY_CONFIG.validator,
6265 suppressEvent: SUBMENU_HIDE_DELAY_CONFIG.suppressEvent
6271 * @config clicktohide
6272 * @description Boolean indicating if the menu will automatically be
6273 * hidden if the user clicks outside of it. This property is only
6274 * applied when the "position" configuration property is set to dynamic
6275 * and is automatically applied to all submenus.
6279 oConfig.addProperty(
6280 CLICK_TO_HIDE_CONFIG.key,
6282 value: CLICK_TO_HIDE_CONFIG.value,
6283 validator: CLICK_TO_HIDE_CONFIG.validator,
6284 suppressEvent: CLICK_TO_HIDE_CONFIG.suppressEvent
6291 * @description HTML element reference or string specifying the id
6292 * attribute of the HTML element that the menu's markup should be
6294 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6295 * level-one-html.html#ID-58190037">HTMLElement</a>|String
6296 * @default document.body
6298 oConfig.addProperty(
6299 CONTAINER_CONFIG.key,
6301 handler: this.configContainer,
6302 value: document.body,
6303 suppressEvent: CONTAINER_CONFIG.suppressEvent
6309 * @config scrollincrement
6310 * @description Number used to control the scroll speed of a menu. Used to
6311 * increment the "scrollTop" property of the menu's body by when a menu's
6312 * content is scrolling. When set this property is automatically applied
6317 oConfig.addProperty(
6318 SCROLL_INCREMENT_CONFIG.key,
6320 value: SCROLL_INCREMENT_CONFIG.value,
6321 validator: SCROLL_INCREMENT_CONFIG.validator,
6322 supercedes: SCROLL_INCREMENT_CONFIG.supercedes,
6323 suppressEvent: SCROLL_INCREMENT_CONFIG.suppressEvent
6329 * @config minscrollheight
6330 * @description Number defining the minimum threshold for the "maxheight"
6331 * configuration property. When set this property is automatically applied
6336 oConfig.addProperty(
6337 MIN_SCROLL_HEIGHT_CONFIG.key,
6339 value: MIN_SCROLL_HEIGHT_CONFIG.value,
6340 validator: MIN_SCROLL_HEIGHT_CONFIG.validator,
6341 supercedes: MIN_SCROLL_HEIGHT_CONFIG.supercedes,
6342 suppressEvent: MIN_SCROLL_HEIGHT_CONFIG.suppressEvent
6349 * @description Number defining the maximum height (in pixels) for a menu's
6350 * body element (<code><div class="bd"<</code>). Once a menu's body
6351 * exceeds this height, the contents of the body are scrolled to maintain
6352 * this value. This value cannot be set lower than the value of the
6353 * "minscrollheight" configuration property.
6357 oConfig.addProperty(
6358 MAX_HEIGHT_CONFIG.key,
6360 handler: this.configMaxHeight,
6361 value: MAX_HEIGHT_CONFIG.value,
6362 validator: MAX_HEIGHT_CONFIG.validator,
6363 suppressEvent: MAX_HEIGHT_CONFIG.suppressEvent,
6364 supercedes: MAX_HEIGHT_CONFIG.supercedes
6371 * @description String representing the CSS class to be applied to the
6372 * menu's root <code><div></code> element. The specified class(es)
6373 * are appended in addition to the default class as specified by the menu's
6374 * CSS_CLASS_NAME constant. When set this property is automatically
6375 * applied to all submenus.
6379 oConfig.addProperty(
6380 CLASS_NAME_CONFIG.key,
6382 handler: this.configClassName,
6383 value: CLASS_NAME_CONFIG.value,
6384 validator: CLASS_NAME_CONFIG.validator,
6385 supercedes: CLASS_NAME_CONFIG.supercedes
6392 * @description Boolean indicating if the menu should be disabled.
6393 * Disabling a menu disables each of its items. (Disabled menu items are
6394 * dimmed and will not respond to user input or fire events.) Disabled
6395 * menus have a corresponding "disabled" CSS class applied to their root
6396 * <code><div></code> element.
6400 oConfig.addProperty(
6401 DISABLED_CONFIG.key,
6403 handler: this.configDisabled,
6404 value: DISABLED_CONFIG.value,
6405 validator: DISABLED_CONFIG.validator,
6406 suppressEvent: DISABLED_CONFIG.suppressEvent
6413 * @description Boolean indicating if the menu should have a shadow.
6417 oConfig.addProperty(
6420 handler: this.configShadow,
6421 value: SHADOW_CONFIG.value,
6422 validator: SHADOW_CONFIG.validator
6429 * @description Boolean indicating if the menu should remain open when clicked.
6433 oConfig.addProperty(
6434 KEEP_OPEN_CONFIG.key,
6436 value: KEEP_OPEN_CONFIG.value,
6437 validator: KEEP_OPEN_CONFIG.validator
6443 }); // END YAHOO.lang.extend
6452 * Creates an item for a menu.
6454 * @param {String} p_oObject String specifying the text of the menu item.
6455 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6456 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying
6457 * the <code><li></code> element of the menu item.
6458 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6459 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
6460 * specifying the <code><optgroup></code> element of the menu item.
6461 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6462 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object
6463 * specifying the <code><option></code> element of the menu item.
6464 * @param {Object} p_oConfig Optional. Object literal specifying the
6465 * configuration for the menu item. See configuration class documentation
6470 YAHOO.widget.MenuItem = function (p_oObject, p_oConfig) {
6476 this.parent = p_oConfig.parent;
6477 this.value = p_oConfig.value;
6478 this.id = p_oConfig.id;
6482 this.init(p_oObject, p_oConfig);
6489 var Dom = YAHOO.util.Dom,
6490 Module = YAHOO.widget.Module,
6491 Menu = YAHOO.widget.Menu,
6492 MenuItem = YAHOO.widget.MenuItem,
6493 CustomEvent = YAHOO.util.CustomEvent,
6497 // Private string constants
6502 _HELP_TEXT = "helptext",
6505 _EMPHASIS = "emphasis",
6506 _STRONG_EMPHASIS = "strongemphasis",
6507 _CHECKED = "checked",
6508 _SUBMENU = "submenu",
6509 _DISABLED = "disabled",
6510 _SELECTED = "selected",
6511 _HAS_SUBMENU = "hassubmenu",
6512 _CHECKED_DISABLED = "checked-disabled",
6513 _HAS_SUBMENU_DISABLED = "hassubmenu-disabled",
6514 _HAS_SUBMENU_SELECTED = "hassubmenu-selected",
6515 _CHECKED_SELECTED = "checked-selected",
6516 _ONCLICK = "onclick",
6517 _CLASSNAME = "classname",
6520 _OPTGROUP = "OPTGROUP",
6521 _LI_UPPERCASE = "LI",
6522 _LI_LOWERCASE = "li",
6524 _ANCHOR_TEMPLATE = "<a href=\"#\"></a>",
6527 _START_HELP_TEXT = "<em class=\"helptext\">",
6530 _START_STRONG = "<strong>",
6531 _END_STRONG = "</strong>",
6532 _PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
6536 _VISIBLE = "visible",
6538 _MENUITEM = "MenuItem",
6542 ["mouseOverEvent", "mouseover"],
6543 ["mouseOutEvent", "mouseout"],
6544 ["mouseDownEvent", "mousedown"],
6545 ["mouseUpEvent", "mouseup"],
6546 ["clickEvent", "click"],
6547 ["keyPressEvent", "keypress"],
6548 ["keyDownEvent", "keydown"],
6549 ["keyUpEvent", "keyup"],
6550 ["focusEvent", "focus"],
6551 ["blurEvent", "blur"],
6552 ["destroyEvent", "destroy"]
6558 value: _EMPTY_STRING,
6559 validator: Lang.isString,
6563 HELP_TEXT_CONFIG = {
6565 supercedes: [_TEXT],
6583 validator: Lang.isBoolean,
6584 suppressEvent: true,
6588 STRONG_EMPHASIS_CONFIG = {
6589 key: _STRONG_EMPHASIS,
6591 validator: Lang.isBoolean,
6592 suppressEvent: true,
6599 validator: Lang.isBoolean,
6600 suppressEvent: true,
6601 supercedes: [_DISABLED, _SELECTED]
6606 suppressEvent: true,
6607 supercedes: [_DISABLED, _SELECTED]
6613 validator: Lang.isBoolean,
6614 suppressEvent: true,
6615 supercedes: [_TEXT, _SELECTED]
6621 validator: Lang.isBoolean,
6630 CLASS_NAME_CONFIG = {
6633 validator: Lang.isString,
6639 m_oMenuItemTemplate;
6643 * @method getClassNameForState
6644 * @description Returns a class name for the specified prefix and state. If the class name does not
6645 * yet exist, it is created and stored in the CLASS_NAMES object to increase performance.
6647 * @param {String} prefix String representing the prefix for the class name
6648 * @param {String} state String representing a state - "disabled," "checked," etc.
6650 var getClassNameForState = function (prefix, state) {
6652 var oClassNames = CLASS_NAMES[prefix];
6655 CLASS_NAMES[prefix] = {};
6656 oClassNames = CLASS_NAMES[prefix];
6660 var sClassName = oClassNames[state];
6663 sClassName = prefix + _HYPHEN + state;
6664 oClassNames[state] = sClassName;
6673 * @method addClassNameForState
6674 * @description Applies a class name to a MenuItem instance's <LI> and <A> elements
6675 * that represents a MenuItem's state - "disabled," "checked," etc.
6677 * @param {String} state String representing a state - "disabled," "checked," etc.
6679 var addClassNameForState = function (state) {
6681 Dom.addClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6682 Dom.addClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6687 * @method removeClassNameForState
6688 * @description Removes a class name from a MenuItem instance's <LI> and <A> elements
6689 * that represents a MenuItem's state - "disabled," "checked," etc.
6691 * @param {String} state String representing a state - "disabled," "checked," etc.
6693 var removeClassNameForState = function (state) {
6695 Dom.removeClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6696 Dom.removeClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6701 MenuItem.prototype = {
6704 * @property CSS_CLASS_NAME
6705 * @description String representing the CSS class(es) to be applied to the
6706 * <code><li></code> element of the menu item.
6707 * @default "yuimenuitem"
6711 CSS_CLASS_NAME: "yuimenuitem",
6715 * @property CSS_LABEL_CLASS_NAME
6716 * @description String representing the CSS class(es) to be applied to the
6717 * menu item's <code><a></code> element.
6718 * @default "yuimenuitemlabel"
6722 CSS_LABEL_CLASS_NAME: "yuimenuitemlabel",
6726 * @property SUBMENU_TYPE
6727 * @description Object representing the type of menu to instantiate and
6728 * add when parsing the child nodes of the menu item's source HTML element.
6730 * @type YAHOO.widget.Menu
6736 // Private member variables
6740 * @property _oAnchor
6741 * @description Object reference to the menu item's
6742 * <code><a></code> element.
6745 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6746 * one-html.html#ID-48250443">HTMLAnchorElement</a>
6752 * @property _oHelpTextEM
6753 * @description Object reference to the menu item's help text
6754 * <code><em></code> element.
6757 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6758 * one-html.html#ID-58190037">HTMLElement</a>
6764 * @property _oSubmenu
6765 * @description Object reference to the menu item's submenu.
6768 * @type YAHOO.widget.Menu
6774 * @property _oOnclickAttributeValue
6775 * @description Object reference to the menu item's current value for the
6776 * "onclick" configuration attribute.
6781 _oOnclickAttributeValue: null,
6785 * @property _sClassName
6786 * @description The current value of the "classname" configuration attribute.
6795 // Public properties
6799 * @property constructor
6800 * @description Object reference to the menu item's constructor function.
6801 * @default YAHOO.widget.MenuItem
6802 * @type YAHOO.widget.MenuItem
6804 constructor: MenuItem,
6809 * @description Number indicating the ordinal position of the menu item in
6818 * @property groupIndex
6819 * @description Number indicating the index of the group to which the menu
6829 * @description Object reference to the menu item's parent menu.
6831 * @type YAHOO.widget.Menu
6838 * @description Object reference to the menu item's
6839 * <code><li></code> element.
6840 * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level
6841 * -one-html.html#ID-74680021">HTMLLIElement</a>
6842 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6843 * one-html.html#ID-74680021">HTMLLIElement</a>
6849 * @property srcElement
6850 * @description Object reference to the HTML element (either
6851 * <code><li></code>, <code><optgroup></code> or
6852 * <code><option></code>) used create the menu item.
6853 * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6854 * level-one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.
6855 * w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247"
6856 * >HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6857 * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6858 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6859 * one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.w3.
6860 * org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247">
6861 * HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6862 * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6869 * @description Object reference to the menu item's value.
6878 * @deprecated Use YAHOO.env.ua
6879 * @description String representing the browser.
6882 browser: Module.prototype.browser,
6887 * @description Id of the menu item's root <code><li></code>
6888 * element. This property should be set via the constructor using the
6889 * configuration object literal. If an id is not specified, then one will
6890 * be created using the "generateId" method of the Dom utility.
6902 * @event destroyEvent
6903 * @description Fires when the menu item's <code><li></code>
6904 * element is removed from its parent <code><ul></code> element.
6905 * @type YAHOO.util.CustomEvent
6910 * @event mouseOverEvent
6911 * @description Fires when the mouse has entered the menu item. Passes
6912 * back the DOM Event object as an argument.
6913 * @type YAHOO.util.CustomEvent
6918 * @event mouseOutEvent
6919 * @description Fires when the mouse has left the menu item. Passes back
6920 * the DOM Event object as an argument.
6921 * @type YAHOO.util.CustomEvent
6926 * @event mouseDownEvent
6927 * @description Fires when the user mouses down on the menu item. Passes
6928 * back the DOM Event object as an argument.
6929 * @type YAHOO.util.CustomEvent
6934 * @event mouseUpEvent
6935 * @description Fires when the user releases a mouse button while the mouse
6936 * is over the menu item. Passes back the DOM Event object as an argument.
6937 * @type YAHOO.util.CustomEvent
6943 * @description Fires when the user clicks the on the menu item. Passes
6944 * back the DOM Event object as an argument.
6945 * @type YAHOO.util.CustomEvent
6950 * @event keyPressEvent
6951 * @description Fires when the user presses an alphanumeric key when the
6952 * menu item has focus. Passes back the DOM Event object as an argument.
6953 * @type YAHOO.util.CustomEvent
6958 * @event keyDownEvent
6959 * @description Fires when the user presses a key when the menu item has
6960 * focus. Passes back the DOM Event object as an argument.
6961 * @type YAHOO.util.CustomEvent
6967 * @description Fires when the user releases a key when the menu item has
6968 * focus. Passes back the DOM Event object as an argument.
6969 * @type YAHOO.util.CustomEvent
6975 * @description Fires when the menu item receives focus.
6976 * @type YAHOO.util.CustomEvent
6982 * @description Fires when the menu item loses the input focus.
6983 * @type YAHOO.util.CustomEvent
6989 * @description The MenuItem class's initialization method. This method is
6990 * automatically called by the constructor, and sets up all DOM references
6991 * for pre-existing markup, and creates required markup if it is not
6993 * @param {String} p_oObject String specifying the text of the menu item.
6994 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6995 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying
6996 * the <code><li></code> element of the menu item.
6997 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6998 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
6999 * specifying the <code><optgroup></code> element of the menu item.
7000 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
7001 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object
7002 * specifying the <code><option></code> element of the menu item.
7003 * @param {Object} p_oConfig Optional. Object literal specifying the
7004 * configuration for the menu item. See configuration class documentation
7007 init: function (p_oObject, p_oConfig) {
7010 if (!this.SUBMENU_TYPE) {
7012 this.SUBMENU_TYPE = Menu;
7017 // Create the config object
7019 this.cfg = new YAHOO.util.Config(this);
7021 this.initDefaultConfig();
7023 var oConfig = this.cfg,
7034 if (Lang.isString(p_oObject)) {
7036 this._createRootNodeStructure();
7038 oConfig.queueProperty(_TEXT, p_oObject);
7041 else if (p_oObject && p_oObject.tagName) {
7043 switch(p_oObject.tagName.toUpperCase()) {
7047 this._createRootNodeStructure();
7049 oConfig.queueProperty(_TEXT, p_oObject.text);
7050 oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7052 this.value = p_oObject.value;
7054 this.srcElement = p_oObject;
7060 this._createRootNodeStructure();
7062 oConfig.queueProperty(_TEXT, p_oObject.label);
7063 oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7065 this.srcElement = p_oObject;
7067 this._initSubTree();
7073 // Get the anchor node (if it exists)
7075 oAnchor = Dom.getFirstChild(p_oObject);
7078 // Capture the "text" and/or the "URL"
7082 sURL = oAnchor.getAttribute(_HREF, 2);
7083 sTarget = oAnchor.getAttribute(_TARGET);
7085 sText = oAnchor.innerHTML;
7089 this.srcElement = p_oObject;
7090 this.element = p_oObject;
7091 this._oAnchor = oAnchor;
7094 Set these properties silently to sync up the
7095 configuration object without making changes to the
7099 oConfig.setProperty(_TEXT, sText, true);
7100 oConfig.setProperty(_URL, sURL, true);
7101 oConfig.setProperty(_TARGET, sTarget, true);
7103 this._initSubTree();
7114 sId = (this.srcElement || this.element).id;
7118 sId = this.id || Dom.generateId();
7120 this.element.id = sId;
7127 Dom.addClass(this.element, this.CSS_CLASS_NAME);
7128 Dom.addClass(this._oAnchor, this.CSS_LABEL_CLASS_NAME);
7131 i = EVENT_TYPES.length - 1;
7135 aEventData = EVENT_TYPES[i];
7137 oCustomEvent = this.createEvent(aEventData[1]);
7138 oCustomEvent.signature = CustomEvent.LIST;
7140 this[aEventData[0]] = oCustomEvent;
7148 oConfig.applyConfig(p_oConfig);
7152 oConfig.fireQueue();
7163 * @method _createRootNodeStructure
7164 * @description Creates the core DOM structure for the menu item.
7167 _createRootNodeStructure: function () {
7172 if (!m_oMenuItemTemplate) {
7174 m_oMenuItemTemplate = document.createElement(_LI_LOWERCASE);
7175 m_oMenuItemTemplate.innerHTML = _ANCHOR_TEMPLATE;
7179 oElement = m_oMenuItemTemplate.cloneNode(true);
7180 oElement.className = this.CSS_CLASS_NAME;
7182 oAnchor = oElement.firstChild;
7183 oAnchor.className = this.CSS_LABEL_CLASS_NAME;
7185 this.element = oElement;
7186 this._oAnchor = oAnchor;
7192 * @method _initSubTree
7193 * @description Iterates the source element's childNodes collection and uses
7194 * the child nodes to instantiate other menus.
7197 _initSubTree: function () {
7199 var oSrcEl = this.srcElement,
7208 if (oSrcEl.childNodes.length > 0) {
7210 if (this.parent.lazyLoad && this.parent.srcElement &&
7211 this.parent.srcElement.tagName.toUpperCase() == _SELECT) {
7213 oConfig.setProperty(
7215 { id: Dom.generateId(), itemdata: oSrcEl.childNodes }
7221 oNode = oSrcEl.firstChild;
7226 if (oNode && oNode.tagName) {
7228 switch(oNode.tagName.toUpperCase()) {
7232 oConfig.setProperty(_SUBMENU, oNode);
7238 aOptions[aOptions.length] = oNode;
7247 while((oNode = oNode.nextSibling));
7250 nOptions = aOptions.length;
7254 oMenu = new this.SUBMENU_TYPE(Dom.generateId());
7256 oConfig.setProperty(_SUBMENU, oMenu);
7258 for(n=0; n<nOptions; n++) {
7260 oMenu.addItem((new oMenu.ITEM_TYPE(aOptions[n])));
7274 // Event handlers for configuration properties
7278 * @method configText
7279 * @description Event handler for when the "text" configuration property of
7280 * the menu item changes.
7281 * @param {String} p_sType String representing the name of the event that
7283 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7284 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7285 * that fired the event.
7287 configText: function (p_sType, p_aArgs, p_oItem) {
7289 var sText = p_aArgs[0],
7291 oAnchor = this._oAnchor,
7292 sHelpText = oConfig.getProperty(_HELP_TEXT),
7293 sHelpTextHTML = _EMPTY_STRING,
7294 sEmphasisStartTag = _EMPTY_STRING,
7295 sEmphasisEndTag = _EMPTY_STRING;
7303 sHelpTextHTML = _START_HELP_TEXT + sHelpText + _END_EM;
7308 if (oConfig.getProperty(_EMPHASIS)) {
7310 sEmphasisStartTag = _START_EM;
7311 sEmphasisEndTag = _END_EM;
7316 if (oConfig.getProperty(_STRONG_EMPHASIS)) {
7318 sEmphasisStartTag = _START_STRONG;
7319 sEmphasisEndTag = _END_STRONG;
7324 oAnchor.innerHTML = (sEmphasisStartTag + sText + sEmphasisEndTag + sHelpTextHTML);
7332 * @method configHelpText
7333 * @description Event handler for when the "helptext" configuration property
7334 * of the menu item changes.
7335 * @param {String} p_sType String representing the name of the event that
7337 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7338 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7339 * that fired the event.
7341 configHelpText: function (p_sType, p_aArgs, p_oItem) {
7343 this.cfg.refireEvent(_TEXT);
7350 * @description Event handler for when the "url" configuration property of
7351 * the menu item changes.
7352 * @param {String} p_sType String representing the name of the event that
7354 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7355 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7356 * that fired the event.
7358 configURL: function (p_sType, p_aArgs, p_oItem) {
7360 var sURL = p_aArgs[0];
7368 var oAnchor = this._oAnchor;
7372 oAnchor.removeAttribute(_HREF);
7376 oAnchor.setAttribute(_HREF, sURL);
7382 * @method configTarget
7383 * @description Event handler for when the "target" configuration property
7384 * of the menu item changes.
7385 * @param {String} p_sType String representing the name of the event that
7387 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7388 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7389 * that fired the event.
7391 configTarget: function (p_sType, p_aArgs, p_oItem) {
7393 var sTarget = p_aArgs[0],
7394 oAnchor = this._oAnchor;
7396 if (sTarget && sTarget.length > 0) {
7398 oAnchor.setAttribute(_TARGET, sTarget);
7403 oAnchor.removeAttribute(_TARGET);
7411 * @method configEmphasis
7412 * @description Event handler for when the "emphasis" configuration property
7413 * of the menu item changes.
7414 * @param {String} p_sType String representing the name of the event that
7416 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7417 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7418 * that fired the event.
7420 configEmphasis: function (p_sType, p_aArgs, p_oItem) {
7422 var bEmphasis = p_aArgs[0],
7426 if (bEmphasis && oConfig.getProperty(_STRONG_EMPHASIS)) {
7428 oConfig.setProperty(_STRONG_EMPHASIS, false);
7433 oConfig.refireEvent(_TEXT);
7439 * @method configStrongEmphasis
7440 * @description Event handler for when the "strongemphasis" configuration
7441 * property of the menu item changes.
7442 * @param {String} p_sType String representing the name of the event that
7444 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7445 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7446 * that fired the event.
7448 configStrongEmphasis: function (p_sType, p_aArgs, p_oItem) {
7450 var bStrongEmphasis = p_aArgs[0],
7454 if (bStrongEmphasis && oConfig.getProperty(_EMPHASIS)) {
7456 oConfig.setProperty(_EMPHASIS, false);
7460 oConfig.refireEvent(_TEXT);
7466 * @method configChecked
7467 * @description Event handler for when the "checked" configuration property
7468 * 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 configChecked: function (p_sType, p_aArgs, p_oItem) {
7477 var bChecked = p_aArgs[0],
7483 addClassNameForState.call(this, _CHECKED);
7488 removeClassNameForState.call(this, _CHECKED);
7492 oConfig.refireEvent(_TEXT);
7495 if (oConfig.getProperty(_DISABLED)) {
7497 oConfig.refireEvent(_DISABLED);
7502 if (oConfig.getProperty(_SELECTED)) {
7504 oConfig.refireEvent(_SELECTED);
7513 * @method configDisabled
7514 * @description Event handler for when the "disabled" configuration property
7515 * of the menu item changes.
7516 * @param {String} p_sType String representing the name of the event that
7518 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7519 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7520 * that fired the event.
7522 configDisabled: function (p_sType, p_aArgs, p_oItem) {
7524 var bDisabled = p_aArgs[0],
7526 oSubmenu = oConfig.getProperty(_SUBMENU),
7527 bChecked = oConfig.getProperty(_CHECKED);
7532 if (oConfig.getProperty(_SELECTED)) {
7534 oConfig.setProperty(_SELECTED, false);
7539 addClassNameForState.call(this, _DISABLED);
7544 addClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7551 addClassNameForState.call(this, _CHECKED_DISABLED);
7558 removeClassNameForState.call(this, _DISABLED);
7563 removeClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7570 removeClassNameForState.call(this, _CHECKED_DISABLED);
7580 * @method configSelected
7581 * @description Event handler for when the "selected" configuration property
7582 * of the menu item changes.
7583 * @param {String} p_sType String representing the name of the event that
7585 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7586 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7587 * that fired the event.
7589 configSelected: function (p_sType, p_aArgs, p_oItem) {
7591 var oConfig = this.cfg,
7592 oAnchor = this._oAnchor,
7594 bSelected = p_aArgs[0],
7595 bChecked = oConfig.getProperty(_CHECKED),
7596 oSubmenu = oConfig.getProperty(_SUBMENU);
7606 if (bSelected && !oConfig.getProperty(_DISABLED)) {
7608 addClassNameForState.call(this, _SELECTED);
7613 addClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7620 addClassNameForState.call(this, _CHECKED_SELECTED);
7627 removeClassNameForState.call(this, _SELECTED);
7632 removeClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7639 removeClassNameForState.call(this, _CHECKED_SELECTED);
7646 if (this.hasFocus() && UA.opera) {
7656 * @method _onSubmenuBeforeHide
7657 * @description "beforehide" Custom Event handler for a submenu.
7659 * @param {String} p_sType String representing the name of the event that
7661 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7663 _onSubmenuBeforeHide: function (p_sType, p_aArgs) {
7665 var oItem = this.parent,
7670 oItem._oAnchor.blur();
7671 oMenu.beforeHideEvent.unsubscribe(onHide);
7676 if (oItem.hasFocus()) {
7678 oMenu = oItem.parent;
7680 oMenu.beforeHideEvent.subscribe(onHide);
7688 * @method configSubmenu
7689 * @description Event handler for when the "submenu" configuration property
7690 * of the menu item changes.
7691 * @param {String} p_sType String representing the name of the event that
7693 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7694 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7695 * that fired the event.
7697 configSubmenu: function (p_sType, p_aArgs, p_oItem) {
7699 var oSubmenu = p_aArgs[0],
7701 bLazyLoad = this.parent && this.parent.lazyLoad,
7709 if (oSubmenu instanceof Menu) {
7712 oMenu.parent = this;
7713 oMenu.lazyLoad = bLazyLoad;
7716 else if (Lang.isObject(oSubmenu) && oSubmenu.id && !oSubmenu.nodeType) {
7718 sSubmenuId = oSubmenu.id;
7719 oSubmenuConfig = oSubmenu;
7721 oSubmenuConfig.lazyload = bLazyLoad;
7722 oSubmenuConfig.parent = this;
7724 oMenu = new this.SUBMENU_TYPE(sSubmenuId, oSubmenuConfig);
7727 // Set the value of the property to the Menu instance
7729 oConfig.setProperty(_SUBMENU, oMenu, true);
7734 oMenu = new this.SUBMENU_TYPE(oSubmenu, { lazyload: bLazyLoad, parent: this });
7737 // Set the value of the property to the Menu instance
7739 oConfig.setProperty(_SUBMENU, oMenu, true);
7746 oMenu.cfg.setProperty(_PREVENT_CONTEXT_OVERLAP, true);
7748 addClassNameForState.call(this, _HAS_SUBMENU);
7751 if (oConfig.getProperty(_URL) === _HASH) {
7753 oConfig.setProperty(_URL, (_HASH + oMenu.id));
7758 this._oSubmenu = oMenu;
7763 oMenu.beforeHideEvent.subscribe(this._onSubmenuBeforeHide);
7772 removeClassNameForState.call(this, _HAS_SUBMENU);
7774 if (this._oSubmenu) {
7776 this._oSubmenu.destroy();
7783 if (oConfig.getProperty(_DISABLED)) {
7785 oConfig.refireEvent(_DISABLED);
7790 if (oConfig.getProperty(_SELECTED)) {
7792 oConfig.refireEvent(_SELECTED);
7800 * @method configOnClick
7801 * @description Event handler for when the "onclick" configuration property
7802 * of the menu item changes.
7803 * @param {String} p_sType String representing the name of the event that
7805 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7806 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7807 * that fired the event.
7809 configOnClick: function (p_sType, p_aArgs, p_oItem) {
7811 var oObject = p_aArgs[0];
7814 Remove any existing listeners if a "click" event handler has
7815 already been specified.
7818 if (this._oOnclickAttributeValue && (this._oOnclickAttributeValue != oObject)) {
7820 this.clickEvent.unsubscribe(this._oOnclickAttributeValue.fn,
7821 this._oOnclickAttributeValue.obj);
7823 this._oOnclickAttributeValue = null;
7828 if (!this._oOnclickAttributeValue && Lang.isObject(oObject) &&
7829 Lang.isFunction(oObject.fn)) {
7831 this.clickEvent.subscribe(oObject.fn,
7832 ((_OBJ in oObject) ? oObject.obj : this),
7833 ((_SCOPE in oObject) ? oObject.scope : null) );
7835 this._oOnclickAttributeValue = oObject;
7843 * @method configClassName
7844 * @description Event handler for when the "classname" configuration
7845 * property of a menu item changes.
7846 * @param {String} p_sType String representing the name of the event that
7848 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7849 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7850 * that fired the event.
7852 configClassName: function (p_sType, p_aArgs, p_oItem) {
7854 var sClassName = p_aArgs[0];
7856 if (this._sClassName) {
7858 Dom.removeClass(this.element, this._sClassName);
7862 Dom.addClass(this.element, sClassName);
7863 this._sClassName = sClassName;
7873 * @method initDefaultConfig
7874 * @description Initializes an item's configurable properties.
7876 initDefaultConfig : function () {
7878 var oConfig = this.cfg;
7881 // Define the configuration attributes
7885 * @description String specifying the text label for the menu item.
7886 * When building a menu from existing HTML the value of this property
7887 * will be interpreted from the menu's markup.
7891 oConfig.addProperty(
7894 handler: this.configText,
7895 value: TEXT_CONFIG.value,
7896 validator: TEXT_CONFIG.validator,
7897 suppressEvent: TEXT_CONFIG.suppressEvent
7904 * @description String specifying additional instructional text to
7905 * accompany the text for the menu item.
7906 * @deprecated Use "text" configuration property to add help text markup.
7907 * For example: <code>oMenuItem.cfg.setProperty("text", "Copy <em
7908 * class=\"helptext\">Ctrl + C</em>");</code>
7910 * @type String|<a href="http://www.w3.org/TR/
7911 * 2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
7914 oConfig.addProperty(
7915 HELP_TEXT_CONFIG.key,
7917 handler: this.configHelpText,
7918 supercedes: HELP_TEXT_CONFIG.supercedes,
7919 suppressEvent: HELP_TEXT_CONFIG.suppressEvent
7926 * @description String specifying the URL for the menu item's anchor's
7927 * "href" attribute. When building a menu from existing HTML the value
7928 * of this property will be interpreted from the menu's markup.
7932 oConfig.addProperty(
7935 handler: this.configURL,
7936 value: URL_CONFIG.value,
7937 suppressEvent: URL_CONFIG.suppressEvent
7944 * @description String specifying the value for the "target" attribute
7945 * of the menu item's anchor element. <strong>Specifying a target will
7946 * require the user to click directly on the menu item's anchor node in
7947 * order to cause the browser to navigate to the specified URL.</strong>
7948 * When building a menu from existing HTML the value of this property
7949 * will be interpreted from the menu's markup.
7953 oConfig.addProperty(
7956 handler: this.configTarget,
7957 suppressEvent: TARGET_CONFIG.suppressEvent
7964 * @description Boolean indicating if the text of the menu item will be
7965 * rendered with emphasis.
7966 * @deprecated Use the "text" configuration property to add emphasis.
7967 * For example: <code>oMenuItem.cfg.setProperty("text", "<em>Some
7968 * Text</em>");</code>
7972 oConfig.addProperty(
7973 EMPHASIS_CONFIG.key,
7975 handler: this.configEmphasis,
7976 value: EMPHASIS_CONFIG.value,
7977 validator: EMPHASIS_CONFIG.validator,
7978 suppressEvent: EMPHASIS_CONFIG.suppressEvent,
7979 supercedes: EMPHASIS_CONFIG.supercedes
7985 * @config strongemphasis
7986 * @description Boolean indicating if the text of the menu item will be
7987 * rendered with strong emphasis.
7988 * @deprecated Use the "text" configuration property to add strong emphasis.
7989 * For example: <code>oMenuItem.cfg.setProperty("text", "<strong>
7990 * Some Text</strong>");</code>
7994 oConfig.addProperty(
7995 STRONG_EMPHASIS_CONFIG.key,
7997 handler: this.configStrongEmphasis,
7998 value: STRONG_EMPHASIS_CONFIG.value,
7999 validator: STRONG_EMPHASIS_CONFIG.validator,
8000 suppressEvent: STRONG_EMPHASIS_CONFIG.suppressEvent,
8001 supercedes: STRONG_EMPHASIS_CONFIG.supercedes
8008 * @description Boolean indicating if the menu item should be rendered
8013 oConfig.addProperty(
8016 handler: this.configChecked,
8017 value: CHECKED_CONFIG.value,
8018 validator: CHECKED_CONFIG.validator,
8019 suppressEvent: CHECKED_CONFIG.suppressEvent,
8020 supercedes: CHECKED_CONFIG.supercedes
8027 * @description Boolean indicating if the menu item should be disabled.
8028 * (Disabled menu items are dimmed and will not respond to user input
8033 oConfig.addProperty(
8034 DISABLED_CONFIG.key,
8036 handler: this.configDisabled,
8037 value: DISABLED_CONFIG.value,
8038 validator: DISABLED_CONFIG.validator,
8039 suppressEvent: DISABLED_CONFIG.suppressEvent
8046 * @description Boolean indicating if the menu item should
8051 oConfig.addProperty(
8052 SELECTED_CONFIG.key,
8054 handler: this.configSelected,
8055 value: SELECTED_CONFIG.value,
8056 validator: SELECTED_CONFIG.validator,
8057 suppressEvent: SELECTED_CONFIG.suppressEvent
8064 * @description Object specifying the submenu to be appended to the
8065 * menu item. The value can be one of the following: <ul><li>Object
8066 * specifying a Menu instance.</li><li>Object literal specifying the
8067 * menu to be created. Format: <code>{ id: [menu id], itemdata:
8068 * [<a href="YAHOO.widget.Menu.html#itemData">array of values for
8069 * items</a>] }</code>.</li><li>String specifying the id attribute
8070 * of the <code><div></code> element of the menu.</li><li>
8071 * Object specifying the <code><div></code> element of the
8074 * @type Menu|String|Object|<a href="http://www.w3.org/TR/2000/
8075 * WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8078 oConfig.addProperty(
8081 handler: this.configSubmenu,
8082 supercedes: SUBMENU_CONFIG.supercedes,
8083 suppressEvent: SUBMENU_CONFIG.suppressEvent
8090 * @description Object literal representing the code to be executed when
8091 * the item is clicked. Format:<br> <code> {<br>
8092 * <strong>fn:</strong> Function, // The handler to call when
8093 * the event fires.<br> <strong>obj:</strong> Object, // An
8094 * object to pass back to the handler.<br> <strong>scope:</strong>
8095 * Object // The object to use for the scope of the handler.
8100 oConfig.addProperty(
8103 handler: this.configOnClick,
8104 suppressEvent: ONCLICK_CONFIG.suppressEvent
8111 * @description CSS class to be applied to the menu item's root
8112 * <code><li></code> element. The specified class(es) are
8113 * appended in addition to the default class as specified by the menu
8114 * item's CSS_CLASS_NAME constant.
8118 oConfig.addProperty(
8119 CLASS_NAME_CONFIG.key,
8121 handler: this.configClassName,
8122 value: CLASS_NAME_CONFIG.value,
8123 validator: CLASS_NAME_CONFIG.validator,
8124 suppressEvent: CLASS_NAME_CONFIG.suppressEvent
8132 * @method getNextEnabledSibling
8133 * @description Finds the menu item's next enabled sibling.
8134 * @return YAHOO.widget.MenuItem
8136 getNextEnabledSibling: function () {
8145 function getNextArrayItem(p_aArray, p_nStartIndex) {
8147 return p_aArray[p_nStartIndex] || getNextArrayItem(p_aArray, (p_nStartIndex+1));
8151 if (this.parent instanceof Menu) {
8153 nGroupIndex = this.groupIndex;
8155 aItemGroups = this.parent.getItemGroups();
8157 if (this.index < (aItemGroups[nGroupIndex].length - 1)) {
8159 oNextItem = getNextArrayItem(aItemGroups[nGroupIndex],
8165 if (nGroupIndex < (aItemGroups.length - 1)) {
8167 nNextGroupIndex = nGroupIndex + 1;
8172 nNextGroupIndex = 0;
8176 aNextGroup = getNextArrayItem(aItemGroups, nNextGroupIndex);
8178 // Retrieve the first menu item in the next group
8180 oNextItem = getNextArrayItem(aNextGroup, 0);
8184 returnVal = (oNextItem.cfg.getProperty(_DISABLED) ||
8185 oNextItem.element.style.display == _NONE) ?
8186 oNextItem.getNextEnabledSibling() : oNextItem;
8196 * @method getPreviousEnabledSibling
8197 * @description Finds the menu item's previous enabled sibling.
8198 * @return {YAHOO.widget.MenuItem}
8200 getPreviousEnabledSibling: function () {
8205 nPreviousGroupIndex,
8209 function getPreviousArrayItem(p_aArray, p_nStartIndex) {
8211 return p_aArray[p_nStartIndex] || getPreviousArrayItem(p_aArray, (p_nStartIndex-1));
8215 function getFirstItemIndex(p_aArray, p_nStartIndex) {
8217 return p_aArray[p_nStartIndex] ? p_nStartIndex :
8218 getFirstItemIndex(p_aArray, (p_nStartIndex+1));
8222 if (this.parent instanceof Menu) {
8224 nGroupIndex = this.groupIndex;
8225 aItemGroups = this.parent.getItemGroups();
8228 if (this.index > getFirstItemIndex(aItemGroups[nGroupIndex], 0)) {
8230 oPreviousItem = getPreviousArrayItem(aItemGroups[nGroupIndex],
8236 if (nGroupIndex > getFirstItemIndex(aItemGroups, 0)) {
8238 nPreviousGroupIndex = nGroupIndex - 1;
8243 nPreviousGroupIndex = aItemGroups.length - 1;
8247 aPreviousGroup = getPreviousArrayItem(aItemGroups,
8248 nPreviousGroupIndex);
8250 oPreviousItem = getPreviousArrayItem(aPreviousGroup,
8251 (aPreviousGroup.length - 1));
8255 returnVal = (oPreviousItem.cfg.getProperty(_DISABLED) ||
8256 oPreviousItem.element.style.display == _NONE) ?
8257 oPreviousItem.getPreviousEnabledSibling() : oPreviousItem;
8268 * @description Causes the menu item to receive the focus and fires the
8271 focus: function () {
8273 var oParent = this.parent,
8274 oAnchor = this._oAnchor,
8275 oActiveItem = oParent.activeItem;
8278 function setFocus() {
8282 if (!(UA.ie && !document.hasFocus())) {
8286 oActiveItem.blurEvent.fire();
8292 this.focusEvent.fire();
8304 if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE) &&
8305 this.element.style.display != _NONE) {
8309 Setting focus via a timer fixes a race condition in Firefox, IE
8310 and Opera where the browser viewport jumps as it trys to
8311 position and focus the menu.
8314 Lang.later(0, this, setFocus);
8323 * @description Causes the menu item to lose focus and fires the
8328 var oParent = this.parent;
8330 if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE)) {
8332 Lang.later(0, this, function () {
8336 this._oAnchor.blur();
8337 this.blurEvent.fire();
8353 * @description Returns a boolean indicating whether or not the menu item
8357 hasFocus: function () {
8359 return (YAHOO.widget.MenuManager.getFocusedMenuItem() == this);
8366 * @description Removes the menu item's <code><li></code> element
8367 * from its parent <code><ul></code> element.
8369 destroy: function () {
8371 var oEl = this.element,
8381 // If the item has a submenu, destroy it first
8383 oSubmenu = this.cfg.getProperty(_SUBMENU);
8392 // Remove the element from the parent node
8394 oParentNode = oEl.parentNode;
8398 oParentNode.removeChild(oEl);
8400 this.destroyEvent.fire();
8405 // Remove CustomEvent listeners
8407 i = EVENT_TYPES.length - 1;
8411 aEventData = EVENT_TYPES[i];
8413 this[aEventData[0]].unsubscribeAll();
8419 this.cfg.configChangedEvent.unsubscribeAll();
8428 * @description Returns a string representing the menu item.
8431 toString: function () {
8433 var sReturnVal = _MENUITEM,
8438 sReturnVal += (_SPACE + sId);
8448 Lang.augmentProto(MenuItem, YAHOO.util.EventProvider);
8454 _MOUSEDOWN = "mousedown",
8455 _CONTEXTMENU = "ContextMenu",
8459 * Creates a list of options or commands which are made visible in response to
8460 * an HTML element's "contextmenu" event ("mousedown" for Opera).
8462 * @param {String} p_oElement String specifying the id attribute of the
8463 * <code><div></code> element of the context menu.
8464 * @param {String} p_oElement String specifying the id attribute of the
8465 * <code><select></code> element to be used as the data source for the
8467 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8468 * html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the
8469 * <code><div></code> element of the context menu.
8470 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8471 * html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying
8472 * the <code><select></code> element to be used as the data source for
8474 * @param {Object} p_oConfig Optional. Object literal specifying the
8475 * configuration for the context menu. See configuration class documentation
8477 * @class ContextMenu
8479 * @extends YAHOO.widget.Menu
8480 * @namespace YAHOO.widget
8482 YAHOO.widget.ContextMenu = function(p_oElement, p_oConfig) {
8484 YAHOO.widget.ContextMenu.superclass.constructor.call(this, p_oElement, p_oConfig);
8489 var Event = YAHOO.util.Event,
8491 ContextMenu = YAHOO.widget.ContextMenu,
8496 * Constant representing the name of the ContextMenu's events
8497 * @property EVENT_TYPES
8504 "TRIGGER_CONTEXT_MENU": "triggerContextMenu",
8505 "CONTEXT_MENU": (UA.opera ? _MOUSEDOWN : "contextmenu"),
8512 * Constant representing the ContextMenu's configuration properties
8513 * @property DEFAULT_CONFIG
8526 * @description "beforeShow" event handler used to position the contextmenu.
8528 * @param {String} p_sType String representing the name of the event that
8530 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
8531 * @param {Array} p_aPos Array representing the xy position for the context menu.
8533 function position(p_sType, p_aArgs, p_aPos) {
8535 this.cfg.setProperty(_XY, p_aPos);
8537 this.beforeShowEvent.unsubscribe(position, p_aPos);
8542 YAHOO.lang.extend(ContextMenu, YAHOO.widget.Menu, {
8546 // Private properties
8550 * @property _oTrigger
8551 * @description Object reference to the current value of the "trigger"
8552 * configuration property.
8555 * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/leve
8556 * l-one-html.html#ID-58190037">HTMLElement</a>|Array
8562 * @property _bCancelled
8563 * @description Boolean indicating if the display of the context menu should
8573 // Public properties
8577 * @property contextEventTarget
8578 * @description Object reference for the HTML element that was the target of the
8579 * "contextmenu" DOM event ("mousedown" for Opera) that triggered the display of
8582 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8583 * html.html#ID-58190037">HTMLElement</a>
8585 contextEventTarget: null,
8593 * @event triggerContextMenuEvent
8594 * @description Custom Event wrapper for the "contextmenu" DOM event
8595 * ("mousedown" for Opera) fired by the element(s) that trigger the display of
8598 triggerContextMenuEvent: null,
8604 * @description The ContextMenu class's initialization method. This method is
8605 * automatically called by the constructor, and sets up all DOM references for
8606 * pre-existing markup, and creates required markup if it is not already present.
8607 * @param {String} p_oElement String specifying the id attribute of the
8608 * <code><div></code> element of the context menu.
8609 * @param {String} p_oElement String specifying the id attribute of the
8610 * <code><select></code> element to be used as the data source for
8612 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8613 * html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the
8614 * <code><div></code> element of the context menu.
8615 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8616 * html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying
8617 * the <code><select></code> element to be used as the data source for
8619 * @param {Object} p_oConfig Optional. Object literal specifying the
8620 * configuration for the context menu. See configuration class documentation
8623 init: function(p_oElement, p_oConfig) {
8626 // Call the init of the superclass (YAHOO.widget.Menu)
8628 ContextMenu.superclass.init.call(this, p_oElement);
8631 this.beforeInitEvent.fire(ContextMenu);
8636 this.cfg.applyConfig(p_oConfig, true);
8640 this.initEvent.fire(ContextMenu);
8646 * @method initEvents
8647 * @description Initializes the custom events for the context menu.
8649 initEvents: function() {
8651 ContextMenu.superclass.initEvents.call(this);
8653 // Create custom events
8655 this.triggerContextMenuEvent = this.createEvent(EVENT_TYPES.TRIGGER_CONTEXT_MENU);
8657 this.triggerContextMenuEvent.signature = YAHOO.util.CustomEvent.LIST;
8664 * @description Cancels the display of the context menu.
8666 cancel: function() {
8668 this._bCancelled = true;
8678 * @method _removeEventHandlers
8679 * @description Removes all of the DOM event handlers from the HTML element(s)
8680 * whose "context menu" event ("click" for Opera) trigger the display of
8684 _removeEventHandlers: function() {
8686 var oTrigger = this._oTrigger;
8689 // Remove the event handlers from the trigger(s)
8693 Event.removeListener(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu);
8697 Event.removeListener(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick);
8707 // Private event handlers
8712 * @method _onTriggerClick
8713 * @description "click" event handler for the HTML element(s) identified as the
8714 * "trigger" for the context menu. Used to cancel default behaviors in Opera.
8716 * @param {Event} p_oEvent Object representing the DOM event object passed back
8717 * by the event utility (YAHOO.util.Event).
8718 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8719 * menu that is handling the event.
8721 _onTriggerClick: function(p_oEvent, p_oMenu) {
8723 if (p_oEvent.ctrlKey) {
8725 Event.stopEvent(p_oEvent);
8733 * @method _onTriggerContextMenu
8734 * @description "contextmenu" event handler ("mousedown" for Opera) for the HTML
8735 * element(s) that trigger the display of the context menu.
8737 * @param {Event} p_oEvent Object representing the DOM event object passed back
8738 * by the event utility (YAHOO.util.Event).
8739 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8740 * menu that is handling the event.
8742 _onTriggerContextMenu: function(p_oEvent, p_oMenu) {
8746 if (!(p_oEvent.type == _MOUSEDOWN && !p_oEvent.ctrlKey)) {
8749 Prevent the browser's default context menu from appearing and
8750 stop the propagation of the "contextmenu" event so that
8751 other ContextMenu instances are not displayed.
8754 Event.stopEvent(p_oEvent);
8757 this.contextEventTarget = Event.getTarget(p_oEvent);
8759 this.triggerContextMenuEvent.fire(p_oEvent);
8762 // Hide any other Menu instances that might be visible
8764 YAHOO.widget.MenuManager.hideVisible();
8768 if (!this._bCancelled) {
8770 // Position and display the context menu
8772 aXY = Event.getXY(p_oEvent);
8775 if (!YAHOO.util.Dom.inDocument(this.element)) {
8777 this.beforeShowEvent.subscribe(position, aXY);
8782 this.cfg.setProperty(_XY, aXY);
8791 this._bCancelled = false;
8804 * @description Returns a string representing the context menu.
8807 toString: function() {
8809 var sReturnVal = _CONTEXTMENU,
8814 sReturnVal += (_SPACE + sId);
8824 * @method initDefaultConfig
8825 * @description Initializes the class's configurable properties which can be
8826 * changed using the context menu's Config object ("cfg").
8828 initDefaultConfig: function() {
8830 ContextMenu.superclass.initDefaultConfig.call(this);
8834 * @description The HTML element(s) whose "contextmenu" event ("mousedown"
8835 * for Opera) trigger the display of the context menu. Can be a string
8836 * representing the id attribute of the HTML element, an object reference
8837 * for the HTML element, or an array of strings or HTML element references.
8839 * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
8840 * level-one-html.html#ID-58190037">HTMLElement</a>|Array
8842 this.cfg.addProperty(TRIGGER_CONFIG.key,
8844 handler: this.configTrigger,
8845 suppressEvent: TRIGGER_CONFIG.suppressEvent
8854 * @description Removes the context menu's <code><div></code> element
8855 * (and accompanying child nodes) from the document.
8857 destroy: function() {
8859 // Remove the DOM event handlers from the current trigger(s)
8861 this._removeEventHandlers();
8864 // Continue with the superclass implementation of this method
8866 ContextMenu.superclass.destroy.call(this);
8872 // Public event handlers for configuration properties
8876 * @method configTrigger
8877 * @description Event handler for when the value of the "trigger" configuration
8879 * @param {String} p_sType String representing the name of the event that
8881 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
8882 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8883 * menu that fired the event.
8885 configTrigger: function(p_sType, p_aArgs, p_oMenu) {
8887 var oTrigger = p_aArgs[0];
8892 If there is a current "trigger" - remove the event handlers
8893 from that element(s) before assigning new ones
8896 if (this._oTrigger) {
8898 this._removeEventHandlers();
8902 this._oTrigger = oTrigger;
8906 Listen for the "mousedown" event in Opera b/c it does not
8907 support the "contextmenu" event
8910 Event.on(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu, this, true);
8914 Assign a "click" event handler to the trigger element(s) for
8915 Opera to prevent default browser behaviors.
8920 Event.on(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick, this, true);
8927 this._removeEventHandlers();
8933 }); // END YAHOO.lang.extend
8940 * Creates an item for a context menu.
8942 * @param {String} p_oObject String specifying the text of the context menu item.
8943 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8944 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
8945 * <code><li></code> element of the context menu item.
8946 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8947 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
8948 * specifying the <code><optgroup></code> element of the context
8950 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8951 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
8952 * the <code><option></code> element of the context menu item.
8953 * @param {Object} p_oConfig Optional. Object literal specifying the
8954 * configuration for the context menu item. See configuration class
8955 * documentation for more details.
8956 * @class ContextMenuItem
8958 * @extends YAHOO.widget.MenuItem
8959 * @deprecated As of version 2.4.0 items for YAHOO.widget.ContextMenu instances
8960 * are of type YAHOO.widget.MenuItem.
8962 YAHOO.widget.ContextMenuItem = YAHOO.widget.MenuItem;
8965 var Lang = YAHOO.lang,
8970 _DYNAMIC_STATIC = "dynamic," + _STATIC,
8971 _DISABLED = "disabled",
8972 _SELECTED = "selected",
8973 _AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
8974 _SUBMENU = "submenu",
8975 _VISIBLE = "visible",
8977 _SUBMENU_TOGGLE_REGION = "submenutoggleregion",
8978 _MENUBAR = "MenuBar";
8981 * Horizontal collection of items, each of which can contain a submenu.
8983 * @param {String} p_oElement String specifying the id attribute of the
8984 * <code><div></code> element of the menu bar.
8985 * @param {String} p_oElement String specifying the id attribute of the
8986 * <code><select></code> element to be used as the data source for the
8988 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8989 * one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying
8990 * the <code><div></code> element of the menu bar.
8991 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8992 * one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object
8993 * specifying the <code><select></code> element to be used as the data
8994 * source for the menu bar.
8995 * @param {Object} p_oConfig Optional. Object literal specifying the
8996 * configuration for the menu bar. See configuration class documentation for
9000 * @extends YAHOO.widget.Menu
9001 * @namespace YAHOO.widget
9003 YAHOO.widget.MenuBar = function(p_oElement, p_oConfig) {
9005 YAHOO.widget.MenuBar.superclass.constructor.call(this, p_oElement, p_oConfig);
9011 * @method checkPosition
9012 * @description Checks to make sure that the value of the "position" property
9013 * is one of the supported strings. Returns true if the position is supported.
9015 * @param {Object} p_sPosition String specifying the position of the menu.
9018 function checkPosition(p_sPosition) {
9020 var returnVal = false;
9022 if (Lang.isString(p_sPosition)) {
9024 returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
9033 var Event = YAHOO.util.Event,
9034 MenuBar = YAHOO.widget.MenuBar,
9039 validator: checkPosition,
9040 supercedes: [_VISIBLE]
9043 SUBMENU_ALIGNMENT_CONFIG = {
9044 key: "submenualignment",
9048 AUTO_SUBMENU_DISPLAY_CONFIG = {
9049 key: _AUTO_SUBMENU_DISPLAY,
9051 validator: Lang.isBoolean,
9055 SUBMENU_TOGGLE_REGION_CONFIG = {
9056 key: _SUBMENU_TOGGLE_REGION,
9058 validator: Lang.isBoolean
9063 Lang.extend(MenuBar, YAHOO.widget.Menu, {
9067 * @description The MenuBar class's initialization method. This method is
9068 * automatically called by the constructor, and sets up all DOM references for
9069 * pre-existing markup, and creates required markup if it is not already present.
9070 * @param {String} p_oElement String specifying the id attribute of the
9071 * <code><div></code> element of the menu bar.
9072 * @param {String} p_oElement String specifying the id attribute of the
9073 * <code><select></code> element to be used as the data source for the
9075 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9076 * one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying
9077 * the <code><div></code> element of the menu bar.
9078 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9079 * one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object
9080 * specifying the <code><select></code> element to be used as the data
9081 * source for the menu bar.
9082 * @param {Object} p_oConfig Optional. Object literal specifying the
9083 * configuration for the menu bar. See configuration class documentation for
9086 init: function(p_oElement, p_oConfig) {
9088 if(!this.ITEM_TYPE) {
9090 this.ITEM_TYPE = YAHOO.widget.MenuBarItem;
9095 // Call the init of the superclass (YAHOO.widget.Menu)
9097 MenuBar.superclass.init.call(this, p_oElement);
9100 this.beforeInitEvent.fire(MenuBar);
9105 this.cfg.applyConfig(p_oConfig, true);
9109 this.initEvent.fire(MenuBar);
9119 * @property CSS_CLASS_NAME
9120 * @description String representing the CSS class(es) to be applied to the menu
9121 * bar's <code><div></code> element.
9122 * @default "yuimenubar"
9126 CSS_CLASS_NAME: "yuimenubar",
9130 * @property SUBMENU_TOGGLE_REGION_WIDTH
9131 * @description Width (in pixels) of the area of a MenuBarItem that, when pressed, will toggle the
9132 * display of the MenuBarItem's submenu.
9137 SUBMENU_TOGGLE_REGION_WIDTH: 20,
9140 // Protected event handlers
9144 * @method _onKeyDown
9145 * @description "keydown" Custom Event handler for the menu bar.
9147 * @param {String} p_sType String representing the name of the event that
9149 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
9150 * @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar
9151 * that fired the event.
9153 _onKeyDown: function(p_sType, p_aArgs, p_oMenuBar) {
9155 var oEvent = p_aArgs[0],
9162 if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9164 oItemCfg = oItem.cfg;
9166 switch(oEvent.keyCode) {
9168 case 37: // Left arrow
9169 case 39: // Right arrow
9171 if(oItem == this.activeItem && !oItemCfg.getProperty(_SELECTED)) {
9173 oItemCfg.setProperty(_SELECTED, true);
9178 oNextItem = (oEvent.keyCode == 37) ?
9179 oItem.getPreviousEnabledSibling() :
9180 oItem.getNextEnabledSibling();
9184 this.clearActiveItem();
9186 oNextItem.cfg.setProperty(_SELECTED, true);
9188 oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
9193 oSubmenu.setInitialFocus();
9204 Event.preventDefault(oEvent);
9208 case 40: // Down arrow
9210 if(this.activeItem != oItem) {
9212 this.clearActiveItem();
9214 oItemCfg.setProperty(_SELECTED, true);
9219 oSubmenu = oItemCfg.getProperty(_SUBMENU);
9223 if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9225 oSubmenu.setInitialSelection();
9226 oSubmenu.setInitialFocus();
9232 oSubmenu.setInitialFocus();
9238 Event.preventDefault(oEvent);
9247 if(oEvent.keyCode == 27 && this.activeItem) { // Esc key
9249 oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
9251 if(oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
9254 this.activeItem.focus();
9259 this.activeItem.cfg.setProperty(_SELECTED, false);
9260 this.activeItem.blur();
9264 Event.preventDefault(oEvent);
9273 * @description "click" event handler for the menu bar.
9275 * @param {String} p_sType String representing the name of the event that
9277 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
9278 * @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar
9279 * that fired the event.
9281 _onClick: function(p_sType, p_aArgs, p_oMenuBar) {
9283 MenuBar.superclass._onClick.call(this, p_sType, p_aArgs, p_oMenuBar);
9285 var oItem = p_aArgs[1],
9297 var toggleSubmenuDisplay = function () {
9299 if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9313 if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9315 oEvent = p_aArgs[0];
9316 oTarget = Event.getTarget(oEvent);
9317 oActiveItem = this.activeItem;
9321 // Hide any other submenus that might be visible
9323 if(oActiveItem && oActiveItem != oItem) {
9325 this.clearActiveItem();
9330 oItem.cfg.setProperty(_SELECTED, true);
9333 // Show the submenu for the item
9335 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
9340 oItemEl = oItem.element;
9341 nMenuItemX = YAHOO.util.Dom.getX(oItemEl);
9342 nToggleRegion = nMenuItemX + (oItemEl.offsetWidth - this.SUBMENU_TOGGLE_REGION_WIDTH);
9344 if (oConfig.getProperty(_SUBMENU_TOGGLE_REGION)) {
9346 if (Event.getPageX(oEvent) > nToggleRegion) {
9348 toggleSubmenuDisplay();
9350 Event.preventDefault(oEvent);
9353 Return false so that other click event handlers are not called when the
9354 user clicks inside the toggle region.
9363 toggleSubmenuDisplay();
9381 * @method configSubmenuToggle
9382 * @description Event handler for when the "submenutoggleregion" configuration property of
9383 * a MenuBar changes.
9384 * @param {String} p_sType The name of the event that was fired.
9385 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
9387 configSubmenuToggle: function (p_sType, p_aArgs) {
9389 var bSubmenuToggle = p_aArgs[0];
9391 if (bSubmenuToggle) {
9393 this.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
9402 * @description Returns a string representing the menu bar.
9405 toString: function() {
9407 var sReturnVal = _MENUBAR,
9412 sReturnVal += (_SPACE + sId);
9422 * @description Initializes the class's configurable properties which can be
9423 * changed using the menu bar's Config object ("cfg").
9424 * @method initDefaultConfig
9426 initDefaultConfig: function() {
9428 MenuBar.superclass.initDefaultConfig.call(this);
9430 var oConfig = this.cfg;
9432 // Add configuration properties
9436 Set the default value for the "position" configuration property
9437 to "static" by re-adding the property.
9443 * @description String indicating how a menu bar should be positioned on the
9444 * screen. Possible values are "static" and "dynamic." Static menu bars
9445 * are visible by default and reside in the normal flow of the document
9446 * (CSS position: static). Dynamic menu bars are hidden by default, reside
9447 * out of the normal flow of the document (CSS position: absolute), and can
9448 * overlay other elements on the screen.
9452 oConfig.addProperty(
9453 POSITION_CONFIG.key,
9455 handler: this.configPosition,
9456 value: POSITION_CONFIG.value,
9457 validator: POSITION_CONFIG.validator,
9458 supercedes: POSITION_CONFIG.supercedes
9464 Set the default value for the "submenualignment" configuration property
9465 to ["tl","bl"] by re-adding the property.
9469 * @config submenualignment
9470 * @description Array defining how submenus should be aligned to their
9471 * parent menu bar item. The format is: [itemCorner, submenuCorner].
9472 * @default ["tl","bl"]
9475 oConfig.addProperty(
9476 SUBMENU_ALIGNMENT_CONFIG.key,
9478 value: SUBMENU_ALIGNMENT_CONFIG.value,
9479 suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
9485 Change the default value for the "autosubmenudisplay" configuration
9486 property to "false" by re-adding the property.
9490 * @config autosubmenudisplay
9491 * @description Boolean indicating if submenus are automatically made
9492 * visible when the user mouses over the menu bar's items.
9496 oConfig.addProperty(
9497 AUTO_SUBMENU_DISPLAY_CONFIG.key,
9499 value: AUTO_SUBMENU_DISPLAY_CONFIG.value,
9500 validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
9501 suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
9507 * @config submenutoggleregion
9508 * @description Boolean indicating if only a specific region of a MenuBarItem should toggle the
9509 * display of a submenu. The default width of the region is determined by the value of the
9510 * SUBMENU_TOGGLE_REGION_WIDTH property. If set to true, the autosubmenudisplay
9511 * configuration property will be set to false, and any click event listeners will not be
9512 * called when the user clicks inside the submenu toggle region of a MenuBarItem. If the
9513 * user clicks outside of the submenu toggle region, the MenuBarItem will maintain its
9514 * standard behavior.
9518 oConfig.addProperty(
9519 SUBMENU_TOGGLE_REGION_CONFIG.key,
9521 value: SUBMENU_TOGGLE_REGION_CONFIG.value,
9522 validator: SUBMENU_TOGGLE_REGION_CONFIG.validator,
9523 handler: this.configSubmenuToggle
9529 }); // END YAHOO.lang.extend
9536 * Creates an item for a menu bar.
9538 * @param {String} p_oObject String specifying the text of the menu bar item.
9539 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9540 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9541 * <code><li></code> element of the menu bar item.
9542 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9543 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9544 * specifying the <code><optgroup></code> element of the menu bar item.
9545 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9546 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9547 * the <code><option></code> element of the menu bar item.
9548 * @param {Object} p_oConfig Optional. Object literal specifying the
9549 * configuration for the menu bar item. See configuration class documentation
9551 * @class MenuBarItem
9553 * @extends YAHOO.widget.MenuItem
9555 YAHOO.widget.MenuBarItem = function(p_oObject, p_oConfig) {
9557 YAHOO.widget.MenuBarItem.superclass.constructor.call(this, p_oObject, p_oConfig);
9561 YAHOO.lang.extend(YAHOO.widget.MenuBarItem, YAHOO.widget.MenuItem, {
9567 * @description The MenuBarItem class's initialization method. This method is
9568 * automatically called by the constructor, and sets up all DOM references for
9569 * pre-existing markup, and creates required markup if it is not already present.
9570 * @param {String} p_oObject String specifying the text of the menu bar item.
9571 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9572 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9573 * <code><li></code> element of the menu bar item.
9574 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9575 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9576 * specifying the <code><optgroup></code> element of the menu bar item.
9577 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9578 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9579 * the <code><option></code> element of the menu bar item.
9580 * @param {Object} p_oConfig Optional. Object literal specifying the
9581 * configuration for the menu bar item. See configuration class documentation
9584 init: function(p_oObject, p_oConfig) {
9586 if(!this.SUBMENU_TYPE) {
9588 this.SUBMENU_TYPE = YAHOO.widget.Menu;
9594 Call the init of the superclass (YAHOO.widget.MenuItem)
9595 Note: We don't pass the user config in here yet
9596 because we only want it executed once, at the lowest
9600 YAHOO.widget.MenuBarItem.superclass.init.call(this, p_oObject);
9603 var oConfig = this.cfg;
9607 oConfig.applyConfig(p_oConfig, true);
9611 oConfig.fireQueue();
9621 * @property CSS_CLASS_NAME
9622 * @description String representing the CSS class(es) to be applied to the
9623 * <code><li></code> element of the menu bar item.
9624 * @default "yuimenubaritem"
9628 CSS_CLASS_NAME: "yuimenubaritem",
9632 * @property CSS_LABEL_CLASS_NAME
9633 * @description String representing the CSS class(es) to be applied to the
9634 * menu bar item's <code><a></code> element.
9635 * @default "yuimenubaritemlabel"
9639 CSS_LABEL_CLASS_NAME: "yuimenubaritemlabel",
9648 * @description Returns a string representing the menu bar item.
9651 toString: function() {
9653 var sReturnVal = "MenuBarItem";
9655 if(this.cfg && this.cfg.getProperty("text")) {
9657 sReturnVal += (": " + this.cfg.getProperty("text"));
9665 }); // END YAHOO.lang.extend
9666 YAHOO.register("menu", YAHOO.widget.Menu, {version: "2.6.0", build: "1321"});