2 Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
11 * @description <p>The Menu family of components features a collection of
12 * controls that make it easy to add menus to your website or web application.
13 * With the Menu Controls you can create website fly-out menus, customized
14 * context menus, or application-style menu bars with just a small amount of
15 * scripting.</p><p>The Menu family of controls features:</p>
17 * <li>Keyboard and mouse navigation.</li>
18 * <li>A rich event model that provides access to all of a menu's
19 * interesting moments.</li>
21 * <a href="http://en.wikipedia.org/wiki/Progressive_Enhancement">Progressive
22 * Enhancement</a>; Menus can be created from simple,
23 * semantic markup on the page or purely through JavaScript.</li>
26 * @namespace YAHOO.widget
27 * @requires Event, Dom, Container
31 var Dom
= YAHOO
.util
.Dom
,
32 Event
= YAHOO
.util
.Event
;
36 * Singleton that manages a collection of all menus and menu items. Listens
37 * for DOM events at the document level and dispatches the events to the
38 * corresponding menu or menu item.
40 * @namespace YAHOO.widget
44 YAHOO
.widget
.MenuManager = function () {
46 // Private member variables
49 // Flag indicating if the DOM event handlers have been attached
51 var m_bInitializedEventHandlers
= false,
54 // Collection of menus
59 // Collection of visible menus
64 // Collection of menu items
69 // Map of DOM event types to their equivalent CustomEvent types
72 "click": "clickEvent",
73 "mousedown": "mouseDownEvent",
74 "mouseup": "mouseUpEvent",
75 "mouseover": "mouseOverEvent",
76 "mouseout": "mouseOutEvent",
77 "keydown": "keyDownEvent",
78 "keyup": "keyUpEvent",
79 "keypress": "keyPressEvent"
83 m_oFocusedMenuItem
= null;
86 var m_oLogger
= new YAHOO
.widget
.LogWriter("MenuManager");
94 * @method getMenuRootElement
95 * @description Finds the root DIV node of a menu or the root LI node of
98 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
99 * level-one-html.html#ID-58190037">HTMLElement</a>} p_oElement Object
100 * specifying an HTML element.
102 function getMenuRootElement(p_oElement
) {
106 if (p_oElement
&& p_oElement
.tagName
) {
108 switch (p_oElement
.tagName
.toUpperCase()) {
112 oParentNode
= p_oElement
.parentNode
;
114 // Check if the DIV is the inner "body" node of a menu
118 Dom
.hasClass(p_oElement
, "hd") ||
119 Dom
.hasClass(p_oElement
, "bd") ||
120 Dom
.hasClass(p_oElement
, "ft")
123 oParentNode
.tagName
&&
124 oParentNode
.tagName
.toUpperCase() == "DIV")
144 oParentNode
= p_oElement
.parentNode
;
148 return getMenuRootElement(oParentNode
);
162 // Private event handlers
167 * @description Generic, global event handler for all of a menu's
168 * DOM-based events. This listens for events against the document
169 * object. If the target of a given event is a member of a menu or
170 * menu item's DOM, the instance's corresponding Custom Event is fired.
172 * @param {Event} p_oEvent Object representing the DOM event object
173 * passed back by the event utility (YAHOO.util.Event).
175 function onDOMEvent(p_oEvent
) {
177 // Get the target node of the DOM event
179 var oTarget
= Event
.getTarget(p_oEvent
),
181 // See if the target of the event was a menu, or a menu item
183 oElement
= getMenuRootElement(oTarget
),
193 sTagName
= oElement
.tagName
.toUpperCase();
195 if (sTagName
== "LI") {
199 if (sId
&& m_oItems
[sId
]) {
201 oMenuItem
= m_oItems
[sId
];
202 oMenu
= oMenuItem
.parent
;
207 else if (sTagName
== "DIV") {
211 oMenu
= m_oMenus
[oElement
.id
];
222 sCustomEventType
= m_oEventTypes
[p_oEvent
.type
];
225 // Fire the Custom Event that corresponds the current DOM event
227 if (oMenuItem
&& !oMenuItem
.cfg
.getProperty("disabled")) {
229 oMenuItem
[sCustomEventType
].fire(p_oEvent
);
233 p_oEvent
.type
== "keyup" ||
234 p_oEvent
.type
== "mousedown")
237 if (m_oFocusedMenuItem
!= oMenuItem
) {
239 if (m_oFocusedMenuItem
) {
241 m_oFocusedMenuItem
.blurEvent
.fire();
245 oMenuItem
.focusEvent
.fire();
253 oMenu
[sCustomEventType
].fire(p_oEvent
, oMenuItem
);
256 else if (p_oEvent
.type
== "mousedown") {
258 if (m_oFocusedMenuItem
) {
260 m_oFocusedMenuItem
.blurEvent
.fire();
262 m_oFocusedMenuItem
= null;
268 If the target of the event wasn't a menu, hide all
269 dynamically positioned menus
272 for (var i
in m_oVisibleMenus
) {
274 if (YAHOO
.lang
.hasOwnProperty(m_oVisibleMenus
, i
)) {
276 oMenu
= m_oVisibleMenus
[i
];
278 if (oMenu
.cfg
.getProperty("clicktohide") &&
279 !(oMenu
instanceof YAHOO
.widget
.MenuBar
) &&
280 oMenu
.cfg
.getProperty("position") == "dynamic") {
287 if (oMenu
.cfg
.getProperty("showdelay") > 0) {
289 oMenu
._cancelShowDelay();
294 if (oMenu
.activeItem
) {
296 oMenu
.activeItem
.blur();
297 oMenu
.activeItem
.cfg
.setProperty("selected", false);
299 oMenu
.activeItem
= null;
310 else if (p_oEvent
.type
== "keyup") {
312 if (m_oFocusedMenuItem
) {
314 m_oFocusedMenuItem
.blurEvent
.fire();
316 m_oFocusedMenuItem
= null;
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
[0];
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 * @method onMenuVisibleConfigChange
387 * @description Event handler for when the "visible" configuration
388 * property of a Menu instance changes.
390 * @param {String} p_sType String representing the name of the event
392 * @param {Array} p_aArgs Array of arguments sent when the event
395 function onMenuVisibleConfigChange(p_sType
, p_aArgs
) {
397 var bVisible
= p_aArgs
[0],
402 m_oVisibleMenus
[sId
] = this;
406 " added to the collection of visible menus.");
409 else if (m_oVisibleMenus
[sId
]) {
411 delete m_oVisibleMenus
[sId
];
415 " removed from the collection of visible menus.");
423 * @method onItemDestroy
424 * @description "destroy" event handler for a MenuItem instance.
426 * @param {String} p_sType String representing the name of the event
428 * @param {Array} p_aArgs Array of arguments sent when the event
431 function onItemDestroy(p_sType
, p_aArgs
) {
438 function removeItem(p_oMenuItem
) {
440 var sId
= p_oMenuItem
.id
;
442 if (sId
&& m_oItems
[sId
]) {
444 if (m_oFocusedMenuItem
== p_oMenuItem
) {
446 m_oFocusedMenuItem
= null;
450 delete m_oItems
[sId
];
452 p_oMenuItem
.destroyEvent
.unsubscribe(onItemDestroy
);
454 m_oLogger
.log(p_oMenuItem
+ " successfully unregistered.");
462 * @method onItemAdded
463 * @description "itemadded" event handler for a Menu instance.
465 * @param {String} p_sType String representing the name of the event
467 * @param {Array} p_aArgs Array of arguments sent when the event
470 function onItemAdded(p_sType
, p_aArgs
) {
472 var oItem
= p_aArgs
[0],
475 if (oItem
instanceof YAHOO
.widget
.MenuItem
) {
479 if (!m_oItems
[sId
]) {
481 m_oItems
[sId
] = oItem
;
483 oItem
.destroyEvent
.subscribe(onItemDestroy
);
485 m_oLogger
.log(oItem
+ " successfully registered.");
496 // Privileged methods
501 * @description Adds a menu to the collection of known menus.
502 * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
503 * instance to be added.
505 addMenu: function (p_oMenu
) {
509 if (p_oMenu
instanceof YAHOO
.widget
.Menu
&& p_oMenu
.id
&&
510 !m_oMenus
[p_oMenu
.id
]) {
512 m_oMenus
[p_oMenu
.id
] = p_oMenu
;
515 if (!m_bInitializedEventHandlers
) {
519 Event
.on(oDoc
, "mouseover", onDOMEvent
, this, true);
520 Event
.on(oDoc
, "mouseout", onDOMEvent
, this, true);
521 Event
.on(oDoc
, "mousedown", onDOMEvent
, this, true);
522 Event
.on(oDoc
, "mouseup", onDOMEvent
, this, true);
523 Event
.on(oDoc
, "click", onDOMEvent
, this, true);
524 Event
.on(oDoc
, "keydown", onDOMEvent
, this, true);
525 Event
.on(oDoc
, "keyup", onDOMEvent
, this, true);
526 Event
.on(oDoc
, "keypress", onDOMEvent
, this, true);
529 m_bInitializedEventHandlers
= true;
531 m_oLogger
.log("DOM event handlers initialized.");
535 p_oMenu
.cfg
.subscribeToConfigEvent("visible",
536 onMenuVisibleConfigChange
);
538 p_oMenu
.destroyEvent
.subscribe(onMenuDestroy
, p_oMenu
,
541 p_oMenu
.itemAddedEvent
.subscribe(onItemAdded
);
542 p_oMenu
.focusEvent
.subscribe(onMenuFocus
);
543 p_oMenu
.blurEvent
.subscribe(onMenuBlur
);
545 m_oLogger
.log(p_oMenu
+ " successfully registered.");
554 * @description Removes a menu from the collection of known menus.
555 * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu
556 * instance to be removed.
558 removeMenu: function (p_oMenu
) {
568 if (m_oMenus
[sId
] == p_oMenu
) {
570 // Unregister each menu item
572 aItems
= p_oMenu
.getItems();
574 if (aItems
&& aItems
.length
> 0) {
576 i
= aItems
.length
- 1;
580 removeItem(aItems
[i
]);
588 // Unregister the menu
590 delete m_oMenus
[sId
];
592 m_oLogger
.log(p_oMenu
+ " successfully unregistered.");
596 Unregister the menu from the collection of
600 if (m_oVisibleMenus
[sId
] == p_oMenu
) {
602 delete m_oVisibleMenus
[sId
];
604 m_oLogger
.log(p_oMenu
+ " unregistered from the" +
605 " collection of visible menus.");
610 // Unsubscribe event listeners
614 p_oMenu
.cfg
.unsubscribeFromConfigEvent("visible",
615 onMenuVisibleConfigChange
);
619 p_oMenu
.destroyEvent
.unsubscribe(onMenuDestroy
,
622 p_oMenu
.itemAddedEvent
.unsubscribe(onItemAdded
);
623 p_oMenu
.focusEvent
.unsubscribe(onMenuFocus
);
624 p_oMenu
.blurEvent
.unsubscribe(onMenuBlur
);
634 * @method hideVisible
635 * @description Hides all visible, dynamically positioned menus
636 * (excluding instances of YAHOO.widget.MenuBar).
638 hideVisible: function () {
642 for (var i
in m_oVisibleMenus
) {
644 if (YAHOO
.lang
.hasOwnProperty(m_oVisibleMenus
, i
)) {
646 oMenu
= m_oVisibleMenus
[i
];
648 if (!(oMenu
instanceof YAHOO
.widget
.MenuBar
) &&
649 oMenu
.cfg
.getProperty("position") == "dynamic") {
664 * @description Returns a collection of all visible menus registered
665 * with the menu manger.
668 getVisible: function () {
670 return m_oVisibleMenus
;
677 * @description Returns a collection of all menus registered with the
681 getMenus: function () {
690 * @description Returns a menu with the specified id.
691 * @param {String} p_sId String specifying the id of the
692 * <code><div></code> element representing the menu to
694 * @return {YAHOO.widget.Menu}
696 getMenu: function (p_sId
) {
698 var oMenu
= m_oMenus
[p_sId
];
710 * @method getMenuItem
711 * @description Returns a menu item with the specified id.
712 * @param {String} p_sId String specifying the id of the
713 * <code><li></code> element representing the menu item to
715 * @return {YAHOO.widget.MenuItem}
717 getMenuItem: function (p_sId
) {
719 var oItem
= m_oItems
[p_sId
];
731 * @method getMenuItemGroup
732 * @description Returns an array of menu item instances whose
733 * corresponding <code><li></code> elements are child
734 * nodes of the <code><ul></code> element with the
736 * @param {String} p_sId String specifying the id of the
737 * <code><ul></code> element representing the group of
738 * menu items to be retrieved.
741 getMenuItemGroup: function (p_sId
) {
743 var oUL
= Dom
.get(p_sId
),
750 if (oUL
&& oUL
.tagName
&&
751 oUL
.tagName
.toUpperCase() == "UL") {
753 oNode
= oUL
.firstChild
;
765 oItem
= this.getMenuItem(sId
);
769 aItems
[aItems
.length
] = oItem
;
776 while ((oNode
= oNode
.nextSibling
));
779 if (aItems
.length
> 0) {
793 * @method getFocusedMenuItem
794 * @description Returns a reference to the menu item that currently
796 * @return {YAHOO.widget.MenuItem}
798 getFocusedMenuItem: function () {
800 return m_oFocusedMenuItem
;
806 * @method getFocusedMenu
807 * @description Returns a reference to the menu that currently
809 * @return {YAHOO.widget.Menu}
811 getFocusedMenu: function () {
813 if (m_oFocusedMenuItem
) {
815 return (m_oFocusedMenuItem
.parent
.getRoot());
824 * @description Returns a string representing the menu manager.
827 toString: function () {
829 return "MenuManager";
845 * The Menu class creates a container that holds a vertical list representing
846 * a set of options or commands. Menu is the base class for all
848 * @param {String} p_oElement String specifying the id attribute of the
849 * <code><div></code> element of the menu.
850 * @param {String} p_oElement String specifying the id attribute of the
851 * <code><select></code> element to be used as the data source
853 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
854 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
855 * specifying the <code><div></code> element of the menu.
856 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
857 * level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
858 * Object specifying the <code><select></code> element to be used as
859 * the data source for the menu.
860 * @param {Object} p_oConfig Optional. Object literal specifying the
861 * configuration for the menu. See configuration class documentation for
863 * @namespace YAHOO.widget
866 * @extends YAHOO.widget.Overlay
868 YAHOO
.widget
.Menu = function (p_oElement
, p_oConfig
) {
872 this.parent
= p_oConfig
.parent
;
873 this.lazyLoad
= p_oConfig
.lazyLoad
|| p_oConfig
.lazyload
;
874 this.itemData
= p_oConfig
.itemData
|| p_oConfig
.itemdata
;
879 YAHOO
.widget
.Menu
.superclass
.constructor.call(this, p_oElement
, p_oConfig
);
886 * @method checkPosition
887 * @description Checks to make sure that the value of the "position" property
888 * is one of the supported strings. Returns true if the position is supported.
890 * @param {Object} p_sPosition String specifying the position of the menu.
893 function checkPosition(p_sPosition
) {
895 if (typeof p_sPosition
== "string") {
897 return ("dynamic,static".indexOf((p_sPosition
.toLowerCase())) != -1);
904 var Dom
= YAHOO
.util
.Dom
,
905 Event
= YAHOO
.util
.Event
,
906 Module
= YAHOO
.widget
.Module
,
907 Overlay
= YAHOO
.widget
.Overlay
,
908 Menu
= YAHOO
.widget
.Menu
,
909 MenuManager
= YAHOO
.widget
.MenuManager
,
910 CustomEvent
= YAHOO
.util
.CustomEvent
,
917 * Constant representing the name of the Menu's events
918 * @property EVENT_TYPES
925 "MOUSE_OVER": "mouseover",
926 "MOUSE_OUT": "mouseout",
927 "MOUSE_DOWN": "mousedown",
928 "MOUSE_UP": "mouseup",
930 "KEY_PRESS": "keypress",
931 "KEY_DOWN": "keydown",
935 "ITEM_ADDED": "itemAdded",
936 "ITEM_REMOVED": "itemRemoved"
942 * Constant representing the Menu's configuration properties
943 * @property DEFAULT_CONFIG
953 validator
: Lang
.isBoolean
956 "CONSTRAIN_TO_VIEWPORT": {
957 key
: "constraintoviewport",
959 validator
: Lang
.isBoolean
,
960 supercedes
: ["iframe","x","y","xy"]
966 validator
: checkPosition
,
967 supercedes
: ["visible", "iframe"]
970 "SUBMENU_ALIGNMENT": {
971 key
: "submenualignment",
976 "AUTO_SUBMENU_DISPLAY": {
977 key
: "autosubmenudisplay",
979 validator
: Lang
.isBoolean
,
986 validator
: Lang
.isNumber
,
993 validator
: Lang
.isNumber
,
997 "SUBMENU_HIDE_DELAY": {
998 key
: "submenuhidedelay",
1000 validator
: Lang
.isNumber
,
1007 validator
: Lang
.isBoolean
,
1016 "SCROLL_INCREMENT": {
1017 key
: "scrollincrement",
1019 validator
: Lang
.isNumber
,
1020 supercedes
: ["maxheight"],
1024 "MIN_SCROLL_HEIGHT": {
1025 key
: "minscrollheight",
1027 validator
: Lang
.isNumber
,
1028 supercedes
: ["maxheight"],
1035 validator
: Lang
.isNumber
,
1036 supercedes
: ["iframe"],
1043 validator
: Lang
.isString
,
1050 validator
: Lang
.isBoolean
,
1058 YAHOO
.lang
.extend(Menu
, Overlay
, {
1065 * @property CSS_CLASS_NAME
1066 * @description String representing the CSS class(es) to be applied to the
1067 * menu's <code><div></code> element.
1068 * @default "yuimenu"
1072 CSS_CLASS_NAME
: "yuimenu",
1076 * @property ITEM_TYPE
1077 * @description Object representing the type of menu item to instantiate and
1078 * add when parsing the child nodes (either <code><li></code> element,
1079 * <code><optgroup></code> element or <code><option></code>)
1080 * of the menu's source HTML element.
1081 * @default YAHOO.widget.MenuItem
1083 * @type YAHOO.widget.MenuItem
1089 * @property GROUP_TITLE_TAG_NAME
1090 * @description String representing the tagname of the HTML element used to
1091 * title the menu's item groups.
1096 GROUP_TITLE_TAG_NAME
: "h6",
1100 * @property OFF_SCREEN_POSITION
1101 * @description Array representing the default x and y position that a menu
1102 * should have when it is positioned outside the viewport by the
1103 * "poistionOffScreen" method.
1104 * @default [-10000, -10000]
1108 OFF_SCREEN_POSITION
: [-10000, -10000],
1111 // Private properties
1115 * @property _nHideDelayId
1116 * @description Number representing the time-out setting used to cancel the
1122 _nHideDelayId
: null,
1126 * @property _nShowDelayId
1127 * @description Number representing the time-out setting used to cancel the
1128 * showing of a menu.
1133 _nShowDelayId
: null,
1137 * @property _nSubmenuHideDelayId
1138 * @description Number representing the time-out setting used to cancel the
1139 * hiding of a submenu.
1144 _nSubmenuHideDelayId
: null,
1148 * @property _nBodyScrollId
1149 * @description Number representing the time-out setting used to cancel the
1150 * scrolling of the menu's body element.
1155 _nBodyScrollId
: null,
1159 * @property _bHideDelayEventHandlersAssigned
1160 * @description Boolean indicating if the "mouseover" and "mouseout" event
1161 * handlers used for hiding the menu via a call to "window.setTimeout" have
1162 * already been assigned.
1167 _bHideDelayEventHandlersAssigned
: false,
1171 * @property _bHandledMouseOverEvent
1172 * @description Boolean indicating the current state of the menu's
1173 * "mouseover" event.
1178 _bHandledMouseOverEvent
: false,
1182 * @property _bHandledMouseOutEvent
1183 * @description Boolean indicating the current state of the menu's
1189 _bHandledMouseOutEvent
: false,
1193 * @property _aGroupTitleElements
1194 * @description Array of HTML element used to title groups of menu items.
1199 _aGroupTitleElements
: null,
1203 * @property _aItemGroups
1204 * @description Multi-dimensional Array representing the menu items as they
1205 * are grouped in the menu.
1214 * @property _aListElements
1215 * @description Array of <code><ul></code> elements, each of which is
1216 * the parent node for each item's <code><li></code> element.
1221 _aListElements
: null,
1225 * @property _nCurrentMouseX
1226 * @description The current x coordinate of the mouse inside the area of
1236 * @property _bStopMouseEventHandlers
1237 * @description Stops "mouseover," "mouseout," and "mousemove" event handlers
1243 _bStopMouseEventHandlers
: false,
1247 * @property _sClassName
1248 * @description The current value of the "classname" configuration attribute.
1257 // Public properties
1261 * @property lazyLoad
1262 * @description Boolean indicating if the menu's "lazy load" feature is
1263 * enabled. If set to "true," initialization and rendering of the menu's
1264 * items will be deferred until the first time it is made visible. This
1265 * property should be set via the constructor using the configuration
1274 * @property itemData
1275 * @description Array of items to be added to the menu. The array can contain
1276 * strings representing the text for each item to be created, object literals
1277 * representing the menu item configuration properties, or MenuItem instances.
1278 * This property should be set via the constructor using the configuration
1287 * @property activeItem
1288 * @description Object reference to the item in the menu that has is selected.
1290 * @type YAHOO.widget.MenuItem
1297 * @description Object reference to the menu's parent menu or menu item.
1298 * This property can be set via the constructor using the configuration
1301 * @type YAHOO.widget.MenuItem
1307 * @property srcElement
1308 * @description Object reference to the HTML element (either
1309 * <code><select></code> or <code><div></code>) used to
1312 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1313 * level-one-html.html#ID-94282980">HTMLSelectElement</a>|<a
1314 * href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.
1315 * html#ID-22445964">HTMLDivElement</a>
1325 * @event mouseOverEvent
1326 * @description Fires when the mouse has entered the menu. Passes back
1327 * the DOM Event object as an argument.
1329 mouseOverEvent
: null,
1333 * @event mouseOutEvent
1334 * @description Fires when the mouse has left the menu. Passes back the DOM
1335 * Event object as an argument.
1336 * @type YAHOO.util.CustomEvent
1338 mouseOutEvent
: null,
1342 * @event mouseDownEvent
1343 * @description Fires when the user mouses down on the menu. Passes back the
1344 * DOM Event object as an argument.
1345 * @type YAHOO.util.CustomEvent
1347 mouseDownEvent
: null,
1351 * @event mouseUpEvent
1352 * @description Fires when the user releases a mouse button while the mouse is
1353 * over the menu. Passes back the DOM Event object as an argument.
1354 * @type YAHOO.util.CustomEvent
1361 * @description Fires when the user clicks the on the menu. Passes back the
1362 * DOM Event object as an argument.
1363 * @type YAHOO.util.CustomEvent
1369 * @event keyPressEvent
1370 * @description Fires when the user presses an alphanumeric key when one of the
1371 * menu's items has focus. Passes back the DOM Event object as an argument.
1372 * @type YAHOO.util.CustomEvent
1374 keyPressEvent
: null,
1378 * @event keyDownEvent
1379 * @description Fires when the user presses a key when one of the menu's items
1380 * has focus. Passes back the DOM Event object as an argument.
1381 * @type YAHOO.util.CustomEvent
1388 * @description Fires when the user releases a key when one of the menu's items
1389 * has focus. Passes back the DOM Event object as an argument.
1390 * @type YAHOO.util.CustomEvent
1396 * @event itemAddedEvent
1397 * @description Fires when an item is added to the menu.
1398 * @type YAHOO.util.CustomEvent
1400 itemAddedEvent
: null,
1404 * @event itemRemovedEvent
1405 * @description Fires when an item is removed to the menu.
1406 * @type YAHOO.util.CustomEvent
1408 itemRemovedEvent
: null,
1413 * @description The Menu class's initialization method. This method is
1414 * automatically called by the constructor, and sets up all DOM references
1415 * for pre-existing markup, and creates required markup if it is not
1417 * @param {String} p_oElement String specifying the id attribute of the
1418 * <code><div></code> element of the menu.
1419 * @param {String} p_oElement String specifying the id attribute of the
1420 * <code><select></code> element to be used as the data source
1422 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1423 * level-one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object
1424 * specifying the <code><div></code> element of the menu.
1425 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
1426 * level-one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement
1427 * Object specifying the <code><select></code> element to be used as
1428 * the data source for the menu.
1429 * @param {Object} p_oConfig Optional. Object literal specifying the
1430 * configuration for the menu. See configuration class documentation for
1433 init: function (p_oElement
, p_oConfig
) {
1435 this._aItemGroups
= [];
1436 this._aListElements
= [];
1437 this._aGroupTitleElements
= [];
1439 if (!this.ITEM_TYPE
) {
1441 this.ITEM_TYPE
= YAHOO
.widget
.MenuItem
;
1448 if (typeof p_oElement
== "string") {
1450 oElement
= document
.getElementById(p_oElement
);
1453 else if (p_oElement
.tagName
) {
1455 oElement
= p_oElement
;
1460 if (oElement
&& oElement
.tagName
) {
1462 switch(oElement
.tagName
.toUpperCase()) {
1466 this.srcElement
= oElement
;
1470 oElement
.setAttribute("id", Dom
.generateId());
1476 Note: we don't pass the user config in here yet
1477 because we only want it executed once, at the lowest
1481 Menu
.superclass
.init
.call(this, oElement
);
1483 this.beforeInitEvent
.fire(Menu
);
1485 this.logger
= new YAHOO
.widget
.LogWriter(this.toString());
1487 this.logger
.log("Source element: " + this.srcElement
.tagName
);
1493 this.srcElement
= oElement
;
1497 The source element is not something that we can use
1498 outright, so we need to create a new Overlay
1500 Note: we don't pass the user config in here yet
1501 because we only want it executed once, at the lowest
1505 Menu
.superclass
.init
.call(this, Dom
.generateId());
1507 this.beforeInitEvent
.fire(Menu
);
1509 this.logger
= new YAHOO
.widget
.LogWriter(this.toString());
1511 this.logger
.log("Source element: " + this.srcElement
.tagName
);
1521 Note: we don't pass the user config in here yet
1522 because we only want it executed once, at the lowest
1526 Menu
.superclass
.init
.call(this, p_oElement
);
1528 this.beforeInitEvent
.fire(Menu
);
1530 this.logger
= new YAHOO
.widget
.LogWriter(this.toString());
1532 this.logger
.log("No source element found. " +
1533 "Created element with id: " + this.id
);
1540 Dom
.addClass(this.element
, this.CSS_CLASS_NAME
);
1543 // Subscribe to Custom Events
1545 this.initEvent
.subscribe(this._onInit
);
1546 this.beforeRenderEvent
.subscribe(this._onBeforeRender
);
1547 this.renderEvent
.subscribe(this._onRender
);
1548 this.renderEvent
.subscribe(this.onRender
);
1549 this.beforeShowEvent
.subscribe(this._onBeforeShow
);
1550 this.hideEvent
.subscribe(this.positionOffScreen
);
1551 this.showEvent
.subscribe(this._onShow
);
1552 this.beforeHideEvent
.subscribe(this._onBeforeHide
);
1553 this.mouseOverEvent
.subscribe(this._onMouseOver
);
1554 this.mouseOutEvent
.subscribe(this._onMouseOut
);
1555 this.clickEvent
.subscribe(this._onClick
);
1556 this.keyDownEvent
.subscribe(this._onKeyDown
);
1557 this.keyPressEvent
.subscribe(this._onKeyPress
);
1560 if (UA
.gecko
|| UA
.webkit
) {
1562 this.cfg
.subscribeToConfigEvent("y", this._onYChange
);
1569 this.cfg
.applyConfig(p_oConfig
, true);
1574 // Register the Menu instance with the MenuManager
1576 MenuManager
.addMenu(this);
1579 this.initEvent
.fire(Menu
);
1591 * @method _initSubTree
1592 * @description Iterates the childNodes of the source element to find nodes
1593 * used to instantiate menu and menu items.
1596 _initSubTree: function () {
1598 var oSrcElement
= this.srcElement
,
1610 sSrcElementTagName
=
1611 (oSrcElement
.tagName
&& oSrcElement
.tagName
.toUpperCase());
1614 if (sSrcElementTagName
== "DIV") {
1616 // Populate the collection of item groups and item group titles
1618 oNode
= this.body
.firstChild
;
1624 sGroupTitleTagName
= this.GROUP_TITLE_TAG_NAME
.toUpperCase();
1629 if (oNode
&& oNode
.tagName
) {
1631 switch (oNode
.tagName
.toUpperCase()) {
1633 case sGroupTitleTagName
:
1635 this._aGroupTitleElements
[nGroup
] = oNode
;
1641 this._aListElements
[nGroup
] = oNode
;
1642 this._aItemGroups
[nGroup
] = [];
1652 while ((oNode
= oNode
.nextSibling
));
1656 Apply the "first-of-type" class to the first UL to mimic
1657 the "first-of-type" CSS3 psuedo class.
1660 if (this._aListElements
[0]) {
1662 Dom
.addClass(this._aListElements
[0], "first-of-type");
1673 this.logger
.log("Searching DOM for items to initialize.");
1676 if (sSrcElementTagName
) {
1678 switch (sSrcElementTagName
) {
1682 aListElements
= this._aListElements
;
1683 nListElements
= aListElements
.length
;
1685 if (nListElements
> 0) {
1687 this.logger
.log("Found " + nListElements
+
1688 " item groups to initialize.");
1690 i
= nListElements
- 1;
1694 oNode
= aListElements
[i
].firstChild
;
1698 this.logger
.log("Scanning " +
1699 aListElements
[i
].childNodes
.length
+
1700 " child nodes for items to initialize.");
1704 if (oNode
&& oNode
.tagName
&&
1705 oNode
.tagName
.toUpperCase() == "LI") {
1707 this.logger
.log("Initializing " +
1708 oNode
.tagName
+ " node.");
1710 this.addItem(new this.ITEM_TYPE(oNode
,
1711 { parent
: this }), i
);
1716 while ((oNode
= oNode
.nextSibling
));
1729 this.logger
.log("Scanning " +
1730 oSrcElement
.childNodes
.length
+
1731 " child nodes for items to initialize.");
1733 oNode
= oSrcElement
.firstChild
;
1737 if (oNode
&& oNode
.tagName
) {
1739 switch (oNode
.tagName
.toUpperCase()) {
1744 this.logger
.log("Initializing " +
1745 oNode
.tagName
+ " node.");
1761 while ((oNode
= oNode
.nextSibling
));
1775 * @method _getFirstEnabledItem
1776 * @description Returns the first enabled item in the menu.
1777 * @return {YAHOO.widget.MenuItem}
1780 _getFirstEnabledItem: function () {
1782 var aItems
= this.getItems(),
1783 nItems
= aItems
.length
,
1786 for(var i
=0; i
<nItems
; i
++) {
1790 if (oItem
&& !oItem
.cfg
.getProperty("disabled") &&
1791 oItem
.element
.style
.display
!= "none") {
1803 * @method _addItemToGroup
1804 * @description Adds a menu item to a group.
1806 * @param {Number} p_nGroupIndex Number indicating the group to which the
1808 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
1809 * instance to be added to the menu.
1810 * @param {String} p_oItem String specifying the text of the item to be added
1812 * @param {Object} p_oItem Object literal containing a set of menu item
1813 * configuration properties.
1814 * @param {Number} p_nItemIndex Optional. Number indicating the index at
1815 * which the menu item should be added.
1816 * @return {YAHOO.widget.MenuItem}
1818 _addItemToGroup: function (p_nGroupIndex
, p_oItem
, p_nItemIndex
) {
1828 function getNextItemSibling(p_aArray
, p_nStartIndex
) {
1830 return (p_aArray
[p_nStartIndex
] || getNextItemSibling(p_aArray
,
1831 (p_nStartIndex
+1)));
1835 if (p_oItem
instanceof this.ITEM_TYPE
) {
1838 oItem
.parent
= this;
1841 else if (typeof p_oItem
== "string") {
1843 oItem
= new this.ITEM_TYPE(p_oItem
, { parent
: this });
1846 else if (typeof p_oItem
== "object") {
1848 p_oItem
.parent
= this;
1850 oItem
= new this.ITEM_TYPE(p_oItem
.text
, p_oItem
);
1857 if (oItem
.cfg
.getProperty("selected")) {
1859 this.activeItem
= oItem
;
1864 nGroupIndex
= typeof p_nGroupIndex
== "number" ? p_nGroupIndex
: 0;
1865 aGroup
= this._getItemGroup(nGroupIndex
);
1871 aGroup
= this._createItemGroup(nGroupIndex
);
1876 if (typeof p_nItemIndex
== "number") {
1878 bAppend
= (p_nItemIndex
>= aGroup
.length
);
1881 if (aGroup
[p_nItemIndex
]) {
1883 aGroup
.splice(p_nItemIndex
, 0, oItem
);
1888 aGroup
[p_nItemIndex
] = oItem
;
1893 oGroupItem
= aGroup
[p_nItemIndex
];
1897 if (bAppend
&& (!oGroupItem
.element
.parentNode
||
1898 oGroupItem
.element
.parentNode
.nodeType
== 11)) {
1900 this._aListElements
[nGroupIndex
].appendChild(
1901 oGroupItem
.element
);
1906 oNextItemSibling
= getNextItemSibling(aGroup
,
1909 if (oNextItemSibling
&& (!oGroupItem
.element
.parentNode
||
1910 oGroupItem
.element
.parentNode
.nodeType
== 11)) {
1912 this._aListElements
[nGroupIndex
].insertBefore(
1914 oNextItemSibling
.element
);
1921 oGroupItem
.parent
= this;
1923 this._subscribeToItemEvents(oGroupItem
);
1925 this._configureSubmenu(oGroupItem
);
1927 this._updateItemProperties(nGroupIndex
);
1929 this.logger
.log("Item inserted." +
1930 " Text: " + oGroupItem
.cfg
.getProperty("text") + ", " +
1931 " Index: " + oGroupItem
.index
+ ", " +
1932 " Group Index: " + oGroupItem
.groupIndex
);
1934 this.itemAddedEvent
.fire(oGroupItem
);
1935 this.changeContentEvent
.fire();
1944 nItemIndex
= aGroup
.length
;
1946 aGroup
[nItemIndex
] = oItem
;
1948 oGroupItem
= aGroup
[nItemIndex
];
1953 if (!Dom
.isAncestor(this._aListElements
[nGroupIndex
],
1954 oGroupItem
.element
)) {
1956 this._aListElements
[nGroupIndex
].appendChild(
1957 oGroupItem
.element
);
1961 oGroupItem
.element
.setAttribute("groupindex", nGroupIndex
);
1962 oGroupItem
.element
.setAttribute("index", nItemIndex
);
1964 oGroupItem
.parent
= this;
1966 oGroupItem
.index
= nItemIndex
;
1967 oGroupItem
.groupIndex
= nGroupIndex
;
1969 this._subscribeToItemEvents(oGroupItem
);
1971 this._configureSubmenu(oGroupItem
);
1973 if (nItemIndex
=== 0) {
1975 Dom
.addClass(oGroupItem
.element
, "first-of-type");
1979 this.logger
.log("Item added." +
1980 " Text: " + oGroupItem
.cfg
.getProperty("text") + ", " +
1981 " Index: " + oGroupItem
.index
+ ", " +
1982 " Group Index: " + oGroupItem
.groupIndex
);
1985 this.itemAddedEvent
.fire(oGroupItem
);
1986 this.changeContentEvent
.fire();
2000 * @method _removeItemFromGroupByIndex
2001 * @description Removes a menu item from a group by index. Returns the menu
2002 * item that was removed.
2004 * @param {Number} p_nGroupIndex Number indicating the group to which the menu
2006 * @param {Number} p_nItemIndex Number indicating the index of the menu item
2008 * @return {YAHOO.widget.MenuItem}
2010 _removeItemFromGroupByIndex: function (p_nGroupIndex
, p_nItemIndex
) {
2012 var nGroupIndex
= typeof p_nGroupIndex
== "number" ? p_nGroupIndex
: 0,
2013 aGroup
= this._getItemGroup(nGroupIndex
),
2020 aArray
= aGroup
.splice(p_nItemIndex
, 1);
2025 // Update the index and className properties of each member
2027 this._updateItemProperties(nGroupIndex
);
2029 if (aGroup
.length
=== 0) {
2033 oUL
= this._aListElements
[nGroupIndex
];
2035 if (this.body
&& oUL
) {
2037 this.body
.removeChild(oUL
);
2041 // Remove the group from the array of items
2043 this._aItemGroups
.splice(nGroupIndex
, 1);
2046 // Remove the UL from the array of ULs
2048 this._aListElements
.splice(nGroupIndex
, 1);
2052 Assign the "first-of-type" class to the new first UL
2056 oUL
= this._aListElements
[0];
2060 Dom
.addClass(oUL
, "first-of-type");
2067 this.itemRemovedEvent
.fire(oItem
);
2068 this.changeContentEvent
.fire();
2071 // Return a reference to the item that was removed
2083 * @method _removeItemFromGroupByValue
2084 * @description Removes a menu item from a group by reference. Returns the
2085 * menu item that was removed.
2087 * @param {Number} p_nGroupIndex Number indicating the group to which the
2088 * menu item belongs.
2089 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2090 * instance to be removed.
2091 * @return {YAHOO.widget.MenuItem}
2093 _removeItemFromGroupByValue: function (p_nGroupIndex
, p_oItem
) {
2095 var aGroup
= this._getItemGroup(p_nGroupIndex
),
2102 nItems
= aGroup
.length
;
2111 if (aGroup
[i
] == p_oItem
) {
2121 if (nItemIndex
> -1) {
2123 return (this._removeItemFromGroupByIndex(p_nGroupIndex
,
2136 * @method _updateItemProperties
2137 * @description Updates the "index," "groupindex," and "className" properties
2138 * of the menu items in the specified group.
2140 * @param {Number} p_nGroupIndex Number indicating the group of items to update.
2142 _updateItemProperties: function (p_nGroupIndex
) {
2144 var aGroup
= this._getItemGroup(p_nGroupIndex
),
2145 nItems
= aGroup
.length
,
2155 // Update the index and className properties of each member
2163 oLI
= oItem
.element
;
2166 oItem
.groupIndex
= p_nGroupIndex
;
2168 oLI
.setAttribute("groupindex", p_nGroupIndex
);
2169 oLI
.setAttribute("index", i
);
2171 Dom
.removeClass(oLI
, "first-of-type");
2181 Dom
.addClass(oLI
, "first-of-type");
2191 * @method _createItemGroup
2192 * @description Creates a new menu item group (array) and its associated
2193 * <code><ul></code> element. Returns an aray of menu item groups.
2195 * @param {Number} p_nIndex Number indicating the group to create.
2198 _createItemGroup: function (p_nIndex
) {
2202 if (!this._aItemGroups
[p_nIndex
]) {
2204 this._aItemGroups
[p_nIndex
] = [];
2206 oUL
= document
.createElement("ul");
2208 this._aListElements
[p_nIndex
] = oUL
;
2210 return this._aItemGroups
[p_nIndex
];
2218 * @method _getItemGroup
2219 * @description Returns the menu item group at the specified index.
2221 * @param {Number} p_nIndex Number indicating the index of the menu item group
2225 _getItemGroup: function (p_nIndex
) {
2227 var nIndex
= ((typeof p_nIndex
== "number") ? p_nIndex
: 0);
2229 return this._aItemGroups
[nIndex
];
2235 * @method _configureSubmenu
2236 * @description Subscribes the menu item's submenu to its parent menu's events.
2238 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2239 * instance with the submenu to be configured.
2241 _configureSubmenu: function (p_oItem
) {
2243 var oSubmenu
= p_oItem
.cfg
.getProperty("submenu");
2248 Listen for configuration changes to the parent menu
2249 so they they can be applied to the submenu.
2252 this.cfg
.configChangedEvent
.subscribe(this._onParentMenuConfigChange
,
2255 this.renderEvent
.subscribe(this._onParentMenuRender
, oSubmenu
, true);
2257 oSubmenu
.beforeShowEvent
.subscribe(this._onSubmenuBeforeShow
);
2267 * @method _subscribeToItemEvents
2268 * @description Subscribes a menu to a menu item's event.
2270 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
2271 * instance whose events should be subscribed to.
2273 _subscribeToItemEvents: function (p_oItem
) {
2275 p_oItem
.focusEvent
.subscribe(this._onMenuItemFocus
);
2277 p_oItem
.blurEvent
.subscribe(this._onMenuItemBlur
);
2279 p_oItem
.destroyEvent
.subscribe(this._onMenuItemDestroy
, p_oItem
, this);
2281 p_oItem
.cfg
.configChangedEvent
.subscribe(this._onMenuItemConfigChange
,
2288 * @method _onVisibleChange
2289 * @description Change event handler for the the menu's "visible" configuration
2292 * @param {String} p_sType String representing the name of the event that
2294 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2296 _onVisibleChange: function (p_sType
, p_aArgs
) {
2298 var bVisible
= p_aArgs
[0];
2302 Dom
.addClass(this.element
, "visible");
2307 Dom
.removeClass(this.element
, "visible");
2315 * @method _cancelHideDelay
2316 * @description Cancels the call to "hideMenu."
2319 _cancelHideDelay: function () {
2321 var oRoot
= this.getRoot();
2323 if (oRoot
._nHideDelayId
) {
2325 window
.clearTimeout(oRoot
._nHideDelayId
);
2333 * @method _execHideDelay
2334 * @description Hides the menu after the number of milliseconds specified by
2335 * the "hidedelay" configuration property.
2338 _execHideDelay: function () {
2340 this._cancelHideDelay();
2342 var oRoot
= this.getRoot(),
2345 function hideMenu() {
2347 if (oRoot
.activeItem
) {
2349 oRoot
.clearActiveItem();
2353 if (oRoot
== me
&& !(me
instanceof YAHOO
.widget
.MenuBar
) &&
2354 me
.cfg
.getProperty("position") == "dynamic") {
2363 oRoot
._nHideDelayId
=
2364 window
.setTimeout(hideMenu
, oRoot
.cfg
.getProperty("hidedelay"));
2370 * @method _cancelShowDelay
2371 * @description Cancels the call to the "showMenu."
2374 _cancelShowDelay: function () {
2376 var oRoot
= this.getRoot();
2378 if (oRoot
._nShowDelayId
) {
2380 window
.clearTimeout(oRoot
._nShowDelayId
);
2388 * @method _execShowDelay
2389 * @description Shows the menu after the number of milliseconds specified by
2390 * the "showdelay" configuration property have ellapsed.
2392 * @param {YAHOO.widget.Menu} p_oMenu Object specifying the menu that should
2395 _execShowDelay: function (p_oMenu
) {
2397 var oRoot
= this.getRoot();
2399 function showMenu() {
2401 if (p_oMenu
.parent
.cfg
.getProperty("selected")) {
2410 oRoot
._nShowDelayId
=
2411 window
.setTimeout(showMenu
, oRoot
.cfg
.getProperty("showdelay"));
2417 * @method _execSubmenuHideDelay
2418 * @description Hides a submenu after the number of milliseconds specified by
2419 * the "submenuhidedelay" configuration property have ellapsed.
2421 * @param {YAHOO.widget.Menu} p_oSubmenu Object specifying the submenu that
2423 * @param {Number} p_nMouseX The x coordinate of the mouse when it left
2424 * the specified submenu's parent menu item.
2425 * @param {Number} p_nHideDelay The number of milliseconds that should ellapse
2426 * before the submenu is hidden.
2428 _execSubmenuHideDelay: function (p_oSubmenu
, p_nMouseX
, p_nHideDelay
) {
2432 p_oSubmenu
._nSubmenuHideDelayId
= window
.setTimeout(function () {
2434 if (me
._nCurrentMouseX
> (p_nMouseX
+ 10)) {
2436 p_oSubmenu
._nSubmenuHideDelayId
= window
.setTimeout(function () {
2455 // Protected methods
2459 * @method _disableScrollHeader
2460 * @description Disables the header used for scrolling the body of the menu.
2463 _disableScrollHeader: function () {
2465 if (!this._bHeaderDisabled
) {
2467 Dom
.addClass(this.header
, "topscrollbar_disabled");
2468 this._bHeaderDisabled
= true;
2476 * @method _disableScrollFooter
2477 * @description Disables the footer used for scrolling the body of the menu.
2480 _disableScrollFooter: function () {
2482 if (!this._bFooterDisabled
) {
2484 Dom
.addClass(this.footer
, "bottomscrollbar_disabled");
2485 this._bFooterDisabled
= true;
2493 * @method _enableScrollHeader
2494 * @description Enables the header used for scrolling the body of the menu.
2497 _enableScrollHeader: function () {
2499 if (this._bHeaderDisabled
) {
2501 Dom
.removeClass(this.header
, "topscrollbar_disabled");
2502 this._bHeaderDisabled
= false;
2510 * @method _enableScrollFooter
2511 * @description Enables the footer used for scrolling the body of the menu.
2514 _enableScrollFooter: function () {
2516 if (this._bFooterDisabled
) {
2518 Dom
.removeClass(this.footer
, "bottomscrollbar_disabled");
2519 this._bFooterDisabled
= false;
2527 * @method _onMouseOver
2528 * @description "mouseover" event handler for the menu.
2530 * @param {String} p_sType String representing the name of the event that
2532 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2534 _onMouseOver: function (p_sType
, p_aArgs
) {
2536 if (this._bStopMouseEventHandlers
) {
2543 var oEvent
= p_aArgs
[0],
2545 oTarget
= Event
.getTarget(oEvent
),
2554 if (!this._bHandledMouseOverEvent
&& (oTarget
== this.element
||
2555 Dom
.isAncestor(this.element
, oTarget
))) {
2557 // Menu mouseover logic
2559 this._nCurrentMouseX
= 0;
2561 Event
.on(this.element
, "mousemove", this._onMouseMove
, this, true);
2563 this.clearActiveItem();
2566 if (this.parent
&& this._nSubmenuHideDelayId
) {
2568 window
.clearTimeout(this._nSubmenuHideDelayId
);
2570 this.parent
.cfg
.setProperty("selected", true);
2572 oParentMenu
= this.parent
.parent
;
2574 oParentMenu
._bHandledMouseOutEvent
= true;
2575 oParentMenu
._bHandledMouseOverEvent
= false;
2580 this._bHandledMouseOverEvent
= true;
2581 this._bHandledMouseOutEvent
= false;
2586 if (oItem
&& !oItem
.handledMouseOverEvent
&&
2587 !oItem
.cfg
.getProperty("disabled") &&
2588 (oTarget
== oItem
.element
|| Dom
.isAncestor(oItem
.element
, oTarget
))) {
2590 // Menu Item mouseover logic
2592 nShowDelay
= this.cfg
.getProperty("showdelay");
2593 bShowDelay
= (nShowDelay
> 0);
2598 this._cancelShowDelay();
2603 oActiveItem
= this.activeItem
;
2607 oActiveItem
.cfg
.setProperty("selected", false);
2612 oItemCfg
= oItem
.cfg
;
2614 // Select and focus the current menu item
2616 oItemCfg
.setProperty("selected", true);
2619 if (this.hasFocus()) {
2626 if (this.cfg
.getProperty("autosubmenudisplay")) {
2628 // Show the submenu this menu item
2630 oSubmenu
= oItemCfg
.getProperty("submenu");
2636 this._execShowDelay(oSubmenu
);
2649 oItem
.handledMouseOverEvent
= true;
2650 oItem
.handledMouseOutEvent
= false;
2658 * @method _onMouseOut
2659 * @description "mouseout" event handler for the menu.
2661 * @param {String} p_sType String representing the name of the event that
2663 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2665 _onMouseOut: function (p_sType
, p_aArgs
) {
2667 if (this._bStopMouseEventHandlers
) {
2674 var oEvent
= p_aArgs
[0],
2676 oRelatedTarget
= Event
.getRelatedTarget(oEvent
),
2677 bMovingToSubmenu
= false,
2684 if (oItem
&& !oItem
.cfg
.getProperty("disabled")) {
2686 oItemCfg
= oItem
.cfg
;
2687 oSubmenu
= oItemCfg
.getProperty("submenu");
2690 if (oSubmenu
&& (oRelatedTarget
== oSubmenu
.element
||
2691 Dom
.isAncestor(oSubmenu
.element
, oRelatedTarget
))) {
2693 bMovingToSubmenu
= true;
2698 if (!oItem
.handledMouseOutEvent
&& ((oRelatedTarget
!= oItem
.element
&&
2699 !Dom
.isAncestor(oItem
.element
, oRelatedTarget
)) ||
2700 bMovingToSubmenu
)) {
2702 // Menu Item mouseout logic
2704 if (!bMovingToSubmenu
) {
2706 oItem
.cfg
.setProperty("selected", false);
2712 this.cfg
.getProperty("submenuhidedelay");
2714 nShowDelay
= this.cfg
.getProperty("showdelay");
2716 if (!(this instanceof YAHOO
.widget
.MenuBar
) &&
2717 nSubmenuHideDelay
> 0 &&
2718 nShowDelay
>= nSubmenuHideDelay
) {
2720 this._execSubmenuHideDelay(oSubmenu
,
2721 Event
.getPageX(oEvent
),
2736 oItem
.handledMouseOutEvent
= true;
2737 oItem
.handledMouseOverEvent
= false;
2744 if (!this._bHandledMouseOutEvent
&& ((oRelatedTarget
!= this.element
&&
2745 !Dom
.isAncestor(this.element
, oRelatedTarget
)) || bMovingToSubmenu
)) {
2747 // Menu mouseout logic
2749 Event
.removeListener(this.element
, "mousemove", this._onMouseMove
);
2751 this._nCurrentMouseX
= Event
.getPageX(oEvent
);
2753 this._bHandledMouseOutEvent
= true;
2754 this._bHandledMouseOverEvent
= false;
2762 * @method _onMouseMove
2763 * @description "click" event handler for the menu.
2765 * @param {Event} p_oEvent Object representing the DOM event object passed
2766 * back by the event utility (YAHOO.util.Event).
2767 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
2770 _onMouseMove: function (p_oEvent
, p_oMenu
) {
2772 if (this._bStopMouseEventHandlers
) {
2778 this._nCurrentMouseX
= Event
.getPageX(p_oEvent
);
2785 * @description "click" event handler for the menu.
2787 * @param {String} p_sType String representing the name of the event that
2789 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2791 _onClick: function (p_sType
, p_aArgs
) {
2793 var oEvent
= p_aArgs
[0],
2795 bInMenuAnchor
= false,
2806 if (oItem
.cfg
.getProperty("disabled")) {
2808 Event
.preventDefault(oEvent
);
2813 oSubmenu
= oItem
.cfg
.getProperty("submenu");
2817 Check if the URL of the anchor is pointing to an element that is
2818 a child of the menu.
2821 sURL
= oItem
.cfg
.getProperty("url");
2826 nHashPos
= sURL
.indexOf("#");
2831 if (nHashPos
!= -1) {
2833 sURL
= sURL
.substr(nHashPos
, nLen
);
2840 sId
= sURL
.substr(1, nLen
);
2842 bInMenuAnchor
= Dom
.isAncestor(this.element
, sId
);
2845 else if (nLen
=== 1) {
2847 bInMenuAnchor
= true;
2857 if (bInMenuAnchor
&& !oItem
.cfg
.getProperty("target")) {
2859 Event
.preventDefault(oEvent
);
2869 oItem
.focusEvent
.fire();
2879 There is an inconsistency between Firefox 2 for Mac OS X and Firefox 2 Windows
2880 regarding the triggering of the display of the browser's context menu and the
2881 subsequent firing of the "click" event. In Firefox for Windows, when the user
2882 triggers the display of the browser's context menu the "click" event also fires
2883 for the document object, even though the "click" event did not fire for the
2884 element that was the original target of the "contextmenu" event. This is unique
2885 to Firefox on Windows. For all other A-Grade browsers, including Firefox 2 for
2886 Mac OS X, the "click" event doesn't fire for the document object.
2888 This bug in Firefox 2 for Windows affects Menu as Menu instances listen for
2889 events at the document level and have an internal "click" event handler they
2890 use to hide themselves when clicked. As a result, in Firefox for Windows a
2891 Menu will hide when the user right clicks on a MenuItem to raise the browser's
2892 default context menu, because its internal "click" event handler ends up
2893 getting called. The following line fixes this bug.
2896 if ((UA
.gecko
&& this.platform
== "windows") && oEvent
.button
> 0) {
2902 oRoot
= this.getRoot();
2904 if (oRoot
instanceof YAHOO
.widget
.MenuBar
||
2905 oRoot
.cfg
.getProperty("position") == "static") {
2907 oRoot
.clearActiveItem();
2926 * @method _onKeyDown
2927 * @description "keydown" event handler for the menu.
2929 * @param {String} p_sType String representing the name of the event that
2931 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
2933 _onKeyDown: function (p_sType
, p_aArgs
) {
2935 var oEvent
= p_aArgs
[0],
2954 This function is called to prevent a bug in Firefox. In Firefox,
2955 moving a DOM element into a stationary mouse pointer will cause the
2956 browser to fire mouse events. This can result in the menu mouse
2957 event handlers being called uncessarily, especially when menus are
2958 moved into a stationary mouse pointer as a result of a
2961 function stopMouseEventHandlers() {
2963 me
._bStopMouseEventHandlers
= true;
2965 window
.setTimeout(function () {
2967 me
._bStopMouseEventHandlers
= false;
2974 if (oItem
&& !oItem
.cfg
.getProperty("disabled")) {
2976 oItemCfg
= oItem
.cfg
;
2977 oParentItem
= this.parent
;
2979 switch(oEvent
.keyCode
) {
2981 case 38: // Up arrow
2982 case 40: // Down arrow
2984 oNextItem
= (oEvent
.keyCode
== 38) ?
2985 oItem
.getPreviousEnabledSibling() :
2986 oItem
.getNextEnabledSibling();
2990 this.clearActiveItem();
2992 oNextItem
.cfg
.setProperty("selected", true);
2996 if (this.cfg
.getProperty("maxheight") > 0) {
2999 nBodyScrollTop
= oBody
.scrollTop
;
3000 nBodyOffsetHeight
= oBody
.offsetHeight
;
3001 aItems
= this.getItems();
3002 nItems
= aItems
.length
- 1;
3003 nNextItemOffsetTop
= oNextItem
.element
.offsetTop
;
3006 if (oEvent
.keyCode
== 40 ) { // Down
3008 if (nNextItemOffsetTop
>= (nBodyOffsetHeight
+ nBodyScrollTop
)) {
3010 oBody
.scrollTop
= nNextItemOffsetTop
- nBodyOffsetHeight
;
3013 else if (nNextItemOffsetTop
<= nBodyScrollTop
) {
3015 oBody
.scrollTop
= 0;
3020 if (oNextItem
== aItems
[nItems
]) {
3022 oBody
.scrollTop
= oNextItem
.element
.offsetTop
;
3029 if (nNextItemOffsetTop
<= nBodyScrollTop
) {
3031 oBody
.scrollTop
= nNextItemOffsetTop
- oNextItem
.element
.offsetHeight
;
3034 else if (nNextItemOffsetTop
>= (nBodyScrollTop
+ nBodyOffsetHeight
)) {
3036 oBody
.scrollTop
= nNextItemOffsetTop
;
3041 if (oNextItem
== aItems
[0]) {
3043 oBody
.scrollTop
= 0;
3050 nBodyScrollTop
= oBody
.scrollTop
;
3051 nScrollTarget
= oBody
.scrollHeight
- oBody
.offsetHeight
;
3053 if (nBodyScrollTop
=== 0) {
3055 this._disableScrollHeader();
3056 this._enableScrollFooter();
3059 else if (nBodyScrollTop
== nScrollTarget
) {
3061 this._enableScrollHeader();
3062 this._disableScrollFooter();
3067 this._enableScrollHeader();
3068 this._enableScrollFooter();
3077 Event
.preventDefault(oEvent
);
3079 stopMouseEventHandlers();
3084 case 39: // Right arrow
3086 oSubmenu
= oItemCfg
.getProperty("submenu");
3090 if (!oItemCfg
.getProperty("selected")) {
3092 oItemCfg
.setProperty("selected", true);
3097 oSubmenu
.setInitialFocus();
3098 oSubmenu
.setInitialSelection();
3103 oRoot
= this.getRoot();
3105 if (oRoot
instanceof YAHOO
.widget
.MenuBar
) {
3107 oNextItem
= oRoot
.activeItem
.getNextEnabledSibling();
3111 oRoot
.clearActiveItem();
3113 oNextItem
.cfg
.setProperty("selected", true);
3115 oSubmenu
= oNextItem
.cfg
.getProperty("submenu");
3132 Event
.preventDefault(oEvent
);
3134 stopMouseEventHandlers();
3139 case 37: // Left arrow
3143 oParentMenu
= oParentItem
.parent
;
3145 if (oParentMenu
instanceof YAHOO
.widget
.MenuBar
) {
3148 oParentMenu
.activeItem
.getPreviousEnabledSibling();
3152 oParentMenu
.clearActiveItem();
3154 oNextItem
.cfg
.setProperty("selected", true);
3156 oSubmenu
= oNextItem
.cfg
.getProperty("submenu");
3173 oParentItem
.focus();
3179 Event
.preventDefault(oEvent
);
3181 stopMouseEventHandlers();
3191 if (oEvent
.keyCode
== 27) { // Esc key
3193 if (this.cfg
.getProperty("position") == "dynamic") {
3199 this.parent
.focus();
3204 else if (this.activeItem
) {
3206 oSubmenu
= this.activeItem
.cfg
.getProperty("submenu");
3208 if (oSubmenu
&& oSubmenu
.cfg
.getProperty("visible")) {
3211 this.activeItem
.focus();
3216 this.activeItem
.blur();
3217 this.activeItem
.cfg
.setProperty("selected", false);
3224 Event
.preventDefault(oEvent
);
3232 * @method _onKeyPress
3233 * @description "keypress" event handler for a Menu instance.
3235 * @param {String} p_sType The name of the event that was fired.
3236 * @param {Array} p_aArgs Collection of arguments sent when the event
3239 _onKeyPress: function (p_sType
, p_aArgs
) {
3241 var oEvent
= p_aArgs
[0];
3244 if (oEvent
.keyCode
== 40 || oEvent
.keyCode
== 38) {
3246 Event
.preventDefault(oEvent
);
3254 * @method _onYChange
3255 * @description "y" event handler for a Menu instance.
3257 * @param {String} p_sType The name of the event that was fired.
3258 * @param {Array} p_aArgs Collection of arguments sent when the event
3261 _onYChange: function (p_sType
, p_aArgs
) {
3263 var oParent
= this.parent
,
3271 nScrollTop
= oParent
.parent
.body
.scrollTop
;
3274 if (nScrollTop
> 0) {
3276 nY
= (this.cfg
.getProperty("y") - nScrollTop
);
3278 Dom
.setY(this.element
, nY
);
3280 oIFrame
= this.iframe
;
3285 Dom
.setY(oIFrame
, nY
);
3289 this.cfg
.setProperty("y", nY
, true);
3299 * @method _onScrollTargetMouseOver
3300 * @description "mouseover" event handler for the menu's "header" and "footer"
3301 * elements. Used to scroll the body of the menu up and down when the
3302 * menu's "maxheight" configuration property is set to a value greater than 0.
3304 * @param {Event} p_oEvent Object representing the DOM event object passed
3305 * back by the event utility (YAHOO.util.Event).
3306 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
3309 _onScrollTargetMouseOver: function (p_oEvent
, p_oMenu
) {
3311 this._cancelHideDelay();
3313 var oTarget
= Event
.getTarget(p_oEvent
),
3316 nScrollIncrement
= this.cfg
.getProperty("scrollincrement"),
3321 function scrollBodyDown() {
3323 var nScrollTop
= oBody
.scrollTop
;
3326 if (nScrollTop
< nScrollTarget
) {
3328 oBody
.scrollTop
= (nScrollTop
+ nScrollIncrement
);
3330 me
._enableScrollHeader();
3335 oBody
.scrollTop
= nScrollTarget
;
3337 window
.clearInterval(me
._nBodyScrollId
);
3339 me
._disableScrollFooter();
3346 function scrollBodyUp() {
3348 var nScrollTop
= oBody
.scrollTop
;
3351 if (nScrollTop
> 0) {
3353 oBody
.scrollTop
= (nScrollTop
- nScrollIncrement
);
3355 me
._enableScrollFooter();
3360 oBody
.scrollTop
= 0;
3362 window
.clearInterval(me
._nBodyScrollId
);
3364 me
._disableScrollHeader();
3371 if (Dom
.hasClass(oTarget
, "hd")) {
3373 fnScrollFunction
= scrollBodyUp
;
3378 nScrollTarget
= oBody
.scrollHeight
- oBody
.offsetHeight
;
3380 fnScrollFunction
= scrollBodyDown
;
3385 this._nBodyScrollId
= window
.setInterval(fnScrollFunction
, 10);
3391 * @method _onScrollTargetMouseOut
3392 * @description "mouseout" event handler for the menu's "header" and "footer"
3393 * elements. Used to stop scrolling the body of the menu up and down when the
3394 * menu's "maxheight" configuration property is set to a value greater than 0.
3396 * @param {Event} p_oEvent Object representing the DOM event object passed
3397 * back by the event utility (YAHOO.util.Event).
3398 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
3401 _onScrollTargetMouseOut: function (p_oEvent
, p_oMenu
) {
3403 window
.clearInterval(this._nBodyScrollId
);
3405 this._cancelHideDelay();
3416 * @description "init" event handler for the menu.
3418 * @param {String} p_sType String representing the name of the event that
3420 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3422 _onInit: function (p_sType
, p_aArgs
) {
3424 this.cfg
.subscribeToConfigEvent("visible", this._onVisibleChange
);
3426 var bRootMenu
= !this.parent
,
3427 bLazyLoad
= this.lazyLoad
;
3431 Automatically initialize a menu's subtree if:
3433 1) This is the root menu and lazyload is off
3435 2) This is the root menu, lazyload is on, but the menu is
3438 3) This menu is a submenu and lazyload is off
3443 if (((bRootMenu
&& !bLazyLoad
) ||
3444 (bRootMenu
&& (this.cfg
.getProperty("visible") ||
3445 this.cfg
.getProperty("position") == "static")) ||
3446 (!bRootMenu
&& !bLazyLoad
)) && this.getItemGroups().length
=== 0) {
3448 if (this.srcElement
) {
3450 this._initSubTree();
3455 if (this.itemData
) {
3457 this.addItems(this.itemData
);
3462 else if (bLazyLoad
) {
3464 this.cfg
.fireQueue();
3472 * @method _onBeforeRender
3473 * @description "beforerender" event handler for the menu. Appends all of the
3474 * <code><ul></code>, <code><li></code> and their accompanying
3475 * title elements to the body element of the menu.
3477 * @param {String} p_sType String representing the name of the event that
3479 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3481 _onBeforeRender: function (p_sType
, p_aArgs
) {
3483 var oEl
= this.element
,
3484 nListElements
= this._aListElements
.length
,
3490 if (nListElements
> 0) {
3494 oUL
= this._aListElements
[i
];
3500 Dom
.addClass(oUL
, "first-of-type");
3506 if (!Dom
.isAncestor(oEl
, oUL
)) {
3508 this.appendToBody(oUL
);
3513 oGroupTitle
= this._aGroupTitleElements
[i
];
3517 if (!Dom
.isAncestor(oEl
, oGroupTitle
)) {
3519 oUL
.parentNode
.insertBefore(oGroupTitle
, oUL
);
3524 Dom
.addClass(oUL
, "hastitle");
3533 while(i
< nListElements
);
3542 * @description "render" event handler for the menu.
3544 * @param {String} p_sType String representing the name of the event that
3546 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3548 _onRender: function (p_sType
, p_aArgs
) {
3550 if (this.cfg
.getProperty("position") == "dynamic") {
3552 if (!this.cfg
.getProperty("visible")) {
3554 this.positionOffScreen();
3567 * @method _onBeforeShow
3568 * @description "beforeshow" event handler for the menu.
3570 * @param {String} p_sType String representing the name of the event that
3572 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3574 _onBeforeShow: function (p_sType
, p_aArgs
) {
3583 if (this.lazyLoad
&& this.getItemGroups().length
=== 0) {
3585 if (this.srcElement
) {
3587 this._initSubTree();
3592 if (this.itemData
) {
3594 if (this.parent
&& this.parent
.parent
&&
3595 this.parent
.parent
.srcElement
&&
3596 this.parent
.parent
.srcElement
.tagName
.toUpperCase() ==
3599 nOptions
= this.itemData
.length
;
3601 for(n
=0; n
<nOptions
; n
++) {
3603 if (this.itemData
[n
].tagName
) {
3605 this.addItem((new this.ITEM_TYPE(this.itemData
[n
])));
3614 this.addItems(this.itemData
);
3621 oSrcElement
= this.srcElement
;
3625 if (oSrcElement
.tagName
.toUpperCase() == "SELECT") {
3627 if (Dom
.inDocument(oSrcElement
)) {
3629 this.render(oSrcElement
.parentNode
);
3634 this.render(this.cfg
.getProperty("container"));
3650 this.render(this.parent
.element
);
3655 this.render(this.cfg
.getProperty("container"));
3664 var nMaxHeight
= this.cfg
.getProperty("maxheight"),
3665 nMinScrollHeight
= this.cfg
.getProperty("minscrollheight"),
3666 bDynamicPos
= this.cfg
.getProperty("position") == "dynamic";
3669 if (!this.parent
&& bDynamicPos
) {
3671 this.cfg
.refireEvent("xy");
3676 function clearMaxHeight() {
3678 this.cfg
.setProperty("maxheight", 0);
3680 this.hideEvent
.unsubscribe(clearMaxHeight
);
3685 if (!(this instanceof YAHOO
.widget
.MenuBar
) && bDynamicPos
) {
3688 if (nMaxHeight
=== 0) {
3690 nViewportHeight
= Dom
.getViewportHeight();
3694 this.parent
.parent
instanceof YAHOO
.widget
.MenuBar
) {
3696 oRegion
= YAHOO
.util
.Region
.getRegion(this.parent
.element
);
3698 nViewportHeight
= (nViewportHeight
- oRegion
.bottom
);
3703 if (this.element
.offsetHeight
>= nViewportHeight
) {
3705 nMaxHeight
= (nViewportHeight
- (Overlay
.VIEWPORT_OFFSET
* 2));
3707 if (nMaxHeight
< nMinScrollHeight
) {
3709 nMaxHeight
= nMinScrollHeight
;
3713 this.cfg
.setProperty("maxheight", nMaxHeight
);
3715 this.hideEvent
.subscribe(clearMaxHeight
);
3728 * @description "show" event handler for the menu.
3730 * @param {String} p_sType String representing the name of the event that
3732 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3734 _onShow: function (p_sType
, p_aArgs
) {
3736 var oParent
= this.parent
,
3742 function disableAutoSubmenuDisplay(p_oEvent
) {
3746 if (p_oEvent
.type
== "mousedown" || (p_oEvent
.type
== "keydown" &&
3747 p_oEvent
.keyCode
== 27)) {
3750 Set the "autosubmenudisplay" to "false" if the user
3751 clicks outside the menu bar.
3754 oTarget
= Event
.getTarget(p_oEvent
);
3756 if (oTarget
!= oParentMenu
.element
||
3757 !Dom
.isAncestor(oParentMenu
.element
, oTarget
)) {
3759 oParentMenu
.cfg
.setProperty("autosubmenudisplay", false);
3761 Event
.removeListener(document
, "mousedown",
3762 disableAutoSubmenuDisplay
);
3764 Event
.removeListener(document
, "keydown",
3765 disableAutoSubmenuDisplay
);
3776 oParentMenu
= oParent
.parent
;
3777 aParentAlignment
= oParentMenu
.cfg
.getProperty("submenualignment");
3778 aAlignment
= this.cfg
.getProperty("submenualignment");
3781 if ((aParentAlignment
[0] != aAlignment
[0]) &&
3782 (aParentAlignment
[1] != aAlignment
[1])) {
3784 this.cfg
.setProperty("submenualignment",
3785 [aParentAlignment
[0], aParentAlignment
[1]]);
3790 if (!oParentMenu
.cfg
.getProperty("autosubmenudisplay") &&
3791 (oParentMenu
instanceof YAHOO
.widget
.MenuBar
||
3792 oParentMenu
.cfg
.getProperty("position") == "static")) {
3794 oParentMenu
.cfg
.setProperty("autosubmenudisplay", true);
3796 Event
.on(document
, "mousedown", disableAutoSubmenuDisplay
);
3797 Event
.on(document
, "keydown", disableAutoSubmenuDisplay
);
3807 * @method _onBeforeHide
3808 * @description "beforehide" event handler for the menu.
3810 * @param {String} p_sType String representing the name of the event that
3812 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3814 _onBeforeHide: function (p_sType
, p_aArgs
) {
3816 var oActiveItem
= this.activeItem
,
3822 oConfig
= oActiveItem
.cfg
;
3824 oConfig
.setProperty("selected", false);
3826 oSubmenu
= oConfig
.getProperty("submenu");
3836 if (this.getRoot() == this) {
3846 * @method _onParentMenuConfigChange
3847 * @description "configchange" event handler for a submenu.
3849 * @param {String} p_sType String representing the name of the event that
3851 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3852 * @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that
3853 * subscribed to the event.
3855 _onParentMenuConfigChange: function (p_sType
, p_aArgs
, p_oSubmenu
) {
3857 var sPropertyName
= p_aArgs
[0][0],
3858 oPropertyValue
= p_aArgs
[0][1];
3860 switch(sPropertyName
) {
3863 case "constraintoviewport":
3866 case "submenuhidedelay":
3870 case "scrollincrement":
3871 case "minscrollheight":
3873 p_oSubmenu
.cfg
.setProperty(sPropertyName
, oPropertyValue
);
3883 * @method _onParentMenuRender
3884 * @description "render" event handler for a submenu. Renders a
3885 * submenu in response to the firing of its parent's "render" event.
3887 * @param {String} p_sType String representing the name of the event that
3889 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3890 * @param {YAHOO.widget.Menu} p_oSubmenu Object representing the submenu that
3891 * subscribed to the event.
3893 _onParentMenuRender: function (p_sType
, p_aArgs
, p_oSubmenu
) {
3895 var oParentCfg
= p_oSubmenu
.parent
.parent
.cfg
,
3899 constraintoviewport
: oParentCfg
.getProperty("constraintoviewport"),
3903 clicktohide
: oParentCfg
.getProperty("clicktohide"),
3905 effect
: oParentCfg
.getProperty("effect"),
3907 showdelay
: oParentCfg
.getProperty("showdelay"),
3909 hidedelay
: oParentCfg
.getProperty("hidedelay"),
3911 submenuhidedelay
: oParentCfg
.getProperty("submenuhidedelay"),
3913 classname
: oParentCfg
.getProperty("classname"),
3915 scrollincrement
: oParentCfg
.getProperty("scrollincrement"),
3917 minscrollheight
: oParentCfg
.getProperty("minscrollheight"),
3919 iframe
: oParentCfg
.getProperty("iframe")
3926 p_oSubmenu
.cfg
.applyConfig(oConfig
);
3929 if (!this.lazyLoad
) {
3931 oLI
= this.parent
.element
;
3933 if (this.element
.parentNode
== oLI
) {
3950 * @method _onSubmenuBeforeShow
3951 * @description "beforeshow" event handler for a submenu.
3953 * @param {String} p_sType String representing the name of the event that
3955 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3957 _onSubmenuBeforeShow: function (p_sType
, p_aArgs
) {
3959 var oParent
= this.parent
,
3960 aAlignment
= oParent
.parent
.cfg
.getProperty("submenualignment");
3963 if (!this.cfg
.getProperty("context")) {
3965 this.cfg
.setProperty("context",
3966 [oParent
.element
, aAlignment
[0], aAlignment
[1]]);
3979 * @method _onMenuItemFocus
3980 * @description "focus" event handler for the menu's items.
3982 * @param {String} p_sType String representing the name of the event that
3984 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
3986 _onMenuItemFocus: function (p_sType
, p_aArgs
) {
3988 this.parent
.focusEvent
.fire(this);
3994 * @method _onMenuItemBlur
3995 * @description "blur" event handler for the menu's items.
3997 * @param {String} p_sType String representing the name of the event
3999 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4001 _onMenuItemBlur: function (p_sType
, p_aArgs
) {
4003 this.parent
.blurEvent
.fire(this);
4009 * @method _onMenuItemDestroy
4010 * @description "destroy" event handler for the menu's items.
4012 * @param {String} p_sType String representing the name of the event
4014 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4015 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
4016 * that fired the event.
4018 _onMenuItemDestroy: function (p_sType
, p_aArgs
, p_oItem
) {
4020 this._removeItemFromGroupByValue(p_oItem
.groupIndex
, p_oItem
);
4026 * @method _onMenuItemConfigChange
4027 * @description "configchange" event handler for the menu's items.
4029 * @param {String} p_sType String representing the name of the event that
4031 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4032 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
4033 * that fired the event.
4035 _onMenuItemConfigChange: function (p_sType
, p_aArgs
, p_oItem
) {
4037 var sPropertyName
= p_aArgs
[0][0],
4038 oPropertyValue
= p_aArgs
[0][1],
4042 switch(sPropertyName
) {
4046 if (oPropertyValue
=== true) {
4048 this.activeItem
= p_oItem
;
4056 oSubmenu
= p_aArgs
[0][1];
4060 this._configureSubmenu(p_oItem
);
4072 // Public event handlers for configuration properties
4076 * @method enforceConstraints
4077 * @description The default event handler executed when the moveEvent is fired,
4078 * if the "constraintoviewport" configuration property is set to true.
4079 * @param {String} type The name of the event that was fired.
4080 * @param {Array} args Collection of arguments sent when the
4082 * @param {Array} obj Array containing the current Menu instance
4083 * and the item that fired the event.
4085 enforceConstraints: function (type
, args
, obj
) {
4087 YAHOO
.widget
.Menu
.superclass
.enforceConstraints
.apply(this, arguments
);
4089 var oParent
= this.parent
,
4098 oParentMenu
= oParent
.parent
;
4100 if (!(oParentMenu
instanceof YAHOO
.widget
.MenuBar
)) {
4102 nParentMenuX
= oParentMenu
.cfg
.getProperty("x");
4103 nX
= this.cfg
.getProperty("x");
4106 if (nX
< (nParentMenuX
+ oParent
.element
.offsetWidth
)) {
4108 nNewX
= (nParentMenuX
- this.element
.offsetWidth
);
4110 this.cfg
.setProperty("x", nNewX
, true);
4111 this.cfg
.setProperty("xy", [nNewX
, (this.cfg
.getProperty("y"))], true);
4123 * @method configVisible
4124 * @description Event handler for when the "visible" configuration property
4126 * @param {String} p_sType String representing the name of the event that
4128 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4129 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4132 configVisible: function (p_sType
, p_aArgs
, p_oMenu
) {
4137 if (this.cfg
.getProperty("position") == "dynamic") {
4139 Menu
.superclass
.configVisible
.call(this, p_sType
, p_aArgs
, p_oMenu
);
4144 bVisible
= p_aArgs
[0];
4145 sDisplay
= Dom
.getStyle(this.element
, "display");
4147 Dom
.setStyle(this.element
, "visibility", "visible");
4151 if (sDisplay
!= "block") {
4152 this.beforeShowEvent
.fire();
4153 Dom
.setStyle(this.element
, "display", "block");
4154 this.showEvent
.fire();
4160 if (sDisplay
== "block") {
4161 this.beforeHideEvent
.fire();
4162 Dom
.setStyle(this.element
, "display", "none");
4163 this.hideEvent
.fire();
4174 * @method configPosition
4175 * @description Event handler for when the "position" configuration property
4176 * of the menu changes.
4177 * @param {String} p_sType String representing the name of the event that
4179 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4180 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4183 configPosition: function (p_sType
, p_aArgs
, p_oMenu
) {
4185 var oElement
= this.element
,
4186 sCSSPosition
= p_aArgs
[0] == "static" ? "static" : "absolute",
4191 Dom
.setStyle(oElement
, "position", sCSSPosition
);
4194 if (sCSSPosition
== "static") {
4196 // Statically positioned menus are visible by default
4198 Dom
.setStyle(oElement
, "display", "block");
4200 oCfg
.setProperty("visible", true);
4206 Even though the "visible" property is queued to
4207 "false" by default, we need to set the "visibility" property to
4208 "hidden" since Overlay's "configVisible" implementation checks the
4209 element's "visibility" style property before deciding whether
4210 or not to show an Overlay instance.
4213 Dom
.setStyle(oElement
, "visibility", "hidden");
4218 if (sCSSPosition
== "absolute") {
4220 nZIndex
= oCfg
.getProperty("zindex");
4222 if (!nZIndex
|| nZIndex
=== 0) {
4224 nZIndex
= this.parent
?
4225 (this.parent
.parent
.cfg
.getProperty("zindex") + 1) : 1;
4227 oCfg
.setProperty("zindex", nZIndex
);
4237 * @method configIframe
4238 * @description Event handler for when the "iframe" configuration property of
4240 * @param {String} p_sType String representing the name of the event that
4242 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4243 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4246 configIframe: function (p_sType
, p_aArgs
, p_oMenu
) {
4248 if (this.cfg
.getProperty("position") == "dynamic") {
4250 Menu
.superclass
.configIframe
.call(this, p_sType
, p_aArgs
, p_oMenu
);
4258 * @method configHideDelay
4259 * @description Event handler for when the "hidedelay" configuration property
4260 * of the menu changes.
4261 * @param {String} p_sType String representing the name of the event that
4263 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4264 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4267 configHideDelay: function (p_sType
, p_aArgs
, p_oMenu
) {
4269 var nHideDelay
= p_aArgs
[0],
4270 oMouseOutEvent
= this.mouseOutEvent
,
4271 oMouseOverEvent
= this.mouseOverEvent
,
4272 oKeyDownEvent
= this.keyDownEvent
;
4274 if (nHideDelay
> 0) {
4277 Only assign event handlers once. This way the user change
4278 the value for the hidedelay as many times as they want.
4281 if (!this._bHideDelayEventHandlersAssigned
) {
4283 oMouseOutEvent
.subscribe(this._execHideDelay
);
4284 oMouseOverEvent
.subscribe(this._cancelHideDelay
);
4285 oKeyDownEvent
.subscribe(this._cancelHideDelay
);
4287 this._bHideDelayEventHandlersAssigned
= true;
4294 oMouseOutEvent
.unsubscribe(this._execHideDelay
);
4295 oMouseOverEvent
.unsubscribe(this._cancelHideDelay
);
4296 oKeyDownEvent
.unsubscribe(this._cancelHideDelay
);
4298 this._bHideDelayEventHandlersAssigned
= false;
4306 * @method configContainer
4307 * @description Event handler for when the "container" configuration property
4308 * of the menu changes.
4309 * @param {String} p_sType String representing the name of the event that
4311 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4312 * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that
4315 configContainer: function (p_sType
, p_aArgs
, p_oMenu
) {
4317 var oElement
= p_aArgs
[0];
4319 if (typeof oElement
== 'string') {
4321 this.cfg
.setProperty("container", document
.getElementById(oElement
),
4330 * @method _setMaxHeight
4331 * @description "renderEvent" handler used to defer the setting of the
4332 * "maxheight" configuration property until the menu is rendered in lazy
4334 * @param {String} p_sType The name of the event that was fired.
4335 * @param {Array} p_aArgs Collection of arguments sent when the event
4337 * @param {Number} p_nMaxHeight Number representing the value to set for the
4338 * "maxheight" configuration property.
4341 _setMaxHeight: function (p_sType
, p_aArgs
, p_nMaxHeight
) {
4343 this.cfg
.setProperty("maxheight", p_nMaxHeight
);
4344 this.renderEvent
.unsubscribe(this._setMaxHeight
);
4350 * @method configMaxHeight
4351 * @description Event handler for when the "maxheight" configuration property of
4353 * @param {String} p_sType The name of the event that was fired.
4354 * @param {Array} p_aArgs Collection of arguments sent when the event
4356 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired
4359 configMaxHeight: function (p_sType
, p_aArgs
, p_oMenu
) {
4361 var nMaxHeight
= p_aArgs
[0],
4362 oElement
= this.element
,
4364 oHeader
= this.header
,
4365 oFooter
= this.footer
,
4366 fnMouseOver
= this._onScrollTargetMouseOver
,
4367 fnMouseOut
= this._onScrollTargetMouseOut
,
4368 nMinScrollHeight
= this.cfg
.getProperty("minscrollheight"),
4374 if (nMaxHeight
!== 0 && nMaxHeight
< nMinScrollHeight
) {
4376 nMaxHeight
= nMinScrollHeight
;
4381 if (this.lazyLoad
&& !oBody
) {
4383 this.renderEvent
.unsubscribe(this._setMaxHeight
);
4385 if (nMaxHeight
> 0) {
4387 this.renderEvent
.subscribe(this._setMaxHeight
, nMaxHeight
, this);
4396 Dom
.setStyle(oBody
, "height", "");
4397 Dom
.removeClass(oBody
, "yui-menu-body-scrolled");
4401 There is a bug in gecko-based browsers where an element whose
4402 "position" property is set to "absolute" and "overflow" property is set
4403 to "hidden" will not render at the correct width when its
4404 offsetParent's "position" property is also set to "absolute." It is
4405 possible to work around this bug by specifying a value for the width
4406 property in addition to overflow.
4408 In IE it is also necessary to give the Menu a width when the scrollbars are
4409 rendered to prevent the Menu from rendering with a width that is 100% of
4410 the browser viewport.
4413 var bSetWidth
= ((UA
.gecko
&& this.parent
&& this.parent
.parent
&&
4414 this.parent
.parent
.cfg
.getProperty("position") == "dynamic") || UA
.ie
);
4419 if (!this.cfg
.getProperty("width")) {
4421 nOffsetWidth
= oElement
.offsetWidth
;
4424 Measuring the difference of the offsetWidth before and after
4425 setting the "width" style attribute allows us to compute the
4426 about of padding and borders applied to the element, which in
4427 turn allows us to set the "width" property correctly.
4430 oElement
.style
.width
= nOffsetWidth
+ "px";
4432 sWidth
= (nOffsetWidth
- (oElement
.offsetWidth
- nOffsetWidth
)) + "px";
4434 this.cfg
.setProperty("width", sWidth
);
4441 if (!oHeader
&& !oFooter
) {
4443 this.setHeader(" ");
4444 this.setFooter(" ");
4446 oHeader
= this.header
;
4447 oFooter
= this.footer
;
4449 Dom
.addClass(oHeader
, "topscrollbar");
4450 Dom
.addClass(oFooter
, "bottomscrollbar");
4452 oElement
.insertBefore(oHeader
, oBody
);
4453 oElement
.appendChild(oFooter
);
4458 nHeight
= (nMaxHeight
- (oHeader
.offsetHeight
+ oHeader
.offsetHeight
));
4461 if (nHeight
> 0 && (oBody
.offsetHeight
> nMaxHeight
)) {
4463 Dom
.addClass(oBody
, "yui-menu-body-scrolled");
4464 Dom
.setStyle(oBody
, "height", (nHeight
+ "px"));
4466 Event
.on(oHeader
, "mouseover", fnMouseOver
, this, true);
4467 Event
.on(oHeader
, "mouseout", fnMouseOut
, this, true);
4468 Event
.on(oFooter
, "mouseover", fnMouseOver
, this, true);
4469 Event
.on(oFooter
, "mouseout", fnMouseOut
, this, true);
4471 this._disableScrollHeader();
4472 this._enableScrollFooter();
4475 else if (oHeader
&& oFooter
) {
4479 this.cfg
.setProperty("width", "");
4484 this._enableScrollHeader();
4485 this._enableScrollFooter();
4487 Event
.removeListener(oHeader
, "mouseover", fnMouseOver
);
4488 Event
.removeListener(oHeader
, "mouseout", fnMouseOut
);
4489 Event
.removeListener(oFooter
, "mouseover", fnMouseOver
);
4490 Event
.removeListener(oFooter
, "mouseout", fnMouseOut
);
4492 oElement
.removeChild(oHeader
);
4493 oElement
.removeChild(oFooter
);
4500 this.cfg
.refireEvent("iframe");
4506 * @method configClassName
4507 * @description Event handler for when the "classname" configuration property of
4509 * @param {String} p_sType The name of the event that was fired.
4510 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4511 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4513 configClassName: function (p_sType
, p_aArgs
, p_oMenu
) {
4515 var sClassName
= p_aArgs
[0];
4517 if (this._sClassName
) {
4519 Dom
.removeClass(this.element
, this._sClassName
);
4523 Dom
.addClass(this.element
, sClassName
);
4524 this._sClassName
= sClassName
;
4530 * @method _onItemAdded
4531 * @description "itemadded" event handler for a Menu instance.
4533 * @param {String} p_sType The name of the event that was fired.
4534 * @param {Array} p_aArgs Collection of arguments sent when the event
4537 _onItemAdded: function (p_sType
, p_aArgs
) {
4539 var oItem
= p_aArgs
[0];
4543 oItem
.cfg
.setProperty("disabled", true);
4551 * @method configDisabled
4552 * @description Event handler for when the "disabled" configuration property of
4554 * @param {String} p_sType The name of the event that was fired.
4555 * @param {Array} p_aArgs Collection of arguments sent when the event was fired.
4556 * @param {YAHOO.widget.Menu} p_oMenu The Menu instance fired the event.
4558 configDisabled: function (p_sType
, p_aArgs
, p_oMenu
) {
4560 var bDisabled
= p_aArgs
[0],
4561 aItems
= this.getItems(),
4565 if (Lang
.isArray(aItems
)) {
4567 nItems
= aItems
.length
;
4575 aItems
[i
].cfg
.setProperty("disabled", bDisabled
);
4585 this.clearActiveItem(true);
4587 Dom
.addClass(this.element
, "disabled");
4589 this.itemAddedEvent
.subscribe(this._onItemAdded
);
4594 Dom
.removeClass(this.element
, "disabled");
4596 this.itemAddedEvent
.unsubscribe(this._onItemAdded
);
4607 * @description "render" event handler for the menu.
4608 * @param {String} p_sType String representing the name of the event that
4610 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
4612 onRender: function (p_sType
, p_aArgs
) {
4614 function sizeShadow() {
4616 var oElement
= this.element
,
4617 oShadow
= this._shadow
;
4619 if (oShadow
&& oElement
) {
4621 // Clear the previous width
4623 if (oShadow
.style
.width
&& oShadow
.style
.height
) {
4625 oShadow
.style
.width
= "";
4626 oShadow
.style
.height
= "";
4630 oShadow
.style
.width
= (oElement
.offsetWidth
+ 6) + "px";
4631 oShadow
.style
.height
= (oElement
.offsetHeight
+ 1) + "px";
4638 function replaceShadow() {
4640 this.element
.appendChild(this._shadow
);
4645 function addShadowVisibleClass() {
4647 Dom
.addClass(this._shadow
, "yui-menu-shadow-visible");
4652 function removeShadowVisibleClass() {
4654 Dom
.removeClass(this._shadow
, "yui-menu-shadow-visible");
4659 function createShadow() {
4661 var oShadow
= this._shadow
,
4667 oElement
= this.element
;
4670 if (!m_oShadowTemplate
) {
4672 m_oShadowTemplate
= document
.createElement("div");
4673 m_oShadowTemplate
.className
=
4674 "yui-menu-shadow yui-menu-shadow-visible";
4678 oShadow
= m_oShadowTemplate
.cloneNode(false);
4680 oElement
.appendChild(oShadow
);
4682 this._shadow
= oShadow
;
4684 this.beforeShowEvent
.subscribe(addShadowVisibleClass
);
4685 this.beforeHideEvent
.subscribe(removeShadowVisibleClass
);
4690 Need to call sizeShadow & syncIframe via setTimeout for
4691 IE 7 Quirks Mode and IE 6 Standards Mode and Quirks Mode
4692 or the shadow and iframe shim will not be sized and
4693 positioned properly.
4696 window
.setTimeout(function () {
4698 sizeShadow
.call(me
);
4703 this.cfg
.subscribeToConfigEvent("width", sizeShadow
);
4704 this.cfg
.subscribeToConfigEvent("height", sizeShadow
);
4705 this.cfg
.subscribeToConfigEvent("maxheight", sizeShadow
);
4706 this.changeContentEvent
.subscribe(sizeShadow
);
4708 Module
.textResizeEvent
.subscribe(sizeShadow
, me
, true);
4710 this.destroyEvent
.subscribe(function () {
4712 Module
.textResizeEvent
.unsubscribe(sizeShadow
, me
);
4718 this.cfg
.subscribeToConfigEvent("maxheight", replaceShadow
);
4725 function onBeforeShow() {
4727 createShadow
.call(this);
4729 this.beforeShowEvent
.unsubscribe(onBeforeShow
);
4734 if (this.cfg
.getProperty("position") == "dynamic") {
4736 if (this.cfg
.getProperty("visible")) {
4738 createShadow
.call(this);
4743 this.beforeShowEvent
.subscribe(onBeforeShow
);
4756 * @method initEvents
4757 * @description Initializes the custom events for the menu.
4759 initEvents: function () {
4761 Menu
.superclass
.initEvents
.call(this);
4763 // Create custom events
4765 var SIGNATURE
= CustomEvent
.LIST
;
4767 this.mouseOverEvent
= this.createEvent(EVENT_TYPES
.MOUSE_OVER
);
4768 this.mouseOverEvent
.signature
= SIGNATURE
;
4770 this.mouseOutEvent
= this.createEvent(EVENT_TYPES
.MOUSE_OUT
);
4771 this.mouseOutEvent
.signature
= SIGNATURE
;
4773 this.mouseDownEvent
= this.createEvent(EVENT_TYPES
.MOUSE_DOWN
);
4774 this.mouseDownEvent
.signature
= SIGNATURE
;
4776 this.mouseUpEvent
= this.createEvent(EVENT_TYPES
.MOUSE_UP
);
4777 this.mouseUpEvent
.signature
= SIGNATURE
;
4779 this.clickEvent
= this.createEvent(EVENT_TYPES
.CLICK
);
4780 this.clickEvent
.signature
= SIGNATURE
;
4782 this.keyPressEvent
= this.createEvent(EVENT_TYPES
.KEY_PRESS
);
4783 this.keyPressEvent
.signature
= SIGNATURE
;
4785 this.keyDownEvent
= this.createEvent(EVENT_TYPES
.KEY_DOWN
);
4786 this.keyDownEvent
.signature
= SIGNATURE
;
4788 this.keyUpEvent
= this.createEvent(EVENT_TYPES
.KEY_UP
);
4789 this.keyUpEvent
.signature
= SIGNATURE
;
4791 this.focusEvent
= this.createEvent(EVENT_TYPES
.FOCUS
);
4792 this.focusEvent
.signature
= SIGNATURE
;
4794 this.blurEvent
= this.createEvent(EVENT_TYPES
.BLUR
);
4795 this.blurEvent
.signature
= SIGNATURE
;
4797 this.itemAddedEvent
= this.createEvent(EVENT_TYPES
.ITEM_ADDED
);
4798 this.itemAddedEvent
.signature
= SIGNATURE
;
4800 this.itemRemovedEvent
= this.createEvent(EVENT_TYPES
.ITEM_REMOVED
);
4801 this.itemRemovedEvent
.signature
= SIGNATURE
;
4807 * @method positionOffScreen
4808 * @description Positions the menu outside of the boundaries of the browser's
4809 * viewport. Called automatically when a menu is hidden to ensure that
4810 * it doesn't force the browser to render uncessary scrollbars.
4812 positionOffScreen: function () {
4814 var oIFrame
= this.iframe
,
4815 aPos
= this.OFF_SCREEN_POSITION
;
4817 Dom
.setXY(this.element
, aPos
);
4821 Dom
.setXY(oIFrame
, aPos
);
4830 * @description Finds the menu's root menu.
4832 getRoot: function () {
4834 var oItem
= this.parent
,
4839 oParentMenu
= oItem
.parent
;
4841 return oParentMenu
? oParentMenu
.getRoot() : this;
4855 * @description Returns a string representing the menu.
4858 toString: function () {
4860 var sReturnVal
= "Menu",
4865 sReturnVal
+= (" " + sId
);
4875 * @method setItemGroupTitle
4876 * @description Sets the title of a group of menu items.
4877 * @param {String} p_sGroupTitle String specifying the title of the group.
4878 * @param {Number} p_nGroupIndex Optional. Number specifying the group to which
4879 * the title belongs.
4881 setItemGroupTitle: function (p_sGroupTitle
, p_nGroupIndex
) {
4888 if (typeof p_sGroupTitle
== "string" && p_sGroupTitle
.length
> 0) {
4890 nGroupIndex
= typeof p_nGroupIndex
== "number" ? p_nGroupIndex
: 0;
4891 oTitle
= this._aGroupTitleElements
[nGroupIndex
];
4896 oTitle
.innerHTML
= p_sGroupTitle
;
4901 oTitle
= document
.createElement(this.GROUP_TITLE_TAG_NAME
);
4903 oTitle
.innerHTML
= p_sGroupTitle
;
4905 this._aGroupTitleElements
[nGroupIndex
] = oTitle
;
4910 i
= this._aGroupTitleElements
.length
- 1;
4914 if (this._aGroupTitleElements
[i
]) {
4916 Dom
.removeClass(this._aGroupTitleElements
[i
], "first-of-type");
4926 if (nFirstIndex
!== null) {
4928 Dom
.addClass(this._aGroupTitleElements
[nFirstIndex
],
4933 this.changeContentEvent
.fire();
4943 * @description Appends an item to the menu.
4944 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
4945 * instance to be added to the menu.
4946 * @param {String} p_oItem String specifying the text of the item to be added
4948 * @param {Object} p_oItem Object literal containing a set of menu item
4949 * configuration properties.
4950 * @param {Number} p_nGroupIndex Optional. Number indicating the group to
4951 * which the item belongs.
4952 * @return {YAHOO.widget.MenuItem}
4954 addItem: function (p_oItem
, p_nGroupIndex
) {
4958 return this._addItemToGroup(p_nGroupIndex
, p_oItem
);
4967 * @description Adds an array of items to the menu.
4968 * @param {Array} p_aItems Array of items to be added to the menu. The array
4969 * can contain strings specifying the text for each item to be created, object
4970 * literals specifying each of the menu item configuration properties,
4971 * or MenuItem instances.
4972 * @param {Number} p_nGroupIndex Optional. Number specifying the group to
4973 * which the items belongs.
4976 addItems: function (p_aItems
, p_nGroupIndex
) {
4983 if (Lang
.isArray(p_aItems
)) {
4985 nItems
= p_aItems
.length
;
4988 for(i
=0; i
<nItems
; i
++) {
4990 oItem
= p_aItems
[i
];
4994 if (Lang
.isArray(oItem
)) {
4996 aItems
[aItems
.length
] = this.addItems(oItem
, i
);
5001 aItems
[aItems
.length
] =
5002 this._addItemToGroup(p_nGroupIndex
, oItem
);
5011 if (aItems
.length
) {
5023 * @method insertItem
5024 * @description Inserts an item into the menu at the specified index.
5025 * @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem
5026 * instance to be added to the menu.
5027 * @param {String} p_oItem String specifying the text of the item to be added
5029 * @param {Object} p_oItem Object literal containing a set of menu item
5030 * configuration properties.
5031 * @param {Number} p_nItemIndex Number indicating the ordinal position at which
5032 * the item should be added.
5033 * @param {Number} p_nGroupIndex Optional. Number indicating the group to which
5035 * @return {YAHOO.widget.MenuItem}
5037 insertItem: function (p_oItem
, p_nItemIndex
, p_nGroupIndex
) {
5041 return this._addItemToGroup(p_nGroupIndex
, p_oItem
, p_nItemIndex
);
5049 * @method removeItem
5050 * @description Removes the specified item from the menu.
5051 * @param {YAHOO.widget.MenuItem} p_oObject Object reference for the MenuItem
5052 * instance to be removed from the menu.
5053 * @param {Number} p_oObject Number specifying the index of the item
5055 * @param {Number} p_nGroupIndex Optional. Number specifying the group to
5056 * which the item belongs.
5057 * @return {YAHOO.widget.MenuItem}
5059 removeItem: function (p_oObject
, p_nGroupIndex
) {
5063 if (typeof p_oObject
!= "undefined") {
5065 if (p_oObject
instanceof YAHOO
.widget
.MenuItem
) {
5067 oItem
= this._removeItemFromGroupByValue(p_nGroupIndex
, p_oObject
);
5070 else if (typeof p_oObject
== "number") {
5072 oItem
= this._removeItemFromGroupByIndex(p_nGroupIndex
, p_oObject
);
5080 this.logger
.log("Item removed." +
5081 " Text: " + oItem
.cfg
.getProperty("text") + ", " +
5082 " Index: " + oItem
.index
+ ", " +
5083 " Group Index: " + oItem
.groupIndex
);
5096 * @description Returns an array of all of the items in the menu.
5099 getItems: function () {
5101 var aGroups
= this._aItemGroups
,
5105 if (Lang
.isArray(aGroups
)) {
5107 nGroups
= aGroups
.length
;
5109 return ((nGroups
== 1) ? aGroups
[0] :
5110 (Array
.prototype.concat
.apply(aItems
, aGroups
)));
5118 * @method getItemGroups
5119 * @description Multi-dimensional Array representing the menu items as they
5120 * are grouped in the menu.
5123 getItemGroups: function () {
5125 return this._aItemGroups
;
5132 * @description Returns the item at the specified index.
5133 * @param {Number} p_nItemIndex Number indicating the ordinal position of the
5134 * item to be retrieved.
5135 * @param {Number} p_nGroupIndex Optional. Number indicating the group to which
5137 * @return {YAHOO.widget.MenuItem}
5139 getItem: function (p_nItemIndex
, p_nGroupIndex
) {
5143 if (typeof p_nItemIndex
== "number") {
5145 aGroup
= this._getItemGroup(p_nGroupIndex
);
5149 return aGroup
[p_nItemIndex
];
5159 * @method getSubmenus
5160 * @description Returns an array of all of the submenus that are immediate
5161 * children of the menu.
5164 getSubmenus: function () {
5166 var aItems
= this.getItems(),
5167 nItems
= aItems
.length
,
5178 for(i
=0; i
<nItems
; i
++) {
5184 oSubmenu
= oItem
.cfg
.getProperty("submenu");
5188 aSubmenus
[aSubmenus
.length
] = oSubmenu
;
5204 * @method clearContent
5205 * @description Removes all of the content from the menu, including the menu
5206 * items, group titles, header and footer.
5208 clearContent: function () {
5210 var aItems
= this.getItems(),
5211 nItems
= aItems
.length
,
5212 oElement
= this.element
,
5214 oHeader
= this.header
,
5215 oFooter
= this.footer
,
5231 oSubmenu
= oItem
.cfg
.getProperty("submenu");
5235 this.cfg
.configChangedEvent
.unsubscribe(
5236 this._onParentMenuConfigChange
, oSubmenu
);
5238 this.renderEvent
.unsubscribe(this._onParentMenuRender
,
5243 this.removeItem(oItem
);
5255 Event
.purgeElement(oHeader
);
5256 oElement
.removeChild(oHeader
);
5263 Event
.purgeElement(oFooter
);
5264 oElement
.removeChild(oFooter
);
5270 Event
.purgeElement(oBody
);
5272 oBody
.innerHTML
= "";
5276 this.activeItem
= null;
5278 this._aItemGroups
= [];
5279 this._aListElements
= [];
5280 this._aGroupTitleElements
= [];
5282 this.cfg
.setProperty("width", null);
5289 * @description Removes the menu's <code><div></code> element
5290 * (and accompanying child nodes) from the document.
5292 destroy: function () {
5296 this.clearContent();
5298 this._aItemGroups
= null;
5299 this._aListElements
= null;
5300 this._aGroupTitleElements
= null;
5303 // Continue with the superclass implementation of this method
5305 Menu
.superclass
.destroy
.call(this);
5307 this.logger
.log("Destroyed.");
5313 * @method setInitialFocus
5314 * @description Sets focus to the menu's first enabled item.
5316 setInitialFocus: function () {
5318 var oItem
= this._getFirstEnabledItem();
5330 * @method setInitialSelection
5331 * @description Sets the "selected" configuration property of the menu's first
5332 * enabled item to "true."
5334 setInitialSelection: function () {
5336 var oItem
= this._getFirstEnabledItem();
5340 oItem
.cfg
.setProperty("selected", true);
5347 * @method clearActiveItem
5348 * @description Sets the "selected" configuration property of the menu's active
5349 * item to "false" and hides the item's submenu.
5350 * @param {Boolean} p_bBlur Boolean indicating if the menu's active item
5351 * should be blurred.
5353 clearActiveItem: function (p_bBlur
) {
5355 if (this.cfg
.getProperty("showdelay") > 0) {
5357 this._cancelShowDelay();
5362 var oActiveItem
= this.activeItem
,
5368 oConfig
= oActiveItem
.cfg
;
5376 oConfig
.setProperty("selected", false);
5378 oSubmenu
= oConfig
.getProperty("submenu");
5386 this.activeItem
= null;
5395 * @description Causes the menu to receive focus and fires the "focus" event.
5397 focus: function () {
5399 if (!this.hasFocus()) {
5401 this.setInitialFocus();
5410 * @description Causes the menu to lose focus and fires the "blur" event.
5416 if (this.hasFocus()) {
5418 oItem
= MenuManager
.getFocusedMenuItem();
5433 * @description Returns a boolean indicating whether or not the menu has focus.
5436 hasFocus: function () {
5438 return (MenuManager
.getFocusedMenu() == this.getRoot());
5444 * Adds the specified CustomEvent subscriber to the menu and each of
5447 * @param p_type {string} the type, or name of the event
5448 * @param p_fn {function} the function to exectute when the event fires
5449 * @param p_obj {Object} An object to be passed along when the event
5451 * @param p_override {boolean} If true, the obj passed in becomes the
5452 * execution scope of the listener
5454 subscribe: function () {
5456 function onItemAdded(p_sType
, p_aArgs
, p_oObject
) {
5458 var oItem
= p_aArgs
[0],
5459 oSubmenu
= oItem
.cfg
.getProperty("submenu");
5463 oSubmenu
.subscribe
.apply(oSubmenu
, p_oObject
);
5470 function onSubmenuAdded(p_sType
, p_aArgs
, p_oObject
) {
5472 var oSubmenu
= this.cfg
.getProperty("submenu");
5476 oSubmenu
.subscribe
.apply(oSubmenu
, p_oObject
);
5483 Menu
.superclass
.subscribe
.apply(this, arguments
);
5484 Menu
.superclass
.subscribe
.call(this, "itemAdded", onItemAdded
, arguments
);
5487 var aItems
= this.getItems(),
5496 nItems
= aItems
.length
;
5506 oSubmenu
= oItem
.cfg
.getProperty("submenu");
5510 oSubmenu
.subscribe
.apply(oSubmenu
, arguments
);
5515 oItem
.cfg
.subscribeToConfigEvent("submenu", onSubmenuAdded
, arguments
);
5530 * @description Initializes the class's configurable properties which can be
5531 * changed using the menu's Config object ("cfg").
5532 * @method initDefaultConfig
5534 initDefaultConfig: function () {
5536 Menu
.superclass
.initDefaultConfig
.call(this);
5538 var oConfig
= this.cfg
;
5541 // Module documentation overrides
5545 * @description Object or array of objects representing the ContainerEffect
5546 * classes that are active for animating the container. When set this
5547 * property is automatically applied to all submenus.
5552 // Overlay documentation overrides
5557 * @description Number representing the absolute x-coordinate position of
5558 * the Menu. This property is only applied when the "position"
5559 * configuration property is set to dynamic.
5567 * @description Number representing the absolute y-coordinate position of
5568 * the Menu. This property is only applied when the "position"
5569 * configuration property is set to dynamic.
5576 * @description Array of the absolute x and y positions of the Menu. This
5577 * property is only applied when the "position" configuration property is
5587 * @description Array of context arguments for context-sensitive positioning.
5588 * The format is: [id or element, element corner, context corner].
5589 * For example, setting this property to ["img1", "tl", "bl"] would
5590 * align the Mnu's top left corner to the context element's
5591 * bottom left corner. This property is only applied when the "position"
5592 * configuration property is set to dynamic.
5599 * @config fixedcenter
5600 * @description Boolean indicating if the Menu should be anchored to the
5601 * center of the viewport. This property is only applied when the
5602 * "position" configuration property is set to dynamic.
5610 * @description Number representing the CSS z-index of the Menu. This
5611 * property is only applied when the "position" configuration property is
5620 * @description Boolean indicating whether or not the Menu should
5621 * have an IFRAME shim; used to prevent SELECT elements from
5622 * poking through an Overlay instance in IE6. When set to "true",
5623 * the iframe shim is created when the Menu instance is intially
5624 * made visible. This property is only applied when the "position"
5625 * configuration property is set to dynamic and is automatically applied
5628 * @default true for IE6 and below, false for all other browsers.
5632 // Add configuration attributes
5635 Change the default value for the "visible" configuration
5636 property to "false" by re-adding the property.
5641 * @description Boolean indicating whether or not the menu is visible. If
5642 * the menu's "position" configuration property is set to "dynamic" (the
5643 * default), this property toggles the menu's <code><div></code>
5644 * element's "visibility" style property between "visible" (true) or
5645 * "hidden" (false). If the menu's "position" configuration property is
5646 * set to "static" this property toggles the menu's
5647 * <code><div></code> element's "display" style property
5648 * between "block" (true) or "none" (false).
5652 oConfig
.addProperty(
5653 DEFAULT_CONFIG
.VISIBLE
.key
,
5655 handler
: this.configVisible
,
5656 value
: DEFAULT_CONFIG
.VISIBLE
.value
,
5657 validator
: DEFAULT_CONFIG
.VISIBLE
.validator
5663 Change the default value for the "constraintoviewport" configuration
5664 property to "true" by re-adding the property.
5668 * @config constraintoviewport
5669 * @description Boolean indicating if the menu will try to remain inside
5670 * the boundaries of the size of viewport. This property is only applied
5671 * when the "position" configuration property is set to dynamic and is
5672 * automatically applied to all submenus.
5676 oConfig
.addProperty(
5677 DEFAULT_CONFIG
.CONSTRAIN_TO_VIEWPORT
.key
,
5679 handler
: this.configConstrainToViewport
,
5680 value
: DEFAULT_CONFIG
.CONSTRAIN_TO_VIEWPORT
.value
,
5681 validator
: DEFAULT_CONFIG
.CONSTRAIN_TO_VIEWPORT
.validator
,
5682 supercedes
: DEFAULT_CONFIG
.CONSTRAIN_TO_VIEWPORT
.supercedes
5689 * @description String indicating how a menu should be positioned on the
5690 * screen. Possible values are "static" and "dynamic." Static menus are
5691 * visible by default and reside in the normal flow of the document
5692 * (CSS position: static). Dynamic menus are hidden by default, reside
5693 * out of the normal flow of the document (CSS position: absolute), and
5694 * can overlay other elements on the screen.
5698 oConfig
.addProperty(
5699 DEFAULT_CONFIG
.POSITION
.key
,
5701 handler
: this.configPosition
,
5702 value
: DEFAULT_CONFIG
.POSITION
.value
,
5703 validator
: DEFAULT_CONFIG
.POSITION
.validator
,
5704 supercedes
: DEFAULT_CONFIG
.POSITION
.supercedes
5710 * @config submenualignment
5711 * @description Array defining how submenus should be aligned to their
5712 * parent menu item. The format is: [itemCorner, submenuCorner]. By default
5713 * a submenu's top left corner is aligned to its parent menu item's top
5715 * @default ["tl","tr"]
5718 oConfig
.addProperty(
5719 DEFAULT_CONFIG
.SUBMENU_ALIGNMENT
.key
,
5721 value
: DEFAULT_CONFIG
.SUBMENU_ALIGNMENT
.value
,
5722 suppressEvent
: DEFAULT_CONFIG
.SUBMENU_ALIGNMENT
.suppressEvent
5728 * @config autosubmenudisplay
5729 * @description Boolean indicating if submenus are automatically made
5730 * visible when the user mouses over the menu's items.
5734 oConfig
.addProperty(
5735 DEFAULT_CONFIG
.AUTO_SUBMENU_DISPLAY
.key
,
5737 value
: DEFAULT_CONFIG
.AUTO_SUBMENU_DISPLAY
.value
,
5738 validator
: DEFAULT_CONFIG
.AUTO_SUBMENU_DISPLAY
.validator
,
5739 suppressEvent
: DEFAULT_CONFIG
.AUTO_SUBMENU_DISPLAY
.suppressEvent
5746 * @description Number indicating the time (in milliseconds) that should
5747 * expire before a submenu is made visible when the user mouses over
5748 * the menu's items. This property is only applied when the "position"
5749 * configuration property is set to dynamic and is automatically applied
5754 oConfig
.addProperty(
5755 DEFAULT_CONFIG
.SHOW_DELAY
.key
,
5757 value
: DEFAULT_CONFIG
.SHOW_DELAY
.value
,
5758 validator
: DEFAULT_CONFIG
.SHOW_DELAY
.validator
,
5759 suppressEvent
: DEFAULT_CONFIG
.SHOW_DELAY
.suppressEvent
5766 * @description Number indicating the time (in milliseconds) that should
5767 * expire before the menu is hidden. This property is only applied when
5768 * the "position" configuration property is set to dynamic and is
5769 * automatically applied to all submenus.
5773 oConfig
.addProperty(
5774 DEFAULT_CONFIG
.HIDE_DELAY
.key
,
5776 handler
: this.configHideDelay
,
5777 value
: DEFAULT_CONFIG
.HIDE_DELAY
.value
,
5778 validator
: DEFAULT_CONFIG
.HIDE_DELAY
.validator
,
5779 suppressEvent
: DEFAULT_CONFIG
.HIDE_DELAY
.suppressEvent
5785 * @config submenuhidedelay
5786 * @description Number indicating the time (in milliseconds) that should
5787 * expire before a submenu is hidden when the user mouses out of a menu item
5788 * heading in the direction of a submenu. The value must be greater than or
5789 * equal to the value specified for the "showdelay" configuration property.
5790 * This property is only applied when the "position" configuration property
5791 * is set to dynamic and is automatically applied to all submenus.
5795 oConfig
.addProperty(
5796 DEFAULT_CONFIG
.SUBMENU_HIDE_DELAY
.key
,
5798 value
: DEFAULT_CONFIG
.SUBMENU_HIDE_DELAY
.value
,
5799 validator
: DEFAULT_CONFIG
.SUBMENU_HIDE_DELAY
.validator
,
5800 suppressEvent
: DEFAULT_CONFIG
.SUBMENU_HIDE_DELAY
.suppressEvent
5806 * @config clicktohide
5807 * @description Boolean indicating if the menu will automatically be
5808 * hidden if the user clicks outside of it. This property is only
5809 * applied when the "position" configuration property is set to dynamic
5810 * and is automatically applied to all submenus.
5814 oConfig
.addProperty(
5815 DEFAULT_CONFIG
.CLICK_TO_HIDE
.key
,
5817 value
: DEFAULT_CONFIG
.CLICK_TO_HIDE
.value
,
5818 validator
: DEFAULT_CONFIG
.CLICK_TO_HIDE
.validator
,
5819 suppressEvent
: DEFAULT_CONFIG
.CLICK_TO_HIDE
.suppressEvent
5826 * @description HTML element reference or string specifying the id
5827 * attribute of the HTML element that the menu's markup should be
5829 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
5830 * level-one-html.html#ID-58190037">HTMLElement</a>|String
5831 * @default document.body
5833 oConfig
.addProperty(
5834 DEFAULT_CONFIG
.CONTAINER
.key
,
5836 handler
: this.configContainer
,
5837 value
: document
.body
,
5838 suppressEvent
: DEFAULT_CONFIG
.CONTAINER
.suppressEvent
5844 * @config scrollincrement
5845 * @description Number used to control the scroll speed of a menu. Used to
5846 * increment the "scrollTop" property of the menu's body by when a menu's
5847 * content is scrolling. When set this property is automatically applied
5852 oConfig
.addProperty(
5853 DEFAULT_CONFIG
.SCROLL_INCREMENT
.key
,
5855 value
: DEFAULT_CONFIG
.SCROLL_INCREMENT
.value
,
5856 validator
: DEFAULT_CONFIG
.SCROLL_INCREMENT
.validator
,
5857 supercedes
: DEFAULT_CONFIG
.SCROLL_INCREMENT
.supercedes
,
5858 suppressEvent
: DEFAULT_CONFIG
.SCROLL_INCREMENT
.suppressEvent
5864 * @config minscrollheight
5865 * @description Number defining the minimum threshold for the "maxheight"
5866 * configuration property. When set this property is automatically applied
5871 oConfig
.addProperty(
5872 DEFAULT_CONFIG
.MIN_SCROLL_HEIGHT
.key
,
5874 value
: DEFAULT_CONFIG
.MIN_SCROLL_HEIGHT
.value
,
5875 validator
: DEFAULT_CONFIG
.MIN_SCROLL_HEIGHT
.validator
,
5876 supercedes
: DEFAULT_CONFIG
.MIN_SCROLL_HEIGHT
.supercedes
,
5877 suppressEvent
: DEFAULT_CONFIG
.MIN_SCROLL_HEIGHT
.suppressEvent
5884 * @description Number defining the maximum height (in pixels) for a menu's
5885 * body element (<code><div class="bd"<</code>). Once a menu's body
5886 * exceeds this height, the contents of the body are scrolled to maintain
5887 * this value. This value cannot be set lower than the value of the
5888 * "minscrollheight" configuration property.
5892 oConfig
.addProperty(
5893 DEFAULT_CONFIG
.MAX_HEIGHT
.key
,
5895 handler
: this.configMaxHeight
,
5896 value
: DEFAULT_CONFIG
.MAX_HEIGHT
.value
,
5897 validator
: DEFAULT_CONFIG
.MAX_HEIGHT
.validator
,
5898 suppressEvent
: DEFAULT_CONFIG
.MAX_HEIGHT
.suppressEvent
,
5899 supercedes
: DEFAULT_CONFIG
.MAX_HEIGHT
.supercedes
5906 * @description String representing the CSS class to be applied to the
5907 * menu's root <code><div></code> element. The specified class(es)
5908 * are appended in addition to the default class as specified by the menu's
5909 * CSS_CLASS_NAME constant. When set this property is automatically
5910 * applied to all submenus.
5914 oConfig
.addProperty(
5915 DEFAULT_CONFIG
.CLASS_NAME
.key
,
5917 handler
: this.configClassName
,
5918 value
: DEFAULT_CONFIG
.CLASS_NAME
.value
,
5919 validator
: DEFAULT_CONFIG
.CLASS_NAME
.validator
,
5920 supercedes
: DEFAULT_CONFIG
.CLASS_NAME
.supercedes
5927 * @description Boolean indicating if the menu should be disabled.
5928 * Disabling a menu disables each of its items. (Disabled menu items are
5929 * dimmed and will not respond to user input or fire events.) Disabled
5930 * menus have a corresponding "disabled" CSS class applied to their root
5931 * <code><div></code> element.
5935 oConfig
.addProperty(
5936 DEFAULT_CONFIG
.DISABLED
.key
,
5938 handler
: this.configDisabled
,
5939 value
: DEFAULT_CONFIG
.DISABLED
.value
,
5940 validator
: DEFAULT_CONFIG
.DISABLED
.validator
,
5941 suppressEvent
: DEFAULT_CONFIG
.DISABLED
.suppressEvent
5947 }); // END YAHOO.lang.extend
5957 * Creates an item for a menu.
5959 * @param {String} p_oObject String specifying the text of the menu item.
5960 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
5961 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying
5962 * the <code><li></code> element of the menu item.
5963 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
5964 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
5965 * specifying the <code><optgroup></code> element of the menu item.
5966 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
5967 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object
5968 * specifying the <code><option></code> element of the menu item.
5969 * @param {Object} p_oConfig Optional. Object literal specifying the
5970 * configuration for the menu item. See configuration class documentation
5975 YAHOO
.widget
.MenuItem = function (p_oObject
, p_oConfig
) {
5981 this.parent
= p_oConfig
.parent
;
5982 this.value
= p_oConfig
.value
;
5983 this.id
= p_oConfig
.id
;
5987 this.init(p_oObject
, p_oConfig
);
5994 var Dom
= YAHOO
.util
.Dom
,
5995 Module
= YAHOO
.widget
.Module
,
5996 Menu
= YAHOO
.widget
.Menu
,
5997 MenuItem
= YAHOO
.widget
.MenuItem
,
5998 CustomEvent
= YAHOO
.util
.CustomEvent
,
6001 m_oMenuItemTemplate
,
6004 * Constant representing the name of the MenuItem's events
6005 * @property EVENT_TYPES
6012 "MOUSE_OVER": "mouseover",
6013 "MOUSE_OUT": "mouseout",
6014 "MOUSE_DOWN": "mousedown",
6015 "MOUSE_UP": "mouseup",
6017 "KEY_PRESS": "keypress",
6018 "KEY_DOWN": "keydown",
6020 "ITEM_ADDED": "itemAdded",
6021 "ITEM_REMOVED": "itemRemoved",
6024 "DESTROY": "destroy"
6029 * Constant representing the MenuItem's configuration properties
6030 * @property DEFAULT_CONFIG
6040 validator
: Lang
.isString
,
6046 supercedes
: ["text"],
6064 validator
: Lang
.isBoolean
,
6065 suppressEvent
: true,
6066 supercedes
: ["text"]
6069 "STRONG_EMPHASIS": {
6070 key
: "strongemphasis",
6072 validator
: Lang
.isBoolean
,
6073 suppressEvent
: true,
6074 supercedes
: ["text"]
6080 validator
: Lang
.isBoolean
,
6081 suppressEvent
: true,
6082 supercedes
: ["disabled", "selected"]
6087 suppressEvent
: true,
6088 supercedes
: ["disabled", "selected"]
6094 validator
: Lang
.isBoolean
,
6095 suppressEvent
: true,
6096 supercedes
: ["text", "selected"]
6102 validator
: Lang
.isBoolean
,
6114 validator
: Lang
.isString
,
6121 MenuItem
.prototype = {
6124 * @property CSS_CLASS_NAME
6125 * @description String representing the CSS class(es) to be applied to the
6126 * <code><li></code> element of the menu item.
6127 * @default "yuimenuitem"
6131 CSS_CLASS_NAME
: "yuimenuitem",
6135 * @property CSS_LABEL_CLASS_NAME
6136 * @description String representing the CSS class(es) to be applied to the
6137 * menu item's <code><a></code> element.
6138 * @default "yuimenuitemlabel"
6142 CSS_LABEL_CLASS_NAME
: "yuimenuitemlabel",
6146 * @property SUBMENU_TYPE
6147 * @description Object representing the type of menu to instantiate and
6148 * add when parsing the child nodes of the menu item's source HTML element.
6150 * @type YAHOO.widget.Menu
6156 // Private member variables
6160 * @property _oAnchor
6161 * @description Object reference to the menu item's
6162 * <code><a></code> element.
6165 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6166 * one-html.html#ID-48250443">HTMLAnchorElement</a>
6172 * @property _oHelpTextEM
6173 * @description Object reference to the menu item's help text
6174 * <code><em></code> element.
6177 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6178 * one-html.html#ID-58190037">HTMLElement</a>
6184 * @property _oSubmenu
6185 * @description Object reference to the menu item's submenu.
6188 * @type YAHOO.widget.Menu
6194 * @property _oOnclickAttributeValue
6195 * @description Object reference to the menu item's current value for the
6196 * "onclick" configuration attribute.
6201 _oOnclickAttributeValue
: null,
6205 * @property _sClassName
6206 * @description The current value of the "classname" configuration attribute.
6215 // Public properties
6219 * @property constructor
6220 * @description Object reference to the menu item's constructor function.
6221 * @default YAHOO.widget.MenuItem
6222 * @type YAHOO.widget.MenuItem
6224 constructor: MenuItem
,
6229 * @description Number indicating the ordinal position of the menu item in
6238 * @property groupIndex
6239 * @description Number indicating the index of the group to which the menu
6249 * @description Object reference to the menu item's parent menu.
6251 * @type YAHOO.widget.Menu
6258 * @description Object reference to the menu item's
6259 * <code><li></code> element.
6260 * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level
6261 * -one-html.html#ID-74680021">HTMLLIElement</a>
6262 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6263 * one-html.html#ID-74680021">HTMLLIElement</a>
6269 * @property srcElement
6270 * @description Object reference to the HTML element (either
6271 * <code><li></code>, <code><optgroup></code> or
6272 * <code><option></code>) used create the menu item.
6273 * @default <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
6274 * level-one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.
6275 * w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247"
6276 * >HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6277 * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6278 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
6279 * one-html.html#ID-74680021">HTMLLIElement</a>|<a href="http://www.w3.
6280 * org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-38450247">
6281 * HTMLOptGroupElement</a>|<a href="http://www.w3.org/TR/2000/WD-DOM-
6282 * Level-1-20000929/level-one-html.html#ID-70901257">HTMLOptionElement</a>
6289 * @description Object reference to the menu item's value.
6298 * @deprecated Use YAHOO.env.ua
6299 * @description String representing the browser.
6302 browser
: Module
.prototype.browser
,
6307 * @description Id of the menu item's root <code><li></code>
6308 * element. This property should be set via the constructor using the
6309 * configuration object literal. If an id is not specified, then one will
6310 * be created using the "generateId" method of the Dom utility.
6322 * @event destroyEvent
6323 * @description Fires when the menu item's <code><li></code>
6324 * element is removed from its parent <code><ul></code> element.
6325 * @type YAHOO.util.CustomEvent
6331 * @event mouseOverEvent
6332 * @description Fires when the mouse has entered the menu item. Passes
6333 * back the DOM Event object as an argument.
6334 * @type YAHOO.util.CustomEvent
6336 mouseOverEvent
: null,
6340 * @event mouseOutEvent
6341 * @description Fires when the mouse has left the menu item. Passes back
6342 * the DOM Event object as an argument.
6343 * @type YAHOO.util.CustomEvent
6345 mouseOutEvent
: null,
6349 * @event mouseDownEvent
6350 * @description Fires when the user mouses down on the menu item. Passes
6351 * back the DOM Event object as an argument.
6352 * @type YAHOO.util.CustomEvent
6354 mouseDownEvent
: null,
6358 * @event mouseUpEvent
6359 * @description Fires when the user releases a mouse button while the mouse
6360 * is over the menu item. Passes back the DOM Event object as an argument.
6361 * @type YAHOO.util.CustomEvent
6368 * @description Fires when the user clicks the on the menu item. Passes
6369 * back the DOM Event object as an argument.
6370 * @type YAHOO.util.CustomEvent
6376 * @event keyPressEvent
6377 * @description Fires when the user presses an alphanumeric key when the
6378 * menu item has focus. Passes back the DOM Event object as an argument.
6379 * @type YAHOO.util.CustomEvent
6381 keyPressEvent
: null,
6385 * @event keyDownEvent
6386 * @description Fires when the user presses a key when the menu item has
6387 * focus. Passes back the DOM Event object as an argument.
6388 * @type YAHOO.util.CustomEvent
6395 * @description Fires when the user releases a key when the menu item has
6396 * focus. Passes back the DOM Event object as an argument.
6397 * @type YAHOO.util.CustomEvent
6404 * @description Fires when the menu item receives focus.
6405 * @type YAHOO.util.CustomEvent
6412 * @description Fires when the menu item loses the input focus.
6413 * @type YAHOO.util.CustomEvent
6420 * @description The MenuItem class's initialization method. This method is
6421 * automatically called by the constructor, and sets up all DOM references
6422 * for pre-existing markup, and creates required markup if it is not
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
6438 init: function (p_oObject
, p_oConfig
) {
6441 if (!this.SUBMENU_TYPE
) {
6443 this.SUBMENU_TYPE
= Menu
;
6448 // Create the config object
6450 this.cfg
= new YAHOO
.util
.Config(this);
6452 this.initDefaultConfig();
6454 var SIGNATURE
= CustomEvent
.LIST
,
6463 if (Lang
.isString(p_oObject
)) {
6465 this._createRootNodeStructure();
6467 oConfig
.queueProperty("text", p_oObject
);
6470 else if (p_oObject
&& p_oObject
.tagName
) {
6472 switch(p_oObject
.tagName
.toUpperCase()) {
6476 this._createRootNodeStructure();
6478 oConfig
.queueProperty("text", p_oObject
.text
);
6479 oConfig
.queueProperty("disabled", p_oObject
.disabled
);
6481 this.value
= p_oObject
.value
;
6483 this.srcElement
= p_oObject
;
6489 this._createRootNodeStructure();
6491 oConfig
.queueProperty("text", p_oObject
.label
);
6492 oConfig
.queueProperty("disabled", p_oObject
.disabled
);
6494 this.srcElement
= p_oObject
;
6496 this._initSubTree();
6502 // Get the anchor node (if it exists)
6504 oAnchor
= Dom
.getFirstChild(p_oObject
);
6507 // Capture the "text" and/or the "URL"
6511 sURL
= oAnchor
.getAttribute("href", 2);
6512 sTarget
= oAnchor
.getAttribute("target");
6514 sText
= oAnchor
.innerHTML
;
6518 this.srcElement
= p_oObject
;
6519 this.element
= p_oObject
;
6520 this._oAnchor
= oAnchor
;
6523 Set these properties silently to sync up the
6524 configuration object without making changes to the
6528 oConfig
.setProperty("text", sText
, true);
6529 oConfig
.setProperty("url", sURL
, true);
6530 oConfig
.setProperty("target", sTarget
, true);
6532 this._initSubTree();
6543 sId
= (this.srcElement
|| this.element
).id
;
6547 sId
= this.id
|| Dom
.generateId();
6549 this.element
.id
= sId
;
6556 Dom
.addClass(this.element
, this.CSS_CLASS_NAME
);
6557 Dom
.addClass(this._oAnchor
, this.CSS_LABEL_CLASS_NAME
);
6560 // Create custom events
6562 this.mouseOverEvent
= this.createEvent(EVENT_TYPES
.MOUSE_OVER
);
6563 this.mouseOverEvent
.signature
= SIGNATURE
;
6565 this.mouseOutEvent
= this.createEvent(EVENT_TYPES
.MOUSE_OUT
);
6566 this.mouseOutEvent
.signature
= SIGNATURE
;
6568 this.mouseDownEvent
= this.createEvent(EVENT_TYPES
.MOUSE_DOWN
);
6569 this.mouseDownEvent
.signature
= SIGNATURE
;
6571 this.mouseUpEvent
= this.createEvent(EVENT_TYPES
.MOUSE_UP
);
6572 this.mouseUpEvent
.signature
= SIGNATURE
;
6574 this.clickEvent
= this.createEvent(EVENT_TYPES
.CLICK
);
6575 this.clickEvent
.signature
= SIGNATURE
;
6577 this.keyPressEvent
= this.createEvent(EVENT_TYPES
.KEY_PRESS
);
6578 this.keyPressEvent
.signature
= SIGNATURE
;
6580 this.keyDownEvent
= this.createEvent(EVENT_TYPES
.KEY_DOWN
);
6581 this.keyDownEvent
.signature
= SIGNATURE
;
6583 this.keyUpEvent
= this.createEvent(EVENT_TYPES
.KEY_UP
);
6584 this.keyUpEvent
.signature
= SIGNATURE
;
6586 this.focusEvent
= this.createEvent(EVENT_TYPES
.FOCUS
);
6587 this.focusEvent
.signature
= SIGNATURE
;
6589 this.blurEvent
= this.createEvent(EVENT_TYPES
.BLUR
);
6590 this.blurEvent
.signature
= SIGNATURE
;
6592 this.destroyEvent
= this.createEvent(EVENT_TYPES
.DESTROY
);
6593 this.destroyEvent
.signature
= SIGNATURE
;
6597 oConfig
.applyConfig(p_oConfig
);
6601 oConfig
.fireQueue();
6613 * @method _createRootNodeStructure
6614 * @description Creates the core DOM structure for the menu item.
6617 _createRootNodeStructure: function () {
6622 if (!m_oMenuItemTemplate
) {
6624 m_oMenuItemTemplate
= document
.createElement("li");
6625 m_oMenuItemTemplate
.innerHTML
= "<a href=\"#\"></a>";
6629 oElement
= m_oMenuItemTemplate
.cloneNode(true);
6630 oElement
.className
= this.CSS_CLASS_NAME
;
6632 oAnchor
= oElement
.firstChild
;
6633 oAnchor
.className
= this.CSS_LABEL_CLASS_NAME
;
6635 this.element
= oElement
;
6636 this._oAnchor
= oAnchor
;
6642 * @method _initSubTree
6643 * @description Iterates the source element's childNodes collection and uses
6644 * the child nodes to instantiate other menus.
6647 _initSubTree: function () {
6649 var oSrcEl
= this.srcElement
,
6658 if (oSrcEl
.childNodes
.length
> 0) {
6660 if (this.parent
.lazyLoad
&& this.parent
.srcElement
&&
6661 this.parent
.srcElement
.tagName
.toUpperCase() == "SELECT") {
6663 oConfig
.setProperty(
6665 { id
: Dom
.generateId(), itemdata
: oSrcEl
.childNodes
}
6671 oNode
= oSrcEl
.firstChild
;
6676 if (oNode
&& oNode
.tagName
) {
6678 switch(oNode
.tagName
.toUpperCase()) {
6682 oConfig
.setProperty("submenu", oNode
);
6688 aOptions
[aOptions
.length
] = oNode
;
6697 while((oNode
= oNode
.nextSibling
));
6700 nOptions
= aOptions
.length
;
6704 oMenu
= new this.SUBMENU_TYPE(Dom
.generateId());
6706 oConfig
.setProperty("submenu", oMenu
);
6708 for(n
=0; n
<nOptions
; n
++) {
6710 oMenu
.addItem((new oMenu
.ITEM_TYPE(aOptions
[n
])));
6724 // Event handlers for configuration properties
6728 * @method configText
6729 * @description Event handler for when the "text" configuration property of
6730 * the menu item changes.
6731 * @param {String} p_sType String representing the name of the event that
6733 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
6734 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
6735 * that fired the event.
6737 configText: function (p_sType
, p_aArgs
, p_oItem
) {
6739 var sText
= p_aArgs
[0],
6741 oAnchor
= this._oAnchor
,
6742 sHelpText
= oConfig
.getProperty("helptext"),
6744 sEmphasisStartTag
= "",
6745 sEmphasisEndTag
= "";
6753 sHelpTextHTML
= "<em class=\"helptext\">" + sHelpText
+ "</em>";
6758 if (oConfig
.getProperty("emphasis")) {
6760 sEmphasisStartTag
= "<em>";
6761 sEmphasisEndTag
= "</em>";
6766 if (oConfig
.getProperty("strongemphasis")) {
6768 sEmphasisStartTag
= "<strong>";
6769 sEmphasisEndTag
= "</strong>";
6774 oAnchor
.innerHTML
= (sEmphasisStartTag
+ sText
+
6775 sEmphasisEndTag
+ sHelpTextHTML
);
6783 * @method configHelpText
6784 * @description Event handler for when the "helptext" configuration property
6785 * of the menu item changes.
6786 * @param {String} p_sType String representing the name of the event that
6788 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
6789 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
6790 * that fired the event.
6792 configHelpText: function (p_sType
, p_aArgs
, p_oItem
) {
6794 this.cfg
.refireEvent("text");
6801 * @description Event handler for when the "url" configuration property of
6802 * the menu item changes.
6803 * @param {String} p_sType String representing the name of the event that
6805 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
6806 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
6807 * that fired the event.
6809 configURL: function (p_sType
, p_aArgs
, p_oItem
) {
6811 var sURL
= p_aArgs
[0];
6819 var oAnchor
= this._oAnchor
;
6821 if (YAHOO
.env
.ua
.opera
) {
6823 oAnchor
.removeAttribute("href");
6827 oAnchor
.setAttribute("href", sURL
);
6833 * @method configTarget
6834 * @description Event handler for when the "target" configuration property
6835 * of the menu item changes.
6836 * @param {String} p_sType String representing the name of the event that
6838 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
6839 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
6840 * that fired the event.
6842 configTarget: function (p_sType
, p_aArgs
, p_oItem
) {
6844 var sTarget
= p_aArgs
[0],
6845 oAnchor
= this._oAnchor
;
6847 if (sTarget
&& sTarget
.length
> 0) {
6849 oAnchor
.setAttribute("target", sTarget
);
6854 oAnchor
.removeAttribute("target");
6862 * @method configEmphasis
6863 * @description Event handler for when the "emphasis" configuration property
6864 * of the menu item changes.
6865 * @param {String} p_sType String representing the name of the event that
6867 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
6868 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
6869 * that fired the event.
6871 configEmphasis: function (p_sType
, p_aArgs
, p_oItem
) {
6873 var bEmphasis
= p_aArgs
[0],
6877 if (bEmphasis
&& oConfig
.getProperty("strongemphasis")) {
6879 oConfig
.setProperty("strongemphasis", false);
6884 oConfig
.refireEvent("text");
6890 * @method configStrongEmphasis
6891 * @description Event handler for when the "strongemphasis" configuration
6892 * property of the menu item changes.
6893 * @param {String} p_sType String representing the name of the event that
6895 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
6896 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
6897 * that fired the event.
6899 configStrongEmphasis: function (p_sType
, p_aArgs
, p_oItem
) {
6901 var bStrongEmphasis
= p_aArgs
[0],
6905 if (bStrongEmphasis
&& oConfig
.getProperty("emphasis")) {
6907 oConfig
.setProperty("emphasis", false);
6911 oConfig
.refireEvent("text");
6917 * @method configChecked
6918 * @description Event handler for when the "checked" configuration property
6919 * of the menu item changes.
6920 * @param {String} p_sType String representing the name of the event that
6922 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
6923 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
6924 * that fired the event.
6926 configChecked: function (p_sType
, p_aArgs
, p_oItem
) {
6928 var bChecked
= p_aArgs
[0],
6929 oElement
= this.element
,
6930 oAnchor
= this._oAnchor
,
6932 sState
= "-checked",
6933 sClassName
= this.CSS_CLASS_NAME
+ sState
,
6934 sLabelClassName
= this.CSS_LABEL_CLASS_NAME
+ sState
;
6939 Dom
.addClass(oElement
, sClassName
);
6940 Dom
.addClass(oAnchor
, sLabelClassName
);
6945 Dom
.removeClass(oElement
, sClassName
);
6946 Dom
.removeClass(oAnchor
, sLabelClassName
);
6951 oConfig
.refireEvent("text");
6954 if (oConfig
.getProperty("disabled")) {
6956 oConfig
.refireEvent("disabled");
6961 if (oConfig
.getProperty("selected")) {
6963 oConfig
.refireEvent("selected");
6972 * @method configDisabled
6973 * @description Event handler for when the "disabled" configuration property
6974 * of the menu item changes.
6975 * @param {String} p_sType String representing the name of the event that
6977 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
6978 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
6979 * that fired the event.
6981 configDisabled: function (p_sType
, p_aArgs
, p_oItem
) {
6983 var bDisabled
= p_aArgs
[0],
6985 oSubmenu
= oConfig
.getProperty("submenu"),
6986 bChecked
= oConfig
.getProperty("checked"),
6987 oElement
= this.element
,
6988 oAnchor
= this._oAnchor
,
6989 sState
= "-disabled",
6990 sCheckedState
= "-checked" + sState
,
6991 sSubmenuState
= "-hassubmenu" + sState
,
6992 sClassName
= this.CSS_CLASS_NAME
+ sState
,
6993 sLabelClassName
= this.CSS_LABEL_CLASS_NAME
+ sState
,
6994 sCheckedClassName
= this.CSS_CLASS_NAME
+ sCheckedState
,
6995 sLabelCheckedClassName
= this.CSS_LABEL_CLASS_NAME
+ sCheckedState
,
6996 sSubmenuClassName
= this.CSS_CLASS_NAME
+ sSubmenuState
,
6997 sLabelSubmenuClassName
= this.CSS_LABEL_CLASS_NAME
+ sSubmenuState
;
7002 if (oConfig
.getProperty("selected")) {
7004 oConfig
.setProperty("selected", false);
7008 Dom
.addClass(oElement
, sClassName
);
7009 Dom
.addClass(oAnchor
, sLabelClassName
);
7014 Dom
.addClass(oElement
, sSubmenuClassName
);
7015 Dom
.addClass(oAnchor
, sLabelSubmenuClassName
);
7022 Dom
.addClass(oElement
, sCheckedClassName
);
7023 Dom
.addClass(oAnchor
, sLabelCheckedClassName
);
7030 Dom
.removeClass(oElement
, sClassName
);
7031 Dom
.removeClass(oAnchor
, sLabelClassName
);
7036 Dom
.removeClass(oElement
, sSubmenuClassName
);
7037 Dom
.removeClass(oAnchor
, sLabelSubmenuClassName
);
7044 Dom
.removeClass(oElement
, sCheckedClassName
);
7045 Dom
.removeClass(oAnchor
, sLabelCheckedClassName
);
7055 * @method configSelected
7056 * @description Event handler for when the "selected" configuration property
7057 * of the menu item changes.
7058 * @param {String} p_sType String representing the name of the event that
7060 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7061 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7062 * that fired the event.
7064 configSelected: function (p_sType
, p_aArgs
, p_oItem
) {
7066 var oConfig
= this.cfg
,
7067 bSelected
= p_aArgs
[0],
7068 oElement
= this.element
,
7069 oAnchor
= this._oAnchor
,
7070 bChecked
= oConfig
.getProperty("checked"),
7071 oSubmenu
= oConfig
.getProperty("submenu"),
7072 sState
= "-selected",
7073 sCheckedState
= "-checked" + sState
,
7074 sSubmenuState
= "-hassubmenu" + sState
,
7075 sClassName
= this.CSS_CLASS_NAME
+ sState
,
7076 sLabelClassName
= this.CSS_LABEL_CLASS_NAME
+ sState
,
7077 sCheckedClassName
= this.CSS_CLASS_NAME
+ sCheckedState
,
7078 sLabelCheckedClassName
= this.CSS_LABEL_CLASS_NAME
+ sCheckedState
,
7079 sSubmenuClassName
= this.CSS_CLASS_NAME
+ sSubmenuState
,
7080 sLabelSubmenuClassName
= this.CSS_LABEL_CLASS_NAME
+ sSubmenuState
;
7083 if (YAHOO
.env
.ua
.opera
) {
7090 if (bSelected
&& !oConfig
.getProperty("disabled")) {
7092 Dom
.addClass(oElement
, sClassName
);
7093 Dom
.addClass(oAnchor
, sLabelClassName
);
7098 Dom
.addClass(oElement
, sSubmenuClassName
);
7099 Dom
.addClass(oAnchor
, sLabelSubmenuClassName
);
7106 Dom
.addClass(oElement
, sCheckedClassName
);
7107 Dom
.addClass(oAnchor
, sLabelCheckedClassName
);
7114 Dom
.removeClass(oElement
, sClassName
);
7115 Dom
.removeClass(oAnchor
, sLabelClassName
);
7120 Dom
.removeClass(oElement
, sSubmenuClassName
);
7121 Dom
.removeClass(oAnchor
, sLabelSubmenuClassName
);
7128 Dom
.removeClass(oElement
, sCheckedClassName
);
7129 Dom
.removeClass(oAnchor
, sLabelCheckedClassName
);
7136 if (this.hasFocus() && YAHOO
.env
.ua
.opera
) {
7146 * @method _onSubmenuBeforeHide
7147 * @description "beforehide" Custom Event handler for a submenu.
7149 * @param {String} p_sType String representing the name of the event that
7151 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7153 _onSubmenuBeforeHide: function (p_sType
, p_aArgs
) {
7155 var oItem
= this.parent
,
7160 oItem
._oAnchor
.blur();
7161 oMenu
.beforeHideEvent
.unsubscribe(onHide
);
7166 if (oItem
.hasFocus()) {
7168 oMenu
= oItem
.parent
;
7170 oMenu
.beforeHideEvent
.subscribe(onHide
);
7178 * @method configSubmenu
7179 * @description Event handler for when the "submenu" configuration property
7180 * of the menu item changes.
7181 * @param {String} p_sType String representing the name of the event that
7183 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7184 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7185 * that fired the event.
7187 configSubmenu: function (p_sType
, p_aArgs
, p_oItem
) {
7189 var oSubmenu
= p_aArgs
[0],
7191 oElement
= this.element
,
7192 oAnchor
= this._oAnchor
,
7193 bLazyLoad
= this.parent
&& this.parent
.lazyLoad
,
7194 sState
= "-hassubmenu",
7195 sClassName
= this.CSS_CLASS_NAME
+ sState
,
7196 sLabelClassName
= this.CSS_LABEL_CLASS_NAME
+ sState
,
7204 if (oSubmenu
instanceof Menu
) {
7207 oMenu
.parent
= this;
7208 oMenu
.lazyLoad
= bLazyLoad
;
7211 else if (typeof oSubmenu
== "object" && oSubmenu
.id
&&
7212 !oSubmenu
.nodeType
) {
7214 sSubmenuId
= oSubmenu
.id
;
7215 oSubmenuConfig
= oSubmenu
;
7217 oSubmenuConfig
.lazyload
= bLazyLoad
;
7218 oSubmenuConfig
.parent
= this;
7220 oMenu
= new this.SUBMENU_TYPE(sSubmenuId
, oSubmenuConfig
);
7223 // Set the value of the property to the Menu instance
7225 oConfig
.setProperty("submenu", oMenu
, true);
7230 oMenu
= new this.SUBMENU_TYPE(oSubmenu
,
7231 { lazyload
: bLazyLoad
, parent
: this });
7234 // Set the value of the property to the Menu instance
7236 oConfig
.setProperty("submenu", oMenu
, true);
7243 Dom
.addClass(oElement
, sClassName
);
7244 Dom
.addClass(oAnchor
, sLabelClassName
);
7246 this._oSubmenu
= oMenu
;
7248 if (YAHOO
.env
.ua
.opera
) {
7250 oMenu
.beforeHideEvent
.subscribe(this._onSubmenuBeforeHide
);
7259 Dom
.removeClass(oElement
, sClassName
);
7260 Dom
.removeClass(oAnchor
, sLabelClassName
);
7262 if (this._oSubmenu
) {
7264 this._oSubmenu
.destroy();
7271 if (oConfig
.getProperty("disabled")) {
7273 oConfig
.refireEvent("disabled");
7278 if (oConfig
.getProperty("selected")) {
7280 oConfig
.refireEvent("selected");
7288 * @method configOnClick
7289 * @description Event handler for when the "onclick" configuration property
7290 * of the menu item changes.
7291 * @param {String} p_sType String representing the name of the event that
7293 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7294 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7295 * that fired the event.
7297 configOnClick: function (p_sType
, p_aArgs
, p_oItem
) {
7299 var oObject
= p_aArgs
[0];
7302 Remove any existing listeners if a "click" event handler has
7303 already been specified.
7306 if (this._oOnclickAttributeValue
&&
7307 (this._oOnclickAttributeValue
!= oObject
)) {
7309 this.clickEvent
.unsubscribe(this._oOnclickAttributeValue
.fn
,
7310 this._oOnclickAttributeValue
.obj
);
7312 this._oOnclickAttributeValue
= null;
7317 if (!this._oOnclickAttributeValue
&& typeof oObject
== "object" &&
7318 typeof oObject
.fn
== "function") {
7320 this.clickEvent
.subscribe(oObject
.fn
,
7321 ((!YAHOO
.lang
.isUndefined(oObject
.obj
)) ? oObject
.obj
: this),
7324 this._oOnclickAttributeValue
= oObject
;
7332 * @method configClassName
7333 * @description Event handler for when the "classname" configuration
7334 * property of a menu item changes.
7335 * @param {String} p_sType String representing the name of the event that
7337 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
7338 * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item
7339 * that fired the event.
7341 configClassName: function (p_sType
, p_aArgs
, p_oItem
) {
7343 var sClassName
= p_aArgs
[0];
7345 if (this._sClassName
) {
7347 Dom
.removeClass(this.element
, this._sClassName
);
7351 Dom
.addClass(this.element
, sClassName
);
7352 this._sClassName
= sClassName
;
7362 * @method initDefaultConfig
7363 * @description Initializes an item's configurable properties.
7365 initDefaultConfig : function () {
7367 var oConfig
= this.cfg
;
7370 // Define the configuration attributes
7374 * @description String specifying the text label for the menu item.
7375 * When building a menu from existing HTML the value of this property
7376 * will be interpreted from the menu's markup.
7380 oConfig
.addProperty(
7381 DEFAULT_CONFIG
.TEXT
.key
,
7383 handler
: this.configText
,
7384 value
: DEFAULT_CONFIG
.TEXT
.value
,
7385 validator
: DEFAULT_CONFIG
.TEXT
.validator
,
7386 suppressEvent
: DEFAULT_CONFIG
.TEXT
.suppressEvent
7393 * @description String specifying additional instructional text to
7394 * accompany the text for the menu item.
7395 * @deprecated Use "text" configuration property to add help text markup.
7396 * For example: <code>oMenuItem.cfg.setProperty("text", "Copy <em
7397 * class=\"helptext\">Ctrl + C</em>");</code>
7399 * @type String|<a href="http://www.w3.org/TR/
7400 * 2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
7403 oConfig
.addProperty(
7404 DEFAULT_CONFIG
.HELP_TEXT
.key
,
7406 handler
: this.configHelpText
,
7407 supercedes
: DEFAULT_CONFIG
.HELP_TEXT
.supercedes
,
7408 suppressEvent
: DEFAULT_CONFIG
.HELP_TEXT
.suppressEvent
7415 * @description String specifying the URL for the menu item's anchor's
7416 * "href" attribute. When building a menu from existing HTML the value
7417 * of this property will be interpreted from the menu's markup.
7421 oConfig
.addProperty(
7422 DEFAULT_CONFIG
.URL
.key
,
7424 handler
: this.configURL
,
7425 value
: DEFAULT_CONFIG
.URL
.value
,
7426 suppressEvent
: DEFAULT_CONFIG
.URL
.suppressEvent
7433 * @description String specifying the value for the "target" attribute
7434 * of the menu item's anchor element. <strong>Specifying a target will
7435 * require the user to click directly on the menu item's anchor node in
7436 * order to cause the browser to navigate to the specified URL.</strong>
7437 * When building a menu from existing HTML the value of this property
7438 * will be interpreted from the menu's markup.
7442 oConfig
.addProperty(
7443 DEFAULT_CONFIG
.TARGET
.key
,
7445 handler
: this.configTarget
,
7446 suppressEvent
: DEFAULT_CONFIG
.TARGET
.suppressEvent
7453 * @description Boolean indicating if the text of the menu item will be
7454 * rendered with emphasis.
7455 * @deprecated Use "text" configuration property to add emphasis.
7456 * For example: <code>oMenuItem.cfg.setProperty("text", "<em>Some
7457 * Text</em>");</code>
7461 oConfig
.addProperty(
7462 DEFAULT_CONFIG
.EMPHASIS
.key
,
7464 handler
: this.configEmphasis
,
7465 value
: DEFAULT_CONFIG
.EMPHASIS
.value
,
7466 validator
: DEFAULT_CONFIG
.EMPHASIS
.validator
,
7467 suppressEvent
: DEFAULT_CONFIG
.EMPHASIS
.suppressEvent
,
7468 supercedes
: DEFAULT_CONFIG
.EMPHASIS
.supercedes
7474 * @config strongemphasis
7475 * @description Boolean indicating if the text of the menu item will be
7476 * rendered with strong emphasis.
7477 * @deprecated Use "text" configuration property to add strong emphasis.
7478 * For example: <code>oMenuItem.cfg.setProperty("text", "<strong>
7479 * Some Text</strong>");</code>
7483 oConfig
.addProperty(
7484 DEFAULT_CONFIG
.STRONG_EMPHASIS
.key
,
7486 handler
: this.configStrongEmphasis
,
7487 value
: DEFAULT_CONFIG
.STRONG_EMPHASIS
.value
,
7488 validator
: DEFAULT_CONFIG
.STRONG_EMPHASIS
.validator
,
7489 suppressEvent
: DEFAULT_CONFIG
.STRONG_EMPHASIS
.suppressEvent
,
7490 supercedes
: DEFAULT_CONFIG
.STRONG_EMPHASIS
.supercedes
7497 * @description Boolean indicating if the menu item should be rendered
7502 oConfig
.addProperty(
7503 DEFAULT_CONFIG
.CHECKED
.key
,
7505 handler
: this.configChecked
,
7506 value
: DEFAULT_CONFIG
.CHECKED
.value
,
7507 validator
: DEFAULT_CONFIG
.CHECKED
.validator
,
7508 suppressEvent
: DEFAULT_CONFIG
.CHECKED
.suppressEvent
,
7509 supercedes
: DEFAULT_CONFIG
.CHECKED
.supercedes
7516 * @description Boolean indicating if the menu item should be disabled.
7517 * (Disabled menu items are dimmed and will not respond to user input
7522 oConfig
.addProperty(
7523 DEFAULT_CONFIG
.DISABLED
.key
,
7525 handler
: this.configDisabled
,
7526 value
: DEFAULT_CONFIG
.DISABLED
.value
,
7527 validator
: DEFAULT_CONFIG
.DISABLED
.validator
,
7528 suppressEvent
: DEFAULT_CONFIG
.DISABLED
.suppressEvent
7535 * @description Boolean indicating if the menu item should
7540 oConfig
.addProperty(
7541 DEFAULT_CONFIG
.SELECTED
.key
,
7543 handler
: this.configSelected
,
7544 value
: DEFAULT_CONFIG
.SELECTED
.value
,
7545 validator
: DEFAULT_CONFIG
.SELECTED
.validator
,
7546 suppressEvent
: DEFAULT_CONFIG
.SELECTED
.suppressEvent
7553 * @description Object specifying the submenu to be appended to the
7554 * menu item. The value can be one of the following: <ul><li>Object
7555 * specifying a Menu instance.</li><li>Object literal specifying the
7556 * menu to be created. Format: <code>{ id: [menu id], itemdata:
7557 * [<a href="YAHOO.widget.Menu.html#itemData">array of values for
7558 * items</a>] }</code>.</li><li>String specifying the id attribute
7559 * of the <code><div></code> element of the menu.</li><li>
7560 * Object specifying the <code><div></code> element of the
7563 * @type Menu|String|Object|<a href="http://www.w3.org/TR/2000/
7564 * WD-DOM-Level-1-20000929/level-one-html.html#ID-58190037">
7567 oConfig
.addProperty(
7568 DEFAULT_CONFIG
.SUBMENU
.key
,
7570 handler
: this.configSubmenu
,
7571 supercedes
: DEFAULT_CONFIG
.SUBMENU
.supercedes
,
7572 suppressEvent
: DEFAULT_CONFIG
.SUBMENU
.suppressEvent
7579 * @description Object literal representing the code to be executed when
7580 * the item is clicked. Format:<br> <code> {<br>
7581 * <strong>fn:</strong> Function, // The handler to call when
7582 * the event fires.<br> <strong>obj:</strong> Object, // An
7583 * object to pass back to the handler.<br> <strong>scope:</strong>
7584 * Object // The object to use for the scope of the handler.
7589 oConfig
.addProperty(
7590 DEFAULT_CONFIG
.ONCLICK
.key
,
7592 handler
: this.configOnClick
,
7593 suppressEvent
: DEFAULT_CONFIG
.ONCLICK
.suppressEvent
7600 * @description CSS class to be applied to the menu item's root
7601 * <code><li></code> element. The specified class(es) are
7602 * appended in addition to the default class as specified by the menu
7603 * item's CSS_CLASS_NAME constant.
7607 oConfig
.addProperty(
7608 DEFAULT_CONFIG
.CLASS_NAME
.key
,
7610 handler
: this.configClassName
,
7611 value
: DEFAULT_CONFIG
.CLASS_NAME
.value
,
7612 validator
: DEFAULT_CONFIG
.CLASS_NAME
.validator
,
7613 suppressEvent
: DEFAULT_CONFIG
.CLASS_NAME
.suppressEvent
7621 * @method getNextEnabledSibling
7622 * @description Finds the menu item's next enabled sibling.
7623 * @return YAHOO.widget.MenuItem
7625 getNextEnabledSibling: function () {
7633 function getNextArrayItem(p_aArray
, p_nStartIndex
) {
7635 return p_aArray
[p_nStartIndex
] ||
7636 getNextArrayItem(p_aArray
, (p_nStartIndex
+1));
7640 if (this.parent
instanceof Menu
) {
7642 nGroupIndex
= this.groupIndex
;
7644 aItemGroups
= this.parent
.getItemGroups();
7646 if (this.index
< (aItemGroups
[nGroupIndex
].length
- 1)) {
7648 oNextItem
= getNextArrayItem(aItemGroups
[nGroupIndex
],
7654 if (nGroupIndex
< (aItemGroups
.length
- 1)) {
7656 nNextGroupIndex
= nGroupIndex
+ 1;
7661 nNextGroupIndex
= 0;
7665 aNextGroup
= getNextArrayItem(aItemGroups
, nNextGroupIndex
);
7667 // Retrieve the first menu item in the next group
7669 oNextItem
= getNextArrayItem(aNextGroup
, 0);
7673 return (oNextItem
.cfg
.getProperty("disabled") ||
7674 oNextItem
.element
.style
.display
== "none") ?
7675 oNextItem
.getNextEnabledSibling() : oNextItem
;
7683 * @method getPreviousEnabledSibling
7684 * @description Finds the menu item's previous enabled sibling.
7685 * @return {YAHOO.widget.MenuItem}
7687 getPreviousEnabledSibling: function () {
7692 nPreviousGroupIndex
,
7695 function getPreviousArrayItem(p_aArray
, p_nStartIndex
) {
7697 return p_aArray
[p_nStartIndex
] ||
7698 getPreviousArrayItem(p_aArray
, (p_nStartIndex
-1));
7702 function getFirstItemIndex(p_aArray
, p_nStartIndex
) {
7704 return p_aArray
[p_nStartIndex
] ? p_nStartIndex
:
7705 getFirstItemIndex(p_aArray
, (p_nStartIndex
+1));
7709 if (this.parent
instanceof Menu
) {
7711 nGroupIndex
= this.groupIndex
;
7712 aItemGroups
= this.parent
.getItemGroups();
7715 if (this.index
> getFirstItemIndex(aItemGroups
[nGroupIndex
], 0)) {
7717 oPreviousItem
= getPreviousArrayItem(aItemGroups
[nGroupIndex
],
7723 if (nGroupIndex
> getFirstItemIndex(aItemGroups
, 0)) {
7725 nPreviousGroupIndex
= nGroupIndex
- 1;
7730 nPreviousGroupIndex
= aItemGroups
.length
- 1;
7734 aPreviousGroup
= getPreviousArrayItem(aItemGroups
,
7735 nPreviousGroupIndex
);
7737 oPreviousItem
= getPreviousArrayItem(aPreviousGroup
,
7738 (aPreviousGroup
.length
- 1));
7742 return (oPreviousItem
.cfg
.getProperty("disabled") ||
7743 oPreviousItem
.element
.style
.display
== "none") ?
7744 oPreviousItem
.getPreviousEnabledSibling() : oPreviousItem
;
7753 * @description Causes the menu item to receive the focus and fires the
7756 focus: function () {
7758 var oParent
= this.parent
,
7759 oAnchor
= this._oAnchor
,
7760 oActiveItem
= oParent
.activeItem
,
7764 function setFocus() {
7768 if (YAHOO
.env
.ua
.ie
&& !document
.hasFocus()) {
7776 oActiveItem
.blurEvent
.fire();
7782 me
.focusEvent
.fire();
7792 if (!this.cfg
.getProperty("disabled") && oParent
&&
7793 oParent
.cfg
.getProperty("visible") &&
7794 this.element
.style
.display
!= "none") {
7798 Setting focus via a timer fixes a race condition in Firefox, IE
7799 and Opera where the browser viewport jumps as it trys to
7800 position and focus the menu.
7803 window
.setTimeout(setFocus
, 0);
7812 * @description Causes the menu item to lose focus and fires the
7817 var oParent
= this.parent
;
7819 if (!this.cfg
.getProperty("disabled") && oParent
&&
7820 oParent
.cfg
.getProperty("visible")) {
7825 window
.setTimeout(function () {
7830 me
.blurEvent
.fire();
7846 * @description Returns a boolean indicating whether or not the menu item
7850 hasFocus: function () {
7852 return (YAHOO
.widget
.MenuManager
.getFocusedMenuItem() == this);
7859 * @description Removes the menu item's <code><li></code> element
7860 * from its parent <code><ul></code> element.
7862 destroy: function () {
7864 var oEl
= this.element
,
7871 // If the item has a submenu, destroy it first
7873 oSubmenu
= this.cfg
.getProperty("submenu");
7882 // Remove CustomEvent listeners
7884 this.mouseOverEvent
.unsubscribeAll();
7885 this.mouseOutEvent
.unsubscribeAll();
7886 this.mouseDownEvent
.unsubscribeAll();
7887 this.mouseUpEvent
.unsubscribeAll();
7888 this.clickEvent
.unsubscribeAll();
7889 this.keyPressEvent
.unsubscribeAll();
7890 this.keyDownEvent
.unsubscribeAll();
7891 this.keyUpEvent
.unsubscribeAll();
7892 this.focusEvent
.unsubscribeAll();
7893 this.blurEvent
.unsubscribeAll();
7894 this.cfg
.configChangedEvent
.unsubscribeAll();
7897 // Remove the element from the parent node
7899 oParentNode
= oEl
.parentNode
;
7903 oParentNode
.removeChild(oEl
);
7905 this.destroyEvent
.fire();
7909 this.destroyEvent
.unsubscribeAll();
7918 * @description Returns a string representing the menu item.
7921 toString: function () {
7923 var sReturnVal
= "MenuItem",
7928 sReturnVal
+= (" " + sId
);
7938 Lang
.augmentProto(MenuItem
, YAHOO
.util
.EventProvider
);
7945 * Creates a list of options or commands which are made visible in response to
7946 * an HTML element's "contextmenu" event ("mousedown" for Opera).
7948 * @param {String} p_oElement String specifying the id attribute of the
7949 * <code><div></code> element of the context menu.
7950 * @param {String} p_oElement String specifying the id attribute of the
7951 * <code><select></code> element to be used as the data source for the
7953 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
7954 * html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the
7955 * <code><div></code> element of the context menu.
7956 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
7957 * html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying
7958 * the <code><select></code> element to be used as the data source for
7960 * @param {Object} p_oConfig Optional. Object literal specifying the
7961 * configuration for the context menu. See configuration class documentation
7963 * @class ContextMenu
7965 * @extends YAHOO.widget.Menu
7966 * @namespace YAHOO.widget
7968 YAHOO
.widget
.ContextMenu = function(p_oElement
, p_oConfig
) {
7970 YAHOO
.widget
.ContextMenu
.superclass
.constructor.call(this,
7971 p_oElement
, p_oConfig
);
7976 var Event
= YAHOO
.util
.Event
,
7977 ContextMenu
= YAHOO
.widget
.ContextMenu
,
7982 * Constant representing the name of the ContextMenu's events
7983 * @property EVENT_TYPES
7990 "TRIGGER_CONTEXT_MENU": "triggerContextMenu",
7991 "CONTEXT_MENU": (YAHOO
.env
.ua
.opera
? "mousedown" : "contextmenu"),
7998 * Constant representing the ContextMenu's configuration properties
7999 * @property DEFAULT_CONFIG
8016 * @description "beforeShow" event handler used to position the contextmenu.
8018 * @param {String} p_sType String representing the name of the event that
8020 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
8021 * @param {Array} p_aPos Array representing the xy position for the context menu.
8023 function position(p_sType
, p_aArgs
, p_aPos
) {
8025 this.cfg
.setProperty("xy", p_aPos
);
8027 this.beforeShowEvent
.unsubscribe(position
, p_aPos
);
8032 YAHOO
.lang
.extend(ContextMenu
, YAHOO
.widget
.Menu
, {
8036 // Private properties
8040 * @property _oTrigger
8041 * @description Object reference to the current value of the "trigger"
8042 * configuration property.
8045 * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/leve
8046 * l-one-html.html#ID-58190037">HTMLElement</a>|Array
8052 * @property _bCancelled
8053 * @description Boolean indicating if the display of the context menu should
8063 // Public properties
8067 * @property contextEventTarget
8068 * @description Object reference for the HTML element that was the target of the
8069 * "contextmenu" DOM event ("mousedown" for Opera) that triggered the display of
8072 * @type <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8073 * html.html#ID-58190037">HTMLElement</a>
8075 contextEventTarget
: null,
8083 * @event triggerContextMenuEvent
8084 * @description Custom Event wrapper for the "contextmenu" DOM event
8085 * ("mousedown" for Opera) fired by the element(s) that trigger the display of
8088 triggerContextMenuEvent
: null,
8094 * @description The ContextMenu class's initialization method. This method is
8095 * automatically called by the constructor, and sets up all DOM references for
8096 * pre-existing markup, and creates required markup if it is not already present.
8097 * @param {String} p_oElement String specifying the id attribute of the
8098 * <code><div></code> element of the context menu.
8099 * @param {String} p_oElement String specifying the id attribute of the
8100 * <code><select></code> element to be used as the data source for
8102 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8103 * html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying the
8104 * <code><div></code> element of the context menu.
8105 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-
8106 * html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object specifying
8107 * the <code><select></code> element to be used as the data source for
8109 * @param {Object} p_oConfig Optional. Object literal specifying the
8110 * configuration for the context menu. See configuration class documentation
8113 init: function(p_oElement
, p_oConfig
) {
8116 // Call the init of the superclass (YAHOO.widget.Menu)
8118 ContextMenu
.superclass
.init
.call(this, p_oElement
);
8121 this.beforeInitEvent
.fire(ContextMenu
);
8126 this.cfg
.applyConfig(p_oConfig
, true);
8131 this.initEvent
.fire(ContextMenu
);
8137 * @method initEvents
8138 * @description Initializes the custom events for the context menu.
8140 initEvents: function() {
8142 ContextMenu
.superclass
.initEvents
.call(this);
8144 // Create custom events
8146 this.triggerContextMenuEvent
=
8147 this.createEvent(EVENT_TYPES
.TRIGGER_CONTEXT_MENU
);
8149 this.triggerContextMenuEvent
.signature
= YAHOO
.util
.CustomEvent
.LIST
;
8156 * @description Cancels the display of the context menu.
8158 cancel: function() {
8160 this._bCancelled
= true;
8170 * @method _removeEventHandlers
8171 * @description Removes all of the DOM event handlers from the HTML element(s)
8172 * whose "context menu" event ("click" for Opera) trigger the display of
8176 _removeEventHandlers: function() {
8178 var oTrigger
= this._oTrigger
;
8181 // Remove the event handlers from the trigger(s)
8185 Event
.removeListener(oTrigger
, EVENT_TYPES
.CONTEXT_MENU
,
8186 this._onTriggerContextMenu
);
8188 if(YAHOO
.env
.ua
.opera
) {
8190 Event
.removeListener(oTrigger
, EVENT_TYPES
.CLICK
,
8191 this._onTriggerClick
);
8201 // Private event handlers
8206 * @method _onTriggerClick
8207 * @description "click" event handler for the HTML element(s) identified as the
8208 * "trigger" for the context menu. Used to cancel default behaviors in Opera.
8210 * @param {Event} p_oEvent Object representing the DOM event object passed back
8211 * by the event utility (YAHOO.util.Event).
8212 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8213 * menu that is handling the event.
8215 _onTriggerClick: function(p_oEvent
, p_oMenu
) {
8217 if(p_oEvent
.ctrlKey
) {
8219 Event
.stopEvent(p_oEvent
);
8227 * @method _onTriggerContextMenu
8228 * @description "contextmenu" event handler ("mousedown" for Opera) for the HTML
8229 * element(s) that trigger the display of the context menu.
8231 * @param {Event} p_oEvent Object representing the DOM event object passed back
8232 * by the event utility (YAHOO.util.Event).
8233 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8234 * menu that is handling the event.
8236 _onTriggerContextMenu: function(p_oEvent
, p_oMenu
) {
8238 if (p_oEvent
.type
== "mousedown" && !p_oEvent
.ctrlKey
) {
8249 Prevent the browser's default context menu from appearing and
8250 stop the propagation of the "contextmenu" event so that
8251 other ContextMenu instances are not displayed.
8254 Event
.stopEvent(p_oEvent
);
8257 this.contextEventTarget
= Event
.getTarget(p_oEvent
);
8259 this.triggerContextMenuEvent
.fire(p_oEvent
);
8262 // Hide any other Menu instances that might be visible
8264 YAHOO
.widget
.MenuManager
.hideVisible();
8268 if(!this._bCancelled
) {
8270 // Position and display the context menu
8272 aXY
= Event
.getXY(p_oEvent
);
8275 if (!YAHOO
.util
.Dom
.inDocument(this.element
)) {
8277 this.beforeShowEvent
.subscribe(position
, aXY
);
8282 this.cfg
.setProperty("xy", aXY
);
8291 this._bCancelled
= false;
8302 * @description Returns a string representing the context menu.
8305 toString: function() {
8307 var sReturnVal
= "ContextMenu",
8312 sReturnVal
+= (" " + sId
);
8322 * @method initDefaultConfig
8323 * @description Initializes the class's configurable properties which can be
8324 * changed using the context menu's Config object ("cfg").
8326 initDefaultConfig: function() {
8328 ContextMenu
.superclass
.initDefaultConfig
.call(this);
8332 * @description The HTML element(s) whose "contextmenu" event ("mousedown"
8333 * for Opera) trigger the display of the context menu. Can be a string
8334 * representing the id attribute of the HTML element, an object reference
8335 * for the HTML element, or an array of strings or HTML element references.
8337 * @type String|<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/
8338 * level-one-html.html#ID-58190037">HTMLElement</a>|Array
8340 this.cfg
.addProperty(DEFAULT_CONFIG
.TRIGGER
.key
,
8342 handler
: this.configTrigger
,
8343 suppressEvent
: DEFAULT_CONFIG
.TRIGGER
.suppressEvent
8352 * @description Removes the context menu's <code><div></code> element
8353 * (and accompanying child nodes) from the document.
8355 destroy: function() {
8357 // Remove the DOM event handlers from the current trigger(s)
8359 this._removeEventHandlers();
8362 // Continue with the superclass implementation of this method
8364 ContextMenu
.superclass
.destroy
.call(this);
8370 // Public event handlers for configuration properties
8374 * @method configTrigger
8375 * @description Event handler for when the value of the "trigger" configuration
8377 * @param {String} p_sType String representing the name of the event that
8379 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
8380 * @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context
8381 * menu that fired the event.
8383 configTrigger: function(p_sType
, p_aArgs
, p_oMenu
) {
8385 var oTrigger
= p_aArgs
[0];
8390 If there is a current "trigger" - remove the event handlers
8391 from that element(s) before assigning new ones
8394 if(this._oTrigger
) {
8396 this._removeEventHandlers();
8400 this._oTrigger
= oTrigger
;
8404 Listen for the "mousedown" event in Opera b/c it does not
8405 support the "contextmenu" event
8408 Event
.on(oTrigger
, EVENT_TYPES
.CONTEXT_MENU
,
8409 this._onTriggerContextMenu
, this, true);
8413 Assign a "click" event handler to the trigger element(s) for
8414 Opera to prevent default browser behaviors.
8417 if(YAHOO
.env
.ua
.opera
) {
8419 Event
.on(oTrigger
, EVENT_TYPES
.CLICK
, this._onTriggerClick
,
8427 this._removeEventHandlers();
8433 }); // END YAHOO.lang.extend
8440 * Creates an item for a context menu.
8442 * @param {String} p_oObject String specifying the text of the context menu item.
8443 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8444 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
8445 * <code><li></code> element of the context menu item.
8446 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8447 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
8448 * specifying the <code><optgroup></code> element of the context
8450 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8451 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
8452 * the <code><option></code> element of the context menu item.
8453 * @param {Object} p_oConfig Optional. Object literal specifying the
8454 * configuration for the context menu item. See configuration class
8455 * documentation for more details.
8456 * @class ContextMenuItem
8458 * @extends YAHOO.widget.MenuItem
8459 * @deprecated As of version 2.4.0 items for YAHOO.widget.ContextMenu instances
8460 * are of type YAHOO.widget.MenuItem.
8462 YAHOO
.widget
.ContextMenuItem
= YAHOO
.widget
.MenuItem
;
8467 * Horizontal collection of items, each of which can contain a submenu.
8469 * @param {String} p_oElement String specifying the id attribute of the
8470 * <code><div></code> element of the menu bar.
8471 * @param {String} p_oElement String specifying the id attribute of the
8472 * <code><select></code> element to be used as the data source for the
8474 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8475 * one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying
8476 * the <code><div></code> element of the menu bar.
8477 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8478 * one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object
8479 * specifying the <code><select></code> element to be used as the data
8480 * source for the menu bar.
8481 * @param {Object} p_oConfig Optional. Object literal specifying the
8482 * configuration for the menu bar. See configuration class documentation for
8486 * @extends YAHOO.widget.Menu
8487 * @namespace YAHOO.widget
8489 YAHOO
.widget
.MenuBar = function(p_oElement
, p_oConfig
) {
8491 YAHOO
.widget
.MenuBar
.superclass
.constructor.call(this,
8492 p_oElement
, p_oConfig
);
8498 * @method checkPosition
8499 * @description Checks to make sure that the value of the "position" property
8500 * is one of the supported strings. Returns true if the position is supported.
8502 * @param {Object} p_sPosition String specifying the position of the menu.
8505 function checkPosition(p_sPosition
) {
8507 if (typeof p_sPosition
== "string") {
8509 return ("dynamic,static".indexOf((p_sPosition
.toLowerCase())) != -1);
8516 var Event
= YAHOO
.util
.Event
,
8517 MenuBar
= YAHOO
.widget
.MenuBar
,
8520 * Constant representing the MenuBar's configuration properties
8521 * @property DEFAULT_CONFIG
8531 validator
: checkPosition
,
8532 supercedes
: ["visible"]
8535 "SUBMENU_ALIGNMENT": {
8536 key
: "submenualignment",
8541 "AUTO_SUBMENU_DISPLAY": {
8542 key
: "autosubmenudisplay",
8544 validator
: YAHOO
.lang
.isBoolean
,
8552 YAHOO
.lang
.extend(MenuBar
, YAHOO
.widget
.Menu
, {
8556 * @description The MenuBar class's initialization method. This method is
8557 * automatically called by the constructor, and sets up all DOM references for
8558 * pre-existing markup, and creates required markup if it is not already present.
8559 * @param {String} p_oElement String specifying the id attribute of the
8560 * <code><div></code> element of the menu bar.
8561 * @param {String} p_oElement String specifying the id attribute of the
8562 * <code><select></code> element to be used as the data source for the
8564 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8565 * one-html.html#ID-22445964">HTMLDivElement</a>} p_oElement Object specifying
8566 * the <code><div></code> element of the menu bar.
8567 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8568 * one-html.html#ID-94282980">HTMLSelectElement</a>} p_oElement Object
8569 * specifying the <code><select></code> element to be used as the data
8570 * source for the menu bar.
8571 * @param {Object} p_oConfig Optional. Object literal specifying the
8572 * configuration for the menu bar. See configuration class documentation for
8575 init: function(p_oElement
, p_oConfig
) {
8577 if(!this.ITEM_TYPE
) {
8579 this.ITEM_TYPE
= YAHOO
.widget
.MenuBarItem
;
8584 // Call the init of the superclass (YAHOO.widget.Menu)
8586 MenuBar
.superclass
.init
.call(this, p_oElement
);
8589 this.beforeInitEvent
.fire(MenuBar
);
8594 this.cfg
.applyConfig(p_oConfig
, true);
8598 this.initEvent
.fire(MenuBar
);
8608 * @property CSS_CLASS_NAME
8609 * @description String representing the CSS class(es) to be applied to the menu
8610 * bar's <code><div></code> element.
8611 * @default "yuimenubar"
8615 CSS_CLASS_NAME
: "yuimenubar",
8619 // Protected event handlers
8623 * @method _onKeyDown
8624 * @description "keydown" Custom Event handler for the menu bar.
8626 * @param {String} p_sType String representing the name of the event that
8628 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
8629 * @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar
8630 * that fired the event.
8632 _onKeyDown: function(p_sType
, p_aArgs
, p_oMenuBar
) {
8634 var oEvent
= p_aArgs
[0],
8641 if(oItem
&& !oItem
.cfg
.getProperty("disabled")) {
8643 oItemCfg
= oItem
.cfg
;
8645 switch(oEvent
.keyCode
) {
8647 case 37: // Left arrow
8648 case 39: // Right arrow
8650 if(oItem
== this.activeItem
&&
8651 !oItemCfg
.getProperty("selected")) {
8653 oItemCfg
.setProperty("selected", true);
8658 oNextItem
= (oEvent
.keyCode
== 37) ?
8659 oItem
.getPreviousEnabledSibling() :
8660 oItem
.getNextEnabledSibling();
8664 this.clearActiveItem();
8666 oNextItem
.cfg
.setProperty("selected", true);
8669 if(this.cfg
.getProperty("autosubmenudisplay")) {
8671 oSubmenu
= oNextItem
.cfg
.getProperty("submenu");
8687 Event
.preventDefault(oEvent
);
8691 case 40: // Down arrow
8693 if(this.activeItem
!= oItem
) {
8695 this.clearActiveItem();
8697 oItemCfg
.setProperty("selected", true);
8702 oSubmenu
= oItemCfg
.getProperty("submenu");
8706 if(oSubmenu
.cfg
.getProperty("visible")) {
8708 oSubmenu
.setInitialSelection();
8709 oSubmenu
.setInitialFocus();
8720 Event
.preventDefault(oEvent
);
8729 if(oEvent
.keyCode
== 27 && this.activeItem
) { // Esc key
8731 oSubmenu
= this.activeItem
.cfg
.getProperty("submenu");
8733 if(oSubmenu
&& oSubmenu
.cfg
.getProperty("visible")) {
8736 this.activeItem
.focus();
8741 this.activeItem
.cfg
.setProperty("selected", false);
8742 this.activeItem
.blur();
8746 Event
.preventDefault(oEvent
);
8755 * @description "click" event handler for the menu bar.
8757 * @param {String} p_sType String representing the name of the event that
8759 * @param {Array} p_aArgs Array of arguments sent when the event was fired.
8760 * @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar
8761 * that fired the event.
8763 _onClick: function(p_sType
, p_aArgs
, p_oMenuBar
) {
8765 MenuBar
.superclass
._onClick
.call(this, p_sType
, p_aArgs
, p_oMenuBar
);
8767 var oItem
= p_aArgs
[1],
8775 if(oItem
&& !oItem
.cfg
.getProperty("disabled")) {
8777 oEvent
= p_aArgs
[0];
8778 oTarget
= Event
.getTarget(oEvent
);
8779 oActiveItem
= this.activeItem
;
8783 // Hide any other submenus that might be visible
8785 if(oActiveItem
&& oActiveItem
!= oItem
) {
8787 this.clearActiveItem();
8792 oItem
.cfg
.setProperty("selected", true);
8795 // Show the submenu for the item
8797 oSubmenu
= oItem
.cfg
.getProperty("submenu");
8802 if(oSubmenu
.cfg
.getProperty("visible")) {
8826 * @description Returns a string representing the menu bar.
8829 toString: function() {
8831 var sReturnVal
= "MenuBar",
8836 sReturnVal
+= (" " + sId
);
8846 * @description Initializes the class's configurable properties which can be
8847 * changed using the menu bar's Config object ("cfg").
8848 * @method initDefaultConfig
8850 initDefaultConfig: function() {
8852 MenuBar
.superclass
.initDefaultConfig
.call(this);
8854 var oConfig
= this.cfg
;
8856 // Add configuration properties
8860 Set the default value for the "position" configuration property
8861 to "static" by re-adding the property.
8867 * @description String indicating how a menu bar should be positioned on the
8868 * screen. Possible values are "static" and "dynamic." Static menu bars
8869 * are visible by default and reside in the normal flow of the document
8870 * (CSS position: static). Dynamic menu bars are hidden by default, reside
8871 * out of the normal flow of the document (CSS position: absolute), and can
8872 * overlay other elements on the screen.
8876 oConfig
.addProperty(
8877 DEFAULT_CONFIG
.POSITION
.key
,
8879 handler
: this.configPosition
,
8880 value
: DEFAULT_CONFIG
.POSITION
.value
,
8881 validator
: DEFAULT_CONFIG
.POSITION
.validator
,
8882 supercedes
: DEFAULT_CONFIG
.POSITION
.supercedes
8888 Set the default value for the "submenualignment" configuration property
8889 to ["tl","bl"] by re-adding the property.
8893 * @config submenualignment
8894 * @description Array defining how submenus should be aligned to their
8895 * parent menu bar item. The format is: [itemCorner, submenuCorner].
8896 * @default ["tl","bl"]
8899 oConfig
.addProperty(
8900 DEFAULT_CONFIG
.SUBMENU_ALIGNMENT
.key
,
8902 value
: DEFAULT_CONFIG
.SUBMENU_ALIGNMENT
.value
,
8903 suppressEvent
: DEFAULT_CONFIG
.SUBMENU_ALIGNMENT
.suppressEvent
8909 Change the default value for the "autosubmenudisplay" configuration
8910 property to "false" by re-adding the property.
8914 * @config autosubmenudisplay
8915 * @description Boolean indicating if submenus are automatically made
8916 * visible when the user mouses over the menu bar's items.
8920 oConfig
.addProperty(
8921 DEFAULT_CONFIG
.AUTO_SUBMENU_DISPLAY
.key
,
8923 value
: DEFAULT_CONFIG
.AUTO_SUBMENU_DISPLAY
.value
,
8924 validator
: DEFAULT_CONFIG
.AUTO_SUBMENU_DISPLAY
.validator
,
8925 suppressEvent
: DEFAULT_CONFIG
.AUTO_SUBMENU_DISPLAY
.suppressEvent
8931 }); // END YAHOO.lang.extend
8938 * Creates an item for a menu bar.
8940 * @param {String} p_oObject String specifying the text of the menu bar item.
8941 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8942 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
8943 * <code><li></code> element of the menu bar item.
8944 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8945 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
8946 * specifying the <code><optgroup></code> element of the menu bar item.
8947 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8948 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
8949 * the <code><option></code> element of the menu bar item.
8950 * @param {Object} p_oConfig Optional. Object literal specifying the
8951 * configuration for the menu bar item. See configuration class documentation
8953 * @class MenuBarItem
8955 * @extends YAHOO.widget.MenuItem
8957 YAHOO
.widget
.MenuBarItem = function(p_oObject
, p_oConfig
) {
8959 YAHOO
.widget
.MenuBarItem
.superclass
.constructor.call(this,
8960 p_oObject
, p_oConfig
);
8964 YAHOO
.lang
.extend(YAHOO
.widget
.MenuBarItem
, YAHOO
.widget
.MenuItem
, {
8970 * @description The MenuBarItem class's initialization method. This method is
8971 * automatically called by the constructor, and sets up all DOM references for
8972 * pre-existing markup, and creates required markup if it is not already present.
8973 * @param {String} p_oObject String specifying the text of the menu bar item.
8974 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8975 * one-html.html#ID-74680021">HTMLLIElement</a>} p_oObject Object specifying the
8976 * <code><li></code> element of the menu bar item.
8977 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8978 * one-html.html#ID-38450247">HTMLOptGroupElement</a>} p_oObject Object
8979 * specifying the <code><optgroup></code> element of the menu bar item.
8980 * @param {<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-
8981 * one-html.html#ID-70901257">HTMLOptionElement</a>} p_oObject Object specifying
8982 * the <code><option></code> element of the menu bar item.
8983 * @param {Object} p_oConfig Optional. Object literal specifying the
8984 * configuration for the menu bar item. See configuration class documentation
8987 init: function(p_oObject
, p_oConfig
) {
8989 if(!this.SUBMENU_TYPE
) {
8991 this.SUBMENU_TYPE
= YAHOO
.widget
.Menu
;
8997 Call the init of the superclass (YAHOO.widget.MenuItem)
8998 Note: We don't pass the user config in here yet
8999 because we only want it executed once, at the lowest
9003 YAHOO
.widget
.MenuBarItem
.superclass
.init
.call(this, p_oObject
);
9006 var oConfig
= this.cfg
;
9010 oConfig
.applyConfig(p_oConfig
, true);
9014 oConfig
.fireQueue();
9024 * @property CSS_CLASS_NAME
9025 * @description String representing the CSS class(es) to be applied to the
9026 * <code><li></code> element of the menu bar item.
9027 * @default "yuimenubaritem"
9031 CSS_CLASS_NAME
: "yuimenubaritem",
9035 * @property CSS_LABEL_CLASS_NAME
9036 * @description String representing the CSS class(es) to be applied to the
9037 * menu bar item's <code><a></code> element.
9038 * @default "yuimenubaritemlabel"
9042 CSS_LABEL_CLASS_NAME
: "yuimenubaritemlabel",
9051 * @description Returns a string representing the menu bar item.
9054 toString: function() {
9056 var sReturnVal
= "MenuBarItem";
9058 if(this.cfg
&& this.cfg
.getProperty("text")) {
9060 sReturnVal
+= (": " + this.cfg
.getProperty("text"));
9068 }); // END YAHOO.lang.extend
9069 YAHOO
.register("menu", YAHOO
.widget
.Menu
, {version
: "2.5.2", build
: "1076"});