2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
11 * @description <p>The Menu family of components features a collection of
12 * controls that make it easy to add menus to your website or web application.
13 * With the Menu Controls you can create website fly-out menus, customized
14 * context menus, or application-style menu bars with just a small amount of
15 * scripting.</p><p>The Menu family of controls features:</p>
17 * <li>Keyboard and mouse navigation.</li>
18 * <li>A rich event model that provides access to all of a menu's
19 * interesting moments.</li>
21 * <a href="http://en.wikipedia.org/wiki/Progressive_Enhancement">Progressive
22 * Enhancement</a>; Menus can be created from simple,
23 * semantic markup on the page or purely through JavaScript.</li>
26 * @namespace YAHOO.widget
27 * @requires Event, Dom, Container
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;
466 else if (m_oVisibleMenus[sId]) {
468 delete m_oVisibleMenus[sId];
477 * @method onItemDestroy
478 * @description "destroy" event handler for a MenuItem instance.
480 * @param {String} p_sType String representing the name of the event
482 * @param {Array} p_aArgs Array of arguments sent when the event
485 function onItemDestroy(p_sType, p_aArgs) {
494 * @description Removes a MenuItem instance from the MenuManager's collection of MenuItems.
496 * @param {MenuItem} p_oMenuItem The MenuItem instance to be removed.
498 function removeItem(p_oMenuItem) {
500 var sId = p_oMenuItem.id;
502 if (sId && m_oItems[sId]) {
504 if (m_oFocusedMenuItem == p_oMenuItem) {
506 m_oFocusedMenuItem = null;
510 delete m_oItems[sId];
512 p_oMenuItem.destroyEvent.unsubscribe(onItemDestroy);
521 * @method onItemAdded
522 * @description "itemadded" event handler for a Menu instance.
524 * @param {String} p_sType String representing the name of the event
526 * @param {Array} p_aArgs Array of arguments sent when the event
529 function onItemAdded(p_sType, p_aArgs) {
531 var oItem = p_aArgs[0],
534 if (oItem instanceof YAHOO.widget.MenuItem) {
538 if (!m_oItems[sId]) {
540 m_oItems[sId] = oItem;
542 oItem.destroyEvent.subscribe(onItemDestroy);
554 // Privileged methods
559 * @description Adds a menu to the collection of known menus.
560 * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
561 * instance to be added.
563 addMenu: function (p_oMenu) {
567 if (p_oMenu instanceof YAHOO.widget.Menu && p_oMenu.id &&
568 !m_oMenus[p_oMenu.id]) {
570 m_oMenus[p_oMenu.id] = p_oMenu;
573 if (!m_bInitializedEventHandlers) {
577 Event.on(oDoc, _MOUSEOVER, onDOMEvent, this, true);
578 Event.on(oDoc, _MOUSEOUT, onDOMEvent, this, true);
579 Event.on(oDoc, _MOUSEDOWN, onDOMEvent, this, true);
580 Event.on(oDoc, _MOUSEUP, onDOMEvent, this, true);
581 Event.on(oDoc, _CLICK, onDOMEvent, this, true);
582 Event.on(oDoc, _KEYDOWN, onDOMEvent, this, true);
583 Event.on(oDoc, _KEYUP, onDOMEvent, this, true);
584 Event.on(oDoc, _KEYPRESS, onDOMEvent, this, true);
586 Event.onFocus(oDoc, onDOMEvent, this, true);
587 Event.onBlur(oDoc, onDOMEvent, this, true);
589 m_bInitializedEventHandlers = true;
594 p_oMenu.cfg.subscribeToConfigEvent(_VISIBLE, onMenuVisibleConfigChange);
595 p_oMenu.destroyEvent.subscribe(onMenuDestroy, p_oMenu, this);
596 p_oMenu.itemAddedEvent.subscribe(onItemAdded);
597 p_oMenu.focusEvent.subscribe(onMenuFocus);
598 p_oMenu.blurEvent.subscribe(onMenuBlur);
599 p_oMenu.showEvent.subscribe(onMenuShow);
609 * @description Removes a menu from the collection of known menus.
610 * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
611 * instance to be removed.
613 removeMenu: function (p_oMenu) {
623 if ((sId in m_oMenus) && (m_oMenus[sId] == p_oMenu)) {
625 // Unregister each menu item
627 aItems = p_oMenu.getItems();
629 if (aItems && aItems.length > 0) {
631 i = aItems.length - 1;
635 removeItem(aItems[i]);
643 // Unregister the menu
645 delete m_oMenus[sId];
650 Unregister the menu from the collection of
654 if ((sId in m_oVisibleMenus) && (m_oVisibleMenus[sId] == p_oMenu)) {
656 delete m_oVisibleMenus[sId];
662 // Unsubscribe event listeners
666 p_oMenu.cfg.unsubscribeFromConfigEvent(_VISIBLE,
667 onMenuVisibleConfigChange);
671 p_oMenu.destroyEvent.unsubscribe(onMenuDestroy,
674 p_oMenu.itemAddedEvent.unsubscribe(onItemAdded);
675 p_oMenu.focusEvent.unsubscribe(onMenuFocus);
676 p_oMenu.blurEvent.unsubscribe(onMenuBlur);
686 * @method hideVisible
687 * @description Hides all visible, dynamically positioned menus
688 * (excluding instances of YAHOO.widget.MenuBar).
690 hideVisible: function () {
694 for (var i in m_oVisibleMenus) {
696 if (Lang.hasOwnProperty(m_oVisibleMenus, i)) {
698 oMenu = m_oVisibleMenus[i];
700 if (!(oMenu instanceof YAHOO.widget.MenuBar) &&
701 oMenu.cfg.getProperty(_POSITION) == _DYNAMIC) {
716 * @description Returns a collection of all visible menus registered
717 * with the menu manger.
720 getVisible: function () {
722 return m_oVisibleMenus;
729 * @description Returns a collection of all menus registered with the
733 getMenus: function () {
742 * @description Returns a menu with the specified id.
743 * @param {String} p_sId String specifying the id of the
744 * <code><div></code> element representing the menu to
746 * @return {YAHOO.widget.Menu}
748 getMenu: function (p_sId) {
752 if (p_sId in m_oMenus) {
754 returnVal = m_oMenus[p_sId];
764 * @method getMenuItem
765 * @description Returns a menu item with the specified id.
766 * @param {String} p_sId String specifying the id of the
767 * <code><li></code> element representing the menu item to
769 * @return {YAHOO.widget.MenuItem}
771 getMenuItem: function (p_sId) {
775 if (p_sId in m_oItems) {
777 returnVal = m_oItems[p_sId];
787 * @method getMenuItemGroup
788 * @description Returns an array of menu item instances whose
789 * corresponding <code><li></code> elements are child
790 * nodes of the <code><ul></code> element with the
792 * @param {String} p_sId String specifying the id of the
793 * <code><ul></code> element representing the group of
794 * menu items to be retrieved.
797 getMenuItemGroup: function (p_sId) {
799 var oUL = Dom.get(p_sId),
807 if (oUL && oUL.tagName && oUL.tagName.toUpperCase() == _UL) {
809 oNode = oUL.firstChild;
821 oItem = this.getMenuItem(sId);
825 aItems[aItems.length] = oItem;
832 while ((oNode = oNode.nextSibling));
835 if (aItems.length > 0) {
851 * @method getFocusedMenuItem
852 * @description Returns a reference to the menu item that currently
854 * @return {YAHOO.widget.MenuItem}
856 getFocusedMenuItem: function () {
858 return m_oFocusedMenuItem;
864 * @method getFocusedMenu
865 * @description Returns a reference to the menu that currently
867 * @return {YAHOO.widget.Menu}
869 getFocusedMenu: function () {
873 if (m_oFocusedMenuItem) {
875 returnVal = m_oFocusedMenuItem.parent.getRoot();
886 * @description Returns a string representing the menu manager.
889 toString: function () {
905 var Lang = YAHOO.lang,
910 _DIV_UPPERCASE = "DIV",
911 _DIV_LOWERCASE = "div",
916 _UL_UPPERCASE = "UL",
917 _UL_LOWERCASE = "ul",
918 _FIRST_OF_TYPE = "first-of-type",
920 _OPTGROUP = "OPTGROUP",
922 _DISABLED = "disabled",
924 _SELECTED = "selected",
925 _GROUP_INDEX = "groupindex",
927 _SUBMENU = "submenu",
928 _VISIBLE = "visible",
929 _HIDE_DELAY = "hidedelay",
930 _POSITION = "position",
931 _DYNAMIC = "dynamic",
933 _DYNAMIC_STATIC = _DYNAMIC + "," + _STATIC,
934 _WINDOWS = "windows",
938 _MAX_HEIGHT = "maxheight",
939 _TOP_SCROLLBAR = "topscrollbar",
940 _BOTTOM_SCROLLBAR = "bottomscrollbar",
942 _TOP_SCROLLBAR_DISABLED = _TOP_SCROLLBAR + _UNDERSCORE + _DISABLED,
943 _BOTTOM_SCROLLBAR_DISABLED = _BOTTOM_SCROLLBAR + _UNDERSCORE + _DISABLED,
944 _MOUSEMOVE = "mousemove",
945 _SHOW_DELAY = "showdelay",
946 _SUBMENU_HIDE_DELAY = "submenuhidedelay",
948 _CONSTRAIN_TO_VIEWPORT = "constraintoviewport",
949 _PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
950 _SUBMENU_ALIGNMENT = "submenualignment",
951 _AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
952 _CLICK_TO_HIDE = "clicktohide",
953 _CONTAINER = "container",
954 _SCROLL_INCREMENT = "scrollincrement",
955 _MIN_SCROLL_HEIGHT = "minscrollheight",
956 _CLASSNAME = "classname",
958 _KEEP_OPEN = "keepopen",
960 _HAS_TITLE = "hastitle",
961 _CONTEXT = "context",
963 _MOUSEDOWN = "mousedown",
964 _KEYDOWN = "keydown",
969 _MONITOR_RESIZE = "monitorresize",
970 _DISPLAY = "display",
972 _VISIBILITY = "visibility",
973 _ABSOLUTE = "absolute",
975 _YUI_MENU_BODY_SCROLLED = "yui-menu-body-scrolled",
976 _NON_BREAKING_SPACE = " ",
978 _MOUSEOVER = "mouseover",
979 _MOUSEOUT = "mouseout",
980 _ITEM_ADDED = "itemAdded",
981 _ITEM_REMOVED = "itemRemoved",
983 _YUI_MENU_SHADOW = "yui-menu-shadow",
984 _YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + "-visible",
985 _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE = _YUI_MENU_SHADOW + _SPACE + _YUI_MENU_SHADOW_VISIBLE;
989 * The Menu class creates a container that holds a vertical list representing
990 * a set of options or commands. Menu is the base class for all
992 * @param {String} p_oElement String specifying the id attribute of the
993 * <code><div></code> element of the menu.
994 * @param {String} p_oElement String specifying the id attribute of the
995 * <code><select></code> element to be used as the data source
997 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
998 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
999 * specifying the <code><div></code> element of the menu.
1000 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1001 * level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
1002 * Object specifying the <code><select></code> element to be used as
1003 * the data source for the menu.
1004 * @param {Object} p_oConfig Optional. Object literal specifying the
1005 * configuration for the menu. See configuration class documentation for
1007 * @namespace YAHOO.widget
1010 * @extends YAHOO.widget.Overlay
1012 YAHOO.widget.Menu = function (p_oElement, p_oConfig) {
1016 this.parent = p_oConfig.parent;
1017 this.lazyLoad = p_oConfig.lazyLoad || p_oConfig.lazyload;
1018 this.itemData = p_oConfig.itemData || p_oConfig.itemdata;
1023 YAHOO.widget.Menu.superclass.constructor.call(this, p_oElement, p_oConfig);
1030 * @method checkPosition
1031 * @description Checks to make sure that the value of the "position" property
1032 * is one of the supported strings. Returns true if the position is supported.
1034 * @param {Object} p_sPosition String specifying the position of the menu.
1037 function checkPosition(p_sPosition) {
1039 var returnVal = false;
1041 if (Lang.isString(p_sPosition)) {
1043 returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
1052 var Dom = YAHOO.util.Dom,
1053 Event = YAHOO.util.Event,
1054 Module = YAHOO.widget.Module,
1055 Overlay = YAHOO.widget.Overlay,
1056 Menu = YAHOO.widget.Menu,
1057 MenuManager = YAHOO.widget.MenuManager,
1058 CustomEvent = YAHOO.util.CustomEvent,
1065 ["mouseOverEvent", _MOUSEOVER],
1066 ["mouseOutEvent", _MOUSEOUT],
1067 ["mouseDownEvent", _MOUSEDOWN],
1068 ["mouseUpEvent", "mouseup"],
1069 ["clickEvent", "click"],
1070 ["keyPressEvent", "keypress"],
1071 ["keyDownEvent", _KEYDOWN],
1072 ["keyUpEvent", "keyup"],
1073 ["focusEvent", "focus"],
1074 ["blurEvent", "blur"],
1075 ["itemAddedEvent", _ITEM_ADDED],
1076 ["itemRemovedEvent", _ITEM_REMOVED]
1083 validator: Lang.isBoolean
1086 CONSTRAIN_TO_VIEWPORT_CONFIG = {
1087 key: _CONSTRAIN_TO_VIEWPORT,
1089 validator: Lang.isBoolean,
1090 supercedes: [_IFRAME,"x",_Y,_XY]
1093 PREVENT_CONTEXT_OVERLAP_CONFIG = {
1094 key: _PREVENT_CONTEXT_OVERLAP,
1096 validator: Lang.isBoolean,
1097 supercedes: [_CONSTRAIN_TO_VIEWPORT]
1103 validator: checkPosition,
1104 supercedes: [_VISIBLE, _IFRAME]
1107 SUBMENU_ALIGNMENT_CONFIG = {
1108 key: _SUBMENU_ALIGNMENT,
1112 AUTO_SUBMENU_DISPLAY_CONFIG = {
1113 key: _AUTO_SUBMENU_DISPLAY,
1115 validator: Lang.isBoolean,
1119 SHOW_DELAY_CONFIG = {
1122 validator: Lang.isNumber,
1126 HIDE_DELAY_CONFIG = {
1129 validator: Lang.isNumber,
1133 SUBMENU_HIDE_DELAY_CONFIG = {
1134 key: _SUBMENU_HIDE_DELAY,
1136 validator: Lang.isNumber,
1140 CLICK_TO_HIDE_CONFIG = {
1141 key: _CLICK_TO_HIDE,
1143 validator: Lang.isBoolean,
1147 CONTAINER_CONFIG = {
1152 SCROLL_INCREMENT_CONFIG = {
1153 key: _SCROLL_INCREMENT,
1155 validator: Lang.isNumber,
1156 supercedes: [_MAX_HEIGHT],
1160 MIN_SCROLL_HEIGHT_CONFIG = {
1161 key: _MIN_SCROLL_HEIGHT,
1163 validator: Lang.isNumber,
1164 supercedes: [_MAX_HEIGHT],
1168 MAX_HEIGHT_CONFIG = {
1171 validator: Lang.isNumber,
1172 supercedes: [_IFRAME],
1176 CLASS_NAME_CONFIG = {
1179 validator: Lang.isString,
1186 validator: Lang.isBoolean,
1193 validator: Lang.isBoolean,
1194 suppressEvent: true,
1195 supercedes: [_VISIBLE]
1198 KEEP_OPEN_CONFIG = {
1201 validator: Lang.isBoolean
1206 YAHOO.lang.extend(Menu, Overlay, {
1213 * @property CSS_CLASS_NAME
1214 * @description String representing the CSS class(es) to be applied to the
1215 * menu's <code><div></code> element.
1216 * @default "yuimenu"
1220 CSS_CLASS_NAME: "yuimenu",
1224 * @property ITEM_TYPE
1225 * @description Object representing the type of menu item to instantiate and
1226 * add when parsing the child nodes (either <code><li></code> element,
1227 * <code><optgroup></code> element or <code><option></code>)
1228 * of the menu's source HTML element.
1229 * @default YAHOO.widget.MenuItem
1231 * @type YAHOO.widget.MenuItem
1237 * @property GROUP_TITLE_TAG_NAME
1238 * @description String representing the tagname of the HTML element used to
1239 * title the menu's item groups.
1244 GROUP_TITLE_TAG_NAME: "h6",
1248 * @property OFF_SCREEN_POSITION
1249 * @description Array representing the default x and y position that a menu
1250 * should have when it is positioned outside the viewport by the
1251 * "poistionOffScreen" method.
1256 OFF_SCREEN_POSITION: "-999em",
1259 // Private properties
1263 * @property _useHideDelay
1264 * @description Boolean indicating if the "mouseover" and "mouseout" event
1265 * handlers used for hiding the menu via a call to "YAHOO.lang.later" have
1266 * already been assigned.
1271 _useHideDelay: false,
1275 * @property _bHandledMouseOverEvent
1276 * @description Boolean indicating the current state of the menu's
1277 * "mouseover" event.
1282 _bHandledMouseOverEvent: false,
1286 * @property _bHandledMouseOutEvent
1287 * @description Boolean indicating the current state of the menu's
1293 _bHandledMouseOutEvent: false,
1297 * @property _aGroupTitleElements
1298 * @description Array of HTML element used to title groups of menu items.
1303 _aGroupTitleElements: null,
1307 * @property _aItemGroups
1308 * @description Multi-dimensional Array representing the menu items as they
1309 * are grouped in the menu.
1318 * @property _aListElements
1319 * @description Array of <code><ul></code> elements, each of which is
1320 * the parent node for each item's <code><li></code> element.
1325 _aListElements: null,
1329 * @property _nCurrentMouseX
1330 * @description The current x coordinate of the mouse inside the area of
1340 * @property _bStopMouseEventHandlers
1341 * @description Stops "mouseover," "mouseout," and "mousemove" event handlers
1347 _bStopMouseEventHandlers: false,
1351 * @property _sClassName
1352 * @description The current value of the "classname" configuration attribute.
1361 // Public properties
1365 * @property lazyLoad
1366 * @description Boolean indicating if the menu's "lazy load" feature is
1367 * enabled. If set to "true," initialization and rendering of the menu's
1368 * items will be deferred until the first time it is made visible. This
1369 * property should be set via the constructor using the configuration
1378 * @property itemData
1379 * @description Array of items to be added to the menu. The array can contain
1380 * strings representing the text for each item to be created, object literals
1381 * representing the menu item configuration properties, or MenuItem instances.
1382 * This property should be set via the constructor using the configuration
1391 * @property activeItem
1392 * @description Object reference to the item in the menu that has is selected.
1394 * @type YAHOO.widget.MenuItem
1401 * @description Object reference to the menu's parent menu or menu item.
1402 * This property can be set via the constructor using the configuration
1405 * @type YAHOO.widget.MenuItem
1411 * @property srcElement
1412 * @description Object reference to the HTML element (either
1413 * <code><select></code> or <code><div></code>) used to
1416 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1417 * level-one-html.html#ID-94282980">HTMLSelectElement</a>|<a
1418 * href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.
1419 * html#ID-22445964">HTMLDivElement</a>
1429 * @event mouseOverEvent
1430 * @description Fires when the mouse has entered the menu. Passes back
1431 * the DOM Event object as an argument.
1436 * @event mouseOutEvent
1437 * @description Fires when the mouse has left the menu. Passes back the DOM
1438 * Event object as an argument.
1439 * @type YAHOO.util.CustomEvent
1444 * @event mouseDownEvent
1445 * @description Fires when the user mouses down on the menu. Passes back the
1446 * DOM Event object as an argument.
1447 * @type YAHOO.util.CustomEvent
1452 * @event mouseUpEvent
1453 * @description Fires when the user releases a mouse button while the mouse is
1454 * over the menu. Passes back the DOM Event object as an argument.
1455 * @type YAHOO.util.CustomEvent
1461 * @description Fires when the user clicks the on the menu. Passes back the
1462 * DOM Event object as an argument.
1463 * @type YAHOO.util.CustomEvent
1468 * @event keyPressEvent
1469 * @description Fires when the user presses an alphanumeric key when one of the
1470 * menu's items has focus. Passes back the DOM Event object as an argument.
1471 * @type YAHOO.util.CustomEvent
1476 * @event keyDownEvent
1477 * @description Fires when the user presses a key when one of the menu's items
1478 * has focus. Passes back the DOM Event object as an argument.
1479 * @type YAHOO.util.CustomEvent
1485 * @description Fires when the user releases a key when one of the menu's items
1486 * has focus. Passes back the DOM Event object as an argument.
1487 * @type YAHOO.util.CustomEvent
1492 * @event itemAddedEvent
1493 * @description Fires when an item is added to the menu.
1494 * @type YAHOO.util.CustomEvent
1499 * @event itemRemovedEvent
1500 * @description Fires when an item is removed to the menu.
1501 * @type YAHOO.util.CustomEvent
1507 * @description The Menu class's initialization method. This method is
1508 * automatically called by the constructor, and sets up all DOM references
1509 * for pre-existing markup, and creates required markup if it is not
1511 * @param {String} p_oElement String specifying the id attribute of the
1512 * <code><div></code> element of the menu.
1513 * @param {String} p_oElement String specifying the id attribute of the
1514 * <code><select></code> element to be used as the data source
1516 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1517 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
1518 * specifying the <code><div></code> element of the menu.
1519 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1520 * level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
1521 * Object specifying the <code><select></code> element to be used as
1522 * the data source for the menu.
1523 * @param {Object} p_oConfig Optional. Object literal specifying the
1524 * configuration for the menu. See configuration class documentation for
1527 init: function (p_oElement, p_oConfig) {
1529 this._aItemGroups = [];
1530 this._aListElements = [];
1531 this._aGroupTitleElements = [];
1533 if (!this.ITEM_TYPE) {
1535 this.ITEM_TYPE = YAHOO.widget.MenuItem;
1542 if (Lang.isString(p_oElement)) {
1544 oElement = Dom.get(p_oElement);
1547 else if (p_oElement.tagName) {
1549 oElement = p_oElement;
1554 if (oElement && oElement.tagName) {
1556 switch(oElement.tagName.toUpperCase()) {
1558 case _DIV_UPPERCASE:
1560 this.srcElement = oElement;
1564 oElement.setAttribute(_ID, Dom.generateId());
1570 Note: we don't pass the user config in here yet
1571 because we only want it executed once, at the lowest
1575 Menu.superclass.init.call(this, oElement);
1577 this.beforeInitEvent.fire(Menu);
1584 this.srcElement = oElement;
1588 The source element is not something that we can use
1589 outright, so we need to create a new Overlay
1591 Note: we don't pass the user config in here yet
1592 because we only want it executed once, at the lowest
1596 Menu.superclass.init.call(this, Dom.generateId());
1598 this.beforeInitEvent.fire(Menu);
1609 Note: we don't pass the user config in here yet
1610 because we only want it executed once, at the lowest
1614 Menu.superclass.init.call(this, p_oElement);
1616 this.beforeInitEvent.fire(Menu);
1624 Dom.addClass(this.element, this.CSS_CLASS_NAME);
1627 // Subscribe to Custom Events
1629 this.initEvent.subscribe(this._onInit);
1630 this.beforeRenderEvent.subscribe(this._onBeforeRender);
1631 this.renderEvent.subscribe(this._onRender);
1632 this.beforeShowEvent.subscribe(this._onBeforeShow);
1633 this.hideEvent.subscribe(this._onHide);
1634 this.showEvent.subscribe(this._onShow);
1635 this.beforeHideEvent.subscribe(this._onBeforeHide);
1636 this.mouseOverEvent.subscribe(this._onMouseOver);
1637 this.mouseOutEvent.subscribe(this._onMouseOut);
1638 this.clickEvent.subscribe(this._onClick);
1639 this.keyDownEvent.subscribe(this._onKeyDown);
1640 this.keyPressEvent.subscribe(this._onKeyPress);
1641 this.blurEvent.subscribe(this._onBlur);
1644 // Fixes an issue in Firefox 2 and Webkit where Dom's "getX" and "getY"
1645 // methods return values that don't take scrollTop into consideration
1647 if ((UA.gecko && UA.gecko < 1.9) || UA.webkit) {
1649 this.cfg.subscribeToConfigEvent(_Y, this._onYChange);
1656 this.cfg.applyConfig(p_oConfig, true);
1661 // Register the Menu instance with the MenuManager
1663 MenuManager.addMenu(this);
1666 this.initEvent.fire(Menu);
1678 * @method _initSubTree
1679 * @description Iterates the childNodes of the source element to find nodes
1680 * used to instantiate menu and menu items.
1683 _initSubTree: function () {
1685 var oSrcElement = this.srcElement,
1697 sSrcElementTagName =
1698 (oSrcElement.tagName && oSrcElement.tagName.toUpperCase());
1701 if (sSrcElementTagName == _DIV_UPPERCASE) {
1703 // Populate the collection of item groups and item group titles
1705 oNode = this.body.firstChild;
1711 sGroupTitleTagName = this.GROUP_TITLE_TAG_NAME.toUpperCase();
1716 if (oNode && oNode.tagName) {
1718 switch (oNode.tagName.toUpperCase()) {
1720 case sGroupTitleTagName:
1722 this._aGroupTitleElements[nGroup] = oNode;
1728 this._aListElements[nGroup] = oNode;
1729 this._aItemGroups[nGroup] = [];
1739 while ((oNode = oNode.nextSibling));
1743 Apply the "first-of-type" class to the first UL to mimic
1744 the ":first-of-type" CSS3 psuedo class.
1747 if (this._aListElements[0]) {
1749 Dom.addClass(this._aListElements[0], _FIRST_OF_TYPE);
1762 if (sSrcElementTagName) {
1764 switch (sSrcElementTagName) {
1766 case _DIV_UPPERCASE:
1768 aListElements = this._aListElements;
1769 nListElements = aListElements.length;
1771 if (nListElements > 0) {
1774 i = nListElements - 1;
1778 oNode = aListElements[i].firstChild;
1785 if (oNode && oNode.tagName &&
1786 oNode.tagName.toUpperCase() == _LI) {
1789 this.addItem(new this.ITEM_TYPE(oNode,
1790 { parent: this }), i);
1795 while ((oNode = oNode.nextSibling));
1809 oNode = oSrcElement.firstChild;
1813 if (oNode && oNode.tagName) {
1815 switch (oNode.tagName.toUpperCase()) {
1835 while ((oNode = oNode.nextSibling));
1849 * @method _getFirstEnabledItem
1850 * @description Returns the first enabled item in the menu.
1851 * @return {YAHOO.widget.MenuItem}
1854 _getFirstEnabledItem: function () {
1856 var aItems = this.getItems(),
1857 nItems = aItems.length,
1862 for(var i=0; i<nItems; i++) {
1866 if (oItem && !oItem.cfg.getProperty(_DISABLED) && oItem.element.style.display != _NONE) {
1881 * @method _addItemToGroup
1882 * @description Adds a menu item to a group.
1884 * @param {Number} p_nGroupIndex Number indicating the group to which the
1886 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
1887 * instance to be added to the menu.
1888 * @param {String} p_oItem String specifying the text of the item to be added
1890 * @param {Object} p_oItem Object literal containing a set of menu item
1891 * configuration properties.
1892 * @param {Number} p_nItemIndex Optional. Number indicating the index at
1893 * which the menu item should be added.
1894 * @return {YAHOO.widget.MenuItem}
1896 _addItemToGroup: function (p_nGroupIndex, p_oItem, p_nItemIndex) {
1908 function getNextItemSibling(p_aArray, p_nStartIndex) {
1910 return (p_aArray[p_nStartIndex] || getNextItemSibling(p_aArray, (p_nStartIndex+1)));
1915 if (p_oItem instanceof this.ITEM_TYPE) {
1918 oItem.parent = this;
1921 else if (Lang.isString(p_oItem)) {
1923 oItem = new this.ITEM_TYPE(p_oItem, { parent: this });
1926 else if (Lang.isObject(p_oItem)) {
1928 p_oItem.parent = this;
1930 oItem = new this.ITEM_TYPE(p_oItem.text, p_oItem);
1937 if (oItem.cfg.getProperty(_SELECTED)) {
1939 this.activeItem = oItem;
1944 nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
1945 aGroup = this._getItemGroup(nGroupIndex);
1951 aGroup = this._createItemGroup(nGroupIndex);
1956 if (Lang.isNumber(p_nItemIndex)) {
1958 bAppend = (p_nItemIndex >= aGroup.length);
1961 if (aGroup[p_nItemIndex]) {
1963 aGroup.splice(p_nItemIndex, 0, oItem);
1968 aGroup[p_nItemIndex] = oItem;
1973 oGroupItem = aGroup[p_nItemIndex];
1977 if (bAppend && (!oGroupItem.element.parentNode ||
1978 oGroupItem.element.parentNode.nodeType == 11)) {
1980 this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
1985 oNextItemSibling = getNextItemSibling(aGroup, (p_nItemIndex+1));
1987 if (oNextItemSibling && (!oGroupItem.element.parentNode ||
1988 oGroupItem.element.parentNode.nodeType == 11)) {
1990 this._aListElements[nGroupIndex].insertBefore(
1991 oGroupItem.element, oNextItemSibling.element);
1998 oGroupItem.parent = this;
2000 this._subscribeToItemEvents(oGroupItem);
2002 this._configureSubmenu(oGroupItem);
2004 this._updateItemProperties(nGroupIndex);
2007 this.itemAddedEvent.fire(oGroupItem);
2008 this.changeContentEvent.fire();
2010 returnVal = oGroupItem;
2017 nItemIndex = aGroup.length;
2019 aGroup[nItemIndex] = oItem;
2021 oGroupItem = aGroup[nItemIndex];
2026 if (!Dom.isAncestor(this._aListElements[nGroupIndex], oGroupItem.element)) {
2028 this._aListElements[nGroupIndex].appendChild(oGroupItem.element);
2032 oGroupItem.element.setAttribute(_GROUP_INDEX, nGroupIndex);
2033 oGroupItem.element.setAttribute(_INDEX, nItemIndex);
2035 oGroupItem.parent = this;
2037 oGroupItem.index = nItemIndex;
2038 oGroupItem.groupIndex = nGroupIndex;
2040 this._subscribeToItemEvents(oGroupItem);
2042 this._configureSubmenu(oGroupItem);
2044 if (nItemIndex === 0) {
2046 Dom.addClass(oGroupItem.element, _FIRST_OF_TYPE);
2052 this.itemAddedEvent.fire(oGroupItem);
2053 this.changeContentEvent.fire();
2055 returnVal = oGroupItem;
2069 * @method _removeItemFromGroupByIndex
2070 * @description Removes a menu item from a group by index. Returns the menu
2071 * item that was removed.
2073 * @param {Number} p_nGroupIndex Number indicating the group to which the menu
2075 * @param {Number} p_nItemIndex Number indicating the index of the menu item
2077 * @return {YAHOO.widget.MenuItem}
2079 _removeItemFromGroupByIndex: function (p_nGroupIndex, p_nItemIndex) {
2081 var nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0,
2082 aGroup = this._getItemGroup(nGroupIndex),
2089 aArray = aGroup.splice(p_nItemIndex, 1);
2094 // Update the index and className properties of each member
2096 this._updateItemProperties(nGroupIndex);
2098 if (aGroup.length === 0) {
2102 oUL = this._aListElements[nGroupIndex];
2104 if (this.body && oUL) {
2106 this.body.removeChild(oUL);
2110 // Remove the group from the array of items
2112 this._aItemGroups.splice(nGroupIndex, 1);
2115 // Remove the UL from the array of ULs
2117 this._aListElements.splice(nGroupIndex, 1);
2121 Assign the "first-of-type" class to the new first UL
2125 oUL = this._aListElements[0];
2129 Dom.addClass(oUL, _FIRST_OF_TYPE);
2136 this.itemRemovedEvent.fire(oItem);
2137 this.changeContentEvent.fire();
2143 // Return a reference to the item that was removed
2151 * @method _removeItemFromGroupByValue
2152 * @description Removes a menu item from a group by reference. Returns the
2153 * menu item that was removed.
2155 * @param {Number} p_nGroupIndex Number indicating the group to which the
2156 * menu item belongs.
2157 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2158 * instance to be removed.
2159 * @return {YAHOO.widget.MenuItem}
2161 _removeItemFromGroupByValue: function (p_nGroupIndex, p_oItem) {
2163 var aGroup = this._getItemGroup(p_nGroupIndex),
2171 nItems = aGroup.length;
2180 if (aGroup[i] == p_oItem) {
2190 if (nItemIndex > -1) {
2192 returnVal = this._removeItemFromGroupByIndex(p_nGroupIndex, nItemIndex);
2206 * @method _updateItemProperties
2207 * @description Updates the "index," "groupindex," and "className" properties
2208 * of the menu items in the specified group.
2210 * @param {Number} p_nGroupIndex Number indicating the group of items to update.
2212 _updateItemProperties: function (p_nGroupIndex) {
2214 var aGroup = this._getItemGroup(p_nGroupIndex),
2215 nItems = aGroup.length,
2225 // Update the index and className properties of each member
2233 oLI = oItem.element;
2236 oItem.groupIndex = p_nGroupIndex;
2238 oLI.setAttribute(_GROUP_INDEX, p_nGroupIndex);
2239 oLI.setAttribute(_INDEX, i);
2241 Dom.removeClass(oLI, _FIRST_OF_TYPE);
2251 Dom.addClass(oLI, _FIRST_OF_TYPE);
2261 * @method _createItemGroup
2262 * @description Creates a new menu item group (array) and its associated
2263 * <code><ul></code> element. Returns an aray of menu item groups.
2265 * @param {Number} p_nIndex Number indicating the group to create.
2268 _createItemGroup: function (p_nIndex) {
2273 if (!this._aItemGroups[p_nIndex]) {
2275 this._aItemGroups[p_nIndex] = [];
2277 oUL = document.createElement(_UL_LOWERCASE);
2279 this._aListElements[p_nIndex] = oUL;
2281 returnVal = this._aItemGroups[p_nIndex];
2291 * @method _getItemGroup
2292 * @description Returns the menu item group at the specified index.
2294 * @param {Number} p_nIndex Number indicating the index of the menu item group
2298 _getItemGroup: function (p_nIndex) {
2300 var nIndex = Lang.isNumber(p_nIndex) ? p_nIndex : 0,
2301 aGroups = this._aItemGroups,
2304 if (nIndex in aGroups) {
2306 returnVal = aGroups[nIndex];
2316 * @method _configureSubmenu
2317 * @description Subscribes the menu item's submenu to its parent menu's events.
2319 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2320 * instance with the submenu to be configured.
2322 _configureSubmenu: function (p_oItem) {
2324 var oSubmenu = p_oItem.cfg.getProperty(_SUBMENU);
2329 Listen for configuration changes to the parent menu
2330 so they they can be applied to the submenu.
2333 this.cfg.configChangedEvent.subscribe(this._onParentMenuConfigChange, oSubmenu, true);
2335 this.renderEvent.subscribe(this._onParentMenuRender, oSubmenu, true);
2345 * @method _subscribeToItemEvents
2346 * @description Subscribes a menu to a menu item's event.
2348 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2349 * instance whose events should be subscribed to.
2351 _subscribeToItemEvents: function (p_oItem) {
2353 p_oItem.destroyEvent.subscribe(this._onMenuItemDestroy, p_oItem, this);
2354 p_oItem.cfg.configChangedEvent.subscribe(this._onMenuItemConfigChange, p_oItem, this);
2360 * @method _onVisibleChange
2361 * @description Change event handler for the the menu's "visible" configuration
2364 * @param {String} p_sType String representing the name of the event that
2366 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2368 _onVisibleChange: function (p_sType, p_aArgs) {
2370 var bVisible = p_aArgs[0];
2374 Dom.addClass(this.element, _VISIBLE);
2379 Dom.removeClass(this.element, _VISIBLE);
2387 * @method _cancelHideDelay
2388 * @description Cancels the call to "hideMenu."
2391 _cancelHideDelay: function () {
2393 var oTimer = this.getRoot()._hideDelayTimer;
2405 * @method _execHideDelay
2406 * @description Hides the menu after the number of milliseconds specified by
2407 * the "hidedelay" configuration property.
2410 _execHideDelay: function () {
2412 this._cancelHideDelay();
2414 var oRoot = this.getRoot();
2416 oRoot._hideDelayTimer = Lang.later(oRoot.cfg.getProperty(_HIDE_DELAY), this, function () {
2418 if (oRoot.activeItem) {
2420 if (oRoot.hasFocus()) {
2422 oRoot.activeItem.focus();
2426 oRoot.clearActiveItem();
2430 if (oRoot == this && !(this instanceof YAHOO.widget.MenuBar) &&
2431 this.cfg.getProperty(_POSITION) == _DYNAMIC) {
2443 * @method _cancelShowDelay
2444 * @description Cancels the call to the "showMenu."
2447 _cancelShowDelay: function () {
2449 var oTimer = this.getRoot()._showDelayTimer;
2461 * @method _execSubmenuHideDelay
2462 * @description Hides a submenu after the number of milliseconds specified by
2463 * the "submenuhidedelay" configuration property have ellapsed.
2465 * @param {YAHOO.widget.Menu} p_oSubmenu Object specifying the submenu that
2467 * @param {Number} p_nMouseX The x coordinate of the mouse when it left
2468 * the specified submenu's parent menu item.
2469 * @param {Number} p_nHideDelay The number of milliseconds that should ellapse
2470 * before the submenu is hidden.
2472 _execSubmenuHideDelay: function (p_oSubmenu, p_nMouseX, p_nHideDelay) {
2474 p_oSubmenu._submenuHideDelayTimer = Lang.later(50, this, function () {
2476 if (this._nCurrentMouseX > (p_nMouseX + 10)) {
2478 p_oSubmenu._submenuHideDelayTimer = Lang.later(p_nHideDelay, p_oSubmenu, function () {
2497 // Protected methods
2501 * @method _disableScrollHeader
2502 * @description Disables the header used for scrolling the body of the menu.
2505 _disableScrollHeader: function () {
2507 if (!this._bHeaderDisabled) {
2509 Dom.addClass(this.header, _TOP_SCROLLBAR_DISABLED);
2510 this._bHeaderDisabled = true;
2518 * @method _disableScrollFooter
2519 * @description Disables the footer used for scrolling the body of the menu.
2522 _disableScrollFooter: function () {
2524 if (!this._bFooterDisabled) {
2526 Dom.addClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2527 this._bFooterDisabled = true;
2535 * @method _enableScrollHeader
2536 * @description Enables the header used for scrolling the body of the menu.
2539 _enableScrollHeader: function () {
2541 if (this._bHeaderDisabled) {
2543 Dom.removeClass(this.header, _TOP_SCROLLBAR_DISABLED);
2544 this._bHeaderDisabled = false;
2552 * @method _enableScrollFooter
2553 * @description Enables the footer used for scrolling the body of the menu.
2556 _enableScrollFooter: function () {
2558 if (this._bFooterDisabled) {
2560 Dom.removeClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
2561 this._bFooterDisabled = false;
2569 * @method _onMouseOver
2570 * @description "mouseover" event handler for the menu.
2572 * @param {String} p_sType String representing the name of the event that
2574 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2576 _onMouseOver: function (p_sType, p_aArgs) {
2578 var oEvent = p_aArgs[0],
2580 oTarget = Event.getTarget(oEvent),
2581 oRoot = this.getRoot(),
2582 oSubmenuHideDelayTimer = this._submenuHideDelayTimer,
2591 var showSubmenu = function () {
2593 if (this.parent.cfg.getProperty(_SELECTED)) {
2602 if (!this._bStopMouseEventHandlers) {
2604 if (!this._bHandledMouseOverEvent && (oTarget == this.element ||
2605 Dom.isAncestor(this.element, oTarget))) {
2607 // Menu mouseover logic
2609 if (this._useHideDelay) {
2610 this._cancelHideDelay();
2613 this._nCurrentMouseX = 0;
2615 Event.on(this.element, _MOUSEMOVE, this._onMouseMove, this, true);
2619 If the mouse is moving from the submenu back to its corresponding menu item,
2620 don't hide the submenu or clear the active MenuItem.
2623 if (!(oItem && Dom.isAncestor(oItem.element, Event.getRelatedTarget(oEvent)))) {
2625 this.clearActiveItem();
2630 if (this.parent && oSubmenuHideDelayTimer) {
2632 oSubmenuHideDelayTimer.cancel();
2634 this.parent.cfg.setProperty(_SELECTED, true);
2636 oParentMenu = this.parent.parent;
2638 oParentMenu._bHandledMouseOutEvent = true;
2639 oParentMenu._bHandledMouseOverEvent = false;
2644 this._bHandledMouseOverEvent = true;
2645 this._bHandledMouseOutEvent = false;
2650 if (oItem && !oItem.handledMouseOverEvent && !oItem.cfg.getProperty(_DISABLED) &&
2651 (oTarget == oItem.element || Dom.isAncestor(oItem.element, oTarget))) {
2653 // Menu Item mouseover logic
2655 nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2656 bShowDelay = (nShowDelay > 0);
2661 this._cancelShowDelay();
2666 oActiveItem = this.activeItem;
2670 oActiveItem.cfg.setProperty(_SELECTED, false);
2675 oItemCfg = oItem.cfg;
2677 // Select and focus the current menu item
2679 oItemCfg.setProperty(_SELECTED, true);
2682 if (this.hasFocus() || oRoot._hasFocus) {
2686 oRoot._hasFocus = false;
2691 if (this.cfg.getProperty(_AUTO_SUBMENU_DISPLAY)) {
2693 // Show the submenu this menu item
2695 oSubmenu = oItemCfg.getProperty(_SUBMENU);
2701 oRoot._showDelayTimer =
2702 Lang.later(oRoot.cfg.getProperty(_SHOW_DELAY), oSubmenu, showSubmenu);
2715 oItem.handledMouseOverEvent = true;
2716 oItem.handledMouseOutEvent = false;
2726 * @method _onMouseOut
2727 * @description "mouseout" event handler for the menu.
2729 * @param {String} p_sType String representing the name of the event that
2731 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2733 _onMouseOut: function (p_sType, p_aArgs) {
2735 var oEvent = p_aArgs[0],
2737 oRelatedTarget = Event.getRelatedTarget(oEvent),
2738 bMovingToSubmenu = false,
2745 if (!this._bStopMouseEventHandlers) {
2747 if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
2749 oItemCfg = oItem.cfg;
2750 oSubmenu = oItemCfg.getProperty(_SUBMENU);
2753 if (oSubmenu && (oRelatedTarget == oSubmenu.element ||
2754 Dom.isAncestor(oSubmenu.element, oRelatedTarget))) {
2756 bMovingToSubmenu = true;
2761 if (!oItem.handledMouseOutEvent && ((oRelatedTarget != oItem.element &&
2762 !Dom.isAncestor(oItem.element, oRelatedTarget)) || bMovingToSubmenu)) {
2764 // Menu Item mouseout logic
2766 if (!bMovingToSubmenu) {
2768 oItem.cfg.setProperty(_SELECTED, false);
2773 nSubmenuHideDelay = this.cfg.getProperty(_SUBMENU_HIDE_DELAY);
2775 nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
2777 if (!(this instanceof YAHOO.widget.MenuBar) && nSubmenuHideDelay > 0 &&
2778 nShowDelay >= nSubmenuHideDelay) {
2780 this._execSubmenuHideDelay(oSubmenu, Event.getPageX(oEvent),
2795 oItem.handledMouseOutEvent = true;
2796 oItem.handledMouseOverEvent = false;
2803 if (!this._bHandledMouseOutEvent && ((oRelatedTarget != this.element &&
2804 !Dom.isAncestor(this.element, oRelatedTarget)) || bMovingToSubmenu)) {
2806 // Menu mouseout logic
2808 if (this._useHideDelay) {
2809 this._execHideDelay();
2812 Event.removeListener(this.element, _MOUSEMOVE, this._onMouseMove);
2814 this._nCurrentMouseX = Event.getPageX(oEvent);
2816 this._bHandledMouseOutEvent = true;
2817 this._bHandledMouseOverEvent = false;
2827 * @method _onMouseMove
2828 * @description "click" event handler for the menu.
2830 * @param {Event} p_oEvent Object representing the DOM event object passed
2831 * back by the event utility (YAHOO.util.Event).
2832 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
2835 _onMouseMove: function (p_oEvent, p_oMenu) {
2837 if (!this._bStopMouseEventHandlers) {
2839 this._nCurrentMouseX = Event.getPageX(p_oEvent);
2848 * @description "click" event handler for the menu.
2850 * @param {String} p_sType String representing the name of the event that
2852 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2854 _onClick: function (p_sType, p_aArgs) {
2856 var oEvent = p_aArgs[0],
2858 bInMenuAnchor = false,
2868 var hide = function () {
2871 There is an inconsistency between Firefox for Mac OS X and Firefox Windows
2872 regarding the triggering of the display of the browser's context menu and the
2873 subsequent firing of the "click" event. In Firefox for Windows, when the user
2874 triggers the display of the browser's context menu the "click" event also fires
2875 for the document object, even though the "click" event did not fire for the
2876 element that was the original target of the "contextmenu" event. This is unique
2877 to Firefox on Windows. For all other A-Grade browsers, including Firefox for
2878 Mac OS X, the "click" event doesn't fire for the document object.
2880 This bug in Firefox for Windows affects Menu as Menu instances listen for
2881 events at the document level and have an internal "click" event handler they
2882 use to hide themselves when clicked. As a result, in Firefox for Windows a
2883 Menu will hide when the user right clicks on a MenuItem to raise the browser's
2884 default context menu, because its internal "click" event handler ends up
2885 getting called. The following line fixes this bug.
2888 if (!((UA.gecko && this.platform == _WINDOWS) && oEvent.button > 0)) {
2890 oRoot = this.getRoot();
2892 if (oRoot instanceof YAHOO.widget.MenuBar ||
2893 oRoot.cfg.getProperty(_POSITION) == _STATIC) {
2895 oRoot.clearActiveItem();
2911 if (oItem.cfg.getProperty(_DISABLED)) {
2913 Event.preventDefault(oEvent);
2920 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
2924 Check if the URL of the anchor is pointing to an element that is
2925 a child of the menu.
2928 sURL = oItem.cfg.getProperty(_URL);
2933 nHashPos = sURL.indexOf(_HASH);
2938 if (nHashPos != -1) {
2940 sURL = sURL.substr(nHashPos, nLen);
2947 sId = sURL.substr(1, nLen);
2949 oMenu = YAHOO.widget.MenuManager.getMenu(sId);
2954 (this.getRoot() === oMenu.getRoot());
2959 else if (nLen === 1) {
2961 bInMenuAnchor = true;
2970 if (bInMenuAnchor && !oItem.cfg.getProperty(_TARGET)) {
2972 Event.preventDefault(oEvent);
2982 oItem.focusEvent.fire();
2989 if (!oSubmenu && !this.cfg.getProperty(_KEEP_OPEN)) {
3003 * @method _onKeyDown
3004 * @description "keydown" event handler for the menu.
3006 * @param {String} p_sType String representing the name of the event that
3008 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3010 _onKeyDown: function (p_sType, p_aArgs) {
3012 var oEvent = p_aArgs[0],
3029 if (this._useHideDelay) {
3030 this._cancelHideDelay();
3035 This function is called to prevent a bug in Firefox. In Firefox,
3036 moving a DOM element into a stationary mouse pointer will cause the
3037 browser to fire mouse events. This can result in the menu mouse
3038 event handlers being called uncessarily, especially when menus are
3039 moved into a stationary mouse pointer as a result of a
3042 function stopMouseEventHandlers() {
3044 this._bStopMouseEventHandlers = true;
3046 Lang.later(10, this, function () {
3048 this._bStopMouseEventHandlers = false;
3055 if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
3057 oItemCfg = oItem.cfg;
3058 oParentItem = this.parent;
3060 switch(oEvent.keyCode) {
3062 case 38: // Up arrow
3063 case 40: // Down arrow
3065 oNextItem = (oEvent.keyCode == 38) ?
3066 oItem.getPreviousEnabledSibling() :
3067 oItem.getNextEnabledSibling();
3071 this.clearActiveItem();
3073 oNextItem.cfg.setProperty(_SELECTED, true);
3077 if (this.cfg.getProperty(_MAX_HEIGHT) > 0) {
3080 nBodyScrollTop = oBody.scrollTop;
3081 nBodyOffsetHeight = oBody.offsetHeight;
3082 aItems = this.getItems();
3083 nItems = aItems.length - 1;
3084 nNextItemOffsetTop = oNextItem.element.offsetTop;
3087 if (oEvent.keyCode == 40 ) { // Down
3089 if (nNextItemOffsetTop >= (nBodyOffsetHeight + nBodyScrollTop)) {
3091 oBody.scrollTop = nNextItemOffsetTop - nBodyOffsetHeight;
3094 else if (nNextItemOffsetTop <= nBodyScrollTop) {
3096 oBody.scrollTop = 0;
3101 if (oNextItem == aItems[nItems]) {
3103 oBody.scrollTop = oNextItem.element.offsetTop;
3110 if (nNextItemOffsetTop <= nBodyScrollTop) {
3112 oBody.scrollTop = nNextItemOffsetTop - oNextItem.element.offsetHeight;
3115 else if (nNextItemOffsetTop >= (nBodyScrollTop + nBodyOffsetHeight)) {
3117 oBody.scrollTop = nNextItemOffsetTop;
3122 if (oNextItem == aItems[0]) {
3124 oBody.scrollTop = 0;
3131 nBodyScrollTop = oBody.scrollTop;
3132 nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3134 if (nBodyScrollTop === 0) {
3136 this._disableScrollHeader();
3137 this._enableScrollFooter();
3140 else if (nBodyScrollTop == nScrollTarget) {
3142 this._enableScrollHeader();
3143 this._disableScrollFooter();
3148 this._enableScrollHeader();
3149 this._enableScrollFooter();
3158 Event.preventDefault(oEvent);
3160 stopMouseEventHandlers();
3165 case 39: // Right arrow
3167 oSubmenu = oItemCfg.getProperty(_SUBMENU);
3171 if (!oItemCfg.getProperty(_SELECTED)) {
3173 oItemCfg.setProperty(_SELECTED, true);
3178 oSubmenu.setInitialFocus();
3179 oSubmenu.setInitialSelection();
3184 oRoot = this.getRoot();
3186 if (oRoot instanceof YAHOO.widget.MenuBar) {
3188 oNextItem = oRoot.activeItem.getNextEnabledSibling();
3192 oRoot.clearActiveItem();
3194 oNextItem.cfg.setProperty(_SELECTED, true);
3196 oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3201 oSubmenu.setInitialFocus();
3217 Event.preventDefault(oEvent);
3219 stopMouseEventHandlers();
3224 case 37: // Left arrow
3228 oParentMenu = oParentItem.parent;
3230 if (oParentMenu instanceof YAHOO.widget.MenuBar) {
3233 oParentMenu.activeItem.getPreviousEnabledSibling();
3237 oParentMenu.clearActiveItem();
3239 oNextItem.cfg.setProperty(_SELECTED, true);
3241 oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
3246 oSubmenu.setInitialFocus();
3262 oParentItem.focus();
3268 Event.preventDefault(oEvent);
3270 stopMouseEventHandlers();
3280 if (oEvent.keyCode == 27) { // Esc key
3282 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3288 this.parent.focus();
3293 else if (this.activeItem) {
3295 oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
3297 if (oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
3300 this.activeItem.focus();
3305 this.activeItem.blur();
3306 this.activeItem.cfg.setProperty(_SELECTED, false);
3313 Event.preventDefault(oEvent);
3321 * @method _onKeyPress
3322 * @description "keypress" event handler for a Menu instance.
3324 * @param {String} p_sType The name of the event that was fired.
3325 * @param {Array} p_aArgs Collection of arguments sent when the event
3328 _onKeyPress: function (p_sType, p_aArgs) {
3330 var oEvent = p_aArgs[0];
3333 if (oEvent.keyCode == 40 || oEvent.keyCode == 38) {
3335 Event.preventDefault(oEvent);
3344 * @description "blur" event handler for a Menu instance.
3346 * @param {String} p_sType The name of the event that was fired.
3347 * @param {Array} p_aArgs Collection of arguments sent when the event
3350 _onBlur: function (p_sType, p_aArgs) {
3352 if (this._hasFocus) {
3353 this._hasFocus = false;
3359 * @method _onYChange
3360 * @description "y" event handler for a Menu instance.
3362 * @param {String} p_sType The name of the event that was fired.
3363 * @param {Array} p_aArgs Collection of arguments sent when the event
3366 _onYChange: function (p_sType, p_aArgs) {
3368 var oParent = this.parent,
3376 nScrollTop = oParent.parent.body.scrollTop;
3379 if (nScrollTop > 0) {
3381 nY = (this.cfg.getProperty(_Y) - nScrollTop);
3383 Dom.setY(this.element, nY);
3385 oIFrame = this.iframe;
3390 Dom.setY(oIFrame, nY);
3394 this.cfg.setProperty(_Y, nY, true);
3404 * @method _onScrollTargetMouseOver
3405 * @description "mouseover" event handler for the menu's "header" and "footer"
3406 * elements. Used to scroll the body of the menu up and down when the
3407 * menu's "maxheight" configuration property is set to a value greater than 0.
3409 * @param {Event} p_oEvent Object representing the DOM event object passed
3410 * back by the event utility (YAHOO.util.Event).
3411 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
3414 _onScrollTargetMouseOver: function (p_oEvent, p_oMenu) {
3416 var oBodyScrollTimer = this._bodyScrollTimer;
3419 if (oBodyScrollTimer) {
3421 oBodyScrollTimer.cancel();
3426 this._cancelHideDelay();
3429 var oTarget = Event.getTarget(p_oEvent),
3431 nScrollIncrement = this.cfg.getProperty(_SCROLL_INCREMENT),
3436 function scrollBodyDown() {
3438 var nScrollTop = oBody.scrollTop;
3441 if (nScrollTop < nScrollTarget) {
3443 oBody.scrollTop = (nScrollTop + nScrollIncrement);
3445 this._enableScrollHeader();
3450 oBody.scrollTop = nScrollTarget;
3452 this._bodyScrollTimer.cancel();
3454 this._disableScrollFooter();
3461 function scrollBodyUp() {
3463 var nScrollTop = oBody.scrollTop;
3466 if (nScrollTop > 0) {
3468 oBody.scrollTop = (nScrollTop - nScrollIncrement);
3470 this._enableScrollFooter();
3475 oBody.scrollTop = 0;
3477 this._bodyScrollTimer.cancel();
3479 this._disableScrollHeader();
3486 if (Dom.hasClass(oTarget, _HD)) {
3488 fnScrollFunction = scrollBodyUp;
3493 nScrollTarget = oBody.scrollHeight - oBody.offsetHeight;
3495 fnScrollFunction = scrollBodyDown;
3500 this._bodyScrollTimer = Lang.later(10, this, fnScrollFunction, null, true);
3506 * @method _onScrollTargetMouseOut
3507 * @description "mouseout" event handler for the menu's "header" and "footer"
3508 * elements. Used to stop scrolling the body of the menu up and down when the
3509 * menu's "maxheight" configuration property is set to a value greater than 0.
3511 * @param {Event} p_oEvent Object representing the DOM event object passed
3512 * back by the event utility (YAHOO.util.Event).
3513 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
3516 _onScrollTargetMouseOut: function (p_oEvent, p_oMenu) {
3518 var oBodyScrollTimer = this._bodyScrollTimer;
3520 if (oBodyScrollTimer) {
3522 oBodyScrollTimer.cancel();
3526 this._cancelHideDelay();
3537 * @description "init" event handler for the menu.
3539 * @param {String} p_sType String representing the name of the event that
3541 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3543 _onInit: function (p_sType, p_aArgs) {
3545 this.cfg.subscribeToConfigEvent(_VISIBLE, this._onVisibleChange);
3547 var bRootMenu = !this.parent,
3548 bLazyLoad = this.lazyLoad;
3552 Automatically initialize a menu's subtree if:
3554 1) This is the root menu and lazyload is off
3556 2) This is the root menu, lazyload is on, but the menu is
3559 3) This menu is a submenu and lazyload is off
3564 if (((bRootMenu && !bLazyLoad) ||
3565 (bRootMenu && (this.cfg.getProperty(_VISIBLE) ||
3566 this.cfg.getProperty(_POSITION) == _STATIC)) ||
3567 (!bRootMenu && !bLazyLoad)) && this.getItemGroups().length === 0) {
3569 if (this.srcElement) {
3571 this._initSubTree();
3576 if (this.itemData) {
3578 this.addItems(this.itemData);
3583 else if (bLazyLoad) {
3585 this.cfg.fireQueue();
3593 * @method _onBeforeRender
3594 * @description "beforerender" event handler for the menu. Appends all of the
3595 * <code><ul></code>, <code><li></code> and their accompanying
3596 * title elements to the body element of the menu.
3598 * @param {String} p_sType String representing the name of the event that
3600 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3602 _onBeforeRender: function (p_sType, p_aArgs) {
3604 var oEl = this.element,
3605 nListElements = this._aListElements.length,
3611 if (nListElements > 0) {
3615 oUL = this._aListElements[i];
3621 Dom.addClass(oUL, _FIRST_OF_TYPE);
3627 if (!Dom.isAncestor(oEl, oUL)) {
3629 this.appendToBody(oUL);
3634 oGroupTitle = this._aGroupTitleElements[i];
3638 if (!Dom.isAncestor(oEl, oGroupTitle)) {
3640 oUL.parentNode.insertBefore(oGroupTitle, oUL);
3645 Dom.addClass(oUL, _HAS_TITLE);
3654 while (i < nListElements);
3663 * @description "render" event handler for the menu.
3665 * @param {String} p_sType String representing the name of the event that
3667 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3669 _onRender: function (p_sType, p_aArgs) {
3671 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3673 if (!this.cfg.getProperty(_VISIBLE)) {
3675 this.positionOffScreen();
3688 * @method _onBeforeShow
3689 * @description "beforeshow" event handler for the menu.
3691 * @param {String} p_sType String representing the name of the event that
3693 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3695 _onBeforeShow: function (p_sType, p_aArgs) {
3700 oContainer = this.cfg.getProperty(_CONTAINER);
3703 if (this.lazyLoad && this.getItemGroups().length === 0) {
3705 if (this.srcElement) {
3707 this._initSubTree();
3712 if (this.itemData) {
3714 if (this.parent && this.parent.parent &&
3715 this.parent.parent.srcElement &&
3716 this.parent.parent.srcElement.tagName.toUpperCase() ==
3719 nOptions = this.itemData.length;
3721 for(n=0; n<nOptions; n++) {
3723 if (this.itemData[n].tagName) {
3725 this.addItem((new this.ITEM_TYPE(this.itemData[n])));
3734 this.addItems(this.itemData);
3741 oSrcElement = this.srcElement;
3745 if (oSrcElement.tagName.toUpperCase() == _SELECT) {
3747 if (Dom.inDocument(oSrcElement)) {
3749 this.render(oSrcElement.parentNode);
3754 this.render(oContainer);
3770 this.render(this.parent.element);
3775 this.render(oContainer);
3785 var oParent = this.parent,
3789 if (!oParent && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
3791 this.cfg.refireEvent(_XY);
3798 aAlignment = oParent.parent.cfg.getProperty(_SUBMENU_ALIGNMENT);
3800 this.cfg.setProperty(_CONTEXT, [oParent.element, aAlignment[0], aAlignment[1]]);
3808 getConstrainedY: function (y) {
3812 aContext = oMenu.cfg.getProperty(_CONTEXT),
3813 nInitialMaxHeight = oMenu.cfg.getProperty(_MAX_HEIGHT),
3817 oOverlapPositions = {
3826 bPotentialContextOverlap = (aContext && oOverlapPositions[aContext[1] + aContext[2]]),
3828 oMenuEl = oMenu.element,
3829 nMenuOffsetHeight = oMenuEl.offsetHeight,
3831 nViewportOffset = Overlay.VIEWPORT_OFFSET,
3832 viewPortHeight = Dom.getViewportHeight(),
3833 scrollY = Dom.getDocumentScrollTop(),
3836 (oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) + nViewportOffset < viewPortHeight),
3847 nBottomRegionHeight,
3849 topConstraint = scrollY + nViewportOffset,
3850 bottomConstraint = scrollY + viewPortHeight - nMenuOffsetHeight - nViewportOffset,
3855 var flipVertical = function () {
3859 // The Menu is below the context element, flip it above
3860 if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3861 nNewY = (nContextElY - nMenuOffsetHeight);
3863 else { // The Menu is above the context element, flip it below
3864 nNewY = (nContextElY + nContextElHeight);
3867 oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3875 Uses the context element's position to calculate the availble height
3876 above and below it to display its corresponding Menu.
3879 var getDisplayRegionHeight = function () {
3881 // The Menu is below the context element
3882 if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3883 return (nBottomRegionHeight - nViewportOffset);
3885 else { // The Menu is above the context element
3886 return (nTopRegionHeight - nViewportOffset);
3893 Sets the Menu's "y" configuration property to the correct value based on its
3894 current orientation.
3897 var alignY = function () {
3901 if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
3902 nNewY = (nContextElY + nContextElHeight);
3905 nNewY = (nContextElY - oMenuEl.offsetHeight);
3908 oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
3913 // Resets the maxheight of the Menu to the value set by the user
3915 var resetMaxHeight = function () {
3917 oMenu._setScrollHeight(this.cfg.getProperty(_MAX_HEIGHT));
3919 oMenu.hideEvent.unsubscribe(resetMaxHeight);
3925 Trys to place the Menu in the best possible position (either above or
3926 below its corresponding context element).
3929 var setVerticalPosition = function () {
3931 var nDisplayRegionHeight = getDisplayRegionHeight(),
3932 bMenuHasItems = (oMenu.getItems().length > 0),
3933 nMenuMinScrollHeight,
3937 if (nMenuOffsetHeight > nDisplayRegionHeight) {
3939 nMenuMinScrollHeight =
3940 bMenuHasItems ? oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) : nMenuOffsetHeight;
3943 if ((nDisplayRegionHeight > nMenuMinScrollHeight) && bMenuHasItems) {
3944 nMaxHeight = nDisplayRegionHeight;
3947 nMaxHeight = nInitialMaxHeight;
3951 oMenu._setScrollHeight(nMaxHeight);
3952 oMenu.hideEvent.subscribe(resetMaxHeight);
3955 // Re-align the Menu since its height has just changed
3956 // as a result of the setting of the maxheight property.
3961 if (nDisplayRegionHeight < nMenuMinScrollHeight) {
3966 All possible positions and values for the "maxheight"
3967 configuration property have been tried, but none were
3968 successful, so fall back to the original size and position.
3980 fnReturnVal = setVerticalPosition();
3987 else if (nMaxHeight && (nMaxHeight !== nInitialMaxHeight)) {
3989 oMenu._setScrollHeight(nInitialMaxHeight);
3990 oMenu.hideEvent.subscribe(resetMaxHeight);
3992 // Re-align the Menu since its height has just changed
3993 // as a result of the setting of the maxheight property.
4004 // Determine if the current value for the Menu's "y" configuration property will
4005 // result in the Menu being positioned outside the boundaries of the viewport
4007 if (y < topConstraint || y > bottomConstraint) {
4009 // The current value for the Menu's "y" configuration property WILL
4010 // result in the Menu being positioned outside the boundaries of the viewport
4012 if (bCanConstrain) {
4014 if (oMenu.cfg.getProperty(_PREVENT_CONTEXT_OVERLAP) && bPotentialContextOverlap) {
4017 // If the "preventcontextoverlap" configuration property is set to "true",
4018 // try to flip and/or scroll the Menu to both keep it inside the boundaries of the
4019 // viewport AND from overlaping its context element (MenuItem or MenuBarItem).
4021 oContextEl = aContext[0];
4022 nContextElHeight = oContextEl.offsetHeight;
4023 nContextElY = (Dom.getY(oContextEl) - scrollY);
4025 nTopRegionHeight = nContextElY;
4026 nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
4028 setVerticalPosition();
4030 yNew = oMenu.cfg.getProperty(_Y);
4033 else if (!(oMenu instanceof YAHOO.widget.MenuBar) &&
4034 nMenuOffsetHeight >= viewPortHeight) {
4037 // If the Menu exceeds the height of the viewport, introduce scroll bars
4038 // to keep the Menu inside the boundaries of the viewport
4040 nAvailableHeight = (viewPortHeight - (nViewportOffset * 2));
4042 if (nAvailableHeight > oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT)) {
4044 oMenu._setScrollHeight(nAvailableHeight);
4045 oMenu.hideEvent.subscribe(resetMaxHeight);
4049 yNew = oMenu.cfg.getProperty(_Y);
4058 if (y < topConstraint) {
4059 yNew = topConstraint;
4060 } else if (y > bottomConstraint) {
4061 yNew = bottomConstraint;
4068 // The "y" configuration property cannot be set to a value that will keep
4069 // entire Menu inside the boundary of the viewport. Therefore, set
4070 // the "y" configuration property to scrollY to keep as much of the
4071 // Menu inside the viewport as possible.
4072 yNew = nViewportOffset + scrollY;
4084 * @description "hide" event handler for the menu.
4086 * @param {String} p_sType String representing the name of the event that
4088 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4090 _onHide: function (p_sType, p_aArgs) {
4092 if (this.cfg.getProperty(_POSITION) === _DYNAMIC) {
4094 this.positionOffScreen();
4103 * @description "show" event handler for the menu.
4105 * @param {String} p_sType String representing the name of the event that
4107 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4109 _onShow: function (p_sType, p_aArgs) {
4111 var oParent = this.parent,
4118 function disableAutoSubmenuDisplay(p_oEvent) {
4122 if (p_oEvent.type == _MOUSEDOWN || (p_oEvent.type == _KEYDOWN && p_oEvent.keyCode == 27)) {
4125 Set the "autosubmenudisplay" to "false" if the user
4126 clicks outside the menu bar.
4129 oTarget = Event.getTarget(p_oEvent);
4131 if (oTarget != oParentMenu.element || !Dom.isAncestor(oParentMenu.element, oTarget)) {
4133 oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
4135 Event.removeListener(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
4136 Event.removeListener(document, _KEYDOWN, disableAutoSubmenuDisplay);
4145 function onSubmenuHide(p_sType, p_aArgs, p_sWidth) {
4147 this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4148 this.hideEvent.unsubscribe(onSubmenuHide, p_sWidth);
4155 oParentMenu = oParent.parent;
4158 if (!oParentMenu.cfg.getProperty(_AUTO_SUBMENU_DISPLAY) &&
4159 (oParentMenu instanceof YAHOO.widget.MenuBar ||
4160 oParentMenu.cfg.getProperty(_POSITION) == _STATIC)) {
4162 oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, true);
4164 Event.on(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
4165 Event.on(document, _KEYDOWN, disableAutoSubmenuDisplay);
4170 // The following fixes an issue with the selected state of a MenuItem
4171 // not rendering correctly when a submenu is aligned to the left of
4172 // its parent Menu instance.
4174 if ((this.cfg.getProperty("x") < oParentMenu.cfg.getProperty("x")) &&
4175 (UA.gecko && UA.gecko < 1.9) && !this.cfg.getProperty(_WIDTH)) {
4177 oElement = this.element;
4178 nOffsetWidth = oElement.offsetWidth;
4181 Measuring the difference of the offsetWidth before and after
4182 setting the "width" style attribute allows us to compute the
4183 about of padding and borders applied to the element, which in
4184 turn allows us to set the "width" property correctly.
4187 oElement.style.width = nOffsetWidth + _PX;
4189 sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4191 this.cfg.setProperty(_WIDTH, sWidth);
4193 this.hideEvent.subscribe(onSubmenuHide, sWidth);
4203 * @method _onBeforeHide
4204 * @description "beforehide" event handler for the menu.
4206 * @param {String} p_sType String representing the name of the event that
4208 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4210 _onBeforeHide: function (p_sType, p_aArgs) {
4212 var oActiveItem = this.activeItem,
4213 oRoot = this.getRoot(),
4220 oConfig = oActiveItem.cfg;
4222 oConfig.setProperty(_SELECTED, false);
4224 oSubmenu = oConfig.getProperty(_SUBMENU);
4236 Focus can get lost in IE when the mouse is moving from a submenu back to its parent Menu.
4237 For this reason, it is necessary to maintain the focused state in a private property
4238 so that the _onMouseOver event handler is able to determined whether or not to set focus
4239 to MenuItems as the user is moving the mouse.
4242 if (UA.ie && this.cfg.getProperty(_POSITION) === _DYNAMIC && this.parent) {
4244 oRoot._hasFocus = this.hasFocus();
4249 if (oRoot == this) {
4259 * @method _onParentMenuConfigChange
4260 * @description "configchange" event handler for a submenu.
4262 * @param {String} p_sType String representing the name of the event that
4264 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4265 * @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that
4266 * subscribed to the event.
4268 _onParentMenuConfigChange: function (p_sType, p_aArgs, p_oSubmenu) {
4270 var sPropertyName = p_aArgs[0][0],
4271 oPropertyValue = p_aArgs[0][1];
4273 switch(sPropertyName) {
4276 case _CONSTRAIN_TO_VIEWPORT:
4279 case _SUBMENU_HIDE_DELAY:
4280 case _CLICK_TO_HIDE:
4283 case _SCROLL_INCREMENT:
4285 case _MIN_SCROLL_HEIGHT:
4286 case _MONITOR_RESIZE:
4288 case _PREVENT_CONTEXT_OVERLAP:
4290 p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4294 case _SUBMENU_ALIGNMENT:
4296 if (!(this.parent.parent instanceof YAHOO.widget.MenuBar)) {
4298 p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
4310 * @method _onParentMenuRender
4311 * @description "render" event handler for a submenu. Renders a
4312 * submenu in response to the firing of its parent's "render" event.
4314 * @param {String} p_sType String representing the name of the event that
4316 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4317 * @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that
4318 * subscribed to the event.
4320 _onParentMenuRender: function (p_sType, p_aArgs, p_oSubmenu) {
4322 var oParentMenu = p_oSubmenu.parent.parent,
4323 oParentCfg = oParentMenu.cfg,
4327 constraintoviewport: oParentCfg.getProperty(_CONSTRAIN_TO_VIEWPORT),
4331 clicktohide: oParentCfg.getProperty(_CLICK_TO_HIDE),
4333 effect: oParentCfg.getProperty(_EFFECT),
4335 showdelay: oParentCfg.getProperty(_SHOW_DELAY),
4337 hidedelay: oParentCfg.getProperty(_HIDE_DELAY),
4339 submenuhidedelay: oParentCfg.getProperty(_SUBMENU_HIDE_DELAY),
4341 classname: oParentCfg.getProperty(_CLASSNAME),
4343 scrollincrement: oParentCfg.getProperty(_SCROLL_INCREMENT),
4345 maxheight: oParentCfg.getProperty(_MAX_HEIGHT),
4347 minscrollheight: oParentCfg.getProperty(_MIN_SCROLL_HEIGHT),
4349 iframe: oParentCfg.getProperty(_IFRAME),
4351 shadow: oParentCfg.getProperty(_SHADOW),
4353 preventcontextoverlap: oParentCfg.getProperty(_PREVENT_CONTEXT_OVERLAP),
4355 monitorresize: oParentCfg.getProperty(_MONITOR_RESIZE)
4363 if (!(oParentMenu instanceof YAHOO.widget.MenuBar)) {
4365 oConfig[_SUBMENU_ALIGNMENT] = oParentCfg.getProperty(_SUBMENU_ALIGNMENT);
4370 p_oSubmenu.cfg.applyConfig(oConfig);
4373 if (!this.lazyLoad) {
4375 oLI = this.parent.element;
4377 if (this.element.parentNode == oLI) {
4394 * @method _onMenuItemDestroy
4395 * @description "destroy" event handler for the menu's items.
4397 * @param {String} p_sType String representing the name of the event
4399 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4400 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
4401 * that fired the event.
4403 _onMenuItemDestroy: function (p_sType, p_aArgs, p_oItem) {
4405 this._removeItemFromGroupByValue(p_oItem.groupIndex, p_oItem);
4411 * @method _onMenuItemConfigChange
4412 * @description "configchange" event handler for the menu's items.
4414 * @param {String} p_sType String representing the name of the event that
4416 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4417 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
4418 * that fired the event.
4420 _onMenuItemConfigChange: function (p_sType, p_aArgs, p_oItem) {
4422 var sPropertyName = p_aArgs[0][0],
4423 oPropertyValue = p_aArgs[0][1],
4427 switch(sPropertyName) {
4431 if (oPropertyValue === true) {
4433 this.activeItem = p_oItem;
4441 oSubmenu = p_aArgs[0][1];
4445 this._configureSubmenu(p_oItem);
4457 // Public event handlers for configuration properties
4461 * @method configVisible
4462 * @description Event handler for when the "visible" configuration property
4464 * @param {String} p_sType String representing the name of the event that
4466 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4467 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4470 configVisible: function (p_sType, p_aArgs, p_oMenu) {
4475 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4477 Menu.superclass.configVisible.call(this, p_sType, p_aArgs, p_oMenu);
4482 bVisible = p_aArgs[0];
4483 sDisplay = Dom.getStyle(this.element, _DISPLAY);
4485 Dom.setStyle(this.element, _VISIBILITY, _VISIBLE);
4489 if (sDisplay != _BLOCK) {
4490 this.beforeShowEvent.fire();
4491 Dom.setStyle(this.element, _DISPLAY, _BLOCK);
4492 this.showEvent.fire();
4498 if (sDisplay == _BLOCK) {
4499 this.beforeHideEvent.fire();
4500 Dom.setStyle(this.element, _DISPLAY, _NONE);
4501 this.hideEvent.fire();
4512 * @method configPosition
4513 * @description Event handler for when the "position" configuration property
4514 * of the menu changes.
4515 * @param {String} p_sType String representing the name of the event that
4517 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4518 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4521 configPosition: function (p_sType, p_aArgs, p_oMenu) {
4523 var oElement = this.element,
4524 sCSSPosition = p_aArgs[0] == _STATIC ? _STATIC : _ABSOLUTE,
4529 Dom.setStyle(oElement, _POSITION, sCSSPosition);
4532 if (sCSSPosition == _STATIC) {
4534 // Statically positioned menus are visible by default
4536 Dom.setStyle(oElement, _DISPLAY, _BLOCK);
4538 oCfg.setProperty(_VISIBLE, true);
4544 Even though the "visible" property is queued to
4545 "false" by default, we need to set the "visibility" property to
4546 "hidden" since Overlay's "configVisible" implementation checks the
4547 element's "visibility" style property before deciding whether
4548 or not to show an Overlay instance.
4551 Dom.setStyle(oElement, _VISIBILITY, _HIDDEN);
4556 if (sCSSPosition == _ABSOLUTE) {
4558 nZIndex = oCfg.getProperty(_ZINDEX);
4560 if (!nZIndex || nZIndex === 0) {
4562 oCfg.setProperty(_ZINDEX, 1);
4572 * @method configIframe
4573 * @description Event handler for when the "iframe" configuration property of
4575 * @param {String} p_sType String representing the name of the event that
4577 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4578 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4581 configIframe: function (p_sType, p_aArgs, p_oMenu) {
4583 if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
4585 Menu.superclass.configIframe.call(this, p_sType, p_aArgs, p_oMenu);
4593 * @method configHideDelay
4594 * @description Event handler for when the "hidedelay" configuration property
4595 * of the menu changes.
4596 * @param {String} p_sType String representing the name of the event that
4598 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4599 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4602 configHideDelay: function (p_sType, p_aArgs, p_oMenu) {
4604 var nHideDelay = p_aArgs[0];
4606 this._useHideDelay = (nHideDelay > 0);
4612 * @method configContainer
4613 * @description Event handler for when the "container" configuration property
4614 * of the menu changes.
4615 * @param {String} p_sType String representing the name of the event that
4617 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4618 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4621 configContainer: function (p_sType, p_aArgs, p_oMenu) {
4623 var oElement = p_aArgs[0];
4625 if (Lang.isString(oElement)) {
4627 this.cfg.setProperty(_CONTAINER, Dom.get(oElement), true);
4635 * @method _clearSetWidthFlag
4636 * @description Change event listener for the "width" configuration property. This listener is
4637 * added when a Menu's "width" configuration property is set by the "_setScrollHeight" method, and
4638 * is used to set the "_widthSetForScroll" property to "false" if the "width" configuration property
4639 * is changed after it was set by the "_setScrollHeight" method. If the "_widthSetForScroll"
4640 * property is set to "false", and the "_setScrollHeight" method is in the process of tearing down
4641 * scrolling functionality, it will maintain the Menu's new width rather than reseting it.
4644 _clearSetWidthFlag: function () {
4646 this._widthSetForScroll = false;
4648 this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4654 * @method _setScrollHeight
4656 * @param {String} p_nScrollHeight Number representing the scrolling height of the Menu.
4659 _setScrollHeight: function (p_nScrollHeight) {
4661 var nScrollHeight = p_nScrollHeight,
4662 bRefireIFrameAndShadow = false,
4676 if (this.getItems().length > 0) {
4678 oElement = this.element;
4680 oHeader = this.header;
4681 oFooter = this.footer;
4682 fnMouseOver = this._onScrollTargetMouseOver;
4683 fnMouseOut = this._onScrollTargetMouseOut;
4684 nMinScrollHeight = this.cfg.getProperty(_MIN_SCROLL_HEIGHT);
4687 if (nScrollHeight > 0 && nScrollHeight < nMinScrollHeight) {
4689 nScrollHeight = nMinScrollHeight;
4694 Dom.setStyle(oBody, _HEIGHT, _EMPTY_STRING);
4695 Dom.removeClass(oBody, _YUI_MENU_BODY_SCROLLED);
4696 oBody.scrollTop = 0;
4699 // Need to set a width for the Menu to fix the following problems in
4700 // Firefox 2 and IE:
4702 // #1) Scrolled Menus will render at 1px wide in Firefox 2
4704 // #2) There is a bug in gecko-based browsers where an element whose
4705 // "position" property is set to "absolute" and "overflow" property is
4706 // set to "hidden" will not render at the correct width when its
4707 // offsetParent's "position" property is also set to "absolute." It is
4708 // possible to work around this bug by specifying a value for the width
4709 // property in addition to overflow.
4711 // #3) In IE it is necessary to give the Menu a width before the
4712 // scrollbars are rendered to prevent the Menu from rendering with a
4713 // width that is 100% of the browser viewport.
4715 bSetWidth = ((UA.gecko && UA.gecko < 1.9) || UA.ie);
4717 if (nScrollHeight > 0 && bSetWidth && !this.cfg.getProperty(_WIDTH)) {
4719 nOffsetWidth = oElement.offsetWidth;
4722 Measuring the difference of the offsetWidth before and after
4723 setting the "width" style attribute allows us to compute the
4724 about of padding and borders applied to the element, which in
4725 turn allows us to set the "width" property correctly.
4728 oElement.style.width = nOffsetWidth + _PX;
4730 sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
4733 this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4736 this.cfg.setProperty(_WIDTH, sWidth);
4740 Set a flag (_widthSetForScroll) to maintain some history regarding how the
4741 "width" configuration property was set. If the "width" configuration property
4742 is set by something other than the "_setScrollHeight" method, it will be
4743 necessary to maintain that new value and not clear the width if scrolling
4747 this._widthSetForScroll = true;
4749 this.cfg.subscribeToConfigEvent(_WIDTH, this._clearSetWidthFlag);
4754 if (nScrollHeight > 0 && (!oHeader && !oFooter)) {
4757 this.setHeader(_NON_BREAKING_SPACE);
4758 this.setFooter(_NON_BREAKING_SPACE);
4760 oHeader = this.header;
4761 oFooter = this.footer;
4763 Dom.addClass(oHeader, _TOP_SCROLLBAR);
4764 Dom.addClass(oFooter, _BOTTOM_SCROLLBAR);
4766 oElement.insertBefore(oHeader, oBody);
4767 oElement.appendChild(oFooter);
4772 nHeight = nScrollHeight;
4775 if (oHeader && oFooter) {
4776 nHeight = (nHeight - (oHeader.offsetHeight + oFooter.offsetHeight));
4780 if ((nHeight > 0) && (oBody.offsetHeight > nScrollHeight)) {
4783 Dom.addClass(oBody, _YUI_MENU_BODY_SCROLLED);
4784 Dom.setStyle(oBody, _HEIGHT, (nHeight + _PX));
4786 if (!this._hasScrollEventHandlers) {
4788 Event.on(oHeader, _MOUSEOVER, fnMouseOver, this, true);
4789 Event.on(oHeader, _MOUSEOUT, fnMouseOut, this, true);
4790 Event.on(oFooter, _MOUSEOVER, fnMouseOver, this, true);
4791 Event.on(oFooter, _MOUSEOUT, fnMouseOut, this, true);
4793 this._hasScrollEventHandlers = true;
4797 this._disableScrollHeader();
4798 this._enableScrollFooter();
4800 bRefireIFrameAndShadow = true;
4803 else if (oHeader && oFooter) {
4808 Only clear the the "width" configuration property if it was set the
4809 "_setScrollHeight" method and wasn't changed by some other means after it was set.
4812 if (this._widthSetForScroll) {
4815 this._widthSetForScroll = false;
4817 this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
4819 this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
4824 this._enableScrollHeader();
4825 this._enableScrollFooter();
4827 if (this._hasScrollEventHandlers) {
4829 Event.removeListener(oHeader, _MOUSEOVER, fnMouseOver);
4830 Event.removeListener(oHeader, _MOUSEOUT, fnMouseOut);
4831 Event.removeListener(oFooter, _MOUSEOVER, fnMouseOver);
4832 Event.removeListener(oFooter, _MOUSEOUT, fnMouseOut);
4834 this._hasScrollEventHandlers = false;
4838 oElement.removeChild(oHeader);
4839 oElement.removeChild(oFooter);
4844 bRefireIFrameAndShadow = true;
4849 if (bRefireIFrameAndShadow) {
4851 this.cfg.refireEvent(_IFRAME);
4852 this.cfg.refireEvent(_SHADOW);
4862 * @method _setMaxHeight
4863 * @description "renderEvent" handler used to defer the setting of the
4864 * "maxheight" configuration property until the menu is rendered in lazy
4866 * @param {String} p_sType The name of the event that was fired.
4867 * @param {Array} p_aArgs Collection of arguments sent when the event
4869 * @param {Number} p_nMaxHeight Number representing the value to set for the
4870 * "maxheight" configuration property.
4873 _setMaxHeight: function (p_sType, p_aArgs, p_nMaxHeight) {
4875 this._setScrollHeight(p_nMaxHeight);
4876 this.renderEvent.unsubscribe(this._setMaxHeight);
4882 * @method configMaxHeight
4883 * @description Event handler for when the "maxheight" configuration property of
4885 * @param {String} p_sType The name of the event that was fired.
4886 * @param {Array} p_aArgs Collection of arguments sent when the event
4888 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired
4891 configMaxHeight: function (p_sType, p_aArgs, p_oMenu) {
4893 var nMaxHeight = p_aArgs[0];
4895 if (this.lazyLoad && !this.body && nMaxHeight > 0) {
4897 this.renderEvent.subscribe(this._setMaxHeight, nMaxHeight, this);
4902 this._setScrollHeight(nMaxHeight);
4910 * @method configClassName
4911 * @description Event handler for when the "classname" configuration property of
4913 * @param {String} p_sType The name of the event that was fired.
4914 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4915 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4917 configClassName: function (p_sType, p_aArgs, p_oMenu) {
4919 var sClassName = p_aArgs[0];
4921 if (this._sClassName) {
4923 Dom.removeClass(this.element, this._sClassName);
4927 Dom.addClass(this.element, sClassName);
4928 this._sClassName = sClassName;
4934 * @method _onItemAdded
4935 * @description "itemadded" event handler for a Menu instance.
4937 * @param {String} p_sType The name of the event that was fired.
4938 * @param {Array} p_aArgs Collection of arguments sent when the event
4941 _onItemAdded: function (p_sType, p_aArgs) {
4943 var oItem = p_aArgs[0];
4947 oItem.cfg.setProperty(_DISABLED, true);
4955 * @method configDisabled
4956 * @description Event handler for when the "disabled" configuration property of
4958 * @param {String} p_sType The name of the event that was fired.
4959 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4960 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4962 configDisabled: function (p_sType, p_aArgs, p_oMenu) {
4964 var bDisabled = p_aArgs[0],
4965 aItems = this.getItems(),
4969 if (Lang.isArray(aItems)) {
4971 nItems = aItems.length;
4979 aItems[i].cfg.setProperty(_DISABLED, bDisabled);
4989 this.clearActiveItem(true);
4991 Dom.addClass(this.element, _DISABLED);
4993 this.itemAddedEvent.subscribe(this._onItemAdded);
4998 Dom.removeClass(this.element, _DISABLED);
5000 this.itemAddedEvent.unsubscribe(this._onItemAdded);
5010 * @method configShadow
5011 * @description Event handler for when the "shadow" configuration property of
5013 * @param {String} p_sType The name of the event that was fired.
5014 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
5015 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
5017 configShadow: function (p_sType, p_aArgs, p_oMenu) {
5019 var sizeShadow = function () {
5021 var oElement = this.element,
5022 oShadow = this._shadow;
5024 if (oShadow && oElement) {
5026 // Clear the previous width
5028 if (oShadow.style.width && oShadow.style.height) {
5030 oShadow.style.width = _EMPTY_STRING;
5031 oShadow.style.height = _EMPTY_STRING;
5035 oShadow.style.width = (oElement.offsetWidth + 6) + _PX;
5036 oShadow.style.height = (oElement.offsetHeight + 1) + _PX;
5043 var replaceShadow = function () {
5045 this.element.appendChild(this._shadow);
5050 var addShadowVisibleClass = function () {
5052 Dom.addClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5057 var removeShadowVisibleClass = function () {
5059 Dom.removeClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
5064 var createShadow = function () {
5066 var oShadow = this._shadow,
5071 oElement = this.element;
5074 if (!m_oShadowTemplate) {
5076 m_oShadowTemplate = document.createElement(_DIV_LOWERCASE);
5077 m_oShadowTemplate.className = _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE;
5081 oShadow = m_oShadowTemplate.cloneNode(false);
5083 oElement.appendChild(oShadow);
5085 this._shadow = oShadow;
5087 this.beforeShowEvent.subscribe(addShadowVisibleClass);
5088 this.beforeHideEvent.subscribe(removeShadowVisibleClass);
5094 Need to call sizeShadow & syncIframe via setTimeout for
5095 IE 7 Quirks Mode and IE 6 Standards Mode and Quirks Mode
5096 or the shadow and iframe shim will not be sized and
5097 positioned properly.
5100 Lang.later(0, this, function () {
5102 sizeShadow.call(this);
5108 this.cfg.subscribeToConfigEvent(_WIDTH, sizeShadow);
5109 this.cfg.subscribeToConfigEvent(_HEIGHT, sizeShadow);
5110 this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, sizeShadow);
5111 this.changeContentEvent.subscribe(sizeShadow);
5113 Module.textResizeEvent.subscribe(sizeShadow, this, true);
5115 this.destroyEvent.subscribe(function () {
5117 Module.textResizeEvent.unsubscribe(sizeShadow, this);
5123 this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, replaceShadow);
5130 var onBeforeShow = function () {
5134 // If called because the "shadow" event was refired - just append again and resize
5136 replaceShadow.call(this);
5139 sizeShadow.call(this);
5145 createShadow.call(this);
5149 this.beforeShowEvent.unsubscribe(onBeforeShow);
5154 var bShadow = p_aArgs[0];
5157 if (bShadow && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
5159 if (this.cfg.getProperty(_VISIBLE)) {
5163 // If the "shadow" event was refired - just append again and resize
5165 replaceShadow.call(this);
5168 sizeShadow.call(this);
5173 createShadow.call(this);
5179 this.beforeShowEvent.subscribe(onBeforeShow);
5193 * @method initEvents
5194 * @description Initializes the custom events for the menu.
5196 initEvents: function () {
5198 Menu.superclass.initEvents.call(this);
5200 // Create custom events
5202 var i = EVENT_TYPES.length - 1,
5209 aEventData = EVENT_TYPES[i];
5211 oCustomEvent = this.createEvent(aEventData[1]);
5212 oCustomEvent.signature = CustomEvent.LIST;
5214 this[aEventData[0]] = oCustomEvent;
5223 * @method positionOffScreen
5224 * @description Positions the menu outside of the boundaries of the browser's
5225 * viewport. Called automatically when a menu is hidden to ensure that
5226 * it doesn't force the browser to render uncessary scrollbars.
5228 positionOffScreen: function () {
5230 var oIFrame = this.iframe,
5231 oElement = this.element,
5232 sPos = this.OFF_SCREEN_POSITION;
5234 oElement.style.top = _EMPTY_STRING;
5235 oElement.style.left = _EMPTY_STRING;
5239 oIFrame.style.top = sPos;
5240 oIFrame.style.left = sPos;
5249 * @description Finds the menu's root menu.
5251 getRoot: function () {
5253 var oItem = this.parent,
5259 oParentMenu = oItem.parent;
5261 returnVal = oParentMenu ? oParentMenu.getRoot() : this;
5277 * @description Returns a string representing the menu.
5280 toString: function () {
5282 var sReturnVal = _MENU,
5287 sReturnVal += (_SPACE + sId);
5297 * @method setItemGroupTitle
5298 * @description Sets the title of a group of menu items.
5299 * @param {String} p_sGroupTitle String specifying the title of the group.
5300 * @param {Number} p_nGroupIndex Optional. Number specifying the group to which
5301 * the title belongs.
5303 setItemGroupTitle: function (p_sGroupTitle, p_nGroupIndex) {
5310 if (Lang.isString(p_sGroupTitle) && p_sGroupTitle.length > 0) {
5312 nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
5313 oTitle = this._aGroupTitleElements[nGroupIndex];
5318 oTitle.innerHTML = p_sGroupTitle;
5323 oTitle = document.createElement(this.GROUP_TITLE_TAG_NAME);
5325 oTitle.innerHTML = p_sGroupTitle;
5327 this._aGroupTitleElements[nGroupIndex] = oTitle;
5332 i = this._aGroupTitleElements.length - 1;
5336 if (this._aGroupTitleElements[i]) {
5338 Dom.removeClass(this._aGroupTitleElements[i], _FIRST_OF_TYPE);
5348 if (nFirstIndex !== null) {
5350 Dom.addClass(this._aGroupTitleElements[nFirstIndex],
5355 this.changeContentEvent.fire();
5365 * @description Appends an item to the menu.
5366 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
5367 * instance to be added to the menu.
5368 * @param {String} p_oItem String specifying the text of the item to be added
5370 * @param {Object} p_oItem Object literal containing a set of menu item
5371 * configuration properties.
5372 * @param {Number} p_nGroupIndex Optional. Number indicating the group to
5373 * which the item belongs.
5374 * @return {YAHOO.widget.MenuItem}
5376 addItem: function (p_oItem, p_nGroupIndex) {
5378 return this._addItemToGroup(p_nGroupIndex, p_oItem);
5385 * @description Adds an array of items to the menu.
5386 * @param {Array} p_aItems Array of items to be added to the menu. The array
5387 * can contain strings specifying the text for each item to be created, object
5388 * literals specifying each of the menu item configuration properties,
5389 * or MenuItem instances.
5390 * @param {Number} p_nGroupIndex Optional. Number specifying the group to
5391 * which the items belongs.
5394 addItems: function (p_aItems, p_nGroupIndex) {
5403 if (Lang.isArray(p_aItems)) {
5405 nItems = p_aItems.length;
5408 for(i=0; i<nItems; i++) {
5410 oItem = p_aItems[i];
5414 if (Lang.isArray(oItem)) {
5416 aItems[aItems.length] = this.addItems(oItem, i);
5421 aItems[aItems.length] = this._addItemToGroup(p_nGroupIndex, oItem);
5430 if (aItems.length) {
5444 * @method insertItem
5445 * @description Inserts an item into the menu at the specified index.
5446 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
5447 * instance to be added to the menu.
5448 * @param {String} p_oItem String specifying the text of the item to be added
5450 * @param {Object} p_oItem Object literal containing a set of menu item
5451 * configuration properties.
5452 * @param {Number} p_nItemIndex Number indicating the ordinal position at which
5453 * the item should be added.
5454 * @param {Number} p_nGroupIndex Optional. Number indicating the group to which
5456 * @return {YAHOO.widget.MenuItem}
5458 insertItem: function (p_oItem, p_nItemIndex, p_nGroupIndex) {
5460 return this._addItemToGroup(p_nGroupIndex, p_oItem, p_nItemIndex);
5466 * @method removeItem
5467 * @description Removes the specified item from the menu.
5468 * @param {YAHOO.widget.MenuItem} p_oObject Object reference for the MenuItem
5469 * instance to be removed from the menu.
5470 * @param {Number} p_oObject Number specifying the index of the item
5472 * @param {Number} p_nGroupIndex Optional. Number specifying the group to
5473 * which the item belongs.
5474 * @return {YAHOO.widget.MenuItem}
5476 removeItem: function (p_oObject, p_nGroupIndex) {
5481 if (!Lang.isUndefined(p_oObject)) {
5483 if (p_oObject instanceof YAHOO.widget.MenuItem) {
5485 oItem = this._removeItemFromGroupByValue(p_nGroupIndex, p_oObject);
5488 else if (Lang.isNumber(p_oObject)) {
5490 oItem = this._removeItemFromGroupByIndex(p_nGroupIndex, p_oObject);
5512 * @description Returns an array of all of the items in the menu.
5515 getItems: function () {
5517 var aGroups = this._aItemGroups,
5523 if (Lang.isArray(aGroups)) {
5525 nGroups = aGroups.length;
5527 returnVal = ((nGroups == 1) ? aGroups[0] : (Array.prototype.concat.apply(aItems, aGroups)));
5537 * @method getItemGroups
5538 * @description Multi-dimensional Array representing the menu items as they
5539 * are grouped in the menu.
5542 getItemGroups: function () {
5544 return this._aItemGroups;
5551 * @description Returns the item at the specified index.
5552 * @param {Number} p_nItemIndex Number indicating the ordinal position of the
5553 * item to be retrieved.
5554 * @param {Number} p_nGroupIndex Optional. Number indicating the group to which
5556 * @return {YAHOO.widget.MenuItem}
5558 getItem: function (p_nItemIndex, p_nGroupIndex) {
5563 if (Lang.isNumber(p_nItemIndex)) {
5565 aGroup = this._getItemGroup(p_nGroupIndex);
5569 returnVal = aGroup[p_nItemIndex];
5581 * @method getSubmenus
5582 * @description Returns an array of all of the submenus that are immediate
5583 * children of the menu.
5586 getSubmenus: function () {
5588 var aItems = this.getItems(),
5589 nItems = aItems.length,
5600 for(i=0; i<nItems; i++) {
5606 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5610 aSubmenus[aSubmenus.length] = oSubmenu;
5626 * @method clearContent
5627 * @description Removes all of the content from the menu, including the menu
5628 * items, group titles, header and footer.
5630 clearContent: function () {
5632 var aItems = this.getItems(),
5633 nItems = aItems.length,
5634 oElement = this.element,
5636 oHeader = this.header,
5637 oFooter = this.footer,
5653 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5657 this.cfg.configChangedEvent.unsubscribe(
5658 this._onParentMenuConfigChange, oSubmenu);
5660 this.renderEvent.unsubscribe(this._onParentMenuRender,
5665 this.removeItem(oItem, oItem.groupIndex);
5677 Event.purgeElement(oHeader);
5678 oElement.removeChild(oHeader);
5685 Event.purgeElement(oFooter);
5686 oElement.removeChild(oFooter);
5692 Event.purgeElement(oBody);
5694 oBody.innerHTML = _EMPTY_STRING;
5698 this.activeItem = null;
5700 this._aItemGroups = [];
5701 this._aListElements = [];
5702 this._aGroupTitleElements = [];
5704 this.cfg.setProperty(_WIDTH, null);
5711 * @description Removes the menu's <code><div></code> element
5712 * (and accompanying child nodes) from the document.
5714 destroy: function () {
5718 this.clearContent();
5720 this._aItemGroups = null;
5721 this._aListElements = null;
5722 this._aGroupTitleElements = null;
5725 // Continue with the superclass implementation of this method
5727 Menu.superclass.destroy.call(this);
5734 * @method setInitialFocus
5735 * @description Sets focus to the menu's first enabled item.
5737 setInitialFocus: function () {
5739 var oItem = this._getFirstEnabledItem();
5751 * @method setInitialSelection
5752 * @description Sets the "selected" configuration property of the menu's first
5753 * enabled item to "true."
5755 setInitialSelection: function () {
5757 var oItem = this._getFirstEnabledItem();
5761 oItem.cfg.setProperty(_SELECTED, true);
5768 * @method clearActiveItem
5769 * @description Sets the "selected" configuration property of the menu's active
5770 * item to "false" and hides the item's submenu.
5771 * @param {Boolean} p_bBlur Boolean indicating if the menu's active item
5772 * should be blurred.
5774 clearActiveItem: function (p_bBlur) {
5776 if (this.cfg.getProperty(_SHOW_DELAY) > 0) {
5778 this._cancelShowDelay();
5783 var oActiveItem = this.activeItem,
5789 oConfig = oActiveItem.cfg;
5795 this.getRoot()._hasFocus = true;
5799 oConfig.setProperty(_SELECTED, false);
5801 oSubmenu = oConfig.getProperty(_SUBMENU);
5810 this.activeItem = null;
5819 * @description Causes the menu to receive focus and fires the "focus" event.
5821 focus: function () {
5823 if (!this.hasFocus()) {
5825 this.setInitialFocus();
5834 * @description Causes the menu to lose focus and fires the "blur" event.
5840 if (this.hasFocus()) {
5842 oItem = MenuManager.getFocusedMenuItem();
5857 * @description Returns a boolean indicating whether or not the menu has focus.
5860 hasFocus: function () {
5862 return (MenuManager.getFocusedMenu() == this.getRoot());
5868 * Adds the specified CustomEvent subscriber to the menu and each of
5871 * @param p_type {string} the type, or name of the event
5872 * @param p_fn {function} the function to exectute when the event fires
5873 * @param p_obj {Object} An object to be passed along when the event
5875 * @param p_override {boolean} If true, the obj passed in becomes the
5876 * execution scope of the listener
5878 subscribe: function () {
5880 function onItemAdded(p_sType, p_aArgs, p_oObject) {
5882 var oItem = p_aArgs[0],
5883 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5887 oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5894 function onSubmenuAdded(p_sType, p_aArgs, p_oObject) {
5896 var oSubmenu = this.cfg.getProperty(_SUBMENU);
5900 oSubmenu.subscribe.apply(oSubmenu, p_oObject);
5907 Menu.superclass.subscribe.apply(this, arguments);
5908 Menu.superclass.subscribe.call(this, _ITEM_ADDED, onItemAdded, arguments);
5911 var aItems = this.getItems(),
5920 nItems = aItems.length;
5930 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
5934 oSubmenu.subscribe.apply(oSubmenu, arguments);
5939 oItem.cfg.subscribeToConfigEvent(_SUBMENU, onSubmenuAdded, arguments);
5954 * @description Initializes the class's configurable properties which can be
5955 * changed using the menu's Config object ("cfg").
5956 * @method initDefaultConfig
5958 initDefaultConfig: function () {
5960 Menu.superclass.initDefaultConfig.call(this);
5962 var oConfig = this.cfg;
5965 // Module documentation overrides
5969 * @description Object or array of objects representing the ContainerEffect
5970 * classes that are active for animating the container. When set this
5971 * property is automatically applied to all submenus.
5976 // Overlay documentation overrides
5981 * @description Number representing the absolute x-coordinate position of
5982 * the Menu. This property is only applied when the "position"
5983 * configuration property is set to dynamic.
5991 * @description Number representing the absolute y-coordinate position of
5992 * the Menu. This property is only applied when the "position"
5993 * configuration property is set to dynamic.
6000 * @description Array of the absolute x and y positions of the Menu. This
6001 * property is only applied when the "position" configuration property is
6011 * @description Array of context arguments for context-sensitive positioning.
6012 * The format is: [id or element, element corner, context corner].
6013 * For example, setting this property to ["img1", "tl", "bl"] would
6014 * align the Mnu's top left corner to the context element's
6015 * bottom left corner. This property is only applied when the "position"
6016 * configuration property is set to dynamic.
6023 * @config fixedcenter
6024 * @description Boolean indicating if the Menu should be anchored to the
6025 * center of the viewport. This property is only applied when the
6026 * "position" configuration property is set to dynamic.
6034 * @description Boolean indicating whether or not the Menu should
6035 * have an IFRAME shim; used to prevent SELECT elements from
6036 * poking through an Overlay instance in IE6. When set to "true",
6037 * the iframe shim is created when the Menu instance is intially
6038 * made visible. This property is only applied when the "position"
6039 * configuration property is set to dynamic and is automatically applied
6042 * @default true for IE6 and below, false for all other browsers.
6046 // Add configuration attributes
6049 Change the default value for the "visible" configuration
6050 property to "false" by re-adding the property.
6055 * @description Boolean indicating whether or not the menu is visible. If
6056 * the menu's "position" configuration property is set to "dynamic" (the
6057 * default), this property toggles the menu's <code><div></code>
6058 * element's "visibility" style property between "visible" (true) or
6059 * "hidden" (false). If the menu's "position" configuration property is
6060 * set to "static" this property toggles the menu's
6061 * <code><div></code> element's "display" style property
6062 * between "block" (true) or "none" (false).
6066 oConfig.addProperty(
6069 handler: this.configVisible,
6070 value: VISIBLE_CONFIG.value,
6071 validator: VISIBLE_CONFIG.validator
6077 Change the default value for the "constraintoviewport" configuration
6078 property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6082 * @config constraintoviewport
6083 * @description Boolean indicating if the menu will try to remain inside
6084 * the boundaries of the size of viewport. This property is only applied
6085 * when the "position" configuration property is set to dynamic and is
6086 * automatically applied to all submenus.
6090 oConfig.addProperty(
6091 CONSTRAIN_TO_VIEWPORT_CONFIG.key,
6093 handler: this.configConstrainToViewport,
6094 value: CONSTRAIN_TO_VIEWPORT_CONFIG.value,
6095 validator: CONSTRAIN_TO_VIEWPORT_CONFIG.validator,
6096 supercedes: CONSTRAIN_TO_VIEWPORT_CONFIG.supercedes
6102 Change the default value for the "preventcontextoverlap" configuration
6103 property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
6107 * @config preventcontextoverlap
6108 * @description Boolean indicating whether or not a submenu should overlap its parent MenuItem
6109 * when the "constraintoviewport" configuration property is set to "true".
6113 oConfig.addProperty(PREVENT_CONTEXT_OVERLAP_CONFIG.key, {
6115 value: PREVENT_CONTEXT_OVERLAP_CONFIG.value,
6116 validator: PREVENT_CONTEXT_OVERLAP_CONFIG.validator,
6117 supercedes: PREVENT_CONTEXT_OVERLAP_CONFIG.supercedes
6124 * @description String indicating how a menu should be positioned on the
6125 * screen. Possible values are "static" and "dynamic." Static menus are
6126 * visible by default and reside in the normal flow of the document
6127 * (CSS position: static). Dynamic menus are hidden by default, reside
6128 * out of the normal flow of the document (CSS position: absolute), and
6129 * can overlay other elements on the screen.
6133 oConfig.addProperty(
6134 POSITION_CONFIG.key,
6136 handler: this.configPosition,
6137 value: POSITION_CONFIG.value,
6138 validator: POSITION_CONFIG.validator,
6139 supercedes: POSITION_CONFIG.supercedes
6145 * @config submenualignment
6146 * @description Array defining how submenus should be aligned to their
6147 * parent menu item. The format is: [itemCorner, submenuCorner]. By default
6148 * a submenu's top left corner is aligned to its parent menu item's top
6150 * @default ["tl","tr"]
6153 oConfig.addProperty(
6154 SUBMENU_ALIGNMENT_CONFIG.key,
6156 value: SUBMENU_ALIGNMENT_CONFIG.value,
6157 suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
6163 * @config autosubmenudisplay
6164 * @description Boolean indicating if submenus are automatically made
6165 * visible when the user mouses over the menu's items.
6169 oConfig.addProperty(
6170 AUTO_SUBMENU_DISPLAY_CONFIG.key,
6172 value: AUTO_SUBMENU_DISPLAY_CONFIG.value,
6173 validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
6174 suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
6181 * @description Number indicating the time (in milliseconds) that should
6182 * expire before a submenu is made visible when the user mouses over
6183 * the menu's items. This property is only applied when the "position"
6184 * configuration property is set to dynamic and is automatically applied
6189 oConfig.addProperty(
6190 SHOW_DELAY_CONFIG.key,
6192 value: SHOW_DELAY_CONFIG.value,
6193 validator: SHOW_DELAY_CONFIG.validator,
6194 suppressEvent: SHOW_DELAY_CONFIG.suppressEvent
6201 * @description Number indicating the time (in milliseconds) that should
6202 * expire before the menu is hidden. This property is only applied when
6203 * the "position" configuration property is set to dynamic and is
6204 * automatically applied to all submenus.
6208 oConfig.addProperty(
6209 HIDE_DELAY_CONFIG.key,
6211 handler: this.configHideDelay,
6212 value: HIDE_DELAY_CONFIG.value,
6213 validator: HIDE_DELAY_CONFIG.validator,
6214 suppressEvent: HIDE_DELAY_CONFIG.suppressEvent
6220 * @config submenuhidedelay
6221 * @description Number indicating the time (in milliseconds) that should
6222 * expire before a submenu is hidden when the user mouses out of a menu item
6223 * heading in the direction of a submenu. The value must be greater than or
6224 * equal to the value specified for the "showdelay" configuration property.
6225 * This property is only applied when the "position" configuration property
6226 * is set to dynamic and is automatically applied to all submenus.
6230 oConfig.addProperty(
6231 SUBMENU_HIDE_DELAY_CONFIG.key,
6233 value: SUBMENU_HIDE_DELAY_CONFIG.value,
6234 validator: SUBMENU_HIDE_DELAY_CONFIG.validator,
6235 suppressEvent: SUBMENU_HIDE_DELAY_CONFIG.suppressEvent
6241 * @config clicktohide
6242 * @description Boolean indicating if the menu will automatically be
6243 * hidden if the user clicks outside of it. This property is only
6244 * applied when the "position" configuration property is set to dynamic
6245 * and is automatically applied to all submenus.
6249 oConfig.addProperty(
6250 CLICK_TO_HIDE_CONFIG.key,
6252 value: CLICK_TO_HIDE_CONFIG.value,
6253 validator: CLICK_TO_HIDE_CONFIG.validator,
6254 suppressEvent: CLICK_TO_HIDE_CONFIG.suppressEvent
6261 * @description HTML element reference or string specifying the id
6262 * attribute of the HTML element that the menu's markup should be
6264 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6265 * level-one-html.html#ID-58190037">HTMLElement</a>|String
6266 * @default document.body
6268 oConfig.addProperty(
6269 CONTAINER_CONFIG.key,
6271 handler: this.configContainer,
6272 value: document.body,
6273 suppressEvent: CONTAINER_CONFIG.suppressEvent
6279 * @config scrollincrement
6280 * @description Number used to control the scroll speed of a menu. Used to
6281 * increment the "scrollTop" property of the menu's body by when a menu's
6282 * content is scrolling. When set this property is automatically applied
6287 oConfig.addProperty(
6288 SCROLL_INCREMENT_CONFIG.key,
6290 value: SCROLL_INCREMENT_CONFIG.value,
6291 validator: SCROLL_INCREMENT_CONFIG.validator,
6292 supercedes: SCROLL_INCREMENT_CONFIG.supercedes,
6293 suppressEvent: SCROLL_INCREMENT_CONFIG.suppressEvent
6299 * @config minscrollheight
6300 * @description Number defining the minimum threshold for the "maxheight"
6301 * configuration property. When set this property is automatically applied
6306 oConfig.addProperty(
6307 MIN_SCROLL_HEIGHT_CONFIG.key,
6309 value: MIN_SCROLL_HEIGHT_CONFIG.value,
6310 validator: MIN_SCROLL_HEIGHT_CONFIG.validator,
6311 supercedes: MIN_SCROLL_HEIGHT_CONFIG.supercedes,
6312 suppressEvent: MIN_SCROLL_HEIGHT_CONFIG.suppressEvent
6319 * @description Number defining the maximum height (in pixels) for a menu's
6320 * body element (<code><div class="bd"<</code>). Once a menu's body
6321 * exceeds this height, the contents of the body are scrolled to maintain
6322 * this value. This value cannot be set lower than the value of the
6323 * "minscrollheight" configuration property.
6327 oConfig.addProperty(
6328 MAX_HEIGHT_CONFIG.key,
6330 handler: this.configMaxHeight,
6331 value: MAX_HEIGHT_CONFIG.value,
6332 validator: MAX_HEIGHT_CONFIG.validator,
6333 suppressEvent: MAX_HEIGHT_CONFIG.suppressEvent,
6334 supercedes: MAX_HEIGHT_CONFIG.supercedes
6341 * @description String representing the CSS class to be applied to the
6342 * menu's root <code><div></code> element. The specified class(es)
6343 * are appended in addition to the default class as specified by the menu's
6344 * CSS_CLASS_NAME constant. When set this property is automatically
6345 * applied to all submenus.
6349 oConfig.addProperty(
6350 CLASS_NAME_CONFIG.key,
6352 handler: this.configClassName,
6353 value: CLASS_NAME_CONFIG.value,
6354 validator: CLASS_NAME_CONFIG.validator,
6355 supercedes: CLASS_NAME_CONFIG.supercedes
6362 * @description Boolean indicating if the menu should be disabled.
6363 * Disabling a menu disables each of its items. (Disabled menu items are
6364 * dimmed and will not respond to user input or fire events.) Disabled
6365 * menus have a corresponding "disabled" CSS class applied to their root
6366 * <code><div></code> element.
6370 oConfig.addProperty(
6371 DISABLED_CONFIG.key,
6373 handler: this.configDisabled,
6374 value: DISABLED_CONFIG.value,
6375 validator: DISABLED_CONFIG.validator,
6376 suppressEvent: DISABLED_CONFIG.suppressEvent
6383 * @description Boolean indicating if the menu should have a shadow.
6387 oConfig.addProperty(
6390 handler: this.configShadow,
6391 value: SHADOW_CONFIG.value,
6392 validator: SHADOW_CONFIG.validator
6399 * @description Boolean indicating if the menu should remain open when clicked.
6403 oConfig.addProperty(
6404 KEEP_OPEN_CONFIG.key,
6406 value: KEEP_OPEN_CONFIG.value,
6407 validator: KEEP_OPEN_CONFIG.validator
6413 }); // END YAHOO.lang.extend
6422 * Creates an item for a menu.
6424 * @param {String} p_oObject String specifying the text of the menu item.
6425 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6426 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying
6427 * the <code><li></code> element of the menu item.
6428 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6429 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
6430 * specifying the <code><optgroup></code> element of the menu item.
6431 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6432 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object
6433 * specifying the <code><option></code> element of the menu item.
6434 * @param {Object} p_oConfig Optional. Object literal specifying the
6435 * configuration for the menu item. See configuration class documentation
6440 YAHOO.widget.MenuItem = function (p_oObject, p_oConfig) {
6446 this.parent = p_oConfig.parent;
6447 this.value = p_oConfig.value;
6448 this.id = p_oConfig.id;
6452 this.init(p_oObject, p_oConfig);
6459 var Dom = YAHOO.util.Dom,
6460 Module = YAHOO.widget.Module,
6461 Menu = YAHOO.widget.Menu,
6462 MenuItem = YAHOO.widget.MenuItem,
6463 CustomEvent = YAHOO.util.CustomEvent,
6467 // Private string constants
6472 _HELP_TEXT = "helptext",
6475 _EMPHASIS = "emphasis",
6476 _STRONG_EMPHASIS = "strongemphasis",
6477 _CHECKED = "checked",
6478 _SUBMENU = "submenu",
6479 _DISABLED = "disabled",
6480 _SELECTED = "selected",
6481 _HAS_SUBMENU = "hassubmenu",
6482 _CHECKED_DISABLED = "checked-disabled",
6483 _HAS_SUBMENU_DISABLED = "hassubmenu-disabled",
6484 _HAS_SUBMENU_SELECTED = "hassubmenu-selected",
6485 _CHECKED_SELECTED = "checked-selected",
6486 _ONCLICK = "onclick",
6487 _CLASSNAME = "classname",
6490 _OPTGROUP = "OPTGROUP",
6491 _LI_UPPERCASE = "LI",
6495 _START_HELP_TEXT = "<em class=\"helptext\">",
6498 _START_STRONG = "<strong>",
6499 _END_STRONG = "</strong>",
6500 _PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
6504 _VISIBLE = "visible",
6506 _MENUITEM = "MenuItem",
6510 _LI_LOWERCASE = "li",
6511 _ANCHOR_TEMPLATE = "<a href=\"#\"></a>",
6515 ["mouseOverEvent", "mouseover"],
6516 ["mouseOutEvent", "mouseout"],
6517 ["mouseDownEvent", "mousedown"],
6518 ["mouseUpEvent", "mouseup"],
6519 ["clickEvent", _CLICK],
6520 ["keyPressEvent", "keypress"],
6521 ["keyDownEvent", "keydown"],
6522 ["keyUpEvent", "keyup"],
6523 ["focusEvent", "focus"],
6524 ["blurEvent", "blur"],
6525 ["destroyEvent", "destroy"]
6531 value: _EMPTY_STRING,
6532 validator: Lang.isString,
6536 HELP_TEXT_CONFIG = {
6538 supercedes: [_TEXT],
6556 validator: Lang.isBoolean,
6557 suppressEvent: true,
6561 STRONG_EMPHASIS_CONFIG = {
6562 key: _STRONG_EMPHASIS,
6564 validator: Lang.isBoolean,
6565 suppressEvent: true,
6572 validator: Lang.isBoolean,
6573 suppressEvent: true,
6574 supercedes: [_DISABLED, _SELECTED]
6579 suppressEvent: true,
6580 supercedes: [_DISABLED, _SELECTED]
6586 validator: Lang.isBoolean,
6587 suppressEvent: true,
6588 supercedes: [_TEXT, _SELECTED]
6594 validator: Lang.isBoolean,
6603 CLASS_NAME_CONFIG = {
6606 validator: Lang.isString,
6610 KEY_LISTENER_CONFIG = {
6616 m_oMenuItemTemplate = null,
6622 * @method getClassNameForState
6623 * @description Returns a class name for the specified prefix and state. If the class name does not
6624 * yet exist, it is created and stored in the CLASS_NAMES object to increase performance.
6626 * @param {String} prefix String representing the prefix for the class name
6627 * @param {String} state String representing a state - "disabled," "checked," etc.
6629 var getClassNameForState = function (prefix, state) {
6631 var oClassNames = CLASS_NAMES[prefix];
6634 CLASS_NAMES[prefix] = {};
6635 oClassNames = CLASS_NAMES[prefix];
6639 var sClassName = oClassNames[state];
6642 sClassName = prefix + _HYPHEN + state;
6643 oClassNames[state] = sClassName;
6652 * @method addClassNameForState
6653 * @description Applies a class name to a MenuItem instance's <LI> and <A> elements
6654 * that represents a MenuItem's state - "disabled," "checked," etc.
6656 * @param {String} state String representing a state - "disabled," "checked," etc.
6658 var addClassNameForState = function (state) {
6660 Dom.addClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6661 Dom.addClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6666 * @method removeClassNameForState
6667 * @description Removes a class name from a MenuItem instance's <LI> and <A> elements
6668 * that represents a MenuItem's state - "disabled," "checked," etc.
6670 * @param {String} state String representing a state - "disabled," "checked," etc.
6672 var removeClassNameForState = function (state) {
6674 Dom.removeClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
6675 Dom.removeClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
6680 MenuItem.prototype = {
6683 * @property CSS_CLASS_NAME
6684 * @description String representing the CSS class(es) to be applied to the
6685 * <code><li></code> element of the menu item.
6686 * @default "yuimenuitem"
6690 CSS_CLASS_NAME: "yuimenuitem",
6694 * @property CSS_LABEL_CLASS_NAME
6695 * @description String representing the CSS class(es) to be applied to the
6696 * menu item's <code><a></code> element.
6697 * @default "yuimenuitemlabel"
6701 CSS_LABEL_CLASS_NAME: "yuimenuitemlabel",
6705 * @property SUBMENU_TYPE
6706 * @description Object representing the type of menu to instantiate and
6707 * add when parsing the child nodes of the menu item's source HTML element.
6709 * @type YAHOO.widget.Menu
6715 // Private member variables
6719 * @property _oAnchor
6720 * @description Object reference to the menu item's
6721 * <code><a></code> element.
6724 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6725 * one-html.html#ID-48250443">HTMLAnchorElement</a>
6731 * @property _oHelpTextEM
6732 * @description Object reference to the menu item's help text
6733 * <code><em></code> element.
6736 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6737 * one-html.html#ID-58190037">HTMLElement</a>
6743 * @property _oSubmenu
6744 * @description Object reference to the menu item's submenu.
6747 * @type YAHOO.widget.Menu
6753 * @property _oOnclickAttributeValue
6754 * @description Object reference to the menu item's current value for the
6755 * "onclick" configuration attribute.
6760 _oOnclickAttributeValue: null,
6764 * @property _sClassName
6765 * @description The current value of the "classname" configuration attribute.
6774 // Public properties
6778 * @property constructor
6779 * @description Object reference to the menu item's constructor function.
6780 * @default YAHOO.widget.MenuItem
6781 * @type YAHOO.widget.MenuItem
6783 constructor: MenuItem,
6788 * @description Number indicating the ordinal position of the menu item in
6797 * @property groupIndex
6798 * @description Number indicating the index of the group to which the menu
6808 * @description Object reference to the menu item's parent menu.
6810 * @type YAHOO.widget.Menu
6817 * @description Object reference to the menu item's
6818 * <code><li></code> element.
6819 * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level
6820 * -one-html.html#ID-74680021">HTMLLIElement</a>
6821 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6822 * one-html.html#ID-74680021">HTMLLIElement</a>
6828 * @property srcElement
6829 * @description Object reference to the HTML element (either
6830 * <code><li></code>, <code><optgroup></code> or
6831 * <code><option></code>) used create the menu item.
6832 * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6833 * level-one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.
6834 * w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247"
6835 * >HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6836 * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6837 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6838 * one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.w3.
6839 * org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247">
6840 * HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6841 * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6848 * @description Object reference to the menu item's value.
6857 * @deprecated Use YAHOO.env.ua
6858 * @description String representing the browser.
6861 browser: Module.prototype.browser,
6866 * @description Id of the menu item's root <code><li></code>
6867 * element. This property should be set via the constructor using the
6868 * configuration object literal. If an id is not specified, then one will
6869 * be created using the "generateId" method of the Dom utility.
6881 * @event destroyEvent
6882 * @description Fires when the menu item's <code><li></code>
6883 * element is removed from its parent <code><ul></code> element.
6884 * @type YAHOO.util.CustomEvent
6889 * @event mouseOverEvent
6890 * @description Fires when the mouse has entered the menu item. Passes
6891 * back the DOM Event object as an argument.
6892 * @type YAHOO.util.CustomEvent
6897 * @event mouseOutEvent
6898 * @description Fires when the mouse has left the menu item. Passes back
6899 * the DOM Event object as an argument.
6900 * @type YAHOO.util.CustomEvent
6905 * @event mouseDownEvent
6906 * @description Fires when the user mouses down on the menu item. Passes
6907 * back the DOM Event object as an argument.
6908 * @type YAHOO.util.CustomEvent
6913 * @event mouseUpEvent
6914 * @description Fires when the user releases a mouse button while the mouse
6915 * is over the menu item. Passes back the DOM Event object as an argument.
6916 * @type YAHOO.util.CustomEvent
6922 * @description Fires when the user clicks the on the menu item. Passes
6923 * back the DOM Event object as an argument.
6924 * @type YAHOO.util.CustomEvent
6929 * @event keyPressEvent
6930 * @description Fires when the user presses an alphanumeric key when the
6931 * menu item has focus. Passes back the DOM Event object as an argument.
6932 * @type YAHOO.util.CustomEvent
6937 * @event keyDownEvent
6938 * @description Fires when the user presses a key when the menu item has
6939 * focus. Passes back the DOM Event object as an argument.
6940 * @type YAHOO.util.CustomEvent
6946 * @description Fires when the user releases a key when the menu item has
6947 * focus. Passes back the DOM Event object as an argument.
6948 * @type YAHOO.util.CustomEvent
6954 * @description Fires when the menu item receives focus.
6955 * @type YAHOO.util.CustomEvent
6961 * @description Fires when the menu item loses the input focus.
6962 * @type YAHOO.util.CustomEvent
6968 * @description The MenuItem class's initialization method. This method is
6969 * automatically called by the constructor, and sets up all DOM references
6970 * for pre-existing markup, and creates required markup if it is not
6972 * @param {String} p_oObject String specifying the text of the menu item.
6973 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6974 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying
6975 * the <code><li></code> element of the menu item.
6976 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6977 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
6978 * specifying the <code><optgroup></code> element of the menu item.
6979 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6980 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object
6981 * specifying the <code><option></code> element of the menu item.
6982 * @param {Object} p_oConfig Optional. Object literal specifying the
6983 * configuration for the menu item. See configuration class documentation
6986 init: function (p_oObject, p_oConfig) {
6989 if (!this.SUBMENU_TYPE) {
6991 this.SUBMENU_TYPE = Menu;
6996 // Create the config object
6998 this.cfg = new YAHOO.util.Config(this);
7000 this.initDefaultConfig();
7002 var oConfig = this.cfg,
7013 if (Lang.isString(p_oObject)) {
7015 this._createRootNodeStructure();
7017 oConfig.queueProperty(_TEXT, p_oObject);
7020 else if (p_oObject && p_oObject.tagName) {
7022 switch(p_oObject.tagName.toUpperCase()) {
7026 this._createRootNodeStructure();
7028 oConfig.queueProperty(_TEXT, p_oObject.text);
7029 oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7031 this.value = p_oObject.value;
7033 this.srcElement = p_oObject;
7039 this._createRootNodeStructure();
7041 oConfig.queueProperty(_TEXT, p_oObject.label);
7042 oConfig.queueProperty(_DISABLED, p_oObject.disabled);
7044 this.srcElement = p_oObject;
7046 this._initSubTree();
7052 // Get the anchor node (if it exists)
7054 oAnchor = Dom.getFirstChild(p_oObject);
7057 // Capture the "text" and/or the "URL"
7061 sURL = oAnchor.getAttribute(_HREF, 2);
7062 sTarget = oAnchor.getAttribute(_TARGET);
7064 sText = oAnchor.innerHTML;
7068 this.srcElement = p_oObject;
7069 this.element = p_oObject;
7070 this._oAnchor = oAnchor;
7073 Set these properties silently to sync up the
7074 configuration object without making changes to the
7078 oConfig.setProperty(_TEXT, sText, true);
7079 oConfig.setProperty(_URL, sURL, true);
7080 oConfig.setProperty(_TARGET, sTarget, true);
7082 this._initSubTree();
7093 sId = (this.srcElement || this.element).id;
7097 sId = this.id || Dom.generateId();
7099 this.element.id = sId;
7106 Dom.addClass(this.element, this.CSS_CLASS_NAME);
7107 Dom.addClass(this._oAnchor, this.CSS_LABEL_CLASS_NAME);
7110 i = EVENT_TYPES.length - 1;
7114 aEventData = EVENT_TYPES[i];
7116 oCustomEvent = this.createEvent(aEventData[1]);
7117 oCustomEvent.signature = CustomEvent.LIST;
7119 this[aEventData[0]] = oCustomEvent;
7127 oConfig.applyConfig(p_oConfig);
7131 oConfig.fireQueue();
7142 * @method _createRootNodeStructure
7143 * @description Creates the core DOM structure for the menu item.
7146 _createRootNodeStructure: function () {
7151 if (!m_oMenuItemTemplate) {
7153 m_oMenuItemTemplate = document.createElement(_LI_LOWERCASE);
7154 m_oMenuItemTemplate.innerHTML = _ANCHOR_TEMPLATE;
7158 oElement = m_oMenuItemTemplate.cloneNode(true);
7159 oElement.className = this.CSS_CLASS_NAME;
7161 oAnchor = oElement.firstChild;
7162 oAnchor.className = this.CSS_LABEL_CLASS_NAME;
7164 this.element = oElement;
7165 this._oAnchor = oAnchor;
7171 * @method _initSubTree
7172 * @description Iterates the source element's childNodes collection and uses
7173 * the child nodes to instantiate other menus.
7176 _initSubTree: function () {
7178 var oSrcEl = this.srcElement,
7187 if (oSrcEl.childNodes.length > 0) {
7189 if (this.parent.lazyLoad && this.parent.srcElement &&
7190 this.parent.srcElement.tagName.toUpperCase() == _SELECT) {
7192 oConfig.setProperty(
7194 { id: Dom.generateId(), itemdata: oSrcEl.childNodes }
7200 oNode = oSrcEl.firstChild;
7205 if (oNode && oNode.tagName) {
7207 switch(oNode.tagName.toUpperCase()) {
7211 oConfig.setProperty(_SUBMENU, oNode);
7217 aOptions[aOptions.length] = oNode;
7226 while((oNode = oNode.nextSibling));
7229 nOptions = aOptions.length;
7233 oMenu = new this.SUBMENU_TYPE(Dom.generateId());
7235 oConfig.setProperty(_SUBMENU, oMenu);
7237 for(n=0; n<nOptions; n++) {
7239 oMenu.addItem((new oMenu.ITEM_TYPE(aOptions[n])));
7253 // Event handlers for configuration properties
7257 * @method configText
7258 * @description Event handler for when the "text" configuration property of
7259 * the menu item changes.
7260 * @param {String} p_sType String representing the name of the event that
7262 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7263 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7264 * that fired the event.
7266 configText: function (p_sType, p_aArgs, p_oItem) {
7268 var sText = p_aArgs[0],
7270 oAnchor = this._oAnchor,
7271 sHelpText = oConfig.getProperty(_HELP_TEXT),
7272 sHelpTextHTML = _EMPTY_STRING,
7273 sEmphasisStartTag = _EMPTY_STRING,
7274 sEmphasisEndTag = _EMPTY_STRING;
7282 sHelpTextHTML = _START_HELP_TEXT + sHelpText + _END_EM;
7287 if (oConfig.getProperty(_EMPHASIS)) {
7289 sEmphasisStartTag = _START_EM;
7290 sEmphasisEndTag = _END_EM;
7295 if (oConfig.getProperty(_STRONG_EMPHASIS)) {
7297 sEmphasisStartTag = _START_STRONG;
7298 sEmphasisEndTag = _END_STRONG;
7303 oAnchor.innerHTML = (sEmphasisStartTag + sText + sEmphasisEndTag + sHelpTextHTML);
7311 * @method configHelpText
7312 * @description Event handler for when the "helptext" configuration property
7313 * of the menu item changes.
7314 * @param {String} p_sType String representing the name of the event that
7316 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7317 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7318 * that fired the event.
7320 configHelpText: function (p_sType, p_aArgs, p_oItem) {
7322 this.cfg.refireEvent(_TEXT);
7329 * @description Event handler for when the "url" configuration property of
7330 * the menu item changes.
7331 * @param {String} p_sType String representing the name of the event that
7333 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7334 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7335 * that fired the event.
7337 configURL: function (p_sType, p_aArgs, p_oItem) {
7339 var sURL = p_aArgs[0];
7347 var oAnchor = this._oAnchor;
7351 oAnchor.removeAttribute(_HREF);
7355 oAnchor.setAttribute(_HREF, sURL);
7361 * @method configTarget
7362 * @description Event handler for when the "target" configuration property
7363 * of the menu item changes.
7364 * @param {String} p_sType String representing the name of the event that
7366 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7367 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7368 * that fired the event.
7370 configTarget: function (p_sType, p_aArgs, p_oItem) {
7372 var sTarget = p_aArgs[0],
7373 oAnchor = this._oAnchor;
7375 if (sTarget && sTarget.length > 0) {
7377 oAnchor.setAttribute(_TARGET, sTarget);
7382 oAnchor.removeAttribute(_TARGET);
7390 * @method configEmphasis
7391 * @description Event handler for when the "emphasis" configuration property
7392 * of the menu item changes.
7393 * @param {String} p_sType String representing the name of the event that
7395 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7396 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7397 * that fired the event.
7399 configEmphasis: function (p_sType, p_aArgs, p_oItem) {
7401 var bEmphasis = p_aArgs[0],
7405 if (bEmphasis && oConfig.getProperty(_STRONG_EMPHASIS)) {
7407 oConfig.setProperty(_STRONG_EMPHASIS, false);
7412 oConfig.refireEvent(_TEXT);
7418 * @method configStrongEmphasis
7419 * @description Event handler for when the "strongemphasis" configuration
7420 * property of the menu item changes.
7421 * @param {String} p_sType String representing the name of the event that
7423 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7424 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7425 * that fired the event.
7427 configStrongEmphasis: function (p_sType, p_aArgs, p_oItem) {
7429 var bStrongEmphasis = p_aArgs[0],
7433 if (bStrongEmphasis && oConfig.getProperty(_EMPHASIS)) {
7435 oConfig.setProperty(_EMPHASIS, false);
7439 oConfig.refireEvent(_TEXT);
7445 * @method configChecked
7446 * @description Event handler for when the "checked" configuration property
7447 * of the menu item changes.
7448 * @param {String} p_sType String representing the name of the event that
7450 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7451 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7452 * that fired the event.
7454 configChecked: function (p_sType, p_aArgs, p_oItem) {
7456 var bChecked = p_aArgs[0],
7462 addClassNameForState.call(this, _CHECKED);
7467 removeClassNameForState.call(this, _CHECKED);
7471 oConfig.refireEvent(_TEXT);
7474 if (oConfig.getProperty(_DISABLED)) {
7476 oConfig.refireEvent(_DISABLED);
7481 if (oConfig.getProperty(_SELECTED)) {
7483 oConfig.refireEvent(_SELECTED);
7492 * @method configDisabled
7493 * @description Event handler for when the "disabled" configuration property
7494 * of the menu item changes.
7495 * @param {String} p_sType String representing the name of the event that
7497 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7498 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7499 * that fired the event.
7501 configDisabled: function (p_sType, p_aArgs, p_oItem) {
7503 var bDisabled = p_aArgs[0],
7505 oSubmenu = oConfig.getProperty(_SUBMENU),
7506 bChecked = oConfig.getProperty(_CHECKED);
7511 if (oConfig.getProperty(_SELECTED)) {
7513 oConfig.setProperty(_SELECTED, false);
7518 addClassNameForState.call(this, _DISABLED);
7523 addClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7530 addClassNameForState.call(this, _CHECKED_DISABLED);
7537 removeClassNameForState.call(this, _DISABLED);
7542 removeClassNameForState.call(this, _HAS_SUBMENU_DISABLED);
7549 removeClassNameForState.call(this, _CHECKED_DISABLED);
7559 * @method configSelected
7560 * @description Event handler for when the "selected" configuration property
7561 * of the menu item changes.
7562 * @param {String} p_sType String representing the name of the event that
7564 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7565 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7566 * that fired the event.
7568 configSelected: function (p_sType, p_aArgs, p_oItem) {
7570 var oConfig = this.cfg,
7571 oAnchor = this._oAnchor,
7573 bSelected = p_aArgs[0],
7574 bChecked = oConfig.getProperty(_CHECKED),
7575 oSubmenu = oConfig.getProperty(_SUBMENU);
7585 if (bSelected && !oConfig.getProperty(_DISABLED)) {
7587 addClassNameForState.call(this, _SELECTED);
7592 addClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7599 addClassNameForState.call(this, _CHECKED_SELECTED);
7606 removeClassNameForState.call(this, _SELECTED);
7611 removeClassNameForState.call(this, _HAS_SUBMENU_SELECTED);
7618 removeClassNameForState.call(this, _CHECKED_SELECTED);
7625 if (this.hasFocus() && UA.opera) {
7635 * @method _onSubmenuBeforeHide
7636 * @description "beforehide" Custom Event handler for a submenu.
7638 * @param {String} p_sType String representing the name of the event that
7640 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7642 _onSubmenuBeforeHide: function (p_sType, p_aArgs) {
7644 var oItem = this.parent,
7649 oItem._oAnchor.blur();
7650 oMenu.beforeHideEvent.unsubscribe(onHide);
7655 if (oItem.hasFocus()) {
7657 oMenu = oItem.parent;
7659 oMenu.beforeHideEvent.subscribe(onHide);
7667 * @method configSubmenu
7668 * @description Event handler for when the "submenu" configuration property
7669 * of the menu item changes.
7670 * @param {String} p_sType String representing the name of the event that
7672 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7673 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7674 * that fired the event.
7676 configSubmenu: function (p_sType, p_aArgs, p_oItem) {
7678 var oSubmenu = p_aArgs[0],
7680 bLazyLoad = this.parent && this.parent.lazyLoad,
7688 if (oSubmenu instanceof Menu) {
7691 oMenu.parent = this;
7692 oMenu.lazyLoad = bLazyLoad;
7695 else if (Lang.isObject(oSubmenu) && oSubmenu.id && !oSubmenu.nodeType) {
7697 sSubmenuId = oSubmenu.id;
7698 oSubmenuConfig = oSubmenu;
7700 oSubmenuConfig.lazyload = bLazyLoad;
7701 oSubmenuConfig.parent = this;
7703 oMenu = new this.SUBMENU_TYPE(sSubmenuId, oSubmenuConfig);
7706 // Set the value of the property to the Menu instance
7708 oConfig.setProperty(_SUBMENU, oMenu, true);
7713 oMenu = new this.SUBMENU_TYPE(oSubmenu, { lazyload: bLazyLoad, parent: this });
7716 // Set the value of the property to the Menu instance
7718 oConfig.setProperty(_SUBMENU, oMenu, true);
7725 oMenu.cfg.setProperty(_PREVENT_CONTEXT_OVERLAP, true);
7727 addClassNameForState.call(this, _HAS_SUBMENU);
7730 if (oConfig.getProperty(_URL) === _HASH) {
7732 oConfig.setProperty(_URL, (_HASH + oMenu.id));
7737 this._oSubmenu = oMenu;
7742 oMenu.beforeHideEvent.subscribe(this._onSubmenuBeforeHide);
7751 removeClassNameForState.call(this, _HAS_SUBMENU);
7753 if (this._oSubmenu) {
7755 this._oSubmenu.destroy();
7762 if (oConfig.getProperty(_DISABLED)) {
7764 oConfig.refireEvent(_DISABLED);
7769 if (oConfig.getProperty(_SELECTED)) {
7771 oConfig.refireEvent(_SELECTED);
7779 * @method configOnClick
7780 * @description Event handler for when the "onclick" configuration property
7781 * of the menu item changes.
7782 * @param {String} p_sType String representing the name of the event that
7784 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7785 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7786 * that fired the event.
7788 configOnClick: function (p_sType, p_aArgs, p_oItem) {
7790 var oObject = p_aArgs[0];
7793 Remove any existing listeners if a "click" event handler has
7794 already been specified.
7797 if (this._oOnclickAttributeValue && (this._oOnclickAttributeValue != oObject)) {
7799 this.clickEvent.unsubscribe(this._oOnclickAttributeValue.fn,
7800 this._oOnclickAttributeValue.obj);
7802 this._oOnclickAttributeValue = null;
7807 if (!this._oOnclickAttributeValue && Lang.isObject(oObject) &&
7808 Lang.isFunction(oObject.fn)) {
7810 this.clickEvent.subscribe(oObject.fn,
7811 ((_OBJ in oObject) ? oObject.obj : this),
7812 ((_SCOPE in oObject) ? oObject.scope : null) );
7814 this._oOnclickAttributeValue = oObject;
7822 * @method configClassName
7823 * @description Event handler for when the "classname" configuration
7824 * property of a menu item changes.
7825 * @param {String} p_sType String representing the name of the event that
7827 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7828 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7829 * that fired the event.
7831 configClassName: function (p_sType, p_aArgs, p_oItem) {
7833 var sClassName = p_aArgs[0];
7835 if (this._sClassName) {
7837 Dom.removeClass(this.element, this._sClassName);
7841 Dom.addClass(this.element, sClassName);
7842 this._sClassName = sClassName;
7848 * @method _dispatchClickEvent
7849 * @description Dispatches a DOM "click" event to the anchor element of a
7850 * MenuItem instance.
7853 _dispatchClickEvent: function () {
7855 var oMenuItem = this,
7859 if (!oMenuItem.cfg.getProperty(_DISABLED)) {
7861 oAnchor = Dom.getFirstChild(oMenuItem.element);
7863 // Dispatch a "click" event to the MenuItem's anchor so that its
7864 // "click" event handlers will get called in response to the user
7865 // pressing the keyboard shortcut defined by the "keylistener"
7866 // configuration property.
7869 oAnchor.fireEvent(_ONCLICK);
7873 if ((UA.gecko && UA.gecko >= 1.9) || UA.opera || UA.webkit) {
7875 oEvent = document.createEvent("HTMLEvents");
7876 oEvent.initEvent(_CLICK, true, true);
7881 oEvent = document.createEvent("MouseEvents");
7882 oEvent.initMouseEvent(_CLICK, true, true, window, 0, 0, 0,
7883 0, 0, false, false, false, false, 0, null);
7887 oAnchor.dispatchEvent(oEvent);
7897 * @method _createKeyListener
7898 * @description "show" event handler for a Menu instance - responsible for
7899 * setting up the KeyListener instance for a MenuItem.
7901 * @param {String} type String representing the name of the event that
7903 * @param {Array} args Array of arguments sent when the event was fired.
7904 * @param {Array} keyData Array of arguments sent when the event was fired.
7906 _createKeyListener: function (type, args, keyData) {
7908 var oMenuItem = this,
7909 oMenu = oMenuItem.parent;
7911 var oKeyListener = new YAHOO.util.KeyListener(
7912 oMenu.element.ownerDocument,
7915 fn: oMenuItem._dispatchClickEvent,
7917 correctScope: true });
7920 if (oMenu.cfg.getProperty(_VISIBLE)) {
7921 oKeyListener.enable();
7925 oMenu.subscribe(_SHOW, oKeyListener.enable, null, oKeyListener);
7926 oMenu.subscribe(_HIDE, oKeyListener.disable, null, oKeyListener);
7928 oMenuItem._keyListener = oKeyListener;
7930 oMenu.unsubscribe(_SHOW, oMenuItem._createKeyListener, keyData);
7936 * @method configKeyListener
7937 * @description Event handler for when the "keylistener" configuration
7938 * property of a menu item changes.
7939 * @param {String} p_sType String representing the name of the event that
7941 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7943 configKeyListener: function (p_sType, p_aArgs) {
7945 var oKeyData = p_aArgs[0],
7947 oMenu = oMenuItem.parent;
7949 if (oMenuItem._keyData) {
7951 // Unsubscribe from the "show" event in case the keylistener
7952 // config was changed before the Menu was ever made visible.
7954 oMenu.unsubscribe(_SHOW,
7955 oMenuItem._createKeyListener, oMenuItem._keyData);
7957 oMenuItem._keyData = null;
7962 // Tear down for the previous value of the "keylistener" property
7964 if (oMenuItem._keyListener) {
7966 oMenu.unsubscribe(_SHOW, oMenuItem._keyListener.enable);
7967 oMenu.unsubscribe(_HIDE, oMenuItem._keyListener.disable);
7969 oMenuItem._keyListener.disable();
7970 oMenuItem._keyListener = null;
7977 oMenuItem._keyData = oKeyData;
7979 // Defer the creation of the KeyListener instance until the
7980 // parent Menu is visible. This is necessary since the
7981 // KeyListener instance needs to be bound to the document the
7982 // Menu has been rendered into. Deferring creation of the
7983 // KeyListener instance also improves performance.
7985 oMenu.subscribe(_SHOW, oMenuItem._createKeyListener,
7986 oKeyData, oMenuItem);
7996 * @method initDefaultConfig
7997 * @description Initializes an item's configurable properties.
7999 initDefaultConfig : function () {
8001 var oConfig = this.cfg;
8004 // Define the configuration attributes
8008 * @description String specifying the text label for the menu item.
8009 * When building a menu from existing HTML the value of this property
8010 * will be interpreted from the menu's markup.
8014 oConfig.addProperty(
8017 handler: this.configText,
8018 value: TEXT_CONFIG.value,
8019 validator: TEXT_CONFIG.validator,
8020 suppressEvent: TEXT_CONFIG.suppressEvent
8027 * @description String specifying additional instructional text to
8028 * accompany the text for the menu item.
8029 * @deprecated Use "text" configuration property to add help text markup.
8030 * For example: <code>oMenuItem.cfg.setProperty("text", "Copy <em
8031 * class=\"helptext\">Ctrl + C</em>");</code>
8033 * @type String|<a href="http://www.w3.org/TR/
8034 * 2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8037 oConfig.addProperty(
8038 HELP_TEXT_CONFIG.key,
8040 handler: this.configHelpText,
8041 supercedes: HELP_TEXT_CONFIG.supercedes,
8042 suppressEvent: HELP_TEXT_CONFIG.suppressEvent
8049 * @description String specifying the URL for the menu item's anchor's
8050 * "href" attribute. When building a menu from existing HTML the value
8051 * of this property will be interpreted from the menu's markup.
8055 oConfig.addProperty(
8058 handler: this.configURL,
8059 value: URL_CONFIG.value,
8060 suppressEvent: URL_CONFIG.suppressEvent
8067 * @description String specifying the value for the "target" attribute
8068 * of the menu item's anchor element. <strong>Specifying a target will
8069 * require the user to click directly on the menu item's anchor node in
8070 * order to cause the browser to navigate to the specified URL.</strong>
8071 * When building a menu from existing HTML the value of this property
8072 * will be interpreted from the menu's markup.
8076 oConfig.addProperty(
8079 handler: this.configTarget,
8080 suppressEvent: TARGET_CONFIG.suppressEvent
8087 * @description Boolean indicating if the text of the menu item will be
8088 * rendered with emphasis.
8089 * @deprecated Use the "text" configuration property to add emphasis.
8090 * For example: <code>oMenuItem.cfg.setProperty("text", "<em>Some
8091 * Text</em>");</code>
8095 oConfig.addProperty(
8096 EMPHASIS_CONFIG.key,
8098 handler: this.configEmphasis,
8099 value: EMPHASIS_CONFIG.value,
8100 validator: EMPHASIS_CONFIG.validator,
8101 suppressEvent: EMPHASIS_CONFIG.suppressEvent,
8102 supercedes: EMPHASIS_CONFIG.supercedes
8108 * @config strongemphasis
8109 * @description Boolean indicating if the text of the menu item will be
8110 * rendered with strong emphasis.
8111 * @deprecated Use the "text" configuration property to add strong emphasis.
8112 * For example: <code>oMenuItem.cfg.setProperty("text", "<strong>
8113 * Some Text</strong>");</code>
8117 oConfig.addProperty(
8118 STRONG_EMPHASIS_CONFIG.key,
8120 handler: this.configStrongEmphasis,
8121 value: STRONG_EMPHASIS_CONFIG.value,
8122 validator: STRONG_EMPHASIS_CONFIG.validator,
8123 suppressEvent: STRONG_EMPHASIS_CONFIG.suppressEvent,
8124 supercedes: STRONG_EMPHASIS_CONFIG.supercedes
8131 * @description Boolean indicating if the menu item should be rendered
8136 oConfig.addProperty(
8139 handler: this.configChecked,
8140 value: CHECKED_CONFIG.value,
8141 validator: CHECKED_CONFIG.validator,
8142 suppressEvent: CHECKED_CONFIG.suppressEvent,
8143 supercedes: CHECKED_CONFIG.supercedes
8150 * @description Boolean indicating if the menu item should be disabled.
8151 * (Disabled menu items are dimmed and will not respond to user input
8156 oConfig.addProperty(
8157 DISABLED_CONFIG.key,
8159 handler: this.configDisabled,
8160 value: DISABLED_CONFIG.value,
8161 validator: DISABLED_CONFIG.validator,
8162 suppressEvent: DISABLED_CONFIG.suppressEvent
8169 * @description Boolean indicating if the menu item should
8174 oConfig.addProperty(
8175 SELECTED_CONFIG.key,
8177 handler: this.configSelected,
8178 value: SELECTED_CONFIG.value,
8179 validator: SELECTED_CONFIG.validator,
8180 suppressEvent: SELECTED_CONFIG.suppressEvent
8187 * @description Object specifying the submenu to be appended to the
8188 * menu item. The value can be one of the following: <ul><li>Object
8189 * specifying a Menu instance.</li><li>Object literal specifying the
8190 * menu to be created. Format: <code>{ id: [menu id], itemdata:
8191 * [<a href="YAHOO.widget.Menu.html#itemData">array of values for
8192 * items</a>] }</code>.</li><li>String specifying the id attribute
8193 * of the <code><div></code> element of the menu.</li><li>
8194 * Object specifying the <code><div></code> element of the
8197 * @type Menu|String|Object|<a href="http://www.w3.org/TR/2000/
8198 * WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
8201 oConfig.addProperty(
8204 handler: this.configSubmenu,
8205 supercedes: SUBMENU_CONFIG.supercedes,
8206 suppressEvent: SUBMENU_CONFIG.suppressEvent
8213 * @description Object literal representing the code to be executed when
8214 * the item is clicked. Format:<br> <code> {<br>
8215 * <strong>fn:</strong> Function, // The handler to call when
8216 * the event fires.<br> <strong>obj:</strong> Object, // An
8217 * object to pass back to the handler.<br> <strong>scope:</strong>
8218 * Object // The object to use for the scope of the handler.
8223 oConfig.addProperty(
8226 handler: this.configOnClick,
8227 suppressEvent: ONCLICK_CONFIG.suppressEvent
8234 * @description CSS class to be applied to the menu item's root
8235 * <code><li></code> element. The specified class(es) are
8236 * appended in addition to the default class as specified by the menu
8237 * item's CSS_CLASS_NAME constant.
8241 oConfig.addProperty(
8242 CLASS_NAME_CONFIG.key,
8244 handler: this.configClassName,
8245 value: CLASS_NAME_CONFIG.value,
8246 validator: CLASS_NAME_CONFIG.validator,
8247 suppressEvent: CLASS_NAME_CONFIG.suppressEvent
8253 * @config keylistener
8254 * @description Object literal representing the key(s) that can be used
8255 * to trigger the MenuItem's "click" event. Possible attributes are
8256 * shift (boolean), alt (boolean), ctrl (boolean) and keys (either an int
8257 * or an array of ints representing keycodes).
8261 oConfig.addProperty(
8262 KEY_LISTENER_CONFIG.key,
8264 handler: this.configKeyListener,
8265 value: KEY_LISTENER_CONFIG.value,
8266 suppressEvent: KEY_LISTENER_CONFIG.suppressEvent
8274 * @method getNextEnabledSibling
8275 * @description Finds the menu item's next enabled sibling.
8276 * @return YAHOO.widget.MenuItem
8278 getNextEnabledSibling: function () {
8287 function getNextArrayItem(p_aArray, p_nStartIndex) {
8289 return p_aArray[p_nStartIndex] || getNextArrayItem(p_aArray, (p_nStartIndex+1));
8293 if (this.parent instanceof Menu) {
8295 nGroupIndex = this.groupIndex;
8297 aItemGroups = this.parent.getItemGroups();
8299 if (this.index < (aItemGroups[nGroupIndex].length - 1)) {
8301 oNextItem = getNextArrayItem(aItemGroups[nGroupIndex],
8307 if (nGroupIndex < (aItemGroups.length - 1)) {
8309 nNextGroupIndex = nGroupIndex + 1;
8314 nNextGroupIndex = 0;
8318 aNextGroup = getNextArrayItem(aItemGroups, nNextGroupIndex);
8320 // Retrieve the first menu item in the next group
8322 oNextItem = getNextArrayItem(aNextGroup, 0);
8326 returnVal = (oNextItem.cfg.getProperty(_DISABLED) ||
8327 oNextItem.element.style.display == _NONE) ?
8328 oNextItem.getNextEnabledSibling() : oNextItem;
8338 * @method getPreviousEnabledSibling
8339 * @description Finds the menu item's previous enabled sibling.
8340 * @return {YAHOO.widget.MenuItem}
8342 getPreviousEnabledSibling: function () {
8347 nPreviousGroupIndex,
8351 function getPreviousArrayItem(p_aArray, p_nStartIndex) {
8353 return p_aArray[p_nStartIndex] || getPreviousArrayItem(p_aArray, (p_nStartIndex-1));
8357 function getFirstItemIndex(p_aArray, p_nStartIndex) {
8359 return p_aArray[p_nStartIndex] ? p_nStartIndex :
8360 getFirstItemIndex(p_aArray, (p_nStartIndex+1));
8364 if (this.parent instanceof Menu) {
8366 nGroupIndex = this.groupIndex;
8367 aItemGroups = this.parent.getItemGroups();
8370 if (this.index > getFirstItemIndex(aItemGroups[nGroupIndex], 0)) {
8372 oPreviousItem = getPreviousArrayItem(aItemGroups[nGroupIndex],
8378 if (nGroupIndex > getFirstItemIndex(aItemGroups, 0)) {
8380 nPreviousGroupIndex = nGroupIndex - 1;
8385 nPreviousGroupIndex = aItemGroups.length - 1;
8389 aPreviousGroup = getPreviousArrayItem(aItemGroups,
8390 nPreviousGroupIndex);
8392 oPreviousItem = getPreviousArrayItem(aPreviousGroup,
8393 (aPreviousGroup.length - 1));
8397 returnVal = (oPreviousItem.cfg.getProperty(_DISABLED) ||
8398 oPreviousItem.element.style.display == _NONE) ?
8399 oPreviousItem.getPreviousEnabledSibling() : oPreviousItem;
8410 * @description Causes the menu item to receive the focus and fires the
8413 focus: function () {
8415 var oParent = this.parent,
8416 oAnchor = this._oAnchor,
8417 oActiveItem = oParent.activeItem;
8420 function setFocus() {
8424 if (!(UA.ie && !document.hasFocus())) {
8428 oActiveItem.blurEvent.fire();
8434 this.focusEvent.fire();
8446 if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE) &&
8447 this.element.style.display != _NONE) {
8451 Setting focus via a timer fixes a race condition in Firefox, IE
8452 and Opera where the browser viewport jumps as it trys to
8453 position and focus the menu.
8456 Lang.later(0, this, setFocus);
8465 * @description Causes the menu item to lose focus and fires the
8470 var oParent = this.parent;
8472 if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE)) {
8474 Lang.later(0, this, function () {
8478 this._oAnchor.blur();
8479 this.blurEvent.fire();
8495 * @description Returns a boolean indicating whether or not the menu item
8499 hasFocus: function () {
8501 return (YAHOO.widget.MenuManager.getFocusedMenuItem() == this);
8508 * @description Removes the menu item's <code><li></code> element
8509 * from its parent <code><ul></code> element.
8511 destroy: function () {
8513 var oEl = this.element,
8523 // If the item has a submenu, destroy it first
8525 oSubmenu = this.cfg.getProperty(_SUBMENU);
8534 // Remove the element from the parent node
8536 oParentNode = oEl.parentNode;
8540 oParentNode.removeChild(oEl);
8542 this.destroyEvent.fire();
8547 // Remove CustomEvent listeners
8549 i = EVENT_TYPES.length - 1;
8553 aEventData = EVENT_TYPES[i];
8555 this[aEventData[0]].unsubscribeAll();
8561 this.cfg.configChangedEvent.unsubscribeAll();
8570 * @description Returns a string representing the menu item.
8573 toString: function () {
8575 var sReturnVal = _MENUITEM,
8580 sReturnVal += (_SPACE + sId);
8590 Lang.augmentProto(MenuItem, YAHOO.util.EventProvider);
8596 _MOUSEDOWN = "mousedown",
8597 _CONTEXTMENU = "ContextMenu",
8601 * Creates a list of options or commands which are made visible in response to
8602 * an HTML element's "contextmenu" event ("mousedown" for Opera).
8604 * @param {String} p_oElement String specifying the id attribute of the
8605 * <code><div></code> element of the context menu.
8606 * @param {String} p_oElement String specifying the id attribute of the
8607 * <code><select></code> element to be used as the data source for the
8609 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8610 * html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the
8611 * <code><div></code> element of the context menu.
8612 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8613 * html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying
8614 * the <code><select></code> element to be used as the data source for
8616 * @param {Object} p_oConfig Optional. Object literal specifying the
8617 * configuration for the context menu. See configuration class documentation
8619 * @class ContextMenu
8621 * @extends YAHOO.widget.Menu
8622 * @namespace YAHOO.widget
8624 YAHOO.widget.ContextMenu = function(p_oElement, p_oConfig) {
8626 YAHOO.widget.ContextMenu.superclass.constructor.call(this, p_oElement, p_oConfig);
8631 var Event = YAHOO.util.Event,
8633 ContextMenu = YAHOO.widget.ContextMenu,
8638 * Constant representing the name of the ContextMenu's events
8639 * @property EVENT_TYPES
8646 "TRIGGER_CONTEXT_MENU": "triggerContextMenu",
8647 "CONTEXT_MENU": (UA.opera ? _MOUSEDOWN : "contextmenu"),
8654 * Constant representing the ContextMenu's configuration properties
8655 * @property DEFAULT_CONFIG
8668 * @description "beforeShow" event handler used to position the contextmenu.
8670 * @param {String} p_sType String representing the name of the event that
8672 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
8673 * @param {Array} p_aPos Array representing the xy position for the context menu.
8675 function position(p_sType, p_aArgs, p_aPos) {
8677 this.cfg.setProperty(_XY, p_aPos);
8679 this.beforeShowEvent.unsubscribe(position, p_aPos);
8684 YAHOO.lang.extend(ContextMenu, YAHOO.widget.Menu, {
8688 // Private properties
8692 * @property _oTrigger
8693 * @description Object reference to the current value of the "trigger"
8694 * configuration property.
8697 * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/leve
8698 * l-one-html.html#ID-58190037">HTMLElement</a>|Array
8704 * @property _bCancelled
8705 * @description Boolean indicating if the display of the context menu should
8715 // Public properties
8719 * @property contextEventTarget
8720 * @description Object reference for the HTML element that was the target of the
8721 * "contextmenu" DOM event ("mousedown" for Opera) that triggered the display of
8724 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8725 * html.html#ID-58190037">HTMLElement</a>
8727 contextEventTarget: null,
8735 * @event triggerContextMenuEvent
8736 * @description Custom Event wrapper for the "contextmenu" DOM event
8737 * ("mousedown" for Opera) fired by the element(s) that trigger the display of
8740 triggerContextMenuEvent: null,
8746 * @description The ContextMenu class's initialization method. This method is
8747 * automatically called by the constructor, and sets up all DOM references for
8748 * pre-existing markup, and creates required markup if it is not already present.
8749 * @param {String} p_oElement String specifying the id attribute of the
8750 * <code><div></code> element of the context menu.
8751 * @param {String} p_oElement String specifying the id attribute of the
8752 * <code><select></code> element to be used as the data source for
8754 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8755 * html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the
8756 * <code><div></code> element of the context menu.
8757 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8758 * html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying
8759 * the <code><select></code> element to be used as the data source for
8761 * @param {Object} p_oConfig Optional. Object literal specifying the
8762 * configuration for the context menu. See configuration class documentation
8765 init: function(p_oElement, p_oConfig) {
8768 // Call the init of the superclass (YAHOO.widget.Menu)
8770 ContextMenu.superclass.init.call(this, p_oElement);
8773 this.beforeInitEvent.fire(ContextMenu);
8778 this.cfg.applyConfig(p_oConfig, true);
8782 this.initEvent.fire(ContextMenu);
8788 * @method initEvents
8789 * @description Initializes the custom events for the context menu.
8791 initEvents: function() {
8793 ContextMenu.superclass.initEvents.call(this);
8795 // Create custom events
8797 this.triggerContextMenuEvent = this.createEvent(EVENT_TYPES.TRIGGER_CONTEXT_MENU);
8799 this.triggerContextMenuEvent.signature = YAHOO.util.CustomEvent.LIST;
8806 * @description Cancels the display of the context menu.
8808 cancel: function() {
8810 this._bCancelled = true;
8820 * @method _removeEventHandlers
8821 * @description Removes all of the DOM event handlers from the HTML element(s)
8822 * whose "context menu" event ("click" for Opera) trigger the display of
8826 _removeEventHandlers: function() {
8828 var oTrigger = this._oTrigger;
8831 // Remove the event handlers from the trigger(s)
8835 Event.removeListener(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu);
8839 Event.removeListener(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick);
8849 // Private event handlers
8854 * @method _onTriggerClick
8855 * @description "click" event handler for the HTML element(s) identified as the
8856 * "trigger" for the context menu. Used to cancel default behaviors in Opera.
8858 * @param {Event} p_oEvent Object representing the DOM event object passed back
8859 * by the event utility (YAHOO.util.Event).
8860 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8861 * menu that is handling the event.
8863 _onTriggerClick: function(p_oEvent, p_oMenu) {
8865 if (p_oEvent.ctrlKey) {
8867 Event.stopEvent(p_oEvent);
8875 * @method _onTriggerContextMenu
8876 * @description "contextmenu" event handler ("mousedown" for Opera) for the HTML
8877 * element(s) that trigger the display of the context menu.
8879 * @param {Event} p_oEvent Object representing the DOM event object passed back
8880 * by the event utility (YAHOO.util.Event).
8881 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8882 * menu that is handling the event.
8884 _onTriggerContextMenu: function(p_oEvent, p_oMenu) {
8888 if (!(p_oEvent.type == _MOUSEDOWN && !p_oEvent.ctrlKey)) {
8890 this.contextEventTarget = Event.getTarget(p_oEvent);
8892 this.triggerContextMenuEvent.fire(p_oEvent);
8895 if (!this._bCancelled) {
8898 Prevent the browser's default context menu from appearing and
8899 stop the propagation of the "contextmenu" event so that
8900 other ContextMenu instances are not displayed.
8903 Event.stopEvent(p_oEvent);
8906 // Hide any other Menu instances that might be visible
8908 YAHOO.widget.MenuManager.hideVisible();
8912 // Position and display the context menu
8914 aXY = Event.getXY(p_oEvent);
8917 if (!YAHOO.util.Dom.inDocument(this.element)) {
8919 this.beforeShowEvent.subscribe(position, aXY);
8924 this.cfg.setProperty(_XY, aXY);
8933 this._bCancelled = false;
8946 * @description Returns a string representing the context menu.
8949 toString: function() {
8951 var sReturnVal = _CONTEXTMENU,
8956 sReturnVal += (_SPACE + sId);
8966 * @method initDefaultConfig
8967 * @description Initializes the class's configurable properties which can be
8968 * changed using the context menu's Config object ("cfg").
8970 initDefaultConfig: function() {
8972 ContextMenu.superclass.initDefaultConfig.call(this);
8976 * @description The HTML element(s) whose "contextmenu" event ("mousedown"
8977 * for Opera) trigger the display of the context menu. Can be a string
8978 * representing the id attribute of the HTML element, an object reference
8979 * for the HTML element, or an array of strings or HTML element references.
8981 * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
8982 * level-one-html.html#ID-58190037">HTMLElement</a>|Array
8984 this.cfg.addProperty(TRIGGER_CONFIG.key,
8986 handler: this.configTrigger,
8987 suppressEvent: TRIGGER_CONFIG.suppressEvent
8996 * @description Removes the context menu's <code><div></code> element
8997 * (and accompanying child nodes) from the document.
8999 destroy: function() {
9001 // Remove the DOM event handlers from the current trigger(s)
9003 this._removeEventHandlers();
9006 // Continue with the superclass implementation of this method
9008 ContextMenu.superclass.destroy.call(this);
9014 // Public event handlers for configuration properties
9018 * @method configTrigger
9019 * @description Event handler for when the value of the "trigger" configuration
9021 * @param {String} p_sType String representing the name of the event that
9023 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
9024 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
9025 * menu that fired the event.
9027 configTrigger: function(p_sType, p_aArgs, p_oMenu) {
9029 var oTrigger = p_aArgs[0];
9034 If there is a current "trigger" - remove the event handlers
9035 from that element(s) before assigning new ones
9038 if (this._oTrigger) {
9040 this._removeEventHandlers();
9044 this._oTrigger = oTrigger;
9048 Listen for the "mousedown" event in Opera b/c it does not
9049 support the "contextmenu" event
9052 Event.on(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu, this, true);
9056 Assign a "click" event handler to the trigger element(s) for
9057 Opera to prevent default browser behaviors.
9062 Event.on(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick, this, true);
9069 this._removeEventHandlers();
9075 }); // END YAHOO.lang.extend
9082 * Creates an item for a context menu.
9084 * @param {String} p_oObject String specifying the text of the context menu item.
9085 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9086 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9087 * <code><li></code> element of the context menu item.
9088 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9089 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9090 * specifying the <code><optgroup></code> element of the context
9092 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9093 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9094 * the <code><option></code> element of the context menu item.
9095 * @param {Object} p_oConfig Optional. Object literal specifying the
9096 * configuration for the context menu item. See configuration class
9097 * documentation for more details.
9098 * @class ContextMenuItem
9100 * @extends YAHOO.widget.MenuItem
9101 * @deprecated As of version 2.4.0 items for YAHOO.widget.ContextMenu instances
9102 * are of type YAHOO.widget.MenuItem.
9104 YAHOO.widget.ContextMenuItem = YAHOO.widget.MenuItem;
9107 var Lang = YAHOO.lang,
9112 _DYNAMIC_STATIC = "dynamic," + _STATIC,
9113 _DISABLED = "disabled",
9114 _SELECTED = "selected",
9115 _AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
9116 _SUBMENU = "submenu",
9117 _VISIBLE = "visible",
9119 _SUBMENU_TOGGLE_REGION = "submenutoggleregion",
9120 _MENUBAR = "MenuBar";
9123 * Horizontal collection of items, each of which can contain a submenu.
9125 * @param {String} p_oElement String specifying the id attribute of the
9126 * <code><div></code> element of the menu bar.
9127 * @param {String} p_oElement String specifying the id attribute of the
9128 * <code><select></code> element to be used as the data source for the
9130 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9131 * one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying
9132 * the <code><div></code> element of the menu bar.
9133 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9134 * one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object
9135 * specifying the <code><select></code> element to be used as the data
9136 * source for the menu bar.
9137 * @param {Object} p_oConfig Optional. Object literal specifying the
9138 * configuration for the menu bar. See configuration class documentation for
9142 * @extends YAHOO.widget.Menu
9143 * @namespace YAHOO.widget
9145 YAHOO.widget.MenuBar = function(p_oElement, p_oConfig) {
9147 YAHOO.widget.MenuBar.superclass.constructor.call(this, p_oElement, p_oConfig);
9153 * @method checkPosition
9154 * @description Checks to make sure that the value of the "position" property
9155 * is one of the supported strings. Returns true if the position is supported.
9157 * @param {Object} p_sPosition String specifying the position of the menu.
9160 function checkPosition(p_sPosition) {
9162 var returnVal = false;
9164 if (Lang.isString(p_sPosition)) {
9166 returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
9175 var Event = YAHOO.util.Event,
9176 MenuBar = YAHOO.widget.MenuBar,
9181 validator: checkPosition,
9182 supercedes: [_VISIBLE]
9185 SUBMENU_ALIGNMENT_CONFIG = {
9186 key: "submenualignment",
9190 AUTO_SUBMENU_DISPLAY_CONFIG = {
9191 key: _AUTO_SUBMENU_DISPLAY,
9193 validator: Lang.isBoolean,
9197 SUBMENU_TOGGLE_REGION_CONFIG = {
9198 key: _SUBMENU_TOGGLE_REGION,
9200 validator: Lang.isBoolean
9205 Lang.extend(MenuBar, YAHOO.widget.Menu, {
9209 * @description The MenuBar class's initialization method. This method is
9210 * automatically called by the constructor, and sets up all DOM references for
9211 * pre-existing markup, and creates required markup if it is not already present.
9212 * @param {String} p_oElement String specifying the id attribute of the
9213 * <code><div></code> element of the menu bar.
9214 * @param {String} p_oElement String specifying the id attribute of the
9215 * <code><select></code> element to be used as the data source for the
9217 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9218 * one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying
9219 * the <code><div></code> element of the menu bar.
9220 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9221 * one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object
9222 * specifying the <code><select></code> element to be used as the data
9223 * source for the menu bar.
9224 * @param {Object} p_oConfig Optional. Object literal specifying the
9225 * configuration for the menu bar. See configuration class documentation for
9228 init: function(p_oElement, p_oConfig) {
9230 if(!this.ITEM_TYPE) {
9232 this.ITEM_TYPE = YAHOO.widget.MenuBarItem;
9237 // Call the init of the superclass (YAHOO.widget.Menu)
9239 MenuBar.superclass.init.call(this, p_oElement);
9242 this.beforeInitEvent.fire(MenuBar);
9247 this.cfg.applyConfig(p_oConfig, true);
9251 this.initEvent.fire(MenuBar);
9261 * @property CSS_CLASS_NAME
9262 * @description String representing the CSS class(es) to be applied to the menu
9263 * bar's <code><div></code> element.
9264 * @default "yuimenubar"
9268 CSS_CLASS_NAME: "yuimenubar",
9272 * @property SUBMENU_TOGGLE_REGION_WIDTH
9273 * @description Width (in pixels) of the area of a MenuBarItem that, when pressed, will toggle the
9274 * display of the MenuBarItem's submenu.
9279 SUBMENU_TOGGLE_REGION_WIDTH: 20,
9282 // Protected event handlers
9286 * @method _onKeyDown
9287 * @description "keydown" Custom Event handler for the menu bar.
9289 * @param {String} p_sType String representing the name of the event that
9291 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
9292 * @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar
9293 * that fired the event.
9295 _onKeyDown: function(p_sType, p_aArgs, p_oMenuBar) {
9297 var oEvent = p_aArgs[0],
9304 if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9306 oItemCfg = oItem.cfg;
9308 switch(oEvent.keyCode) {
9310 case 37: // Left arrow
9311 case 39: // Right arrow
9313 if(oItem == this.activeItem && !oItemCfg.getProperty(_SELECTED)) {
9315 oItemCfg.setProperty(_SELECTED, true);
9320 oNextItem = (oEvent.keyCode == 37) ?
9321 oItem.getPreviousEnabledSibling() :
9322 oItem.getNextEnabledSibling();
9326 this.clearActiveItem();
9328 oNextItem.cfg.setProperty(_SELECTED, true);
9330 oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
9335 oSubmenu.setInitialFocus();
9346 Event.preventDefault(oEvent);
9350 case 40: // Down arrow
9352 if(this.activeItem != oItem) {
9354 this.clearActiveItem();
9356 oItemCfg.setProperty(_SELECTED, true);
9361 oSubmenu = oItemCfg.getProperty(_SUBMENU);
9365 if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9367 oSubmenu.setInitialSelection();
9368 oSubmenu.setInitialFocus();
9374 oSubmenu.setInitialFocus();
9380 Event.preventDefault(oEvent);
9389 if(oEvent.keyCode == 27 && this.activeItem) { // Esc key
9391 oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
9393 if(oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
9396 this.activeItem.focus();
9401 this.activeItem.cfg.setProperty(_SELECTED, false);
9402 this.activeItem.blur();
9406 Event.preventDefault(oEvent);
9415 * @description "click" event handler for the menu bar.
9417 * @param {String} p_sType String representing the name of the event that
9419 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
9420 * @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar
9421 * that fired the event.
9423 _onClick: function(p_sType, p_aArgs, p_oMenuBar) {
9425 MenuBar.superclass._onClick.call(this, p_sType, p_aArgs, p_oMenuBar);
9427 var oItem = p_aArgs[1],
9439 var toggleSubmenuDisplay = function () {
9441 if(oSubmenu.cfg.getProperty(_VISIBLE)) {
9455 if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
9457 oEvent = p_aArgs[0];
9458 oTarget = Event.getTarget(oEvent);
9459 oActiveItem = this.activeItem;
9463 // Hide any other submenus that might be visible
9465 if(oActiveItem && oActiveItem != oItem) {
9467 this.clearActiveItem();
9472 oItem.cfg.setProperty(_SELECTED, true);
9475 // Show the submenu for the item
9477 oSubmenu = oItem.cfg.getProperty(_SUBMENU);
9482 oItemEl = oItem.element;
9483 nMenuItemX = YAHOO.util.Dom.getX(oItemEl);
9484 nToggleRegion = nMenuItemX + (oItemEl.offsetWidth - this.SUBMENU_TOGGLE_REGION_WIDTH);
9486 if (oConfig.getProperty(_SUBMENU_TOGGLE_REGION)) {
9488 if (Event.getPageX(oEvent) > nToggleRegion) {
9490 toggleSubmenuDisplay();
9492 Event.preventDefault(oEvent);
9495 Return false so that other click event handlers are not called when the
9496 user clicks inside the toggle region.
9505 toggleSubmenuDisplay();
9523 * @method configSubmenuToggle
9524 * @description Event handler for when the "submenutoggleregion" configuration property of
9525 * a MenuBar changes.
9526 * @param {String} p_sType The name of the event that was fired.
9527 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
9529 configSubmenuToggle: function (p_sType, p_aArgs) {
9531 var bSubmenuToggle = p_aArgs[0];
9533 if (bSubmenuToggle) {
9535 this.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
9544 * @description Returns a string representing the menu bar.
9547 toString: function() {
9549 var sReturnVal = _MENUBAR,
9554 sReturnVal += (_SPACE + sId);
9564 * @description Initializes the class's configurable properties which can be
9565 * changed using the menu bar's Config object ("cfg").
9566 * @method initDefaultConfig
9568 initDefaultConfig: function() {
9570 MenuBar.superclass.initDefaultConfig.call(this);
9572 var oConfig = this.cfg;
9574 // Add configuration properties
9578 Set the default value for the "position" configuration property
9579 to "static" by re-adding the property.
9585 * @description String indicating how a menu bar should be positioned on the
9586 * screen. Possible values are "static" and "dynamic." Static menu bars
9587 * are visible by default and reside in the normal flow of the document
9588 * (CSS position: static). Dynamic menu bars are hidden by default, reside
9589 * out of the normal flow of the document (CSS position: absolute), and can
9590 * overlay other elements on the screen.
9594 oConfig.addProperty(
9595 POSITION_CONFIG.key,
9597 handler: this.configPosition,
9598 value: POSITION_CONFIG.value,
9599 validator: POSITION_CONFIG.validator,
9600 supercedes: POSITION_CONFIG.supercedes
9606 Set the default value for the "submenualignment" configuration property
9607 to ["tl","bl"] by re-adding the property.
9611 * @config submenualignment
9612 * @description Array defining how submenus should be aligned to their
9613 * parent menu bar item. The format is: [itemCorner, submenuCorner].
9614 * @default ["tl","bl"]
9617 oConfig.addProperty(
9618 SUBMENU_ALIGNMENT_CONFIG.key,
9620 value: SUBMENU_ALIGNMENT_CONFIG.value,
9621 suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
9627 Change the default value for the "autosubmenudisplay" configuration
9628 property to "false" by re-adding the property.
9632 * @config autosubmenudisplay
9633 * @description Boolean indicating if submenus are automatically made
9634 * visible when the user mouses over the menu bar's items.
9638 oConfig.addProperty(
9639 AUTO_SUBMENU_DISPLAY_CONFIG.key,
9641 value: AUTO_SUBMENU_DISPLAY_CONFIG.value,
9642 validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
9643 suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
9649 * @config submenutoggleregion
9650 * @description Boolean indicating if only a specific region of a MenuBarItem should toggle the
9651 * display of a submenu. The default width of the region is determined by the value of the
9652 * SUBMENU_TOGGLE_REGION_WIDTH property. If set to true, the autosubmenudisplay
9653 * configuration property will be set to false, and any click event listeners will not be
9654 * called when the user clicks inside the submenu toggle region of a MenuBarItem. If the
9655 * user clicks outside of the submenu toggle region, the MenuBarItem will maintain its
9656 * standard behavior.
9660 oConfig.addProperty(
9661 SUBMENU_TOGGLE_REGION_CONFIG.key,
9663 value: SUBMENU_TOGGLE_REGION_CONFIG.value,
9664 validator: SUBMENU_TOGGLE_REGION_CONFIG.validator,
9665 handler: this.configSubmenuToggle
9671 }); // END YAHOO.lang.extend
9678 * Creates an item for a menu bar.
9680 * @param {String} p_oObject String specifying the text of the menu bar item.
9681 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9682 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9683 * <code><li></code> element of the menu bar item.
9684 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9685 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9686 * specifying the <code><optgroup></code> element of the menu bar item.
9687 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9688 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9689 * the <code><option></code> element of the menu bar item.
9690 * @param {Object} p_oConfig Optional. Object literal specifying the
9691 * configuration for the menu bar item. See configuration class documentation
9693 * @class MenuBarItem
9695 * @extends YAHOO.widget.MenuItem
9697 YAHOO.widget.MenuBarItem = function(p_oObject, p_oConfig) {
9699 YAHOO.widget.MenuBarItem.superclass.constructor.call(this, p_oObject, p_oConfig);
9703 YAHOO.lang.extend(YAHOO.widget.MenuBarItem, YAHOO.widget.MenuItem, {
9709 * @description The MenuBarItem class's initialization method. This method is
9710 * automatically called by the constructor, and sets up all DOM references for
9711 * pre-existing markup, and creates required markup if it is not already present.
9712 * @param {String} p_oObject String specifying the text of the menu bar item.
9713 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9714 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
9715 * <code><li></code> element of the menu bar item.
9716 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9717 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
9718 * specifying the <code><optgroup></code> element of the menu bar item.
9719 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
9720 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
9721 * the <code><option></code> element of the menu bar item.
9722 * @param {Object} p_oConfig Optional. Object literal specifying the
9723 * configuration for the menu bar item. See configuration class documentation
9726 init: function(p_oObject, p_oConfig) {
9728 if(!this.SUBMENU_TYPE) {
9730 this.SUBMENU_TYPE = YAHOO.widget.Menu;
9736 Call the init of the superclass (YAHOO.widget.MenuItem)
9737 Note: We don't pass the user config in here yet
9738 because we only want it executed once, at the lowest
9742 YAHOO.widget.MenuBarItem.superclass.init.call(this, p_oObject);
9745 var oConfig = this.cfg;
9749 oConfig.applyConfig(p_oConfig, true);
9753 oConfig.fireQueue();
9763 * @property CSS_CLASS_NAME
9764 * @description String representing the CSS class(es) to be applied to the
9765 * <code><li></code> element of the menu bar item.
9766 * @default "yuimenubaritem"
9770 CSS_CLASS_NAME: "yuimenubaritem",
9774 * @property CSS_LABEL_CLASS_NAME
9775 * @description String representing the CSS class(es) to be applied to the
9776 * menu bar item's <code><a></code> element.
9777 * @default "yuimenubaritemlabel"
9781 CSS_LABEL_CLASS_NAME: "yuimenubaritemlabel",
9790 * @description Returns a string representing the menu bar item.
9793 toString: function() {
9795 var sReturnVal = "MenuBarItem";
9797 if(this.cfg && this.cfg.getProperty("text")) {
9799 sReturnVal += (": " + this.cfg.getProperty("text"));
9807 }); // END YAHOO.lang.extend
9808 YAHOO.register("menu", YAHOO.widget.Menu, {version: "2.7.0", build: "1799"});