Index: openacs-4/packages/ajaxhelper/www/resources/yui/menu/menu.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/yui/menu/menu.js,v diff -u -r1.1 -r1.2 --- openacs-4/packages/ajaxhelper/www/resources/yui/menu/menu.js 21 Oct 2006 06:14:59 -0000 1.1 +++ openacs-4/packages/ajaxhelper/www/resources/yui/menu/menu.js 25 Dec 2006 16:40:03 -0000 1.2 @@ -2,159 +2,228 @@ Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.txt -Version: 0.11.3 +version: 0.12.1 */ +/** +* @module menu +* @description

The Menu Library features a collection of widgets that make +* it easy to add menus to your website or web application. With the Menu +* Library you can create website fly-out menus, customized context menus, or +* application-style menu bars with just a small amount of scripting.

+* +* @title Menu Library +* @namespace YAHOO.widget +* @requires Event, Dom, Container +*/ +(function() { +var Dom = YAHOO.util.Dom, + Event = YAHOO.util.Event; /** -* @class The superclass of all menu containers. -* @constructor -* @extends YAHOO.widget.Overlay -* @base YAHOO.widget.Overlay -* @param {String or HTMLElement} p_oElement String id or HTMLElement -* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node. -* @param {Object} p_oConfig Optional. The configuration object literal -* containing the configuration for a MenuModule instance. See -* configuration class documentation for more details. +* Singleton that manages a collection of all menus and menu items. Listens for +* DOM events at the document level and dispatches the events to the +* corresponding menu or menu item. +* +* @namespace YAHOO.widget +* @class MenuManager +* @static */ -YAHOO.widget.MenuModule = function(p_oElement, p_oConfig) { +YAHOO.widget.MenuManager = function() { - YAHOO.widget.MenuModule.superclass.constructor.call( - this, - p_oElement, - p_oConfig - ); + // Private member variables -}; + // Flag indicating if the DOM event handlers have been attached -YAHOO.extend(YAHOO.widget.MenuModule, YAHOO.widget.Overlay); + var m_bInitializedEventHandlers = false, -// Private globals + // Collection of menus -/** -* Private global flag indicating if the DOM event handlers have been attached -* @private -* @type {Boolean} -*/ -YAHOO.widget.MenuModule._initEventHandlers = true; + m_oMenus = {}, -/** -* Private global collection of menus -* @private -* @type {Object} -*/ -YAHOO.widget.MenuModule._menus = {}; -/** -* Private global collection of menu items -* @private -* @type {Object} -*/ -YAHOO.widget.MenuModule._menuItems = {}; + // Collection of menu items -/** -* Generic, global event handler for all of a menu's DOM-based events. This -* listens for events against the document object. If the target of a given -* event is a member of a menu or menu item's DOM, the instance's corresponding -* Custom Event is fired. -* @private -* @param {Event} p_oEvent Event object passed back by the event -* utility (YAHOO.util.Event). -*/ -YAHOO.widget.MenuModule._onDOMEvent = function(p_oEvent) { + m_oItems = {}, - // Create references to the DOM and Event utilities + // Collection of visible menus - var Dom = YAHOO.util.Dom; - var Event = YAHOO.util.Event; + m_oVisibleMenus = {}, - // The target node of the DOM event + // Logger - var oTarget = Event.getTarget(p_oEvent); - // A reference to the root LI node of a menu item + me = this; - var oMenuItemRootElement; + // Private methods /** - * Finds the root DIV node of a menu and the root LI node of a menu item + * @method addItem + * @description Adds an item to the collection of known menu items. * @private - * @param {HTMLElement} p_oElement An HTML element + * @param {YAHOO.widget.MenuItem} p_oItem Object specifying the MenuItem + * instance to be added. */ + function addItem(p_oItem) { + + var sYUIId = Dom.generateId(); + + if(p_oItem && m_oItems[sYUIId] != p_oItem) { + + p_oItem.element.setAttribute("yuiid", sYUIId); + + m_oItems[sYUIId] = p_oItem; + + p_oItem.destroyEvent.subscribe(onItemDestroy, p_oItem); + + + } + + } + + /** + * @method removeItem + * @description Removes an item from the collection of known menu items. + * @private + * @param {YAHOO.widget.MenuItem} p_oItem Object specifying the MenuItem + * instance to be removed. + */ + function removeItem(p_oItem) { + + var sYUIId = p_oItem.element.getAttribute("yuiid"); + + if(sYUIId && m_oItems[sYUIId]) { + + delete m_oItems[sYUIId]; + + + } + + } + + /** + * @method getMenuRootElement + * @description Finds the root DIV node of a menu or the root LI node of a + * menu item. + * @private + * @param {HTMLElement} p_oElement Object specifying + * an HTML element. + */ function getMenuRootElement(p_oElement) { var oParentNode; - switch(p_oElement.tagName) { + if(p_oElement && p_oElement.tagName) { - case "DIV": + switch(p_oElement.tagName.toUpperCase()) { - oParentNode = p_oElement.parentNode; + case "DIV": - // Check if the DIV is the inner "body" node of a menu - if( - Dom.hasClass(p_oElement, "bd") && - oParentNode && - oParentNode.tagName == "DIV" - ) { + oParentNode = p_oElement.parentNode; - return oParentNode; + // Check if the DIV is the inner "body" node of a menu - } - else { + if( + Dom.hasClass(p_oElement, "bd") && + oParentNode && + oParentNode.tagName && + oParentNode.tagName.toUpperCase() == "DIV" + ) { - return p_oElement; + return oParentNode; - } + } + else { - break; + return p_oElement; - case "LI": + } - /* - Capture the root LI node of the menu item and allow - fall through to keep climbing up to find the item's parent - root DIV - */ + break; - oMenuItemRootElement = p_oElement; + case "LI": - default: + return p_oElement; - oParentNode = p_oElement.parentNode; + default: - if(oParentNode) { + oParentNode = p_oElement.parentNode; - return getMenuRootElement(oParentNode); + if(oParentNode) { - } + return getMenuRootElement(oParentNode); - break; + } + break; + + } + } } - // The root DIV node of a menu + // Private event handlers - var oMenuRootElement = getMenuRootElement(oTarget); + /** + * @method onDOMEvent + * @description Generic, global event handler for all of a menu's DOM-based + * events. This listens for events against the document object. If the + * target of a given event is a member of a menu or menu item's DOM, the + * instance's corresponding Custom Event is fired. + * @private + * @param {Event} p_oEvent Object representing the DOM event object passed + * back by the event utility (YAHOO.util.Event). + */ + function onDOMEvent(p_oEvent) { - if(oMenuRootElement && oMenuRootElement.id) { + // Get the target node of the DOM event - var oMenuItem; - var oMenu = YAHOO.widget.MenuModule._menus[oMenuRootElement.id]; + var oTarget = Event.getTarget(p_oEvent), - if(oMenuItemRootElement) { + // See if the target of the event was a menu, or a menu item - var sYUIId = oMenuItemRootElement.getAttribute("yuiid"); + oElement = getMenuRootElement(oTarget), + oMenuItem, + oMenu; - if(sYUIId) { + if(oElement) { - oMenuItem = YAHOO.widget.MenuModule._menuItems[sYUIId]; + var sTagName = oElement.tagName.toUpperCase(); + if(sTagName == "LI") { + + var sYUIId = oElement.getAttribute("yuiid"); + + if(sYUIId) { + + oMenuItem = m_oItems[sYUIId]; + oMenu = oMenuItem.parent; + + } + } + else if(sTagName == "DIV") { + if(oElement.id) { + + oMenu = m_oMenus[oElement.id]; + + } + + } + } if(oMenu) { @@ -170,2464 +239,7788 @@ "keydown": "keyDownEvent", "keyup": "keyUpEvent", "keypress": "keyPressEvent" - }; + }, - var sCustomEventType = oEventTypes[p_oEvent.type]; + sCustomEventType = oEventTypes[p_oEvent.type]; - switch(p_oEvent.type) { + // Fire the Custom Even that corresponds the current DOM event - case "mouseover": + if(oMenuItem && !oMenuItem.cfg.getProperty("disabled")) { - if( - !oMenu._bFiredMouseOverEvent && - ( - oTarget == oMenu.element || - Dom.isAncestor(oMenu.element, oTarget) - ) - ) { + oMenuItem[sCustomEventType].fire(p_oEvent); - oMenu.mouseOverEvent.fire(p_oEvent); + } - oMenu._bFiredMouseOverEvent = true; - oMenu._bFiredMouseOutEvent = false; + oMenu[sCustomEventType].fire(p_oEvent, oMenuItem); - } + } + else if(p_oEvent.type == "mousedown") { + /* + If the target of the event wasn't a menu, hide all + dynamically positioned menus + */ + + var oActiveItem; + + for(var i in m_oMenus) { + + if(m_oMenus.hasOwnProperty(i)) { + + oMenu = m_oMenus[i]; + if( - oMenuItem && - !oMenuItem._bFiredMouseOverEvent && - ( - oTarget == oMenuItem.element || - Dom.isAncestor(oMenuItem.element, oTarget) - ) && - !oMenuItem.cfg.getProperty("disabled") + oMenu.cfg.getProperty("clicktohide") && + oMenu.cfg.getProperty("position") == "dynamic" ) { - oMenuItem.mouseOverEvent.fire(p_oEvent); + oMenu.hide(); - oMenuItem._bFiredMouseOverEvent = true; - oMenuItem._bFiredMouseOutEvent = false; + } + else { + oMenu.clearActiveItem(true); + } - break; + } - case "mouseout": + } - var oRelatedTarget = Event.getRelatedTarget(p_oEvent); - var bMovingToSubmenu = false; + } - if(oMenuItem) { + } - var oSubmenu = oMenuItem.cfg.getProperty("submenu"); + /** + * @method onMenuDestroy + * @description "destroy" event handler for a menu. + * @private + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + * fired the event. + */ + function onMenuDestroy(p_sType, p_aArgs, p_oMenu) { - if( - oSubmenu && - ( - oRelatedTarget == oSubmenu.element || - Dom.isAncestor(oSubmenu.element, oRelatedTarget) - ) - ) { + if(p_oMenu && m_oMenus[p_oMenu.id]) { - bMovingToSubmenu = true; + delete m_oMenus[p_oMenu.id]; - } - } + } - if( - oMenuItem && - !oMenuItem._bFiredMouseOutEvent && - ( - ( - oRelatedTarget != oMenuItem.element && - !Dom.isAncestor( - oMenuItem.element, - oRelatedTarget - ) - ) || bMovingToSubmenu - ) && - !oMenuItem.cfg.getProperty("disabled") - ) { + } - // Fire the "mouseout" Custom Event for the item + /** + * @method onItemDestroy + * @description "destroy" event handler for a MenuItem instance. + * @private + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item + * that fired the event. + */ + function onItemDestroy(p_sType, p_aArgs, p_oItem) { - oMenuItem.mouseOutEvent.fire(p_oEvent); + var sYUIId = p_oItem.element.getAttribute("yuiid"); - oMenuItem._bFiredMouseOutEvent = true; - oMenuItem._bFiredMouseOverEvent = false; + if(sYUIId) { - } + delete m_oItems[sYUIId]; - if( - !oMenu._bFiredMouseOutEvent && - ( - ( - oRelatedTarget != oMenu.element && - !Dom.isAncestor(oMenu.element, oRelatedTarget) - ) - || bMovingToSubmenu - ) - ) { + } - oMenu.mouseOutEvent.fire(p_oEvent); + } - oMenu._bFiredMouseOutEvent = true; - oMenu._bFiredMouseOverEvent = false; + /** + * @method onMenuVisibleConfigChange + * @description Event handler for when the "visible" configuration property + * of a Menu instance changes. + * @private + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + * fired the event. + */ + function onMenuVisibleConfigChange(p_sType, p_aArgs, p_oMenu) { - } + var bVisible = p_aArgs[0]; - break; + if(bVisible) { - default: + m_oVisibleMenus[p_oMenu.id] = p_oMenu; - if(oMenuItem && !oMenuItem.cfg.getProperty("disabled")) { - oMenuItem[sCustomEventType].fire(p_oEvent); + } + else if(m_oVisibleMenus[p_oMenu.id]) { + delete m_oVisibleMenus[p_oMenu.id]; + + + } + + } + + /** + * @method onItemAdded + * @description "itemadded" event handler for a Menu instance. + * @private + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + */ + function onItemAdded(p_sType, p_aArgs) { + + addItem(p_aArgs[0]); + + } + + + /** + * @method onItemRemoved + * @description "itemremoved" event handler for a Menu instance. + * @private + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + */ + function onItemRemoved(p_sType, p_aArgs) { + + removeItem(p_aArgs[0]); + + } + + return { + + // Privileged methods + + /** + * @method addMenu + * @description Adds a menu to the collection of known menus. + * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu + * instance to be added. + */ + addMenu: function(p_oMenu) { + + if(p_oMenu && p_oMenu.id && !m_oMenus[p_oMenu.id]) { + + m_oMenus[p_oMenu.id] = p_oMenu; + + + if(!m_bInitializedEventHandlers) { + + var oDoc = document; + + Event.addListener(oDoc, "mouseover", onDOMEvent, me, true); + Event.addListener(oDoc, "mouseout", onDOMEvent, me, true); + Event.addListener(oDoc, "mousedown", onDOMEvent, me, true); + Event.addListener(oDoc, "mouseup", onDOMEvent, me, true); + Event.addListener(oDoc, "click", onDOMEvent, me, true); + Event.addListener(oDoc, "keydown", onDOMEvent, me, true); + Event.addListener(oDoc, "keyup", onDOMEvent, me, true); + Event.addListener(oDoc, "keypress", onDOMEvent, me, true); + + m_bInitializedEventHandlers = true; + + + } + + p_oMenu.destroyEvent.subscribe(onMenuDestroy, p_oMenu, me); + + p_oMenu.cfg.subscribeToConfigEvent( + "visible", + onMenuVisibleConfigChange, + p_oMenu + ); + + p_oMenu.itemAddedEvent.subscribe(onItemAdded); + p_oMenu.itemRemovedEvent.subscribe(onItemRemoved); + + + } + + }, + + + /** + * @method removeMenu + * @description Removes a menu from the collection of known menus. + * @param {YAHOO.widget.Menu} p_oMenu Object specifying the Menu + * instance to be removed. + */ + removeMenu: function(p_oMenu) { + + if(p_oMenu && m_oMenus[p_oMenu.id]) { + + delete m_oMenus[p_oMenu.id]; + + + } + + }, + + + /** + * @method hideVisible + * @description Hides all visible, dynamically positioned menus. + */ + hideVisible: function() { + + var oMenu; + + for(var i in m_oVisibleMenus) { + + if(m_oVisibleMenus.hasOwnProperty(i)) { + + oMenu = m_oVisibleMenus[i]; + + if(oMenu.cfg.getProperty("position") == "dynamic") { + + oMenu.hide(); + } - oMenu[sCustomEventType].fire(p_oEvent); + } - break; + } + }, + + /** + * @method getMenus + * @description Returns an array of all menus registered with the + * menu manger. + * @return {Array} + */ + getMenus: function() { + + return m_oMenus; + + }, + + /** + * @method getMenu + * @description Returns a menu with the specified id. + * @param {String} p_sId String specifying the id of the menu to + * be retrieved. + * @return {YAHOO.widget.Menu} + */ + getMenu: function(p_sId) { + + if(m_oMenus[p_sId]) { + + return m_oMenus[p_sId]; + } + }, + + + /** + * @method toString + * @description Returns a string representing the menu manager. + * @return {String} + */ + toString: function() { + + return ("MenuManager"); + } - } + }; -}; +}(); -// Constants +})(); -/** -* Constant representing the CSS class(es) to be applied to the root -* HTMLDivElement of the MenuModule instance. -* @final -* @type String -*/ -YAHOO.widget.MenuModule.prototype.CSS_CLASS_NAME = "yuimenu"; + -/** -* Constant representing the type of item to instantiate and add when parsing -* the child nodes (either HTMLLIElement, HTMLOptGroupElement or -* HTMLOptionElement) of a menu's DOM. The default -* is YAHOO.widget.MenuModuleItem. -* @final -* @type YAHOO.widget.MenuModuleItem -*/ -YAHOO.widget.MenuModule.prototype.ITEM_TYPE = null; + -/** -* Constant representing the tagname of the HTMLElement used to title -* a group of items. -* @final -* @type String -*/ -YAHOO.widget.MenuModule.prototype.GROUP_TITLE_TAG_NAME = "H6"; +(function() { -// Private properties + -/** -* The current state of a MenuModule instance's "mouseover" event -* @private -* @type {Boolean} -*/ -YAHOO.widget.MenuModule.prototype._bFiredMouseOverEvent = false; +var Dom = YAHOO.util.Dom, -/** -* The current state of a MenuModule instance's "mouseout" event -* @private -* @type {Boolean} -*/ -YAHOO.widget.MenuModule.prototype._bFiredMouseOutEvent = false; + Event = YAHOO.util.Event; -/** -* Array of HTMLElements used to title groups of items. -* @private -* @type {Array} -*/ -YAHOO.widget.MenuModule.prototype._aGroupTitleElements = null; + -/** -* Multi-dimensional array of items. -* @private -* @type {Array} -*/ -YAHOO.widget.MenuModule.prototype._aItemGroups = null; + -/** -* An array of HTMLUListElements, each of which is the parent node of each -* items's HTMLLIElement node. -* @private -* @type {Array} -*/ -YAHOO.widget.MenuModule.prototype._aListElements = null; +/** -/** -* Reference to the Event utility singleton. -* @private -* @type {YAHOO.util.Event} -*/ -YAHOO.widget.MenuModule.prototype._oEventUtil = YAHOO.util.Event; +* The Menu class creates a container that holds a vertical list representing -/** -* Reference to the Dom utility singleton. -* @private -* @type {YAHOO.util.Dom} -*/ -YAHOO.widget.MenuModule.prototype._oDom = YAHOO.util.Dom; +* a set of options or commands. Menu is the base class for all -// Public properties +* menu containers. -/** -* Reference to the item that has focus. -* @private -* @type {YAHOO.widget.MenuModuleItem} -*/ -YAHOO.widget.MenuModule.prototype.activeItem = null; +* @param {String} p_oElement String specifying the id attribute of the -/** -* Returns a MenuModule instance's parent object. -* @type {YAHOO.widget.MenuModuleItem} -*/ -YAHOO.widget.MenuModule.prototype.parent = null; +* <div> element of the menu. -/** -* Returns the HTMLElement (either HTMLSelectElement or HTMLDivElement) -* used create the MenuModule instance. -* @type {HTMLSelectElement/HTMLDivElement} -*/ -YAHOO.widget.MenuModule.prototype.srcElement = null; +* @param {String} p_oElement String specifying the id attribute of the -// Events +* <select> element to be used as the data source -/** -* Fires when the mouse has entered a MenuModule instance. Passes back the -* DOM Event object as an argument. -* @type {YAHOO.util.CustomEvent} -* @see YAHOO.util.CustomEvent -*/ -YAHOO.widget.MenuModule.prototype.mouseOverEvent = null; +* for the menu. -/** -* Fires when the mouse has left a MenuModule instance. Passes back the DOM -* Event object as an argument. -* @type {YAHOO.util.CustomEvent} -* @see YAHOO.util.CustomEvent -*/ -YAHOO.widget.MenuModule.prototype.mouseOutEvent = null; +* @param {HTMLDivElement} p_oElement Object -/** -* Fires when the user releases a mouse button while the mouse is over -* a MenuModule instance. Passes back the DOM Event object as an argument. -* @type {YAHOO.util.CustomEvent} -* @see YAHOO.util.CustomEvent -*/ -YAHOO.widget.MenuModule.prototype.mouseUpEvent = null; +* specifying the <div> element of the menu. -/** -* Fires when the user clicks the on a MenuModule instance. Passes back the -* DOM Event object as an argument. -* @type {YAHOO.util.CustomEvent} -* @see YAHOO.util.CustomEvent -*/ -YAHOO.widget.MenuModule.prototype.clickEvent = null; +* @param {HTMLSelectElement} p_oElement -/** -* Fires when the user presses a key. Passes back the DOM Event -* object as an argument. -* @type {YAHOO.util.CustomEvent} -* @see YAHOO.util.CustomEvent -*/ -YAHOO.widget.MenuModule.prototype.keyDownEvent = null; +* Object specifying the <select> element to be used as -/** -* Fires when the user releases a key. Passes back the DOM Event -* object as an argument. -* @type {YAHOO.util.CustomEvent} -* @see YAHOO.util.CustomEvent -*/ -YAHOO.widget.MenuModule.prototype.keyUpEvent = null; +* the data source for the menu. -/** -* The MenuModule class's initialization method. This method is automatically -* called by the constructor, and sets up all DOM references for -* pre-existing markup, and creates required markup if it is not already present. -* @param {String or HTMLElement} p_oElement String id or HTMLElement -* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node. -* @param {Object} p_oConfig Optional. The configuration object literal -* containing the configuration for a MenuModule instance. See -* configuration class documentation for more details. -*/ -YAHOO.widget.MenuModule.prototype.init = function(p_oElement, p_oConfig) { +* @param {Object} p_oConfig Optional. Object literal specifying the - var Dom = this._oDom; - var Event = this._oEventUtil; +* configuration for the menu. See configuration class documentation for - if(!this.ITEM_TYPE) { +* more details. - this.ITEM_TYPE = YAHOO.widget.MenuModuleItem; +* @namespace YAHOO.widget - } +* @class Menu - this._aItemGroups = []; - this._aListElements = []; - this._aGroupTitleElements = []; +* @constructor - var oElement; +* @extends YAHOO.widget.Overlay - if(typeof p_oElement == "string") { +*/ - oElement = document.getElementById(p_oElement); +YAHOO.widget.Menu = function(p_oElement, p_oConfig) { - } - else if(p_oElement.tagName) { + - oElement = p_oElement; + if(p_oConfig) { - } + - if(oElement) { + this.parent = p_oConfig.parent; - switch(oElement.tagName) { + - case "DIV": + this.lazyLoad = p_oConfig.lazyLoad || p_oConfig.lazyload; - this.srcElement = oElement; + - /* - Note: we don't pass the user config in here yet - because we only want it executed once, at the lowest - subclass level. - */ + this.itemData = p_oConfig.itemData || p_oConfig.itemdata; - YAHOO.widget.MenuModule.superclass.init.call(this, oElement); + - this.beforeInitEvent.fire(YAHOO.widget.MenuModule); + } - /* - Populate the collection of item groups and item - group titles - */ + - var oNode = this.body.firstChild; - var i = 0; + - do { + YAHOO.widget.Menu.superclass.constructor.call( - switch(oNode.tagName) { + this, - case this.GROUP_TITLE_TAG_NAME: + p_oElement, - this._aGroupTitleElements[i] = oNode; + p_oConfig - break; + ); - case "UL": + - this._aListElements[i] = oNode; - this._aItemGroups[i] = []; - i++; +}; - break; + - } +YAHOO.extend(YAHOO.widget.Menu, YAHOO.widget.Overlay, { - } - while((oNode = oNode.nextSibling)); + - /* - Apply the "first-of-type" class to the first UL to mimic - the "first-of-type" CSS3 psuedo class. - */ + - if(this._aListElements[0]) { + - Dom.addClass(this._aListElements[0], "first-of-type"); +// Constants - } + + +/** - break; +* @property CSS_CLASS_NAME - case "SELECT": +* @description String representing the CSS class(es) to be applied to the - this.srcElement = oElement; +* menu's <div> element. +* @default "yuimenu" - /* - The source element is not something that we can use - outright, so we need to create a new Overlay - */ +* @final - var sId = Dom.generateId(); +* @type String - /* - Note: we don't pass the user config in here yet - because we only want it executed once, at the lowest - subclass level. - */ +*/ - YAHOO.widget.MenuModule.superclass.init.call(this, sId); +CSS_CLASS_NAME: "yuimenu", - this.beforeInitEvent.fire(YAHOO.widget.MenuModule); + + +/** - break; +* @property ITEM_TYPE - } +* @description Object representing the type of menu item to instantiate and - } - else { +* add when parsing the child nodes (either <li> element, - /* - Note: we don't pass the user config in here yet - because we only want it executed once, at the lowest - subclass level. - */ +* <optgroup> element or <option>) - YAHOO.widget.MenuModule.superclass.init.call(this, p_oElement); +* of the menu's source HTML element. - this.beforeInitEvent.fire(YAHOO.widget.MenuModule); +* @default YAHOO.widget.MenuItem +* @final +* @type YAHOO.widget.MenuItem - } +*/ - if(this.element) { +ITEM_TYPE: null, - var oEl = this.element; - var CustomEvent = YAHOO.util.CustomEvent; + - Dom.addClass(oEl, this.CSS_CLASS_NAME); + - // Assign DOM event handlers +/** - if(YAHOO.widget.MenuModule._initEventHandlers) { +* @property GROUP_TITLE_TAG_NAME - var oDoc = document; - var onDOMEvent = YAHOO.widget.MenuModule._onDOMEvent; +* @description String representing the tagname of the HTML element used to - Event.addListener(oDoc, "mouseover", onDOMEvent); - Event.addListener(oDoc, "mouseout", onDOMEvent); - Event.addListener(oDoc, "mousedown", onDOMEvent); - Event.addListener(oDoc, "mouseup", onDOMEvent); - Event.addListener(oDoc, "click", onDOMEvent); - Event.addListener(oDoc, "keydown", onDOMEvent); - Event.addListener(oDoc, "keyup", onDOMEvent); - Event.addListener(oDoc, "keypress", onDOMEvent); +* title the menu's item groups. - YAHOO.widget.MenuModule._initEventHandlers = false; +* @default H6 - } +* @final - // Create custom events +* @type String - this.mouseOverEvent = new CustomEvent("mouseOverEvent", this); - this.mouseOutEvent = new CustomEvent("mouseOutEvent", this); - this.mouseDownEvent = new CustomEvent("mouseDownEvent", this); - this.mouseUpEvent = new CustomEvent("mouseUpEvent", this); - this.clickEvent = new CustomEvent("clickEvent", this); - this.keyPressEvent = new CustomEvent("keyPressEvent", this); - this.keyDownEvent = new CustomEvent("keyDownEvent", this); - this.keyUpEvent = new CustomEvent("keyUpEvent", this); +*/ - // Subscribe to Custom Events +GROUP_TITLE_TAG_NAME: "h6", - this.initEvent.subscribe(this._onInit, this, true); - this.beforeRenderEvent.subscribe(this._onBeforeRender, this, true); - this.renderEvent.subscribe(this._onRender, this, true); - this.showEvent.subscribe(this._onShow, this, true); - this.beforeHideEvent.subscribe(this._onBeforeHide, this, true); + - if(p_oConfig) { + - this.cfg.applyConfig(p_oConfig, true); + - } +// Private properties - this.cfg.queueProperty("visible", false); + - if(this.srcElement) { + - this._initSubTree(); +/** - } +* @property _nHideDelayId - YAHOO.widget.MenuModule._menus[oEl.id] = this; +* @description Number representing the time-out setting used to cancel the - } +* hiding of a menu. - this.initEvent.fire(YAHOO.widget.MenuModule); +* @default null -}; +* @private -// Private methods +* @type Number -/** -* Iterates the source element's childNodes collection and uses the child -* nodes to instantiate MenuModule and MenuModuleItem instances. -* @private -*/ -YAHOO.widget.MenuModule.prototype._initSubTree = function() { +*/ - var oNode; +_nHideDelayId: null, + - switch(this.srcElement.tagName) { + - case "DIV": +/** - if(this._aListElements.length > 0) { +* @property _nShowDelayId +* @description Number representing the time-out setting used to cancel the - var i = this._aListElements.length - 1; +* showing of a menu. - do { +* @default null - oNode = this._aListElements[i].firstChild; +* @private +* @type Number - do { +*/ - switch(oNode.tagName) { +_nShowDelayId: null, - case "LI": + + - this.addItem(new this.ITEM_TYPE(oNode), i); +/** - break; +* @property _hideDelayEventHandlersAssigned - } +* @description Boolean indicating if the "mouseover" and "mouseout" event - } - while((oNode = oNode.nextSibling)); +* handlers used for hiding the menu via a call to "window.setTimeout" have - } - while(i--); +* already been assigned. - } +* @default false - break; +* @private - case "SELECT": +* @type Boolean +*/ - oNode = this.srcElement.firstChild; +_hideDelayEventHandlersAssigned: false, - do { + - switch(oNode.tagName) { + - case "OPTGROUP": - case "OPTION": +/** +* @property _bHandledMouseOverEvent - this.addItem(new this.ITEM_TYPE(oNode)); +* @description Boolean indicating the current state of the menu's - break; +* "mouseover" event. - } +* @default false - } - while((oNode = oNode.nextSibling)); +* @private - break; +* @type Boolean - } +*/ -}; +_bHandledMouseOverEvent: false, -/** -* Returns the first enabled item in a menu instance. -* @return Returns a MenuModuleItem instance. -* @type YAHOO.widget.MenuModuleItem -* @private -*/ -YAHOO.widget.MenuModule.prototype._getFirstEnabledItem = function() { + - var nGroups = this._aItemGroups.length; - var oItem; - var aItemGroup; + - for(var i=0; i<ul> elements, each of which is - var oGroupItem; +* the parent node for each item's <li> element. +* @default [] - if(!aGroup) { +* @private - aGroup = this._createItemGroup(nGroupIndex); +* @type Array - } +*/ - if(typeof p_nItemIndex == "number") { +_aListElements: null, - var bAppend = (p_nItemIndex >= aGroup.length); + + - if(aGroup[p_nItemIndex]) { + - aGroup.splice(p_nItemIndex, 0, oItem); +// Public properties - } - else { + - aGroup[p_nItemIndex] = oItem; + - } +/** +* @property lazyLoad - oGroupItem = aGroup[p_nItemIndex]; +* @description Boolean indicating if the menu's "lazy load" feature is - if(oGroupItem) { +* enabled. If set to "true," initialization and rendering of the menu's - if( - bAppend && - ( - !oGroupItem.element.parentNode || - oGroupItem.element.parentNode.nodeType == 11 - ) - ) { +* items will be deferred until the first time it is made visible. This - this._aListElements[nGroupIndex].appendChild( - oGroupItem.element - ); +* property should be set via the constructor using the configuration - } - else { +* object literal. +* @default false - /** - * Returns the next sibling of an item in an array - * @param {p_aArray} An array - * @param {p_nStartIndex} The index to start searching - * the array - * @ignore - * @return Returns an item in an array - * @type Object - */ - function getNextItemSibling(p_aArray, p_nStartIndex) { +* @type Boolean - return ( - p_aArray[p_nStartIndex] || - getNextItemSibling( - p_aArray, - (p_nStartIndex+1) - ) - ); +*/ - } +lazyLoad: false, + - var oNextItemSibling = - getNextItemSibling(aGroup, (p_nItemIndex+1)); + - if( - oNextItemSibling && - ( - !oGroupItem.element.parentNode || - oGroupItem.element.parentNode.nodeType == 11 - ) - ) { +/** - this._aListElements[nGroupIndex].insertBefore( - oGroupItem.element, - oNextItemSibling.element - ); +* @property itemData - } +* @description Array of items to be added to the menu. The array can contain - } +* strings representing the text for each item to be created, object literals +* representing the menu item configuration properties, or MenuItem instances. - oGroupItem.parent = this; +* This property should be set via the constructor using the configuration - this._subscribeToItemEvents(oGroupItem); +* object literal. - this._configureItemSubmenuModule(oGroupItem); +* @default null - this._updateItemProperties(nGroupIndex); +* @type Array +*/ - return oGroupItem; +itemData: null, - } + - } - else { + - var nItemIndex = aGroup.length; +/** - aGroup[nItemIndex] = oItem; +* @property activeItem +* @description Object reference to the item in the menu that has focus. - oGroupItem = aGroup[nItemIndex]; +* @default null - if(oGroupItem) { +* @type YAHOO.widget.MenuItem - if( - !Dom.isAncestor( - this._aListElements[nGroupIndex], - oGroupItem.element - ) - ) { +*/ - this._aListElements[nGroupIndex].appendChild( - oGroupItem.element - ); +activeItem: null, - } + - oGroupItem.element.setAttribute("groupindex", nGroupIndex); - oGroupItem.element.setAttribute("index", nItemIndex); + - oGroupItem.parent = this; +/** - oGroupItem.index = nItemIndex; - oGroupItem.groupIndex = nGroupIndex; +* @property parent - this._subscribeToItemEvents(oGroupItem); +* @description Object reference to the menu's parent menu or menu item. - this._configureItemSubmenuModule(oGroupItem); +* This property can be set via the constructor using the configuration - if(nItemIndex === 0) { +* object literal. - Dom.addClass(oGroupItem.element, "first-of-type"); +* @default null - } +* @type YAHOO.widget.MenuItem +*/ - return oGroupItem; +parent: null, - } + - } + - } +/** - }; +* @property srcElement -/** -* Removes an item from a group by index. -* @private -* @param {Number} p_nGroupIndex Number indicating the group to which -* the item belongs. -* @param {Number} p_nItemIndex Number indicating the index of the item to -* be removed. -* @return The item that was removed. -* @type YAHOO.widget.MenuModuleItem -*/ -YAHOO.widget.MenuModule.prototype._removeItemFromGroupByIndex = +* @description Object reference to the HTML element (either - function(p_nGroupIndex, p_nItemIndex) { +* <select> or <div>) used to - var nGroupIndex = typeof p_nGroupIndex == "number" ? p_nGroupIndex : 0; - var aGroup = this._getItemGroup(nGroupIndex); +* create the menu. - if(aGroup) { +* @default null - var aArray = aGroup.splice(p_nItemIndex, 1); - var oItem = aArray[0]; +* @type HTMLSelectElement|HTMLDivElement - if(aGroup.length === 0) { +*/ - // Remove the UL +srcElement: null, - var oUL = this._aListElements[nGroupIndex]; + - if(this.body && oUL) { + - this.body.removeChild(oUL); + - } +// Events - // Remove the group from the array of items + - this._aItemGroups.splice(nGroupIndex, 1); + +/** - // Remove the UL from the array of ULs +* @event mouseOverEvent - this._aListElements.splice(nGroupIndex, 1); +* @description Fires when the mouse has entered the menu. Passes back +* the DOM Event object as an argument. - /* - Assign the "first-of-type" class to the new first UL - in the collection - */ +*/ - oUL = this._aListElements[0]; +mouseOverEvent: null, - if(oUL) { + - this._oDom.addClass(oUL, "first-of-type"); + - } +/** - } +* @event mouseOutEvent +* @description Fires when the mouse has left the menu. Passes back the DOM - // Return a reference to the item that was removed +* Event object as an argument. - return oItem; +* @type YAHOO.util.CustomEvent - } +*/ - } +mouseOutEvent: null, - }; + -/** -* Removes a item from a group by reference. -* @private -* @param {Number} p_nGroupIndex Number indicating the group to which -* the item belongs. -* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to be removed. -* @return The item that was removed. -* @type YAHOO.widget.MenuModuleItem -*/ -YAHOO.widget.MenuModule.prototype._removeItemFromGroupByValue = + - function(p_nGroupIndex, p_oItem) { +/** - var aGroup = this._getItemGroup(p_nGroupIndex); +* @event mouseDownEvent - if(aGroup) { +* @description Fires when the user mouses down on the menu. Passes back the - var nItems = aGroup.length; - var nItemIndex = -1; +* DOM Event object as an argument. - if(nItems > 0) { +* @type YAHOO.util.CustomEvent - var i = nItems-1; +*/ - do { +mouseDownEvent: null, - if(aGroup[i] == p_oItem) { + - nItemIndex = i; - break; + - } +/** - } - while(i--); +* @event mouseUpEvent - if(nItemIndex > -1) { +* @description Fires when the user releases a mouse button while the mouse is - return this._removeItemFromGroupByIndex( - p_nGroupIndex, - nItemIndex - ); +* over the menu. Passes back the DOM Event object as an argument. - } +* @type YAHOO.util.CustomEvent - } +*/ - } +mouseUpEvent: null, - }; + -/** -* Updates the index, groupindex, and className properties of the items -* in the specified group. -* @private -* @param {Number} p_nGroupIndex Number indicating the group of items to update. -*/ -YAHOO.widget.MenuModule.prototype._updateItemProperties = + - function(p_nGroupIndex) { +/** - var aGroup = this._getItemGroup(p_nGroupIndex); - var nItems = aGroup.length; +* @event clickEvent - if(nItems > 0) { +* @description Fires when the user clicks the on the menu. Passes back the - var Dom = this._oDom; - var i = nItems - 1; - var oItem; - var oLI; +* DOM Event object as an argument. - // Update the index and className properties of each member +* @type YAHOO.util.CustomEvent - do { +*/ - oItem = aGroup[i]; +clickEvent: null, - if(oItem) { + - oLI = oItem.element; + - oItem.index = i; - oItem.groupIndex = p_nGroupIndex; +/** - oLI.setAttribute("groupindex", p_nGroupIndex); - oLI.setAttribute("index", i); +* @event keyPressEvent - Dom.removeClass(oLI, "first-of-type"); +* @description Fires when the user presses an alphanumeric key when one of the - } +* menu's items has focus. Passes back the DOM Event object as an argument. - } - while(i--); +* @type YAHOO.util.CustomEvent +*/ - if(oLI) { +keyPressEvent: null, - Dom.addClass(oLI, "first-of-type"); + - } + - } +/** - }; +* @event keyDownEvent -/** -* Creates a new item group (array) and it's associated HTMLUlElement node -* @private -* @param {Number} p_nIndex Number indicating the group to create. -* @return An item group. -* @type Array -*/ -YAHOO.widget.MenuModule.prototype._createItemGroup = function(p_nIndex) { +* @description Fires when the user presses a key when one of the menu's items - if(!this._aItemGroups[p_nIndex]) { +* has focus. Passes back the DOM Event object as an argument. - this._aItemGroups[p_nIndex] = []; +* @type YAHOO.util.CustomEvent - var oUL = document.createElement("ul"); +*/ - this._aListElements[p_nIndex] = oUL; +keyDownEvent: null, - return this._aItemGroups[p_nIndex]; + - } + -}; +/** -/** -* Returns the item group at the specified index. -* @private -* @param {Number} p_nIndex Number indicating the index of the item group to -* be retrieved. -* @return An array of items. -* @type Array -*/ -YAHOO.widget.MenuModule.prototype._getItemGroup = function(p_nIndex) { +* @event keyUpEvent - var nIndex = ((typeof p_nIndex == "number") ? p_nIndex : 0); +* @description Fires when the user releases a key when one of the menu's items - return this._aItemGroups[nIndex]; +* has focus. Passes back the DOM Event object as an argument. -}; +* @type YAHOO.util.CustomEvent -/** -* Subscribe's a MenuModule instance to it's parent MenuModule instance's events. -* @private -* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to listen -* for events on. -*/ -YAHOO.widget.MenuModule.prototype._configureItemSubmenuModule = +*/ - function(p_oItem) { +keyUpEvent: null, - var oSubmenu = p_oItem.cfg.getProperty("submenu"); + - if(oSubmenu) { + - /* - Listen for configuration changes to the parent MenuModule - instance so they they can be applied to the submenu. - */ +/** - this.cfg.configChangedEvent.subscribe( - this._onParentMenuModuleConfigChange, - oSubmenu, - true - ); +* @event itemAddedEvent - this.renderEvent.subscribe( - this._onParentMenuModuleRender, - oSubmenu, - true - ); +* @description Fires when an item is added to the menu. - oSubmenu.beforeShowEvent.subscribe( - this._onSubmenuBeforeShow, - oSubmenu, - true - ); +* @type YAHOO.util.CustomEvent - oSubmenu.showEvent.subscribe(this._onSubmenuShow, oSubmenu, true); +*/ - oSubmenu.hideEvent.subscribe(this._onSubmenuHide, oSubmenu, true); +itemAddedEvent: null, - } + -}; + -/** -* Subscribes a MenuModule instance to the specified item's Custom Events. -* @private -* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to listen for events on. -*/ -YAHOO.widget.MenuModule.prototype._subscribeToItemEvents = function(p_oItem) { +/** - var aArguments = [this, p_oItem]; +* @event itemRemovedEvent - p_oItem.focusEvent.subscribe(this._onItemFocus, aArguments); +* @description Fires when an item is removed to the menu. - p_oItem.blurEvent.subscribe(this._onItemBlur, aArguments); +* @type YAHOO.util.CustomEvent - p_oItem.cfg.configChangedEvent.subscribe( - this._onItemConfigChange, - aArguments - ); +*/ -}; +itemRemovedEvent: null, -/** -* Returns the offset width of a MenuModule instance. -* @private -*/ -YAHOO.widget.MenuModule.prototype._getOffsetWidth = function() { + - var oClone = this.element.cloneNode(true); + - this._oDom.setStyle(oClone, "width", ""); +/** - document.body.appendChild(oClone); +* @method init - var sWidth = oClone.offsetWidth; +* @description The Menu class's initialization method. This method is - document.body.removeChild(oClone); +* automatically called by the constructor, and sets up all DOM references - return sWidth; +* for pre-existing markup, and creates required markup if it is not -}; +* already present. -// Private Custom Event handlers +* @param {String} p_oElement String specifying the id attribute of the -/** -* "init" Custom Event handler for a MenuModule instance. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that -* fired the event. -*/ -YAHOO.widget.MenuModule.prototype._onInit = +* <div> element of the menu. - function(p_sType, p_aArgs, p_oMenuModule) { +* @param {String} p_oElement String specifying the id attribute of the - var sCSSPosition = (this.cfg.getProperty("position") == "static") ? - "static" : "absolute"; +* <select> element to be used as the data source - this._oDom.setStyle(this.element, "position", sCSSPosition); +* for the menu. - }; +* @param {HTMLDivElement} p_oElement Object - function(p_sType, p_aArgs, p_oMenuModule) { +* specifying the <div> element of the menu. - var Dom = this._oDom; - var oConfig = this.cfg; - var oEl = this.element; - var nListElements = this._aListElements.length; +* @param {HTMLSelectElement} p_oElement - if(oConfig.getProperty("position") == "static") { +* Object specifying the <select> element to be used as - oConfig.queueProperty("iframe", false); - oConfig.queueProperty("visible", true); +* the data source for the menu. - } +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the menu. See configuration class documentation for - if(nListElements > 0) { +* more details. - var i = 0; - var bFirstList = true; - var oUL; - var oGroupTitle; +*/ +init: function(p_oElement, p_oConfig) { - do { + - oUL = this._aListElements[i]; + this._aItemGroups = []; - if(oUL) { + this._aListElements = []; - if(bFirstList) { + this._aGroupTitleElements = []; - Dom.addClass(oUL, "first-of-type"); - bFirstList = false; + - } + + if(!this.ITEM_TYPE) { - if(!Dom.isAncestor(oEl, oUL)) { + - this.appendToBody(oUL); + this.ITEM_TYPE = YAHOO.widget.MenuItem; - } + + } - oGroupTitle = this._aGroupTitleElements[i]; + - if(oGroupTitle) { + - if(!Dom.isAncestor(oEl, oGroupTitle)) { + var oElement; - oUL.parentNode.insertBefore(oGroupTitle, oUL); + - } + if(typeof p_oElement == "string") { + - Dom.addClass(oUL, "hastitle"); + oElement = document.getElementById(p_oElement); - } + - } + } - i++; + else if(p_oElement.tagName) { - } - while(i < nListElements); + - } + oElement = p_oElement; - }; + -/** -* "render" Custom Event handler for a MenuModule instance. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that -* fired the event. -*/ -YAHOO.widget.MenuModule.prototype._onRender = + } - function(p_sType, p_aArgs, p_oMenuModule) { + - if(this.cfg.getProperty("position") == "dynamic") { + - var sWidth = this.element.parentNode.tagName == "BODY" ? - this.element.offsetWidth : this._getOffsetWidth(); + if(oElement && oElement.tagName) { - this.cfg.setProperty("width", (sWidth + "px")); + - } + switch(oElement.tagName.toUpperCase()) { - }; + -/** -* "show" Custom Event handler for a MenuModule instance. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that -* fired the event. -*/ -YAHOO.widget.MenuModule.prototype._onShow = + case "DIV": - function(p_sType, p_aArgs, p_oMenuModule) { + - /* - Setting focus to an item in the newly visible submenu alerts the - contents of the submenu to the screen reader. - */ + this.srcElement = oElement; - this.setInitialFocus(); + - }; + if(!oElement.id) { -/** -* "hide" Custom Event handler for a MenuModule instance. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that -* fired the event. -*/ -YAHOO.widget.MenuModule.prototype._onBeforeHide = + - function(p_sType, p_aArgs, p_oMenuModule) { + oElement.setAttribute("id", Dom.generateId()); - var oActiveItem = this.activeItem; + - if(oActiveItem) { + } - oActiveItem.blur(); + - if(oActiveItem.cfg.getProperty("selected")) { + - oActiveItem.cfg.setProperty("selected", false); + /* - } + Note: we don't pass the user config in here yet - var oSubmenu = oActiveItem.cfg.getProperty("submenu"); + because we only want it executed once, at the lowest - if(oSubmenu && oSubmenu.cfg.getProperty("visible")) { + subclass level. - oSubmenu.hide(); + */ - } + - } + YAHOO.widget.Menu.superclass.init.call(this, oElement); - }; + -/** -* "configchange" Custom Event handler for a submenu. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oSubmenu The submenu that subscribed -* to the event. -*/ -YAHOO.widget.MenuModule.prototype._onParentMenuModuleConfigChange = + this.beforeInitEvent.fire(YAHOO.widget.Menu); - function(p_sType, p_aArgs, p_oSubmenu) { + - var sPropertyName = p_aArgs[0][0]; - var oPropertyValue = p_aArgs[0][1]; + - switch(sPropertyName) { + - case "iframe": - case "constraintoviewport": + break; - p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue); + - break; + case "SELECT": - } + - }; + this.srcElement = oElement; -/** -* "render" Custom Event handler for a MenuModule instance. Renders a -* submenu in response to the firing of it's parent's "render" event. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oSubmenu The submenu that subscribed -* to the event. -*/ -YAHOO.widget.MenuModule.prototype._onParentMenuModuleRender = + - function(p_sType, p_aArgs, p_oSubmenu) { + - /* - Set the "constraintoviewport" configuration - property to match the parent MenuModule - */ + /* - var oParentMenu = p_oSubmenu.parent.parent; + The source element is not something that we can use - var oConfig = { + outright, so we need to create a new Overlay - constraintoviewport: - oParentMenu.cfg.getProperty("constraintoviewport"), + - xy: [0,0] + Note: we don't pass the user config in here yet - }; + because we only want it executed once, at the lowest - /* - Only sync the "iframe" configuration property if the parent - MenuModule instance's position is of the same value - */ + subclass level. - if( - this.cfg.getProperty("position") == - oParentMenu.cfg.getProperty("position") - ) { + */ - oConfig.iframe = oParentMenu.cfg.getProperty("iframe"); + - } + YAHOO.widget.Menu.superclass.init.call(this, Dom.generateId()); + - p_oSubmenu.cfg.applyConfig(oConfig); + this.beforeInitEvent.fire(YAHOO.widget.Menu); + - if(this._oDom.inDocument(this.element)) { + - this.render(); + - } - else { + break; - this.render(this.parent.element); + - } + } - }; + -/** -* "beforeshow" Custom Event handler for a submenu. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oSubmenu The submenu that fired -* the event. -*/ -YAHOO.widget.MenuModule.prototype._onSubmenuBeforeShow = + } - function(p_sType, p_aArgs, p_oSubmenu) { + else { - var oParent = this.parent; - var aAlignment = oParent.parent.cfg.getProperty("submenualignment"); + - this.cfg.setProperty( - "context", - [ - oParent.element, - aAlignment[0], - aAlignment[1] - ] - ); + /* - oParent.submenuIndicator.alt = - oParent.EXPANDED_SUBMENU_INDICATOR_ALT_TEXT; + Note: we don't pass the user config in here yet - }; + because we only want it executed once, at the lowest -/** -* "show" Custom Event handler for a submenu. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oSubmenu The submenu that fired -* the event. -*/ -YAHOO.widget.MenuModule.prototype._onSubmenuShow = + subclass level. - function(p_sType, p_aArgs, p_oSubmenu) { + */ - var oParent = this.parent; + - oParent.submenuIndicator.alt = - oParent.EXPANDED_SUBMENU_INDICATOR_ALT_TEXT; + YAHOO.widget.Menu.superclass.init.call(this, p_oElement); - }; + -/** -* "hide" Custom Event handler for a submenu. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oSubmenu The submenu that fired -* the event. -*/ -YAHOO.widget.MenuModule.prototype._onSubmenuHide = + this.beforeInitEvent.fire(YAHOO.widget.Menu); - function(p_sType, p_aArgs, p_oSubmenu) { + - var oParent = this.parent; + - if(oParent.parent.cfg.getProperty("visible")) { + - oParent.cfg.setProperty("selected", false); + } - oParent.focus(); + - } + - oParent.submenuIndicator.alt = - oParent.COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT; + if(this.element) { - }; + -/** -* "focus" YAHOO.util.CustomEvent handler for a MenuModule instance's items. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {Array} p_aObjects Array containing the current MenuModule instance -* and the item that fired the event. -*/ -YAHOO.widget.MenuModule.prototype._onItemFocus = + var oEl = this.element; - function(p_sType, p_aArgs, p_aObjects) { + - var me = p_aObjects[0]; - var oItem = p_aObjects[1]; + Dom.addClass(oEl, this.CSS_CLASS_NAME); - me.activeItem = oItem; + - }; + -/** -* "blur" YAHOO.util.CustomEvent handler for a MenuModule instance's items. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {Array} p_aObjects Array containing the current MenuModule instance -* and the item that fired the event. -*/ -YAHOO.widget.MenuModule.prototype._onItemBlur = + // Subscribe to Custom Events - function(p_sType, p_aArgs, p_aObjects) { + - var me = p_aObjects[0]; - var oItem = p_aObjects[1]; - var oSubmenu = oItem.cfg.getProperty("submenu"); + this.initEvent.subscribe(this._onInit, this, true); - if(!oSubmenu || (oSubmenu && !oSubmenu.cfg.getProperty("visible"))) { + this.beforeRenderEvent.subscribe(this._onBeforeRender, this, true); - me.activeItem = null; + this.renderEvent.subscribe(this._onRender, this, true); - } + this.beforeShowEvent.subscribe(this._onBeforeShow, this, true); - }; + this.showEvent.subscribe(this._onShow, this, true); -/** -* "configchange" YAHOO.util.CustomEvent handler for the MenuModule -* instance's items. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the -* event was fired. -* @param {Array} p_aObjects Array containing the current MenuModule instance -* and the item that fired the event. -*/ -YAHOO.widget.MenuModule.prototype._onItemConfigChange = + this.beforeHideEvent.subscribe(this._onBeforeHide, this, true); - function(p_sType, p_aArgs, p_aObjects) { + this.mouseOverEvent.subscribe(this._onMouseOver, this, true); - var me = p_aObjects[0]; - var sProperty = p_aArgs[0][0]; - var oItem = p_aObjects[1]; + this.mouseOutEvent.subscribe(this._onMouseOut, this, true); - switch(sProperty) { + this.clickEvent.subscribe(this._onClick, this, true); - case "submenu": + this.keyDownEvent.subscribe(this._onKeyDown, this, true); - var oSubmenu = p_aArgs[0][1]; + - if(oSubmenu) { + YAHOO.widget.Module.textResizeEvent.subscribe( - me._configureItemSubmenuModule(oItem); + this._onTextResize, - } + this, - break; + true - case "text": - case "helptext": + ); - /* - A change to an item's "text" or "helptext" - configuration properties requires the width of the parent - MenuModule instance to be recalculated. - */ + - if(me.element.style.width) { + - var sWidth = me._getOffsetWidth() + "px"; + if(p_oConfig) { - me._oDom.setStyle(me.element, "width", sWidth); + - } + this.cfg.applyConfig(p_oConfig, true); - break; + - } + } - }; + -/** -* The default event handler executed when the moveEvent is fired, if the -* "constraintoviewport" configuration property is set to true. -*/ -YAHOO.widget.MenuModule.prototype.enforceConstraints = + - function(type, args, obj) { + // Register the Menu instance with the MenuManager - var Dom = this._oDom; - var oConfig = this.cfg; + - var pos = args[0]; + YAHOO.widget.MenuManager.addMenu(this); - var x = pos[0]; - var y = pos[1]; + - var bod = document.getElementsByTagName('body')[0]; - var htm = document.getElementsByTagName('html')[0]; + - var bodyOverflow = Dom.getStyle(bod, "overflow"); - var htmOverflow = Dom.getStyle(htm, "overflow"); + this.initEvent.fire(YAHOO.widget.Menu); - var offsetHeight = this.element.offsetHeight; - var offsetWidth = this.element.offsetWidth; + - var viewPortWidth = Dom.getClientWidth(); - var viewPortHeight = Dom.getClientHeight(); + } - var scrollX = window.scrollX || document.body.scrollLeft; - var scrollY = window.scrollY || document.body.scrollTop; + - var topConstraint = scrollY + 10; - var leftConstraint = scrollX + 10; - var bottomConstraint = scrollY + viewPortHeight - offsetHeight - 10; - var rightConstraint = scrollX + viewPortWidth - offsetWidth - 10; +}, - var aContext = oConfig.getProperty("context"); - var oContextElement = aContext ? aContext[0] : null; + + - if (x < 10) { + - x = leftConstraint; +// Private methods - } else if ((x + offsetWidth) > viewPortWidth) { + - if( - oContextElement && - ((x - oContextElement.offsetWidth) > offsetWidth) - ) { + - x = (x - (oContextElement.offsetWidth + offsetWidth)); +/** - } - else { +* @method _initSubTree - x = rightConstraint; +* @description Iterates the childNodes of the source element to find nodes - } +* used to instantiate menu and menu items. - } +* @private - if (y < 10) { +*/ - y = topConstraint; +_initSubTree: function() { - } else if (y > bottomConstraint) { + - if(oContextElement && (y > offsetHeight)) { + var oNode; - y = ((y + oContextElement.offsetHeight) - offsetHeight); + - } - else { + if(this.srcElement.tagName == "DIV") { - y = bottomConstraint; + - } + /* - } + Populate the collection of item groups and item - oConfig.setProperty("x", x, true); - oConfig.setProperty("y", y, true); + group titles - }; + */ -// Event handlers for configuration properties + -/** -* Event handler for when the "position" configuration property of a -* MenuModule changes. -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance fired -* the event. -*/ -YAHOO.widget.MenuModule.prototype.configPosition = + oNode = this.body.firstChild; - function(p_sType, p_aArgs, p_oMenuModule) { + - var sCSSPosition = p_aArgs[0] == "static" ? "static" : "absolute"; + var nGroup = 0, - this._oDom.setStyle(this.element, "position", sCSSPosition); + sGroupTitleTagName = this.GROUP_TITLE_TAG_NAME.toUpperCase(); - }; + -/** -* Event handler for when the "iframe" configuration property of a -* MenuModule changes. -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance fired -* the event. -* @see YAHOO.widget.Overlay#configIframe -*/ -YAHOO.widget.MenuModule.prototype.configIframe = + do { - function(p_sType, p_aArgs, p_oMenuModule) { + - if(this.cfg.getProperty("position") == "dynamic") { + if(oNode && oNode.tagName) { - YAHOO.widget.MenuModule.superclass.configIframe.call( - this, - p_sType, - p_aArgs, - p_oMenuModule - ); + - } + switch(oNode.tagName.toUpperCase()) { - }; + -// Public methods + case sGroupTitleTagName: -YAHOO.widget.MenuModule.prototype.toString = function() { + - return ("Menu " + this.id); + this._aGroupTitleElements[nGroup] = oNode; -}; + -/** -* Sets the title of a group of items. -* @param {String} p_sGroupTitle The title of the group. -* @param {Number} p_nGroupIndex Optional. Number indicating the group to which -* the title belongs. -*/ -YAHOO.widget.MenuModule.prototype.setItemGroupTitle = + break; - function(p_sGroupTitle, p_nGroupIndex) { + - if(typeof p_sGroupTitle == "string" && p_sGroupTitle.length > 0) { + case "UL": - var Dom = this._oDom; + - var nGroupIndex = - typeof p_nGroupIndex == "number" ? p_nGroupIndex : 0; + this._aListElements[nGroup] = oNode; - var oTitle = this._aGroupTitleElements[nGroupIndex]; + this._aItemGroups[nGroup] = []; + nGroup++; - if(oTitle) { + - oTitle.innerHTML = p_sGroupTitle; + break; - } - else { + - oTitle = document.createElement(this.GROUP_TITLE_TAG_NAME); + } - oTitle.innerHTML = p_sGroupTitle; + - this._aGroupTitleElements[nGroupIndex] = oTitle; + } - } + + } - var i = this._aGroupTitleElements.length - 1; - var nFirstIndex; + while((oNode = oNode.nextSibling)); - do { + - if(this._aGroupTitleElements[i]) { + - Dom.removeClass( - this._aGroupTitleElements[i], - "first-of-type" - ); + /* - nFirstIndex = i; + Apply the "first-of-type" class to the first UL to mimic - } + the "first-of-type" CSS3 psuedo class. - } - while(i--); + */ + - if(nFirstIndex !== null) { + if(this._aListElements[0]) { - Dom.addClass( - this._aGroupTitleElements[nFirstIndex], - "first-of-type" - ); + - } + Dom.addClass(this._aListElements[0], "first-of-type"); - } + - }; + } -/** -* Appends the specified item to a MenuModule instance. -* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to be added. -* @param {Number} p_nGroupIndex Optional. Number indicating the group to which -* the item belongs. -* @return The item that was added to the MenuModule. -* @type YAHOO.widget.MenuModuleItem -*/ -YAHOO.widget.MenuModule.prototype.addItem = function(p_oItem, p_nGroupIndex) { + - if(p_oItem) { + } - return this._addItemToGroup(p_nGroupIndex, p_oItem); + - } + -}; + oNode = null; -/** -* Inserts an item into a MenuModule instance at the specified index. -* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to be inserted. -* @param {Number} p_nItemIndex Number indicating the ordinal position -* at which the item should be added. -* @param {Number} p_nGroupIndex Optional. Number indicating the group to which -* the item belongs. -* @return The item that was inserted into the MenuModule. -* @type YAHOO.widget.MenuModuleItem -*/ -YAHOO.widget.MenuModule.prototype.insertItem = + - function(p_oItem, p_nItemIndex, p_nGroupIndex) { + - if(p_oItem) { + if(this.srcElement.tagName) { - return this._addItemToGroup(p_nGroupIndex, p_oItem, p_nItemIndex); + - } + var sSrcElementTagName = this.srcElement.tagName.toUpperCase(); - }; + -/** -* Removes the specified item from a MenuModule instance. -* @param {YAHOO.widget.MenuModuleItem/Number} p_oObject The item or index of -* the item to be removed. -* @param {Number} p_nGroupIndex Optional. Number indicating the group to which -* the item belongs. -* @return The item that was removed from the MenuModule. -* @type YAHOO.widget.MenuModuleItem -*/ -YAHOO.widget.MenuModule.prototype.removeItem = + - function(p_oObject, p_nGroupIndex) { + switch(sSrcElementTagName) { - if(typeof p_oObject != "undefined") { + - var oItem; + case "DIV": - if(p_oObject instanceof YAHOO.widget.MenuModuleItem) { + - oItem = - this._removeItemFromGroupByValue(p_nGroupIndex, p_oObject); + if(this._aListElements.length > 0) { - } - else if(typeof p_oObject == "number") { + - oItem = - this._removeItemFromGroupByIndex(p_nGroupIndex, p_oObject); + - } + var i = this._aListElements.length - 1; - if(oItem) { + - oItem.destroy(); + do { + - return oItem; + oNode = this._aListElements[i].firstChild; - } + - } + - }; + do { -/** -* Returns a multi-dimensional array of all of a MenuModule's items. -* @return An array of items. -* @type Array -*/ -YAHOO.widget.MenuModule.prototype.getItemGroups = function() { + - return this._aItemGroups; + if( -}; + oNode && -/** -* Returns the item at the specified index. -* @param {Number} p_nItemIndex Number indicating the ordinal position of the -* item to be retrieved. -* @param {Number} p_nGroupIndex Optional. Number indicating the group to which -* the item belongs. -* @return An item. -* @type YAHOO.widget.MenuModuleItem -*/ -YAHOO.widget.MenuModule.prototype.getItem = + oNode.tagName && - function(p_nItemIndex, p_nGroupIndex) { + oNode.tagName.toUpperCase() == "LI" - if(typeof p_nItemIndex == "number") { + ) { - var aGroup = this._getItemGroup(p_nGroupIndex); + - if(aGroup) { + - return aGroup[p_nItemIndex]; + this.addItem( - } + new this.ITEM_TYPE( - } + oNode, - }; + { parent: this } -/** -* Removes the MenuModule instance's element from the DOM and sets all child -* elements to null. -*/ -YAHOO.widget.MenuModule.prototype.destroy = function() { + ), - // Remove Custom Event listeners + i - this.mouseOverEvent.unsubscribeAll(); - this.mouseOutEvent.unsubscribeAll(); - this.mouseDownEvent.unsubscribeAll(); - this.mouseUpEvent.unsubscribeAll(); - this.clickEvent.unsubscribeAll(); - this.keyPressEvent.unsubscribeAll(); - this.keyDownEvent.unsubscribeAll(); - this.keyUpEvent.unsubscribeAll(); + ); - var nItemGroups = this._aItemGroups.length; - var nItems; - var oItemGroup; - var oItem; - var i; - var n; + - // Remove all items + } - if(nItemGroups > 0) { + - i = nItemGroups - 1; + } - do { + while((oNode = oNode.nextSibling)); - oItemGroup = this._aItemGroups[i]; + - if(oItemGroup) { + } - nItems = oItemGroup.length; + while(i--); - if(nItems > 0) { + - n = nItems - 1; + } - do { + - oItem = this._aItemGroups[i][n]; + break; - if(oItem) { + - oItem.destroy(); - } + case "SELECT": - } - while(n--); + - } + - } + oNode = this.srcElement.firstChild; - } - while(i--); + - } + do { - // Continue with the superclass implementation of this method + - YAHOO.widget.MenuModule.superclass.destroy.call(this); + if(oNode && oNode.tagName) { + -}; + switch(oNode.tagName.toUpperCase()) { -/** -* Sets focus to a MenuModule instance's first enabled item. -*/ -YAHOO.widget.MenuModule.prototype.setInitialFocus = function() { + - var oItem = this._getFirstEnabledItem(); + case "OPTGROUP": - if(oItem) { + case "OPTION": - oItem.focus(); - } + -}; + -/** -* Sets the "selected" configuration property of a MenuModule instance's first -* enabled item to "true." -*/ -YAHOO.widget.MenuModule.prototype.setInitialSelection = function() { + this.addItem( - var oItem = this._getFirstEnabledItem(); + new this.ITEM_TYPE( - if(oItem) { + oNode, - oItem.cfg.setProperty("selected", true); - } + { parent: this } -}; + ) -/** -* Sets the "selected" configuration property of a MenuModule instance's active -* item to "false," blurs the item and hide's the item's submenu. -*/ -YAHOO.widget.MenuModule.prototype.clearActiveItem = function () { + ); - if(this.activeItem) { + - var oConfig = this.activeItem.cfg; + break; - oConfig.setProperty("selected", false); + - var oSubmenu = oConfig.getProperty("submenu"); + } - if(oSubmenu) { + - oSubmenu.hide(); + } - } + - } + } -}; + while((oNode = oNode.nextSibling)); -/** -* Initializes the class's configurable properties which can be changed using -* the MenuModule's Config object (cfg). -*/ -YAHOO.widget.MenuModule.prototype.initDefaultConfig = function() { + - YAHOO.widget.MenuModule.superclass.initDefaultConfig.call(this); + break; - var oConfig = this.cfg; + - // Add configuration properties + } - oConfig.addProperty( - "position", - { - value: "dynamic", - handler: this.configPosition, - validator: this._checkPosition - } - ); + -// this.cfg.refireEvent("position"); + } - oConfig.addProperty("submenualignment", { value: ["tl","tr"] } ); + -}; +}, + + + + +/** + +* @method _getFirstEnabledItem + +* @description Returns the first enabled item in the menu. + +* @return {YAHOO.widget.MenuItem} + +* @private + +*/ + +_getFirstEnabledItem: function() { + + + + var nGroups = this._aItemGroups.length, + + oItem, + + aItemGroup; + + + + for(var i=0; i= aGroup.length); + + + + + + if(aGroup[p_nItemIndex]) { + + + + aGroup.splice(p_nItemIndex, 0, oItem); + + + + } + + else { + + + + aGroup[p_nItemIndex] = oItem; + + + + } + + + + + + oGroupItem = aGroup[p_nItemIndex]; + + + + if(oGroupItem) { + + + + if( + + bAppend && + + ( + + !oGroupItem.element.parentNode || + + oGroupItem.element.parentNode.nodeType == 11 + + ) + + ) { + + + + this._aListElements[nGroupIndex].appendChild( + + oGroupItem.element + + ); + + + + } + + else { + + + + + + /** + + * Returns the next sibling of an item in an array. + + * @private + + * @param {p_aArray} Array to search. + + * @param {p_nStartIndex} Number indicating the index to + + * start searching the array. + + * @return {Object} + + */ + + function getNextItemSibling(p_aArray, p_nStartIndex) { + + + + return ( + + p_aArray[p_nStartIndex] || + + getNextItemSibling( + + p_aArray, + + (p_nStartIndex+1) + + ) + + ); + + + + } + + + + + + var oNextItemSibling = + + getNextItemSibling(aGroup, (p_nItemIndex+1)); + + + + if( + + oNextItemSibling && + + ( + + !oGroupItem.element.parentNode || + + oGroupItem.element.parentNode.nodeType == 11 + + ) + + ) { + + + + this._aListElements[nGroupIndex].insertBefore( + + oGroupItem.element, + + oNextItemSibling.element + + ); + + + + } + + + + } + + + + + + oGroupItem.parent = this; + + + + this._subscribeToItemEvents(oGroupItem); + + + + this._configureSubmenu(oGroupItem); + + + + this._updateItemProperties(nGroupIndex); + + + + + + this.itemAddedEvent.fire(oGroupItem); + + + + return oGroupItem; + + + + } + + + + } + + else { + + + + var nItemIndex = aGroup.length; + + + + aGroup[nItemIndex] = oItem; + + + + oGroupItem = aGroup[nItemIndex]; + + + + + + if(oGroupItem) { + + + + if( + + !Dom.isAncestor( + + this._aListElements[nGroupIndex], + + oGroupItem.element + + ) + + ) { + + + + this._aListElements[nGroupIndex].appendChild( + + oGroupItem.element + + ); + + + + } + + + + oGroupItem.element.setAttribute("groupindex", nGroupIndex); + + oGroupItem.element.setAttribute("index", nItemIndex); + + + + oGroupItem.parent = this; + + + + oGroupItem.index = nItemIndex; + + oGroupItem.groupIndex = nGroupIndex; + + + + this._subscribeToItemEvents(oGroupItem); + + + + this._configureSubmenu(oGroupItem); + + + + if(nItemIndex === 0) { + + + + Dom.addClass(oGroupItem.element, "first-of-type"); + + + + } + + + + + + + + this.itemAddedEvent.fire(oGroupItem); + + + + return oGroupItem; + + + + } + + + + } + + + + } + + + +}, + + + + + +/** + +* @method _removeItemFromGroupByIndex + +* @description Removes a menu item from a group by index. Returns the menu + +* item that was removed. + +* @private + +* @param {Number} p_nGroupIndex Number indicating the group to which the menu + +* item belongs. + +* @param {Number} p_nItemIndex Number indicating the index of the menu item + +* to be removed. + +* @return {YAHOO.widget.MenuItem} + +*/ + +_removeItemFromGroupByIndex: function(p_nGroupIndex, p_nItemIndex) { + + + + var nGroupIndex = typeof p_nGroupIndex == "number" ? p_nGroupIndex : 0, + + aGroup = this._getItemGroup(nGroupIndex); + + + + if(aGroup) { + + + + var aArray = aGroup.splice(p_nItemIndex, 1), + + oItem = aArray[0]; + + + + if(oItem) { + + + + // Update the index and className properties of each member + + + + this._updateItemProperties(nGroupIndex); + + + + if(aGroup.length === 0) { + + + + // Remove the UL + + + + var oUL = this._aListElements[nGroupIndex]; + + + + if(this.body && oUL) { + + + + this.body.removeChild(oUL); + + + + } + + + + // Remove the group from the array of items + + + + this._aItemGroups.splice(nGroupIndex, 1); + + + + + + // Remove the UL from the array of ULs + + + + this._aListElements.splice(nGroupIndex, 1); + + + + + + /* + + Assign the "first-of-type" class to the new first UL + + in the collection + + */ + + + + oUL = this._aListElements[0]; + + + + if(oUL) { + + + + Dom.addClass(oUL, "first-of-type"); + + + + } + + + + } + + + + + + this.itemRemovedEvent.fire(oItem); + + + + + + // Return a reference to the item that was removed + + + + return oItem; + + + + } + + + + } + + + +}, + + + + + +/** + +* @method _removeItemFromGroupByValue + +* @description Removes a menu item from a group by reference. Returns the + +* menu item that was removed. + +* @private + +* @param {Number} p_nGroupIndex Number indicating the group to which the + +* menu item belongs. + +* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem + +* instance to be removed. + +* @return {YAHOO.widget.MenuItem} + +*/ + +_removeItemFromGroupByValue: function(p_nGroupIndex, p_oItem) { + + + + var aGroup = this._getItemGroup(p_nGroupIndex); + + + + if(aGroup) { + + + + var nItems = aGroup.length, + + nItemIndex = -1; + + + + if(nItems > 0) { + + + + var i = nItems-1; + + + + do { + + + + if(aGroup[i] == p_oItem) { + + + + nItemIndex = i; + + break; + + + + } + + + + } + + while(i--); + + + + if(nItemIndex > -1) { + + + + return this._removeItemFromGroupByIndex( + + p_nGroupIndex, + + nItemIndex + + ); + + + + } + + + + } + + + + } + + + +}, + + + + + +/** + +* @method _updateItemProperties + +* @description Updates the "index," "groupindex," and "className" properties + +* of the menu items in the specified group. + +* @private + +* @param {Number} p_nGroupIndex Number indicating the group of items to update. + +*/ + +_updateItemProperties: function(p_nGroupIndex) { + + + + var aGroup = this._getItemGroup(p_nGroupIndex), + + nItems = aGroup.length; + + + + if(nItems > 0) { + + + + var i = nItems - 1, + + oItem, + + oLI; + + + + // Update the index and className properties of each member + + + + do { + + + + oItem = aGroup[i]; + + + + if(oItem) { + + + + oLI = oItem.element; + + + + oItem.index = i; + + oItem.groupIndex = p_nGroupIndex; + + + + oLI.setAttribute("groupindex", p_nGroupIndex); + + oLI.setAttribute("index", i); + + + + Dom.removeClass(oLI, "first-of-type"); + + + + } + + + + } + + while(i--); + + + + + + if(oLI) { + + + + Dom.addClass(oLI, "first-of-type"); + + + + } + + + + } + + + +}, + + + + + +/** + +* @method _createItemGroup + +* @description Creates a new menu item group (array) and its associated + +* <ul> element. Returns an aray of menu item groups. + +* @private + +* @param {Number} p_nIndex Number indicating the group to create. + +* @return {Array} + +*/ + +_createItemGroup: function(p_nIndex) { + + + + if(!this._aItemGroups[p_nIndex]) { + + + + this._aItemGroups[p_nIndex] = []; + + + + var oUL = document.createElement("ul"); + + + + this._aListElements[p_nIndex] = oUL; + + + + return this._aItemGroups[p_nIndex]; + + + + } + + + +}, + + + + + +/** + +* @method _getItemGroup + +* @description Returns the menu item group at the specified index. + +* @private + +* @param {Number} p_nIndex Number indicating the index of the menu item group + +* to be retrieved. + +* @return {Array} + +*/ + +_getItemGroup: function(p_nIndex) { + + + + var nIndex = ((typeof p_nIndex == "number") ? p_nIndex : 0); + + + + return this._aItemGroups[nIndex]; + + + +}, + + + + + +/** + +* @method _configureSubmenu + +* @description Subscribes the menu item's submenu to its parent menu's events. + +* @private + +* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem + +* instance with the submenu to be configured. + +*/ + +_configureSubmenu: function(p_oItem) { + + + + var oSubmenu = p_oItem.cfg.getProperty("submenu"); + + + + if(oSubmenu) { + + + + /* + + Listen for configuration changes to the parent menu + + so they they can be applied to the submenu. + + */ + + + + this.cfg.configChangedEvent.subscribe( + + this._onParentMenuConfigChange, + + oSubmenu, + + true + + ); + + + + this.renderEvent.subscribe( + + this._onParentMenuRender, + + oSubmenu, + + true + + ); + + + + oSubmenu.beforeShowEvent.subscribe( + + this._onSubmenuBeforeShow, + + oSubmenu, + + true + + ); + + + + oSubmenu.showEvent.subscribe( + + this._onSubmenuShow, + + oSubmenu, + + true + + ); + + + + oSubmenu.hideEvent.subscribe( + + this._onSubmenuHide, + + oSubmenu, + + true + + ); + + + + } + + + +}, + + + + + +/** + +* @method _subscribeToItemEvents + +* @description Subscribes a menu to a menu item's event. + +* @private + +* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem + +* instance whose events should be subscribed to. + +*/ + +_subscribeToItemEvents: function(p_oItem) { + + + + p_oItem.focusEvent.subscribe(this._onMenuItemFocus, p_oItem, this); + + + + p_oItem.blurEvent.subscribe(this._onMenuItemBlur, this, true); + + + + p_oItem.cfg.configChangedEvent.subscribe( + + this._onMenuItemConfigChange, + + p_oItem, + + this + + ); + + + +}, + + + + + +/** + +* @method _getOffsetWidth + +* @description Returns the offset width of the menu's + +* <div> element. + +* @private + +*/ + +_getOffsetWidth: function() { + + + + var oClone = this.element.cloneNode(true); + + + + Dom.setStyle(oClone, "width", ""); + + + + document.body.appendChild(oClone); + + + + var sWidth = oClone.offsetWidth; + + + + document.body.removeChild(oClone); + + + + return sWidth; + + + +}, + + + + + +/** + +* @method _cancelHideDelay + +* @description Cancels the call to "hideMenu." + +* @private + +*/ + +_cancelHideDelay: function() { + + + + var oRoot = this.getRoot(); + + + + if(oRoot._nHideDelayId) { + + + + window.clearTimeout(oRoot._nHideDelayId); + + + + } + + + +}, + + + + + +/** + +* @method _execHideDelay + +* @description Hides the menu after the number of milliseconds specified by + +* the "hidedelay" configuration property. + +* @private + +*/ + +_execHideDelay: function() { + + + + this._cancelHideDelay(); + + + + var oRoot = this.getRoot(), + + me = this; + + + + function hideMenu() { + + + + if(oRoot.activeItem) { + + + + oRoot.clearActiveItem(); + + + + } + + + + if(oRoot == me && me.cfg.getProperty("position") == "dynamic") { + + + + me.hide(); + + + + } + + + + } + + + + + + oRoot._nHideDelayId = + + window.setTimeout(hideMenu, oRoot.cfg.getProperty("hidedelay")); + + + +}, + + + + + +/** + +* @method _cancelShowDelay + +* @description Cancels the call to the "showMenu." + +* @private + +*/ + +_cancelShowDelay: function() { + + + + var oRoot = this.getRoot(); + + + + if(oRoot._nShowDelayId) { + + + + window.clearTimeout(oRoot._nShowDelayId); + + + + } + + + +}, + + + + + +/** + +* @method _execShowDelay + +* @description Shows the menu after the number of milliseconds specified by + +* the "showdelay" configuration property have ellapsed. + +* @private + +* @param {YAHOO.widget.Menu} p_oMenu Object specifying the menu that should + +* be made visible. + +*/ + +_execShowDelay: function(p_oMenu) { + + + + var oRoot = this.getRoot(); + + + + function showMenu() { + + + + p_oMenu.show(); + + + + } + + + + + + oRoot._nShowDelayId = + + window.setTimeout(showMenu, oRoot.cfg.getProperty("showdelay")); + + + +}, + + + + + + + +// Protected methods + + + + + +/** + +* @method _onMouseOver + +* @description "mouseover" event handler for the menu. + +* @protected + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +_onMouseOver: function(p_sType, p_aArgs, p_oMenu) { + + + + var oEvent = p_aArgs[0], + + oItem = p_aArgs[1], + + oTarget = Event.getTarget(oEvent); + + + + + + if( + + !this._bHandledMouseOverEvent && + + (oTarget == this.element || Dom.isAncestor(this.element, oTarget)) + + ) { + + + + this.clearActiveItem(); + + + + this._bHandledMouseOverEvent = true; + + this._bHandledMouseOutEvent = false; + + + + } + + + + + + if( + + oItem && !oItem.handledMouseOverEvent && + + !oItem.cfg.getProperty("disabled") && + + (oTarget == oItem.element || Dom.isAncestor(oItem.element, oTarget)) + + ) { + + + + var nShowDelay = this.cfg.getProperty("showdelay"), + + bShowDelay = (nShowDelay > 0); + + + + + + if(bShowDelay) { + + + + this._cancelShowDelay(); + + + + } + + + + + + var oActiveItem = this.activeItem; + + + + if(oActiveItem) { + + + + oActiveItem.cfg.setProperty("selected", false); + + + + var oActiveSubmenu = oActiveItem.cfg.getProperty("submenu"); + + + + if(oActiveSubmenu) { + + + + oActiveSubmenu.hide(); + + + + } + + + + } + + + + + + var oItemCfg = oItem.cfg; + + + + // Select and focus the current menu item + + + + oItemCfg.setProperty("selected", true); + + oItem.focus(); + + + + + + if(this.cfg.getProperty("autosubmenudisplay")) { + + + + // Show the submenu this menu item + + + + var oSubmenu = oItemCfg.getProperty("submenu"); + + + + if(oSubmenu) { + + + + if(bShowDelay) { + + + + this._execShowDelay(oSubmenu); + + + + } + + else { + + + + oSubmenu.show(); + + + + } + + + + } + + + + } + + + + oItem.handledMouseOverEvent = true; + + oItem.handledMouseOutEvent = false; + + + + } + + + +}, + + + + + +/** + +* @method _onMouseOut + +* @description "mouseout" event handler for the menu. + +* @protected + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +_onMouseOut: function(p_sType, p_aArgs, p_oMenu) { + + + + var oEvent = p_aArgs[0], + + oItem = p_aArgs[1], + + oRelatedTarget = Event.getRelatedTarget(oEvent), + + bMovingToSubmenu = false; + + + + + + if(oItem && !oItem.cfg.getProperty("disabled")) { + + + + var oItemCfg = oItem.cfg, + + oSubmenu = oItemCfg.getProperty("submenu"); + + + + + + if( + + oSubmenu && + + ( + + oRelatedTarget == oSubmenu.element || + + Dom.isAncestor(oSubmenu.element, oRelatedTarget) + + ) + + ) { + + + + bMovingToSubmenu = true; + + + + } + + + + + + if( + + !oItem.handledMouseOutEvent && + + ( + + ( + + oRelatedTarget != oItem.element && + + !Dom.isAncestor(oItem.element, oRelatedTarget) + + ) || bMovingToSubmenu + + ) + + ) { + + + + if( + + !oSubmenu || + + (oSubmenu && !oSubmenu.cfg.getProperty("visible")) + + ) { + + + + oItem.cfg.setProperty("selected", false); + + + + if( + + oSubmenu && + + oSubmenu.cfg.getProperty("showdelay") && + + !oSubmenu.cfg.getProperty("visible") + + ) { + + + + this._cancelShowDelay(); + + + + } + + + + } + + + + + + oItem.handledMouseOutEvent = true; + + oItem.handledMouseOverEvent = false; + + + + } + + + + } + + + + + + if( + + !this._bHandledMouseOutEvent && + + ( + + ( + + oRelatedTarget != this.element && + + !Dom.isAncestor(this.element, oRelatedTarget) + + ) + + || bMovingToSubmenu + + ) + + ) { + + + + this._bHandledMouseOutEvent = true; + + this._bHandledMouseOverEvent = false; + + + + } + + + +}, + + + + + +/** + +* @method _onClick + +* @description "click" event handler for the menu. + +* @protected + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +_onClick: function(p_sType, p_aArgs, p_oMenu) { + + + + var oEvent = p_aArgs[0], + + oItem = p_aArgs[1], + + oTarget = Event.getTarget(oEvent); + + + + if(oItem && !oItem.cfg.getProperty("disabled")) { + + + + var oItemCfg = oItem.cfg, + + oSubmenu = oItemCfg.getProperty("submenu"); + + + + + + /* + + ACCESSIBILITY FEATURE FOR SCREEN READERS: + + Expand/collapse the submenu when the user clicks + + on the submenu indicator image. + + */ + + + + if(oTarget == oItem.submenuIndicator && oSubmenu) { + + + + if(oSubmenu.cfg.getProperty("visible")) { + + + + oSubmenu.hide(); + + + + } + + else { + + + + this.clearActiveItem(); + + + + this.activeItem = oItem; + + + + oItem.cfg.setProperty("selected", true); + + + + oSubmenu.show(); + + + + } + + + + } + + else { + + + + var sURL = oItemCfg.getProperty("url"), + + bCurrentPageURL = (sURL.substr((sURL.length-1),1) == "#"), + + sTarget = oItemCfg.getProperty("target"), + + bHasTarget = (sTarget && sTarget.length > 0); + + + + /* + + Prevent the browser from following links + + equal to "#" + + */ + + + + if( + + oTarget.tagName.toUpperCase() == "A" && + + bCurrentPageURL && !bHasTarget + + ) { + + + + Event.preventDefault(oEvent); + + + + } + + + + if( + + oTarget.tagName.toUpperCase() != "A" && + + !bCurrentPageURL && !bHasTarget + + ) { + + + + /* + + Follow the URL of the item regardless of + + whether or not the user clicked specifically + + on the anchor element. + + */ + + + + document.location = sURL; + + + + } + + + + + + /* + + If the item doesn't navigate to a URL and it doesn't have + + a submenu, then collapse the menu tree. + + */ + + + + if(bCurrentPageURL && !oSubmenu) { + + + + var oRoot = this.getRoot(); + + + + if(oRoot.cfg.getProperty("position") == "static") { + + + + oRoot.clearActiveItem(); + + + + } + + else { + + + + oRoot.hide(); + + + + } + + + + } + + + + } + + + + } + + + +}, + + + + + +/** + +* @method _onKeyDown + +* @description "keydown" event handler for the menu. + +* @protected + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +_onKeyDown: function(p_sType, p_aArgs, p_oMenu) { + + + + var oEvent = p_aArgs[0], + + oItem = p_aArgs[1], + + oSubmenu; + + + + if(oItem && !oItem.cfg.getProperty("disabled")) { + + + + var oItemCfg = oItem.cfg, + + oParentItem = this.parent, + + oRoot, + + oNextItem; + + + + + + switch(oEvent.keyCode) { + + + + case 38: // Up arrow + + case 40: // Down arrow + + + + if( + + oItem == this.activeItem && + + !oItemCfg.getProperty("selected") + + ) { + + + + oItemCfg.setProperty("selected", true); + + + + } + + else { + + + + oNextItem = (oEvent.keyCode == 38) ? + + oItem.getPreviousEnabledSibling() : + + oItem.getNextEnabledSibling(); + + + + if(oNextItem) { + + + + this.clearActiveItem(); + + + + oNextItem.cfg.setProperty("selected", true); + + oNextItem.focus(); + + + + } + + + + } + + + + Event.preventDefault(oEvent); + + + + break; + + + + + + case 39: // Right arrow + + + + oSubmenu = oItemCfg.getProperty("submenu"); + + + + if(oSubmenu) { + + + + if(!oItemCfg.getProperty("selected")) { + + + + oItemCfg.setProperty("selected", true); + + + + } + + + + oSubmenu.show(); + + + + oSubmenu.setInitialSelection(); + + + + } + + else { + + + + oRoot = this.getRoot(); + + + + if(oRoot instanceof YAHOO.widget.MenuBar) { + + + + oNextItem = oRoot.activeItem.getNextEnabledSibling(); + + + + if(oNextItem) { + + + + oRoot.clearActiveItem(); + + + + oNextItem.cfg.setProperty("selected", true); + + + + oSubmenu = oNextItem.cfg.getProperty("submenu"); + + + + if(oSubmenu) { + + + + oSubmenu.show(); + + + + } + + + + oNextItem.focus(); + + + + } + + + + } + + + + } + + + + + + Event.preventDefault(oEvent); + + + + break; + + + + + + case 37: // Left arrow + + + + if(oParentItem) { + + + + var oParentMenu = oParentItem.parent; + + + + if(oParentMenu instanceof YAHOO.widget.MenuBar) { + + + + oNextItem = + + oParentMenu.activeItem.getPreviousEnabledSibling(); + + + + if(oNextItem) { + + + + oParentMenu.clearActiveItem(); + + + + oNextItem.cfg.setProperty("selected", true); + + + + oSubmenu = oNextItem.cfg.getProperty("submenu"); + + + + if(oSubmenu) { + + + + oSubmenu.show(); + + + + } + + + + oNextItem.focus(); + + + + } + + + + } + + else { + + + + this.hide(); + + + + oParentItem.focus(); + + + + } + + + + } + + + + Event.preventDefault(oEvent); + + + + break; + + + + } + + + + + + } + + + + + + if(oEvent.keyCode == 27) { // Esc key + + + + if(this.cfg.getProperty("position") == "dynamic") { + + + + this.hide(); + + + + if(this.parent) { + + + + this.parent.focus(); + + + + } + + + + } + + else if(this.activeItem) { + + + + oSubmenu = this.activeItem.cfg.getProperty("submenu"); + + + + if(oSubmenu && oSubmenu.cfg.getProperty("visible")) { + + + + oSubmenu.hide(); + + this.activeItem.focus(); + + + + } + + else { + + + + this.activeItem.cfg.setProperty("selected", false); + + this.activeItem.blur(); + + + + } + + + + } + + + + + + Event.preventDefault(oEvent); + + + + } + + + +}, + + + + + +/** + +* @method _onTextResize + +* @description "textresize" event handler for the menu. + +* @protected + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +_onTextResize: function(p_sType, p_aArgs, p_oMenu) { + + + + if(this.browser == "gecko" && !this._handleResize) { + + + + this._handleResize = true; + + return; + + + + } + + + + + + var oConfig = this.cfg; + + + + if(oConfig.getProperty("position") == "dynamic") { + + + + oConfig.setProperty("width", (this._getOffsetWidth() + "px")); + + + + } + + + +}, + + + + + + + +// Private methods + + + + + +/** + +* @method _onInit + +* @description "init" event handler for the menu. + +* @private + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +_onInit: function(p_sType, p_aArgs, p_oMenu) { + + + + if( + + ( + + (this.parent && !this.lazyLoad) || + + (!this.parent && this.cfg.getProperty("position") == "static") || + + ( + + !this.parent && + + !this.lazyLoad && + + this.cfg.getProperty("position") == "dynamic" + + ) + + ) && + + this.getItemGroups().length === 0 + + ) { + + + + if(this.srcElement) { + + + + this._initSubTree(); + + + + } + + + + + + if(this.itemData) { + + + + this.addItems(this.itemData); + + + + } + + + + } + + else if(this.lazyLoad) { + + + + this.cfg.fireQueue(); + + + + } + + + +}, + + + + + +/** + +* @method _onBeforeRender + +* @description "beforerender" event handler for the menu. Appends all of the + +* <ul>, <li> and their accompanying + +* title elements to the body element of the menu. + +* @private + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +_onBeforeRender: function(p_sType, p_aArgs, p_oMenu) { + + + + var oConfig = this.cfg, + + oEl = this.element, + + nListElements = this._aListElements.length; + + + + + + if(nListElements > 0) { + + + + var i = 0, + + bFirstList = true, + + oUL, + + oGroupTitle; + + + + + + do { + + + + oUL = this._aListElements[i]; + + + + if(oUL) { + + + + if(bFirstList) { + + + + Dom.addClass(oUL, "first-of-type"); + + bFirstList = false; + + + + } + + + + + + if(!Dom.isAncestor(oEl, oUL)) { + + + + this.appendToBody(oUL); + + + + } + + + + + + oGroupTitle = this._aGroupTitleElements[i]; + + + + if(oGroupTitle) { + + + + if(!Dom.isAncestor(oEl, oGroupTitle)) { + + + + oUL.parentNode.insertBefore(oGroupTitle, oUL); + + + + } + + + + + + Dom.addClass(oUL, "hastitle"); + + + + } + + + + } + + + + i++; + + + + } + + while(i < nListElements); + + + + } + + + +}, + + + + + +/** + +* @method _onRender + +* @description "render" event handler for the menu. + +* @private + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +_onRender: function(p_sType, p_aArgs, p_oMenu) { + + + + if(this.cfg.getProperty("position") == "dynamic") { + + + + var sWidth = + + this.element.parentNode.tagName.toUpperCase() == "BODY" ? + + this.element.offsetWidth : this._getOffsetWidth(); + + + + this.cfg.setProperty("width", (sWidth + "px")); + + + + } + + + +}, + + + + + +/** + +* @method _onBeforeShow + +* @description "beforeshow" event handler for the menu. + +* @private + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +_onBeforeShow: function(p_sType, p_aArgs, p_oMenu) { + + + + if(this.lazyLoad && this.getItemGroups().length === 0) { + + + + if(this.srcElement) { + + + + this._initSubTree(); + + + + } + + + + + + if(this.itemData) { + + + + if( + + this.parent && this.parent.parent && + + this.parent.parent.srcElement && + + this.parent.parent.srcElement.tagName.toUpperCase() == "SELECT" + + ) { + + + + var nOptions = this.itemData.length; + + + + for(var n=0; n viewPortWidth) { + + + + if( + + oContextElement && + + ((x - oContextElement.offsetWidth) > offsetWidth) + + ) { + + + + x = (x - (oContextElement.offsetWidth + offsetWidth)); + + + + } + + else { + + + + x = rightConstraint; + + + + } + + + + } + + + + if (y < 10) { + + + + y = topConstraint; + + + + } else if (y > bottomConstraint) { + + + + if(oContextElement && (y > offsetHeight)) { + + + + y = ((y + oContextElement.offsetHeight) - offsetHeight); + + + + } + + else { + + + + y = bottomConstraint; + + + + } + + + + } + + + + oConfig.setProperty("x", x, true); + + oConfig.setProperty("y", y, true); + + oConfig.setProperty("xy", [x,y], true); + + + +}, + + + + + +/** + +* @method configVisible + +* @description Event handler for when the "visible" configuration property + +* the menu changes. + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +configVisible: function(p_sType, p_aArgs, p_oMenu) { + + + + if(this.cfg.getProperty("position") == "dynamic") { + + + + YAHOO.widget.Menu.superclass.configVisible.call( + + this, + + p_sType, + + p_aArgs, + + p_oMenu + + ); + + + + } + + else { + + + + var bVisible = p_aArgs[0], + + sDisplay = Dom.getStyle(this.element, "display"); + + + + if(bVisible) { + + + + if(sDisplay != "block") { + + this.beforeShowEvent.fire(); + + Dom.setStyle(this.element, "display", "block"); + + this.showEvent.fire(); + + } + + + + } + + else { + + + + if(sDisplay == "block") { + + this.beforeHideEvent.fire(); + + Dom.setStyle(this.element, "display", "none"); + + this.hideEvent.fire(); + + } + + + + } + + + + } + + + +}, + + + + + +/** + +* @method configPosition + +* @description Event handler for when the "position" configuration property + +* of the menu changes. + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +configPosition: function(p_sType, p_aArgs, p_oMenu) { + + + + var sCSSPosition = p_aArgs[0] == "static" ? "static" : "absolute", + + oCfg = this.cfg; + + + + Dom.setStyle(this.element, "position", sCSSPosition); + + + + + + if(sCSSPosition == "static") { + + + + /* + + Remove the iframe for statically positioned menus since it will + + intercept mouse events. + + */ + + + + oCfg.setProperty("iframe", false); + + + + + + // Statically positioned menus are visible by default + + + + Dom.setStyle(this.element, "display", "block"); + + + + oCfg.setProperty("visible", true); + + + + } + + else { + + + + /* + + Even though the "visible" property is queued to + + "false" by default, we need to set the "visibility" property to + + "hidden" since Overlay's "configVisible" implementation checks the + + element's "visibility" style property before deciding whether + + or not to show an Overlay instance. + + */ + + + + Dom.setStyle(this.element, "visibility", "hidden"); + + + + } + + + + + + if(sCSSPosition == "absolute") { + + + + var nZIndex = oCfg.getProperty("zindex"); + + + + if(!nZIndex || nZIndex === 0) { + + + + nZIndex = this.parent ? + + (this.parent.parent.cfg.getProperty("zindex") + 1) : 1; + + + + oCfg.setProperty("zindex", nZIndex); + + + + } + + + + } + + + +}, + + + + + +/** + +* @method configIframe + +* @description Event handler for when the "iframe" configuration property of + +* the menu changes. + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +configIframe: function(p_sType, p_aArgs, p_oMenu) { + + + + if(this.cfg.getProperty("position") == "dynamic") { + + + + YAHOO.widget.Menu.superclass.configIframe.call( + + this, + + p_sType, + + p_aArgs, + + p_oMenu + + ); + + + + } + + + +}, + + + + + +/** + +* @method configHideDelay + +* @description Event handler for when the "hidedelay" configuration property + +* of the menu changes. + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +configHideDelay: function(p_sType, p_aArgs, p_oMenu) { + + + + var nHideDelay = p_aArgs[0], + + oMouseOutEvent = this.mouseOutEvent, + + oMouseOverEvent = this.mouseOverEvent, + + oKeyDownEvent = this.keyDownEvent; + + + + if(nHideDelay > 0) { + + + + /* + + Only assign event handlers once. This way the user change + + the value for the hidedelay as many times as they want. + + */ + + + + if(!this._hideDelayEventHandlersAssigned) { + + + + oMouseOutEvent.subscribe(this._execHideDelay, true); + + oMouseOverEvent.subscribe(this._cancelHideDelay, this, true); + + oKeyDownEvent.subscribe(this._cancelHideDelay, this, true); + + + + this._hideDelayEventHandlersAssigned = true; + + + + } + + + + } + + else { + + + + oMouseOutEvent.unsubscribe(this._execHideDelay, this); + + oMouseOverEvent.unsubscribe(this._cancelHideDelay, this); + + oKeyDownEvent.unsubscribe(this._cancelHideDelay, this); + + + + this._hideDelayEventHandlersAssigned = false; + + + + } + + + +}, + + + + + +/** + +* @method configContainer + +* @description Event handler for when the "container" configuration property + +of the menu changes. + +* @param {String} p_sType String representing the name of the event that + +* was fired. + +* @param {Array} p_aArgs Array of arguments sent when the event was fired. + +* @param {YAHOO.widget.Menu} p_oMenu Object representing the menu that + +* fired the event. + +*/ + +configContainer: function(p_sType, p_aArgs, p_oMenu) { + + + + var oElement = p_aArgs[0]; + + + + if(typeof oElement == 'string') { + + + + this.cfg.setProperty( + + "container", + + document.getElementById(oElement), + + true + + ); + + + + } + + + +}, + + + + + + + +// Public methods + + + + + +/** + +* @method initEvents + +* @description Initializes the custom events for the menu. + +*/ + +initEvents: function() { + + + + YAHOO.widget.Menu.superclass.initEvents.call(this); + + + + // Create custom events + + + + var CustomEvent = YAHOO.util.CustomEvent; + + + + this.mouseOverEvent = new CustomEvent("mouseOverEvent", this); + + this.mouseOutEvent = new CustomEvent("mouseOutEvent", this); + + this.mouseDownEvent = new CustomEvent("mouseDownEvent", this); + + this.mouseUpEvent = new CustomEvent("mouseUpEvent", this); + + this.clickEvent = new CustomEvent("clickEvent", this); + + this.keyPressEvent = new CustomEvent("keyPressEvent", this); + + this.keyDownEvent = new CustomEvent("keyDownEvent", this); + + this.keyUpEvent = new CustomEvent("keyUpEvent", this); + + this.itemAddedEvent = new CustomEvent("itemAddedEvent", this); + + this.itemRemovedEvent = new CustomEvent("itemRemovedEvent", this); + + + +}, + + + + + +/** + +* @method getRoot + +* @description Finds the menu's root menu. + +*/ + +getRoot: function() { + + + + var oItem = this.parent; + + + + if(oItem) { + + + + var oParentMenu = oItem.parent; + + + + return oParentMenu ? oParentMenu.getRoot() : this; + + + + } + + else { + + + + return this; + + + + } + + + +}, + + + + + +/** + +* @method toString + +* @description Returns a string representing the menu. + +* @return {String} + +*/ + +toString: function() { + + + + return ("Menu " + this.id); + + + +}, + + + + + +/** + +* @method setItemGroupTitle + +* @description Sets the title of a group of menu items. + +* @param {String} p_sGroupTitle String specifying the title of the group. + +* @param {Number} p_nGroupIndex Optional. Number specifying the group to which + +* the title belongs. + +*/ + +setItemGroupTitle: function(p_sGroupTitle, p_nGroupIndex) { + + + + if(typeof p_sGroupTitle == "string" && p_sGroupTitle.length > 0) { + + + + var nGroupIndex = typeof p_nGroupIndex == "number" ? p_nGroupIndex : 0, + + oTitle = this._aGroupTitleElements[nGroupIndex]; + + + + + + if(oTitle) { + + + + oTitle.innerHTML = p_sGroupTitle; + + + + } + + else { + + + + oTitle = document.createElement(this.GROUP_TITLE_TAG_NAME); + + + + oTitle.innerHTML = p_sGroupTitle; + + + + this._aGroupTitleElements[nGroupIndex] = oTitle; + + + + } + + + + + + var i = this._aGroupTitleElements.length - 1, + + nFirstIndex; + + + + do { + + + + if(this._aGroupTitleElements[i]) { + + + + Dom.removeClass(this._aGroupTitleElements[i], "first-of-type"); + + + + nFirstIndex = i; + + + + } + + + + } + + while(i--); + + + + + + if(nFirstIndex !== null) { + + + + Dom.addClass( + + this._aGroupTitleElements[nFirstIndex], + + "first-of-type" + + ); + + + + } + + + + } + + + +}, + + + + + + + +/** + +* @method addItem + +* @description Appends an item to the menu. + +* @param {YAHOO.widget.MenuItem} p_oItem Object reference for the MenuItem + +* instance to be added to the menu. + +* @param {String} p_oItem String specifying the text of the item to be added + +* to the menu. + +* @param {Object} p_oItem Object literal containing a set of menu item + +* configuration properties. + +* @param {Number} p_nGroupIndex Optional. Number indicating the group to + +* which the item belongs. + +* @return {YAHOO.widget.MenuItem} + +*/ + +addItem: function(p_oItem, p_nGroupIndex) { + + + + if(p_oItem) { + + + + return this._addItemToGroup(p_nGroupIndex, p_oItem); + + + + } + + + +}, + + + + + +/** + +* @method addItems + +* @description Adds an array of items to the menu. + +* @param {Array} p_aItems Array of items to be added to the menu. The array + +* can contain strings specifying the text for each item to be created, object + +* literals specifying each of the menu item configuration properties, + +* or MenuItem instances. + +* @param {Number} p_nGroupIndex Optional. Number specifying the group to + +* which the items belongs. + +* @return {Array} + +*/ + +addItems: function(p_aItems, p_nGroupIndex) { + + + + function isArray(p_oValue) { + + + + return (typeof p_oValue == "object" && p_oValue.constructor == Array); + + + + } + + + + + + if(isArray(p_aItems)) { + + + + var nItems = p_aItems.length, + + aItems = [], + + oItem; + + + + + + for(var i=0; i<div> element + +* (and accompanying child nodes) from the document. + +*/ + +destroy: function() { + + + + // Remove Custom Event listeners + + + + this.mouseOverEvent.unsubscribeAll(); + + this.mouseOutEvent.unsubscribeAll(); + + this.mouseDownEvent.unsubscribeAll(); + + this.mouseUpEvent.unsubscribeAll(); + + this.clickEvent.unsubscribeAll(); + + this.keyPressEvent.unsubscribeAll(); + + this.keyDownEvent.unsubscribeAll(); + + this.keyUpEvent.unsubscribeAll(); + + this.itemAddedEvent.unsubscribeAll(); + + this.itemRemovedEvent.unsubscribeAll(); + + + + var nItemGroups = this._aItemGroups.length, + + nItems, + + oItemGroup, + + oItem, + + i, + + n; + + + + + + // Remove all items + + + + if(nItemGroups > 0) { + + + + i = nItemGroups - 1; + + + + do { + + + + oItemGroup = this._aItemGroups[i]; + + + + if(oItemGroup) { + + + + nItems = oItemGroup.length; + + + + if(nItems > 0) { + + + + n = nItems - 1; + + + + do { + + + + oItem = this._aItemGroups[i][n]; + + + + if(oItem) { + + + + oItem.destroy(); + + } + + + + } + + while(n--); + + + + } + + + + } + + + + } + + while(i--); + + + + } + + + + + + // Continue with the superclass implementation of this method + + + + YAHOO.widget.Menu.superclass.destroy.call(this); + + + + + +}, + + + + + +/** + +* @method setInitialFocus + +* @description Sets focus to the menu's first enabled item. + +*/ + +setInitialFocus: function() { + + + + var oItem = this._getFirstEnabledItem(); + + + + if(oItem) { + + + + oItem.focus(); + + } + + + +}, + + + + + +/** + +* @method setInitialSelection + +* @description Sets the "selected" configuration property of the menu's first + +* enabled item to "true." + +*/ + +setInitialSelection: function() { + + + + var oItem = this._getFirstEnabledItem(); + + + + if(oItem) { + + + + oItem.cfg.setProperty("selected", true); + + } + + + +}, + + + + + +/** + +* @method clearActiveItem + +* @description Sets the "selected" configuration property of the menu's active + +* item to "false" and hides the item's submenu. + +* @param {Boolean} p_bBlur Boolean indicating if the menu's active item + +* should be blurred. + +*/ + +clearActiveItem: function(p_bBlur) { + + + + if(this.cfg.getProperty("showdelay") > 0) { + + + + this._cancelShowDelay(); + + + + } + + + + + + var oActiveItem = this.activeItem; + + + + if(oActiveItem) { + + + + var oConfig = oActiveItem.cfg; + + + + oConfig.setProperty("selected", false); + + + + var oSubmenu = oConfig.getProperty("submenu"); + + + + if(oSubmenu) { + + + + oSubmenu.hide(); + + + + } + + + + if(p_bBlur) { + + + + oActiveItem.blur(); + + + + } + + + + } + + + +}, + + + + + +/** + +* @description Initializes the class's configurable properties which can be + +* changed using the menu's Config object ("cfg"). + +* @method initDefaultConfig + +*/ + +initDefaultConfig: function() { + + + + YAHOO.widget.Menu.superclass.initDefaultConfig.call(this); + + + + var oConfig = this.cfg; + + + + // Add configuration properties + + + + /* + + Change the default value for the "visible" configuration + + property to "false" by re-adding the property. + + */ + + + + /** + + * @config visible + + * @description Boolean indicating whether or not the menu is visible. If + + * the menu's "position" configuration property is set to "dynamic" (the + + * default), this property toggles the menu's <div> + + * element's "visibility" style property between "visible" (true) or + + * "hidden" (false). If the menu's "position" configuration property is + + * set to "static" this property toggles the menu's + + * <div> element's "display" style property + + * between "block" (true) or "none" (false). + + * @default false + + * @type Boolean + + */ + + oConfig.addProperty( + + "visible", + + { + + value:false, + + handler:this.configVisible, + + validator:this.cfg.checkBoolean + + } + + ); + + + + + + /* + + Change the default value for the "constraintoviewport" configuration + + property to "true" by re-adding the property. + + */ + + + + /** + + * @config constraintoviewport + + * @description Boolean indicating if the menu will try to remain inside + + * the boundaries of the size of viewport. + + * @default true + + * @type Boolean + + */ + + oConfig.addProperty( + + "constraintoviewport", + + { + + value:true, + + handler:this.configConstrainToViewport, + + validator:this.cfg.checkBoolean, + + supercedes:["iframe","x","y","xy"] + + } + + ); + + + + + + /** + + * @config position + + * @description String indicating how a menu should be positioned on the + + * screen. Possible values are "static" and "dynamic." Static menus are + + * visible by default and reside in the normal flow of the document + + * (CSS position: static). Dynamic menus are hidden by default, reside + + * out of the normal flow of the document (CSS position: absolute), and + + * can overlay other elements on the screen. + + * @default dynamic + + * @type String + + */ + + oConfig.addProperty( + + "position", + + { + + value: "dynamic", + + handler: this.configPosition, + + validator: this._checkPosition, + + supercedes: ["visible"] + + } + + ); + + + + + + /** + + * @config submenualignment + + * @description Array defining how submenus should be aligned to their + + * parent menu item. The format is: [itemCorner, submenuCorner]. By default + + * a submenu's top left corner is aligned to its parent menu item's top + + * right corner. + + * @default ["tl","tr"] + + * @type Array + + */ + + oConfig.addProperty("submenualignment", { value: ["tl","tr"] } ); + + + + + + /** + + * @config autosubmenudisplay + + * @description Boolean indicating if submenus are automatically made + + * visible when the user mouses over the menu's items. + + * @default true + + * @type Boolean + + */ + + oConfig.addProperty( + + "autosubmenudisplay", + + { + + value: true, + + validator: oConfig.checkBoolean + + } + + ); + + + + + + /** + + * @config showdelay + + * @description Number indicating the time (in milliseconds) that should + + * expire before a submenu is made visible when the user mouses over + + * the menu's items. + + * @default 0 + + * @type Number + + */ + + oConfig.addProperty( + + "showdelay", + + { + + value: 0, + + validator: oConfig.checkNumber + + } + + ); + + + + + + /** + + * @config hidedelay + + * @description Number indicating the time (in milliseconds) that should + + * expire before the menu is hidden. + + * @default 0 + + * @type Number + + */ + + oConfig.addProperty( + + "hidedelay", + + { + + value: 0, + + validator: oConfig.checkNumber, + + handler: this.configHideDelay, + + suppressEvent: true + + } + + ); + + + + + + /** + + * @config clicktohide + + * @description Boolean indicating if the menu will automatically be + + * hidden if the user clicks outside of it. + + * @default true + + * @type Boolean + + */ + + oConfig.addProperty( + + "clicktohide", + + { + + value: true, + + validator: oConfig.checkBoolean + + } + + ); + + + + + + /** + + * @config container + + * @description HTML element reference or string specifying the id + + * attribute of the HTML element that the menu's markup should be rendered into. + + * @type HTMLElement|String + + * @default document.body + + */ + + this.cfg.addProperty( + + "container", + + { value:document.body, handler:this.configContainer } + + ); + + + +} + + + +}); // END YAHOO.extend + + + +})(); + /** -* @class The MenuModuleItem class allows you to create and modify an item for a -* MenuModule instance. +* The base class for all menuing containers. +* +* @param {String} p_oElement String specifying the id attribute of the +* <div> element of the menu module. +* @param {String} p_oElement String specifying the id attribute of the +* <select> element to be used as the data source for the +* menu module. +* @param {HTMLDivElement} p_oElement Object +* specifying the <div> element of the menu module. +* @param {HTMLSelectElement} p_oElement Object +* specifying the <select> element to be used as the data +* source for the menu module. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the menu module. See configuration class documentation for +* more details. +* @class MenuModule * @constructor -* @param {String or HTMLElement} p_oObject String or HTMLElement -* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the -* source HTMLElement node. -* @param {Object} p_oConfig The configuration object literal containing -* the configuration for a MenuModuleItem instance. See the configuration -* class documentation for more details. +* @extends YAHOO.widget.Overlay +* @deprecated As of version 0.12, all MenuModule functionality has been +* implemented directly in YAHOO.widget.Menu, making YAHOO.widget.Menu the base +* class for all menuing containers. */ -YAHOO.widget.MenuModuleItem = function(p_oObject, p_oConfig) { +YAHOO.widget.MenuModule = YAHOO.widget.Menu; +(function() { + +var Dom = YAHOO.util.Dom, + Module = YAHOO.widget.Module, + Menu = YAHOO.widget.Menu; + +/** +* Creates an item for a menu. +* +* @param {String} p_oObject String specifying the text of the menu item. +* @param {HTMLLIElement} p_oObject Object specifying +* the <li> element of the menu item. +* @param {HTMLOptGroupElement} p_oObject Object +* specifying the <optgroup> element of the menu item. +* @param {HTMLOptionElement} p_oObject Object +* specifying the <option> element of the menu item. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the menu item. See configuration class documentation +* for more details. +* @class MenuItem +* @constructor +*/ +YAHOO.widget.MenuItem = function(p_oObject, p_oConfig) { + if(p_oObject) { + if(p_oConfig) { + + this.parent = p_oConfig.parent; + this.value = p_oConfig.value; + + } + this.init(p_oObject, p_oConfig); } }; -YAHOO.widget.MenuModuleItem.prototype = { +YAHOO.widget.MenuItem.prototype = { // Constants /** - * Constant representing the path to the image to be used for the submenu - * arrow indicator. + * @property SUBMENU_INDICATOR_IMAGE_PATH + * @description String representing the path to the image to be used for the + * menu item's submenu arrow indicator. + * @default "nt/ic/ut/alt1/menuarorght8_nrm_1.gif" * @final * @type String */ SUBMENU_INDICATOR_IMAGE_PATH: "nt/ic/ut/alt1/menuarorght8_nrm_1.gif", /** - * Constant representing the path to the image to be used for the submenu - * arrow indicator when a MenuModuleItem instance is selected. + * @property SELECTED_SUBMENU_INDICATOR_IMAGE_PATH + * @description String representing the path to the image to be used for the + * submenu arrow indicator when the menu item is selected. + * @default "nt/ic/ut/alt1/menuarorght8_hov_1.gif" * @final * @type String */ SELECTED_SUBMENU_INDICATOR_IMAGE_PATH: "nt/ic/ut/alt1/menuarorght8_hov_1.gif", /** - * Constant representing the path to the image to be used for the submenu - * arrow indicator when a MenuModuleItem instance is disabled. + * @property DISABLED_SUBMENU_INDICATOR_IMAGE_PATH + * @description String representing the path to the image to be used for the + * submenu arrow indicator when the menu item is disabled. + * @default "nt/ic/ut/alt1/menuarorght8_dim_1.gif" * @final * @type String */ DISABLED_SUBMENU_INDICATOR_IMAGE_PATH: "nt/ic/ut/alt1/menuarorght8_dim_1.gif", /** - * Constant representing the alt text for the image to be used for the - * submenu arrow indicator. + * @property COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT + * @description String representing the alt text for the image to be used + * for the submenu arrow indicator. + * @default "Collapsed. Click to expand." * @final * @type String */ COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT: "Collapsed. Click to expand.", /** - * Constant representing the alt text for the image to be used for the - * submenu arrow indicator when the submenu is visible. + * @property EXPANDED_SUBMENU_INDICATOR_ALT_TEXT + * @description String representing the alt text for the image to be used + * for the submenu arrow indicator when the submenu is visible. + * @default "Expanded. Click to collapse." * @final * @type String */ EXPANDED_SUBMENU_INDICATOR_ALT_TEXT: "Expanded. Click to collapse.", /** - * Constant representing the alt text for the image to be used for the - * submenu arrow indicator when a MenuModuleItem instance is disabled. + * @property DISABLED_SUBMENU_INDICATOR_ALT_TEXT + * @description String representing the alt text for the image to be used + * for the submenu arrow indicator when the menu item is disabled. + * @default "Disabled." * @final * @type String */ DISABLED_SUBMENU_INDICATOR_ALT_TEXT: "Disabled.", /** - * Constant representing the CSS class(es) to be applied to the root - * HTMLLIElement of the MenuModuleItem. + * @property CHECKED_IMAGE_PATH + * @description String representing the path to the image to be used for + * the checked state. + * @default "nt/ic/ut/bsc/menuchk8_nrm_1.gif" * @final * @type String */ - CSS_CLASS_NAME: "yuimenuitem", + CHECKED_IMAGE_PATH: "nt/ic/ut/bsc/menuchk8_nrm_1.gif", + /** - * Constant representing the type of menu to instantiate when creating - * submenu instances from parsing the child nodes (either HTMLSelectElement - * or HTMLDivElement) of the item's DOM. The default - * is YAHOO.widget.MenuModule. + * @property SELECTED_CHECKED_IMAGE_PATH + * @description String representing the path to the image to be used for + * the selected checked state. + * @default "nt/ic/ut/bsc/menuchk8_hov_1.gif" * @final - * @type YAHOO.widget.MenuModule + * @type String */ - SUBMENU_TYPE: null, + SELECTED_CHECKED_IMAGE_PATH: "nt/ic/ut/bsc/menuchk8_hov_1.gif", + /** - * Constant representing the type of item to instantiate when - * creating item instances from parsing the child nodes (either - * HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the - * submenu's DOM. - * The default is YAHOO.widget.MenuModuleItem. + * @property DISABLED_CHECKED_IMAGE_PATH + * @description String representing the path to the image to be used for + * the disabled checked state. + * @default "nt/ic/ut/bsc/menuchk8_dim_1.gif" * @final - * @type YAHOO.widget.MenuModuleItem + * @type String */ - SUBMENU_ITEM_TYPE: null, + DISABLED_CHECKED_IMAGE_PATH: "nt/ic/ut/bsc/menuchk8_dim_1.gif", + /** - * Constant representing the prefix path to use for non-secure images - * @type string + * @property CHECKED_IMAGE_ALT_TEXT + * @description String representing the alt text for the image to be used + * for the checked image. + * @default "Checked." + * @final + * @type String */ + CHECKED_IMAGE_ALT_TEXT: "Checked.", + + + /** + * @property DISABLED_CHECKED_IMAGE_ALT_TEXT + * @description String representing the alt text for the image to be used + * for the checked image when the item is disabled. + * @default "Checked. (Item disabled.)" + * @final + * @type String + */ + DISABLED_CHECKED_IMAGE_ALT_TEXT: "Checked. (Item disabled.)", + + /** + * @property CSS_CLASS_NAME + * @description String representing the CSS class(es) to be applied to the + * <li> element of the menu item. + * @default "yuimenuitem" + * @final + * @type String + */ + CSS_CLASS_NAME: "yuimenuitem", + + /** + * @property SUBMENU_TYPE + * @description Object representing the type of menu to instantiate and + * add when parsing the child nodes of the menu item's source HTML element. + * @final + * @type YAHOO.widget.Menu + */ + SUBMENU_TYPE: null, + + /** + * @property IMG_ROOT + * @description String representing the prefix path to use for + * non-secure images. + * @default "http://us.i1.yimg.com/us.yimg.com/i/" + * @type String + */ IMG_ROOT: "http://us.i1.yimg.com/us.yimg.com/i/", /** - * Constant representing the prefix path to use for securely served images - * @type string + * @property IMG_ROOT_SSL + * @description String representing the prefix path to use for securely + * served images. + * @default "https://a248.e.akamai.net/sec.yimg.com/i/" + * @type String */ IMG_ROOT_SSL: "https://a248.e.akamai.net/sec.yimg.com/i/", // Private member variables /** - * Reference to the HTMLAnchorElement of the MenuModuleItem's core internal - * DOM structure. + * @property _oAnchor + * @description Object reference to the menu item's + * <a> element. + * @default null * @private - * @type {HTMLAnchorElement} + * @type HTMLAnchorElement */ _oAnchor: null, /** - * Reference to the text node of the MenuModuleItem's core internal - * DOM structure. + * @property _oText + * @description Object reference to the menu item's text node. + * @default null * @private - * @type {Text} + * @type TextNode */ _oText: null, /** - * Reference to the HTMLElement (<EM<) used to create the optional - * help text for a MenuModuleItem instance. + * @property _oHelpTextEM + * @description Object reference to the menu item's help text + * <em> element. + * @default null * @private - * @type {HTMLElement} + * @type HTMLElement */ _oHelpTextEM: null, /** - * Reference to the submenu for a MenuModuleItem instance. + * @property _oSubmenu + * @description Object reference to the menu item's submenu. + * @default null * @private - * @type {YAHOO.widget.MenuModule} + * @type YAHOO.widget.Menu */ _oSubmenu: null, - /** - * Reference to the Dom utility singleton. + * @property _checkImage + * @description Object reference to the menu item's checkmark image. + * @default null * @private - * @type {YAHOO.util.Dom} + * @type HTMLImageElement */ - _oDom: YAHOO.util.Dom, + _checkImage: null, - /** - * The current state of a MenuModuleItem instance's "mouseover" event - * @private - * @type {Boolean} - */ - _bFiredMouseOverEvent: false, - - - /** - * The current state of a MenuModuleItem instance's "mouseout" event - * @private - * @type {Boolean} - */ - _bFiredMouseOutEvent: false, - // Public properties /** - * The class's constructor function - * @type YAHOO.widget.MenuModuleItem + * @property constructor + * @description Object reference to the menu item's constructor function. + * @default YAHOO.widget.MenuItem + * @type YAHOO.widget.MenuItem */ - constructor: YAHOO.widget.MenuModuleItem, + constructor: YAHOO.widget.MenuItem, /** - * The string representing the image root - * @type string + * @property imageRoot + * @description String representing the root path for all of the menu + * item's images. + * @type String */ imageRoot: null, /** - * Boolean representing whether or not the current browsing context - * is secure (https) - * @type boolean + * @property isSecure + * @description Boolean representing whether or not the current browsing + * context is secure (HTTPS). + * @type Boolean */ - isSecure: YAHOO.widget.Module.prototype.isSecure, + isSecure: Module.prototype.isSecure, /** - * Returns the ordinal position of a MenuModuleItem instance in a group. + * @property index + * @description Number indicating the ordinal position of the menu item in + * its group. + * @default null * @type Number */ index: null, /** - * Returns the index of the group to which a MenuModuleItem instance belongs. + * @property groupIndex + * @description Number indicating the index of the group to which the menu + * item belongs. + * @default null * @type Number */ groupIndex: null, /** - * Returns the parent object for a MenuModuleItem instance. - * @type {YAHOO.widget.MenuModule} + * @property parent + * @description Object reference to the menu item's parent menu. + * @default null + * @type YAHOO.widget.Menu */ parent: null, /** - * Returns the HTMLLIElement for a MenuModuleItem instance. - * @type {HTMLLIElement} + * @property element + * @description Object reference to the menu item's + * <li> element. + * @default HTMLLIElement + * @type HTMLLIElement */ element: null, /** - * Returns the HTMLElement (either HTMLLIElement, HTMLOptGroupElement or - * HTMLOptionElement) used create the MenuModuleItem instance. - * @type {HTMLLIElement/HTMLOptGroupElement/HTMLOptionElement} + * @property srcElement + * @description Object reference to the HTML element (either + * <li>, <optgroup> or + * <option>) used create the menu item. + * @default HTMLLIElement|HTMLOptGroupElement|HTMLOptionElement + * @type HTMLLIElement| + * HTMLOptGroupElement|HTMLOptionElement */ srcElement: null, /** - * Specifies an arbitrary value for a MenuModuleItem instance. - * @type {Object} + * @property value + * @description Object reference to the menu item's value. + * @default null + * @type Object */ value: null, /** - * Reference to the HTMLImageElement used to create the submenu - * indicator for a MenuModuleItem instance. - * @type {HTMLImageElement} + * @property submenuIndicator + * @description Object reference to the <img> element + * used to create the submenu indicator for the menu item. + * @default HTMLImageElement + * @type HTMLImageElement */ submenuIndicator: null, /** - * String representing the browser - * @type string + * @property browser + * @description String representing the browser. + * @type String */ - browser: YAHOO.widget.Module.prototype.browser, + browser: Module.prototype.browser, // Events /** - * Fires when a MenuModuleItem instances's HTMLLIElement is removed from - * it's parent HTMLUListElement node. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @event destroyEvent + * @description Fires when the menu item's <li> + * element is removed from its parent <ul> element. + * @type YAHOO.util.CustomEvent */ destroyEvent: null, /** - * Fires when the mouse has entered a MenuModuleItem instance. Passes + * @event mouseOverEvent + * @description Fires when the mouse has entered the menu item. Passes * back the DOM Event object as an argument. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @type YAHOO.util.CustomEvent */ mouseOverEvent: null, /** - * Fires when the mouse has left a MenuModuleItem instance. Passes back + * @event mouseOutEvent + * @description Fires when the mouse has left the menu item. Passes back * the DOM Event object as an argument. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @type YAHOO.util.CustomEvent */ mouseOutEvent: null, /** - * Fires when the user mouses down on a MenuModuleItem instance. Passes + * @event mouseDownEvent + * @description Fires when the user mouses down on the menu item. Passes * back the DOM Event object as an argument. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @type YAHOO.util.CustomEvent */ mouseDownEvent: null, /** - * Fires when the user releases a mouse button while the mouse is - * over a MenuModuleItem instance. Passes back the DOM Event object as - * an argument. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @event mouseUpEvent + * @description Fires when the user releases a mouse button while the mouse + * is over the menu item. Passes back the DOM Event object as an argument. + * @type YAHOO.util.CustomEvent */ mouseUpEvent: null, /** - * Fires when the user clicks the on a MenuModuleItem instance. Passes + * @event clickEvent + * @description Fires when the user clicks the on the menu item. Passes * back the DOM Event object as an argument. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @type YAHOO.util.CustomEvent */ clickEvent: null, /** - * Fires when the user presses an alphanumeric key. Passes back the - * DOM Event object as an argument. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @event keyPressEvent + * @description Fires when the user presses an alphanumeric key when the + * menu item has focus. Passes back the DOM Event object as an argument. + * @type YAHOO.util.CustomEvent */ keyPressEvent: null, /** - * Fires when the user presses a key. Passes back the DOM Event - * object as an argument. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @event keyDownEvent + * @description Fires when the user presses a key when the menu item has + * focus. Passes back the DOM Event object as an argument. + * @type YAHOO.util.CustomEvent */ keyDownEvent: null, /** - * Fires when the user releases a key. Passes back the DOM Event - * object as an argument. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @event keyUpEvent + * @description Fires when the user releases a key when the menu item has + * focus. Passes back the DOM Event object as an argument. + * @type YAHOO.util.CustomEvent */ keyUpEvent: null, /** - * Fires when a MenuModuleItem instance receives focus. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @event focusEvent + * @description Fires when the menu item receives focus. + * @type YAHOO.util.CustomEvent */ focusEvent: null, /** - * Fires when a MenuModuleItem instance loses the input focus. - * @type {YAHOO.util.CustomEvent} - * @see YAHOO.util.CustomEvent + * @event blurEvent + * @description Fires when the menu item loses the input focus. + * @type YAHOO.util.CustomEvent */ blurEvent: null, /** - * The MenuModuleItem class's initialization method. This method is + * @method init + * @description The MenuItem class's initialization method. This method is * automatically called by the constructor, and sets up all DOM references * for pre-existing markup, and creates required markup if it is not * already present. - * @param {String or HTMLElement} p_oObject String or HTMLElement - * (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the - * source HTMLElement node. - * @param {Object} p_oConfig The configuration object literal containing - * the configuration for a MenuModuleItem instance. See the configuration - * class documentation for more details. + * @param {String} p_oObject String specifying the text of the menu item. + * @param {HTMLLIElement} p_oObject Object specifying + * the <li> element of the menu item. + * @param {HTMLOptGroupElement} p_oObject Object + * specifying the <optgroup> element of the menu item. + * @param {HTMLOptionElement} p_oObject Object + * specifying the <option> element of the menu item. + * @param {Object} p_oConfig Optional. Object literal specifying the + * configuration for the menu item. See configuration class documentation + * for more details. */ init: function(p_oObject, p_oConfig) { this.imageRoot = (this.isSecure) ? this.IMG_ROOT_SSL : this.IMG_ROOT; if(!this.SUBMENU_TYPE) { - this.SUBMENU_TYPE = YAHOO.widget.MenuModule; + this.SUBMENU_TYPE = Menu; } - if(!this.SUBMENU_ITEM_TYPE) { - - this.SUBMENU_ITEM_TYPE = YAHOO.widget.MenuModuleItem; - - } - // Create the config object this.cfg = new YAHOO.util.Config(this); @@ -2645,7 +8038,7 @@ } else if(this._checkDOMNode(p_oObject)) { - switch(p_oObject.tagName) { + switch(p_oObject.tagName.toUpperCase()) { case "OPTION": @@ -2673,10 +8066,10 @@ // Get the anchor node (if it exists) - var oAnchor = this._getFirstElement(p_oObject, "A"); - var sURL = "#"; - var sTarget = null; - var sText = null; + var oAnchor = this._getFirstElement(p_oObject, "A"), + sURL = "#", + sTarget, + sText; // Capture the "text" and/or the "URL" @@ -2722,19 +8115,19 @@ this._oAnchor = oAnchor; - // Check if emphasis has been applied to the MenuModuleItem + // Check if emphasis has been applied to the MenuItem - var oEmphasisNode = this._getFirstElement(oAnchor); - var bEmphasis = false; - var bStrongEmphasis = false; + var oEmphasisNode = this._getFirstElement(oAnchor), + bEmphasis = false, + bStrongEmphasis = false; if(oEmphasisNode) { // Set a reference to the text node this._oText = oEmphasisNode.firstChild; - switch(oEmphasisNode.tagName) { + switch(oEmphasisNode.tagName.toUpperCase()) { case "EM": @@ -2785,7 +8178,7 @@ if(this.element) { - this._oDom.addClass(this.element, this.CSS_CLASS_NAME); + Dom.addClass(this.element, this.CSS_CLASS_NAME); // Create custom events @@ -2803,10 +8196,6 @@ this.focusEvent = new CustomEvent("focusEvent", this); this.blurEvent = new CustomEvent("blurEvent", this); - // Subscribe to custom event - - this.clickEvent.subscribe(this._onMenuModuleItemClick, this, true); - if(p_oConfig) { oConfig.applyConfig(p_oConfig); @@ -2822,12 +8211,16 @@ // Private methods /** - * Returns an HTMLElement's first HTMLElement node + * @method _getFirstElement + * @description Returns an HTML element's first HTML element node. * @private - * @param {HTMLElement} p_oElement The element to be evaluated. - * @param {String} p_sTagName Optional. The tagname of the element. - * @return Returns an HTMLElement node. - * @type Boolean + * @param {HTMLElement} p_oElement Object + * reference specifying the element to be evaluated. + * @param {String} p_sTagName Optional. String specifying the tagname of + * the element to be retrieved. + * @return {HTMLElement} */ _getFirstElement: function(p_oElement, p_sTagName) { @@ -2850,7 +8243,7 @@ if(p_sTagName) { - return (oElement && oElement.tagName == p_sTagName) ? + return (oElement && oElement.tagName.toUpperCase() == p_sTagName) ? oElement : false; } @@ -2860,11 +8253,11 @@ }, /** - * Determines if an object is a string + * @method _checkString + * @description Determines if an object is a string. * @private - * @param {Object} p_oObject The object to be evaluated. - * @return Returns true if the object is a string. - * @type Boolean + * @param {Object} p_oObject Object to be evaluated. + * @return {Boolean} */ _checkString: function(p_oObject) { @@ -2873,11 +8266,11 @@ }, /** - * Determines if an object is an HTMLElement. + * @method _checkDOMNode + * @description Determines if an object is an HTML element. * @private - * @param {Object} p_oObject The object to be evaluated. - * @return Returns true if the object is an HTMLElement. - * @type Boolean + * @param {Object} p_oObject Object to be evaluated. + * @return {Boolean} */ _checkDOMNode: function(p_oObject) { @@ -2886,7 +8279,8 @@ }, /** - * Creates the core DOM structure for a MenuModuleItem instance. + * @method _createRootNodeStructure + * @description Creates the core DOM structure for the menu item. * @private */ _createRootNodeStructure: function () { @@ -2905,155 +8299,118 @@ }, /** - * Iterates the source element's childNodes collection and uses the - * child nodes to instantiate other menus. + * @method _initSubTree + * @description Iterates the source element's childNodes collection and uses + * the child nodes to instantiate other menus. * @private */ _initSubTree: function() { - var Menu = this.SUBMENU_TYPE; - var MenuModuleItem = this.SUBMENU_ITEM_TYPE; - var oSrcEl = this.srcElement; - var oConfig = this.cfg; + var oSrcEl = this.srcElement, + oConfig = this.cfg; if(oSrcEl.childNodes.length > 0) { - var oNode = oSrcEl.firstChild; - var aOptions = []; + if( + this.parent.lazyLoad && + this.parent.srcElement && + this.parent.srcElement.tagName.toUpperCase() == "SELECT" + ) { - do { + oConfig.setProperty( + "submenu", + { id: Dom.generateId(), itemdata: oSrcEl.childNodes } + ); - switch(oNode.tagName) { + } + else { - case "DIV": + var oNode = oSrcEl.firstChild, + aOptions = []; - oConfig.setProperty("submenu", (new Menu(oNode))); + do { - break; + if(oNode && oNode.tagName) { - case "OPTION": + switch(oNode.tagName.toUpperCase()) { - aOptions[aOptions.length] = oNode; + case "DIV": - break; + oConfig.setProperty("submenu", oNode); - } + break; - } - while((oNode = oNode.nextSibling)); + case "OPTION": - var nOptions = aOptions.length; + aOptions[aOptions.length] = oNode; - if(nOptions > 0) { + break; - oConfig.setProperty( - "submenu", - (new Menu(this._oDom.generateId())) - ); + } - for(var n=0; n 0) { - /** - * "click" event handler for a MenuModuleItem - * @private - * @param {String} p_sType The name of the event that was fired. - * @param {Array} p_aArgs Collection of arguments sent when the event - * was fired. - * @param {YAHOO.widget.MenuItem} p_oMenuModuleItem The MenuModule instance - * that fired the event. - */ - _onMenuModuleItemClick: function(p_sType, p_aArgs, p_oMenuModuleItem) { + var oMenu = new this.SUBMENU_TYPE(Dom.generateId()); - var Event = YAHOO.util.Event; - var oEvent = p_aArgs[0]; - var oTarget = Event.getTarget(oEvent); - var oSubmenu = this.cfg.getProperty("submenu"); + oConfig.setProperty("submenu", oMenu); - /* - ACCESSIBILITY FEATURE FOR SCREEN READERS: Expand/collapse the - submenu when the user clicks on the submenu indicator image. - */ + for(var n=0; n 0); + /** + * @method _preloadImage + * @description Preloads an image by creating an image element from the + * specified path and appending the image to the body of the document. + * @private + * @param {String} p_sPath String specifying the path to the image. + */ + _preloadImage: function(p_sPath) { - // Prevent the browser from following links equal to "#" + var sPath = this.imageRoot + p_sPath; - if(oTarget.tagName == "A" && bCurrentPageURL && !bHasTarget) { + if(!document.images[sPath]) { - Event.preventDefault(oEvent); + var oImage = document.createElement("img"); + oImage.src = sPath; + oImage.name = sPath; + oImage.id = sPath; + oImage.style.display = "none"; - } + document.body.appendChild(oImage); - if(oTarget.tagName != "A" && !bCurrentPageURL && !bHasTarget) { - - /* - Follow the URL of the item regardless of whether or - not the user clicked specifically on the - HTMLAnchorElement (<A<) node. - */ - - document.location = sURL; - - } - } }, // Event handlers for configuration properties /** - * Event handler for when the "text" configuration property of - * a MenuModuleItem instance changes. - * @param {String} p_sType The name of the event that was fired. - * @param {Array} p_aArgs Collection of arguments sent when the - * event was fired. - * @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance + * @method configText + * @description Event handler for when the "text" configuration property of + * the menu item changes. + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item * that fired the event. */ configText: function(p_sType, p_aArgs, p_oItem) { @@ -3069,28 +8426,28 @@ }, /** - * Event handler for when the "helptext" configuration property of - * a MenuModuleItem instance changes. - * @param {String} p_sType The name of the event that was fired. - * @param {Array} p_aArgs Collection of arguments sent when the - * event was fired. - * @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance + * @method configHelpText + * @description Event handler for when the "helptext" configuration property + * of the menu item changes. + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item * that fired the event. */ configHelpText: function(p_sType, p_aArgs, p_oItem) { - var me = this; - var Dom = this._oDom; - var oHelpText = p_aArgs[0]; - var oEl = this.element; - var oConfig = this.cfg; - var aNodes = [oEl, this._oAnchor]; - var oImg = this.submenuIndicator; + var me = this, + oHelpText = p_aArgs[0], + oEl = this.element, + oConfig = this.cfg, + aNodes = [oEl, this._oAnchor], + oImg = this.submenuIndicator; /** * Adds the "hashelptext" class to the necessary nodes and refires the - * "selected" and "disabled" configuration events - * @ignore + * "selected" and "disabled" configuration events. + * @private */ function initHelpText() { @@ -3111,8 +8468,8 @@ } /** - * Removes the "hashelptext" class and corresponding DOM element (EM) - * @ignore + * Removes the "hashelptext" class and corresponding DOM element (EM). + * @private */ function removeHelpText() { @@ -3177,12 +8534,13 @@ }, /** - * Event handler for when the "url" configuration property of - * a MenuModuleItem instance changes. - * @param {String} p_sType The name of the event that was fired. - * @param {Array} p_aArgs Collection of arguments sent when the - * event was fired. - * @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance + * @method configURL + * @description Event handler for when the "url" configuration property of + * the menu item changes. + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item * that fired the event. */ configURL: function(p_sType, p_aArgs, p_oItem) { @@ -3200,18 +8558,19 @@ }, /** - * Event handler for when the "target" configuration property of - * a MenuModuleItem instance changes. - * @param {String} p_sType The name of the event that was fired. - * @param {Array} p_aArgs Collection of arguments sent when the - * event was fired. - * @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance + * @method configTarget + * @description Event handler for when the "target" configuration property + * of the menu item changes. + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item * that fired the event. */ configTarget: function(p_sType, p_aArgs, p_oItem) { - var sTarget = p_aArgs[0]; - var oAnchor = this._oAnchor; + var sTarget = p_aArgs[0], + oAnchor = this._oAnchor; if(sTarget && sTarget.length > 0) { @@ -3227,21 +8586,22 @@ }, /** - * Event handler for when the "emphasis" configuration property of - * a MenuModuleItem instance changes. - * @param {String} p_sType The name of the event that was fired. - * @param {Array} p_aArgs Collection of arguments sent when the - * event was fired. - * @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance + * @method configEmphasis + * @description Event handler for when the "emphasis" configuration property + * of the menu item changes. + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item * that fired the event. */ configEmphasis: function(p_sType, p_aArgs, p_oItem) { - var bEmphasis = p_aArgs[0]; - var oAnchor = this._oAnchor; - var oText = this._oText; - var oConfig = this.cfg; - var oEM; + var bEmphasis = p_aArgs[0], + oAnchor = this._oAnchor, + oText = this._oText, + oConfig = this.cfg, + oEM; if(bEmphasis && oConfig.getProperty("strongemphasis")) { @@ -3263,31 +8623,36 @@ oEM = this._getFirstElement(oAnchor, "EM"); - oAnchor.removeChild(oEM); - oAnchor.appendChild(oText); + if(oEM) { + oAnchor.removeChild(oEM); + oAnchor.appendChild(oText); + + } + } } }, /** - * Event handler for when the "strongemphasis" configuration property of - * a MenuModuleItem instance changes. - * @param {String} p_sType The name of the event that was fired. - * @param {Array} p_aArgs Collection of arguments sent when the - * event was fired. - * @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance + * @method configStrongEmphasis + * @description Event handler for when the "strongemphasis" configuration + * property of the menu item changes. + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item * that fired the event. */ configStrongEmphasis: function(p_sType, p_aArgs, p_oItem) { - var bStrongEmphasis = p_aArgs[0]; - var oAnchor = this._oAnchor; - var oText = this._oText; - var oConfig = this.cfg; - var oStrong; + var bStrongEmphasis = p_aArgs[0], + oAnchor = this._oAnchor, + oText = this._oText, + oConfig = this.cfg, + oStrong; if(bStrongEmphasis && oConfig.getProperty("emphasis")) { @@ -3309,42 +8674,142 @@ oStrong = this._getFirstElement(oAnchor, "STRONG"); - oAnchor.removeChild(oStrong); - oAnchor.appendChild(oText); + if(oStrong) { + oAnchor.removeChild(oStrong); + oAnchor.appendChild(oText); + + } + } } }, /** - * Event handler for when the "disabled" configuration property of - * a MenuModuleItem instance changes. - * @param {String} p_sType The name of the event that was fired. - * @param {Array} p_aArgs Collection of arguments sent when the - * event was fired. - * @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance + * @method configChecked + * @description Event handler for when the "checked" configuration property + * of the menu item changes. + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item * that fired the event. */ + configChecked: function(p_sType, p_aArgs, p_oItem) { + + var bChecked = p_aArgs[0], + oEl = this.element, + oConfig = this.cfg, + oImg; + + + if(bChecked) { + + this._preloadImage(this.CHECKED_IMAGE_PATH); + this._preloadImage(this.SELECTED_CHECKED_IMAGE_PATH); + this._preloadImage(this.DISABLED_CHECKED_IMAGE_PATH); + + oImg = document.createElement("img"); + oImg.src = (this.imageRoot + this.CHECKED_IMAGE_PATH); + oImg.alt = this.CHECKED_IMAGE_ALT_TEXT; + + var oSubmenu = this.cfg.getProperty("submenu"); + + if(oSubmenu) { + + oEl.insertBefore(oImg, oSubmenu.element); + + } + else { + + oEl.appendChild(oImg); + + } + + Dom.addClass([oEl, oImg], "checked"); + + this._checkImage = oImg; + + if(oConfig.getProperty("disabled")) { + + oConfig.refireEvent("disabled"); + + } + + if(oConfig.getProperty("selected")) { + + oConfig.refireEvent("selected"); + + } + + } + else { + + oImg = this._checkImage; + + Dom.removeClass([oEl, oImg], "checked"); + + if(oImg) { + + oEl.removeChild(oImg); + + } + + this._checkImage = null; + + } + + }, + + /** + * @method configDisabled + * @description Event handler for when the "disabled" configuration property + * of the menu item changes. + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item + * that fired the event. + */ configDisabled: function(p_sType, p_aArgs, p_oItem) { - var bDisabled = p_aArgs[0]; - var Dom = this._oDom; - var oAnchor = this._oAnchor; - var aNodes = [this.element, oAnchor]; - var oEM = this._oHelpTextEM; - var oConfig = this.cfg; - var oImg = this.submenuIndicator; - var sImageSrc; - var sImageAlt; + var bDisabled = p_aArgs[0], + oAnchor = this._oAnchor, + aNodes = [this.element, oAnchor], + oEM = this._oHelpTextEM, + oConfig = this.cfg, + oImg, + sImgSrc, + sImgAlt; if(oEM) { aNodes[2] = oEM; } + if(this.cfg.getProperty("checked")) { + + sImgAlt = this.CHECKED_IMAGE_ALT_TEXT; + sImgSrc = this.CHECKED_IMAGE_PATH; + oImg = this._checkImage; + + if(bDisabled) { + + sImgAlt = this.DISABLED_CHECKED_IMAGE_ALT_TEXT; + sImgSrc = this.DISABLED_CHECKED_IMAGE_PATH; + + } + + oImg.src = document.images[(this.imageRoot + sImgSrc)].src; + oImg.alt = sImgAlt; + + } + + oImg = this.submenuIndicator; + if(bDisabled) { if(oConfig.getProperty("selected")) { @@ -3357,8 +8822,8 @@ Dom.addClass(aNodes, "disabled"); - sImageSrc = this.DISABLED_SUBMENU_INDICATOR_IMAGE_PATH; - sImageAlt = this.DISABLED_SUBMENU_INDICATOR_ALT_TEXT; + sImgSrc = this.DISABLED_SUBMENU_INDICATOR_IMAGE_PATH; + sImgAlt = this.DISABLED_SUBMENU_INDICATOR_ALT_TEXT; } else { @@ -3367,39 +8832,39 @@ Dom.removeClass(aNodes, "disabled"); - sImageSrc = this.SUBMENU_INDICATOR_IMAGE_PATH; - sImageAlt = this.COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT; + sImgSrc = this.SUBMENU_INDICATOR_IMAGE_PATH; + sImgAlt = this.COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT; } if(oImg) { - oImg.src = this.imageRoot + sImageSrc; - oImg.alt = sImageAlt; + oImg.src = this.imageRoot + sImgSrc; + oImg.alt = sImgAlt; } }, /** - * Event handler for when the "selected" configuration property of - * a MenuModuleItem instance changes. - * @param {String} p_sType The name of the event that was fired. - * @param {Array} p_aArgs Collection of arguments sent when the - * event was fired. - * @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance + * @method configSelected + * @description Event handler for when the "selected" configuration property + * of the menu item changes. + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item * that fired the event. */ configSelected: function(p_sType, p_aArgs, p_oItem) { if(!this.cfg.getProperty("disabled")) { - var Dom = this._oDom; - var bSelected = p_aArgs[0]; - var oEM = this._oHelpTextEM; - var aNodes = [this.element, this._oAnchor]; - var oImg = this.submenuIndicator; - var sImageSrc; + var bSelected = p_aArgs[0], + oEM = this._oHelpTextEM, + aNodes = [this.element, this._oAnchor], + oImg = this.submenuIndicator, + sImgSrc; if(oEM) { @@ -3413,22 +8878,32 @@ } + + if(this.cfg.getProperty("checked")) { + + sImgSrc = this.imageRoot + (bSelected ? + this.SELECTED_CHECKED_IMAGE_PATH : this.CHECKED_IMAGE_PATH); + + this._checkImage.src = document.images[sImgSrc].src; + + } + if(bSelected) { Dom.addClass(aNodes, "selected"); - sImageSrc = this.SELECTED_SUBMENU_INDICATOR_IMAGE_PATH; + sImgSrc = this.SELECTED_SUBMENU_INDICATOR_IMAGE_PATH; } else { Dom.removeClass(aNodes, "selected"); - sImageSrc = this.SUBMENU_INDICATOR_IMAGE_PATH; + sImgSrc = this.SUBMENU_INDICATOR_IMAGE_PATH; } if(oImg) { - oImg.src = document.images[(this.imageRoot + sImageSrc)].src; + oImg.src = document.images[(this.imageRoot + sImgSrc)].src; } @@ -3437,77 +8912,106 @@ }, /** - * Event handler for when the "submenu" configuration property of - * a MenuModuleItem instance changes. - * @param {String} p_sType The name of the event that was fired. - * @param {Array} p_aArgs Collection of arguments sent when the - * event was fired. - * @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance + * @method configSubmenu + * @description Event handler for when the "submenu" configuration property + * of the menu item changes. + * @param {String} p_sType String representing the name of the event that + * was fired. + * @param {Array} p_aArgs Array of arguments sent when the event was fired. + * @param {YAHOO.widget.MenuItem} p_oItem Object representing the menu item * that fired the event. */ configSubmenu: function(p_sType, p_aArgs, p_oItem) { - var Dom = this._oDom; - var oEl = this.element; - var oSubmenu = p_aArgs[0]; - var oImg = this.submenuIndicator; - var oConfig = this.cfg; - var aNodes = [this.element, this._oAnchor]; + var oEl = this.element, + oSubmenu = p_aArgs[0], + oImg = this.submenuIndicator, + oConfig = this.cfg, + aNodes = [this.element, this._oAnchor], + oMenu, + bLazyLoad = this.parent && this.parent.lazyLoad; if(oSubmenu) { - // Set the submenu's parent to this MenuModuleItem instance + if(oSubmenu instanceof Menu) { - oSubmenu.parent = this; + oMenu = oSubmenu; + oMenu.parent = this; + oMenu.lazyLoad = bLazyLoad; - this._oSubmenu = oSubmenu; + } + else if( + typeof oSubmenu == "object" && + oSubmenu.id && + !oSubmenu.nodeType + ) { - if(!oImg) { + var sSubmenuId = oSubmenu.id, + oSubmenuConfig = oSubmenu; - var me = this; + oSubmenuConfig.lazyload = bLazyLoad; + oSubmenuConfig.parent = this; - function preloadImage(p_sPath) { + oMenu = new this.SUBMENU_TYPE(sSubmenuId, oSubmenuConfig); - var sPath = me.imageRoot + p_sPath; + // Set the value of the property to the Menu instance - if(!document.images[sPath]) { + this.cfg.setProperty("submenu", oMenu, true); - var oImage = document.createElement("img"); - oImage.src = sPath; - oImage.name = sPath; - oImage.id = sPath; - oImage.style.display = "none"; + } + else { - document.body.appendChild(oImage); + oMenu = new this.SUBMENU_TYPE( + oSubmenu, + { lazyload: bLazyLoad, parent: this } + ); - } + // Set the value of the property to the Menu instance - } + this.cfg.setProperty("submenu", oMenu, true); - preloadImage(this.SUBMENU_INDICATOR_IMAGE_PATH); - preloadImage(this.SELECTED_SUBMENU_INDICATOR_IMAGE_PATH); - preloadImage(this.DISABLED_SUBMENU_INDICATOR_IMAGE_PATH); + } - oImg = document.createElement("img"); - oImg.src = (this.imageRoot + this.SUBMENU_INDICATOR_IMAGE_PATH); - oImg.alt = this.COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT; + if(oMenu) { - oEl.appendChild(oImg); + this._oSubmenu = oMenu; - this.submenuIndicator = oImg; + if(!oImg) { - Dom.addClass(aNodes, "hassubmenu"); + this._preloadImage(this.SUBMENU_INDICATOR_IMAGE_PATH); + this._preloadImage( + this.SELECTED_SUBMENU_INDICATOR_IMAGE_PATH + ); - if(oConfig.getProperty("disabled")) { + this._preloadImage( + this.DISABLED_SUBMENU_INDICATOR_IMAGE_PATH + ); - oConfig.refireEvent("disabled"); + oImg = document.createElement("img"); - } + oImg.src = + (this.imageRoot + this.SUBMENU_INDICATOR_IMAGE_PATH); - if(oConfig.getProperty("selected")) { + oImg.alt = this.COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT; - oConfig.refireEvent("selected"); + oEl.appendChild(oImg); + this.submenuIndicator = oImg; + + Dom.addClass(aNodes, "hassubmenu"); + + if(oConfig.getProperty("disabled")) { + + oConfig.refireEvent("disabled"); + + } + + if(oConfig.getProperty("selected")) { + + oConfig.refireEvent("selected"); + + } + } } @@ -3536,15 +9040,24 @@ // Public methods /** - * Initializes an item's configurable properties. + * @method initDefaultConfig + * @description Initializes an item's configurable properties. */ initDefaultConfig : function() { - var oConfig = this.cfg; - var CheckBoolean = oConfig.checkBoolean; + var oConfig = this.cfg, + CheckBoolean = oConfig.checkBoolean; // Define the config properties + /** + * @config text + * @description String specifying the text label for the menu item. + * When building a menu from existing HTML the value of this property + * will be interpreted from the menu's markup. + * @default "" + * @type String + */ oConfig.addProperty( "text", { @@ -3555,18 +9068,55 @@ } ); + + /** + * @config helptext + * @description String specifying additional instructional text to + * accompany the text for the nenu item. + * @default null + * @type String| + * HTMLElement + */ oConfig.addProperty("helptext", { handler: this.configHelpText }); + /** + * @config url + * @description String specifying the URL for the menu item's anchor's + * "href" attribute. When building a menu from existing HTML the value + * of this property will be interpreted from the menu's markup. + * @default "#" + * @type String + */ oConfig.addProperty( "url", { value: "#", handler: this.configURL, suppressEvent: true } ); + /** + * @config target + * @description String specifying the value for the "target" attribute + * of the menu item's anchor element. Specifying a target will + * require the user to click directly on the menu item's anchor node in + * order to cause the browser to navigate to the specified URL. + * When building a menu from existing HTML the value of this property + * will be interpreted from the menu's markup. + * @default null + * @type String + */ oConfig.addProperty( "target", { handler: this.configTarget, suppressEvent: true } ); + /** + * @config emphasis + * @description Boolean indicating if the text of the menu item will be + * rendered with emphasis. When building a menu from existing HTML the + * value of this property will be interpreted from the menu's markup. + * @default false + * @type Boolean + */ oConfig.addProperty( "emphasis", { @@ -3577,6 +9127,15 @@ } ); + /** + * @config strongemphasis + * @description Boolean indicating if the text of the menu item will be + * rendered with strong emphasis. When building a menu from existing + * HTML the value of this property will be interpreted from the + * menu's markup. + * @default false + * @type Boolean + */ oConfig.addProperty( "strongemphasis", { @@ -3587,7 +9146,33 @@ } ); + /** + * @config checked + * @description Boolean indicating if the menu item should be rendered + * with a checkmark. + * @default false + * @type Boolean + */ oConfig.addProperty( + "checked", + { + value: false, + handler: this.configChecked, + validator: this.cfg.checkBoolean, + suppressEvent: true, + supercedes:["disabled"] + } + ); + + /** + * @config disabled + * @description Boolean indicating if the menu item should be disabled. + * (Disabled menu items are dimmed and will not respond to user input + * or fire events.) + * @default false + * @type Boolean + */ + oConfig.addProperty( "disabled", { value: false, @@ -3597,6 +9182,13 @@ } ); + /** + * @config selected + * @description Boolean indicating if the menu item should + * be highlighted. + * @default false + * @type Boolean + */ oConfig.addProperty( "selected", { @@ -3607,28 +9199,44 @@ } ); + /** + * @config submenu + * @description Object specifying the submenu to be appended to the + * menu item. The value can be one of the following:
  • Object + * specifying a Menu instance.
  • Object literal specifying the + * menu to be created. Format: { id: [menu id], itemdata: + * [array of values for + * items] }.
  • String specifying the id attribute + * of the <div> element of the menu.
  • + * Object specifying the <div> element of the + * menu.
+ * @default null + * @type Menu|String|Object| + * HTMLElement + */ oConfig.addProperty("submenu", { handler: this.configSubmenu }); }, /** - * Finds the next enabled MenuModuleItem instance in a MenuModule instance - * @return Returns a MenuModuleItem instance. - * @type YAHOO.widget.MenuModuleItem + * @method getNextEnabledSibling + * @description Finds the menu item's next enabled sibling. + * @return YAHOO.widget.MenuItem */ getNextEnabledSibling: function() { - if(this.parent instanceof YAHOO.widget.MenuModule) { + if(this.parent instanceof Menu) { var nGroupIndex = this.groupIndex; /** - * Returns the next item in an array - * @param {p_aArray} An array - * @param {p_nStartIndex} The index to start searching the array - * @ignore - * @return Returns an item in an array - * @type Object + * Finds the next item in an array. + * @private + * @param {p_aArray} Array to search. + * @param {p_nStartIndex} Number indicating the index to + * start searching the array. + * @return {Object} */ function getNextArrayItem(p_aArray, p_nStartIndex) { @@ -3638,8 +9246,8 @@ } - var aItemGroups = this.parent.getItemGroups(); - var oNextItem; + var aItemGroups = this.parent.getItemGroups(), + oNextItem; if(this.index < (aItemGroups[nGroupIndex].length - 1)) { @@ -3667,7 +9275,7 @@ var aNextGroup = getNextArrayItem(aItemGroups, nNextGroupIndex); - // Retrieve the first MenuModuleItem instance in the next group + // Retrieve the first menu item in the next group oNextItem = getNextArrayItem(aNextGroup, 0); @@ -3684,24 +9292,23 @@ }, /** - * Finds the previous enabled MenuModuleItem instance in a - * MenuModule instance - * @return Returns a MenuModuleItem instance. - * @type YAHOO.widget.MenuModuleItem + * @method getPreviousEnabledSibling + * @description Finds the menu item's previous enabled sibling. + * @return {YAHOO.widget.MenuItem} */ getPreviousEnabledSibling: function() { - if(this.parent instanceof YAHOO.widget.MenuModule) { + if(this.parent instanceof Menu) { var nGroupIndex = this.groupIndex; /** * Returns the previous item in an array - * @param {p_aArray} An array - * @param {p_nStartIndex} The index to start searching the array - * @ignore - * @return Returns an item in an array - * @type Object + * @private + * @param {p_aArray} Array to search. + * @param {p_nStartIndex} Number indicating the index to + * start searching the array. + * @return {Object} */ function getPreviousArrayItem(p_aArray, p_nStartIndex) { @@ -3712,11 +9319,11 @@ /** * Get the index of the first item in an array - * @param {p_aArray} An array - * @param {p_nStartIndex} The index to start searching the array - * @ignore - * @return Returns an item in an array - * @type Object + * @private + * @param {p_aArray} Array to search. + * @param {p_nStartIndex} Number indicating the index to + * start searching the array. + * @return {Object} */ function getFirstItemIndex(p_aArray, p_nStartIndex) { @@ -3726,8 +9333,8 @@ } - var aItemGroups = this.parent.getItemGroups(); - var oPreviousItem; + var aItemGroups = this.parent.getItemGroups(), + oPreviousItem; if( this.index > getFirstItemIndex(aItemGroups[nGroupIndex], 0) @@ -3777,15 +9384,29 @@ }, /** - * Causes a MenuModuleItem instance to receive the focus and fires the + * @method focus + * @description Causes the menu item to receive the focus and fires the * focus event. */ focus: function() { - var oParent = this.parent; - var oAnchor = this._oAnchor; - var oActiveItem = oParent.activeItem; + var oParent = this.parent, + oAnchor = this._oAnchor, + oActiveItem = oParent.activeItem; + function setFocus() { + + try { + + oAnchor.focus(); + + } + catch(e) { + + } + + } + if( !this.cfg.getProperty("disabled") && oParent && @@ -3799,16 +9420,24 @@ } - oAnchor.focus(); + /* + Setting focus via a timer fixes a race condition in Firefox, IE + and Opera where the browser viewport jumps as it trys to + position and focus the menu. + */ + window.setTimeout(setFocus, 0); + this.focusEvent.fire(); } }, /** - * Causes a MenuModuleItem instance to lose focus and fires the onblur event. + * @method blur + * @description Causes the menu item to lose focus and fires the + * onblur event. */ blur: function() { @@ -3817,7 +9446,7 @@ if( !this.cfg.getProperty("disabled") && oParent && - this._oDom.getStyle(oParent.element, "visibility") == "visible" + Dom.getStyle(oParent.element, "visibility") == "visible" ) { this._oAnchor.blur(); @@ -3829,15 +9458,26 @@ }, /** - * Removes a MenuModuleItem instance's HTMLLIElement from it's parent - * HTMLUListElement node. + * @method destroy + * @description Removes the menu item's <li> element + * from its parent <ul> element. */ destroy: function() { var oEl = this.element; if(oEl) { + // If the item has a submenu, destroy it first + + var oSubmenu = this.cfg.getProperty("submenu"); + + if(oSubmenu) { + + oSubmenu.destroy(); + + } + // Remove CustomEvent listeners this.mouseOverEvent.unsubscribeAll(); @@ -3868,1269 +9508,881 @@ } + }, + + /** + * @method toString + * @description Returns a string representing the menu item. + * @return {String} + */ + toString: function() { + + return ("MenuItem: " + this.cfg.getProperty("text")); + } }; +})(); + /** -* @class Extends YAHOO.widget.MenuModule to provide a set of default mouse and -* key event behaviors. +* Creates an item for a menu module. +* +* @param {String} p_oObject String specifying the text of the menu module item. +* @param {HTMLLIElement} p_oObject Object specifying the +* <li> element of the menu module item. +* @param {HTMLOptGroupElement} p_oObject Object specifying +* the <optgroup> element of the menu module item. +* @param {HTMLOptionElement} p_oObject Object specifying the +* <option> element of the menu module item. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the menu module item. See configuration class documentation +* for more details. +* @class MenuModuleItem * @constructor -* @extends YAHOO.widget.MenuModule -* @base YAHOO.widget.MenuModule -* @param {String or HTMLElement} p_oElement String id or HTMLElement -* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node. -* @param {Object} p_oConfig Optional. The configuration object literal -* containing the configuration for a Menu instance. See -* configuration class documentation for more details. +* @deprecated As of version 0.12, all MenuModuleItem functionality has been +* implemented directly in YAHOO.widget.MenuItem, making YAHOO.widget.MenuItem +* the base class for all menu items. */ -YAHOO.widget.Menu = function(p_oElement, p_oConfig) { +YAHOO.widget.MenuModuleItem = YAHOO.widget.MenuItem; - YAHOO.widget.Menu.superclass.constructor.call( +/** +* Creates a list of options or commands which are made visible in response to +* an HTML element's "contextmenu" event ("mousedown" for Opera). +* +* @param {String} p_oElement String specifying the id attribute of the +* <div> element of the context menu. +* @param {String} p_oElement String specifying the id attribute of the +* <select> element to be used as the data source for the +* context menu. +* @param {HTMLDivElement} p_oElement Object specifying the +* <div> element of the context menu. +* @param {HTMLSelectElement} p_oElement Object specifying +* the <select> element to be used as the data source for +* the context menu. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the context menu. See configuration class documentation +* for more details. +* @class ContextMenu +* @constructor +* @extends YAHOO.widget.Menu +* @namespace YAHOO.widget +*/ +YAHOO.widget.ContextMenu = function(p_oElement, p_oConfig) { + + YAHOO.widget.ContextMenu.superclass.constructor.call( this, p_oElement, p_oConfig ); }; -YAHOO.extend(YAHOO.widget.Menu, YAHOO.widget.MenuModule); +YAHOO.extend(YAHOO.widget.ContextMenu, YAHOO.widget.Menu, { +// Private properties + /** -* The Menu class's initialization method. This method is automatically -* called by the constructor, and sets up all DOM references for pre-existing -* markup, and creates required markup if it is not already present. -* @param {String or HTMLElement} p_oElement String id or HTMLElement -* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node. -* @param {Object} p_oConfig Optional. The configuration object literal -* containing the configuration for a Menu instance. See -* configuration class documentation for more details. +* @property _oTrigger +* @description Object reference to the current value of the "trigger" +* configuration property. +* @default null +* @private +* @type String|HTMLElement|Array */ -YAHOO.widget.Menu.prototype.init = function(p_oElement, p_oConfig) { +_oTrigger: null, +// Public properties + +/** +* @property contextEventTarget +* @description Object reference for the HTML element that was the target of the +* "contextmenu" DOM event ("mousedown" for Opera) that triggered the display of +* the context menu. +* @default null +* @type HTMLElement +*/ +contextEventTarget: null, + +/** +* @method init +* @description The ContextMenu class's initialization method. This method is +* automatically called by the constructor, and sets up all DOM references for +* pre-existing markup, and creates required markup if it is not already present. +* @param {String} p_oElement String specifying the id attribute of the +* <div> element of the context menu. +* @param {String} p_oElement String specifying the id attribute of the +* <select> element to be used as the data source for +* the context menu. +* @param {HTMLDivElement} p_oElement Object specifying the +* <div> element of the context menu. +* @param {HTMLSelectElement} p_oElement Object specifying +* the <select> element to be used as the data source for +* the context menu. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the context menu. See configuration class documentation +* for more details. +*/ +init: function(p_oElement, p_oConfig) { + if(!this.ITEM_TYPE) { - this.ITEM_TYPE = YAHOO.widget.MenuItem; + this.ITEM_TYPE = YAHOO.widget.ContextMenuItem; } // Call the init of the superclass (YAHOO.widget.Menu) - YAHOO.widget.Menu.superclass.init.call(this, p_oElement); + YAHOO.widget.ContextMenu.superclass.init.call(this, p_oElement); - this.beforeInitEvent.fire(YAHOO.widget.Menu); + this.beforeInitEvent.fire(YAHOO.widget.ContextMenu); - // Add event handlers - - this.showEvent.subscribe(this._onMenuShow, this, true); - this.mouseOverEvent.subscribe(this._onMenuMouseOver, this, true); - this.keyDownEvent.subscribe(this._onMenuKeyDown, this, true); - if(p_oConfig) { this.cfg.applyConfig(p_oConfig, true); } - this.initEvent.fire(YAHOO.widget.Menu); -}; + this.initEvent.fire(YAHOO.widget.ContextMenu); -// Private event handlers +}, +// Private methods + /** -* "show" Custom Event handler for a menu. +* @method _removeEventHandlers +* @description Removes all of the DOM event handlers from the HTML element(s) +* whose "context menu" event ("click" for Opera) trigger the display of +* the context menu. * @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.Menu} p_oMenu The menu that fired the event. */ -YAHOO.widget.Menu.prototype._onMenuShow = +_removeEventHandlers: function() { - function(p_sType, p_aArgs, p_oMenu) { + var Event = YAHOO.util.Event, + oTrigger = this._oTrigger, + bOpera = (this.browser == "opera"); - var oParent = this.parent; + // Remove the event handlers from the trigger(s) - if(oParent && oParent.parent instanceof YAHOO.widget.Menu) { + Event.removeListener( + oTrigger, + (bOpera ? "mousedown" : "contextmenu"), + this._onTriggerContextMenu + ); - var aAlignment = oParent.parent.cfg.getProperty("submenualignment"); + if(bOpera) { - this.cfg.setProperty( - "submenualignment", - [ aAlignment[0], aAlignment[1] ] - ); + Event.removeListener(oTrigger, "click", this._onTriggerClick); - } + } - }; +}, +// Private event handlers + /** -* "mouseover" Custom Event handler for a Menu instance. +* @method _onTriggerClick +* @description "click" event handler for the HTML element(s) identified as the +* "trigger" for the context menu. Used to cancel default behaviors in Opera. * @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.Menu} p_oMenu The Menu instance that fired the event. +* @param {Event} p_oEvent Object representing the DOM event object passed back +* by the event utility (YAHOO.util.Event). +* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context +* menu that is handling the event. */ -YAHOO.widget.Menu.prototype._onMenuMouseOver = +_onTriggerClick: function(p_oEvent, p_oMenu) { - function(p_sType, p_aArgs, p_oMenu) { + if(p_oEvent.ctrlKey) { - /* - If the menu is a submenu, then select the menu's parent - MenuItem instance - */ + YAHOO.util.Event.stopEvent(p_oEvent); - if(this.parent) { + } - this.parent.cfg.setProperty("selected", true); +}, - } - - }; - /** -* "mouseover" Custom Event handler for a Menu instance. +* @method _onTriggerContextMenu +* @description "contextmenu" event handler ("mousedown" for Opera) for the HTML +* element(s) that trigger the display of the context menu. * @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.Menu} p_oMenu The Menu instance that fired the event. +* @param {Event} p_oEvent Object representing the DOM event object passed back +* by the event utility (YAHOO.util.Event). +* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context +* menu that is handling the event. */ -YAHOO.widget.Menu.prototype._onMenuKeyDown = +_onTriggerContextMenu: function(p_oEvent, p_oMenu) { - function(p_sType, p_aArgs, p_oMenu) { + // Hide any other ContextMenu instances that might be visible - if(this.cfg.getProperty("position") == "dynamic") { + YAHOO.widget.MenuManager.hideVisible(); - var oDOMEvent = p_aArgs[0]; - var oParent = this.parent; + var Event = YAHOO.util.Event, + oConfig = this.cfg; - if(oDOMEvent.keyCode == 27) { // Esc key + if(p_oEvent.type == "mousedown" && !p_oEvent.ctrlKey) { - this.hide(); - - // Set focus to the parent MenuItem if one exists - - if(oParent) { - - oParent.focus(); - - if(oParent.parent instanceof YAHOO.widget.Menu) { - - oParent.cfg.setProperty("selected", true); - - } - - YAHOO.util.Event.preventDefault(oDOMEvent); - - } - - } - - } - - }; - - -// Public event handlers - -/** -* Event handler fired when the resize monitor element is resized. -*/ -YAHOO.widget.Menu.prototype.onDomResize = function(e, obj) { - - if(!this._handleResize) { - - this._handleResize = true; return; } + this.contextEventTarget = Event.getTarget(p_oEvent); - var me = this; - var oConfig = this.cfg; + // Position and display the context menu - if(oConfig.getProperty("position") == "dynamic") { + var nX = Event.getPageX(p_oEvent), + nY = Event.getPageY(p_oEvent); - oConfig.setProperty("width", (this._getOffsetWidth() + "px")); + oConfig.applyConfig( { xy:[nX, nY], visible:true } ); + oConfig.fireQueue(); - if(this.parent && oConfig.getProperty("visible")) { - - function align() { - - me.align(); - - } - - window.setTimeout(align, 0); - - } - - } - - YAHOO.widget.Menu.superclass.onDomResize.call(this, e, obj); - -}; - -/** -* @class The MenuItem class allows you to create and modify an item for a -* Menu instance. MenuItem extends YAHOO.widget.MenuModuleItem to provide a -* set of default mouse and key event behaviors. -* @constructor -* @extends YAHOO.widget.MenuModuleItem -* @base YAHOO.widget.MenuModuleItem -* @param {String or HTMLElement} p_oObject String or HTMLElement -* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the -* source HTMLElement node. -* @param {Object} p_oConfig The configuration object literal containing -* the configuration for a MenuItem instance. See the configuration -* class documentation for more details. -*/ -YAHOO.widget.MenuItem = function(p_oObject, p_oConfig) { - - YAHOO.widget.MenuItem.superclass.constructor.call( - this, - p_oObject, - p_oConfig - ); - -}; - -YAHOO.extend(YAHOO.widget.MenuItem, YAHOO.widget.MenuModuleItem); - -/** -* The MenuItem class's initialization method. This method is automatically -* called by the constructor, and sets up all DOM references for -* pre-existing markup, and creates required markup if it is not -* already present. -* @param {String or HTMLElement} p_oObject String or HTMLElement -* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the -* source HTMLElement node. -* @param {Object} p_oConfig The configuration object literal containing -* the configuration for a MenuItem instance. See the configuration -* class documentation for more details. -*/ -YAHOO.widget.MenuItem.prototype.init = function(p_oObject, p_oConfig) { - - if(!this.SUBMENU_TYPE) { - - this.SUBMENU_TYPE = YAHOO.widget.Menu; - - } - - if(!this.SUBMENU_ITEM_TYPE) { - - this.SUBMENU_ITEM_TYPE = YAHOO.widget.MenuItem; - - } - /* - Call the init of the superclass (YAHOO.widget.MenuModuleItem) - Note: We don't pass the user config in here yet - because we only want it executed once, at the lowest - subclass level. + Prevent the browser's default context menu from appearing and + stop the propagation of the "contextmenu" event so that + other ContextMenu instances are not displayed. */ - YAHOO.widget.MenuItem.superclass.init.call(this, p_oObject); + Event.stopEvent(p_oEvent); - // Add event handlers to each "MenuItem" instance +}, - this.keyDownEvent.subscribe(this._onKeyDown, this, true); - this.mouseOverEvent.subscribe(this._onMouseOver, this, true); - this.mouseOutEvent.subscribe(this._onMouseOut, this, true); - this.clickEvent.subscribe(this._onClick, this, true); +// Public methods - var oConfig = this.cfg; - - if(p_oConfig) { - - oConfig.applyConfig(p_oConfig, true); - - } - - oConfig.fireQueue(); - -}; - -// Constants - /** -* Constant representing the path to the image to be used for the checked state. -* @final -* @type String +* @method toString +* @description Returns a string representing the context menu. +* @return {String} */ -YAHOO.widget.MenuItem.prototype.CHECKED_IMAGE_PATH = - "nt/ic/ut/bsc/menuchk8_nrm_1.gif"; +toString: function() { -/** -* Constant representing the path to the image to be used for the selected -* checked state. -* @final -* @type String -*/ -YAHOO.widget.MenuItem.prototype.SELECTED_CHECKED_IMAGE_PATH = - "nt/ic/ut/bsc/menuchk8_hov_1.gif"; + return ("ContextMenu " + this.id); -/** -* Constant representing the path to the image to be used for the disabled -* checked state. -* @final -* @type String -*/ -YAHOO.widget.MenuItem.prototype.DISABLED_CHECKED_IMAGE_PATH = - "nt/ic/ut/bsc/menuchk8_dim_1.gif"; +}, /** -* Constant representing the alt text for the image to be used for the -* checked image. -* @final -* @type String +* @method initDefaultConfig +* @description Initializes the class's configurable properties which can be +* changed using the context menu's Config object ("cfg"). */ -YAHOO.widget.MenuItem.prototype.CHECKED_IMAGE_ALT_TEXT = "Checked."; +initDefaultConfig: function() { -/** -* Constant representing the alt text for the image to be used for the -* checked image when the item is disabled. -* @final -* @type String -*/ -YAHOO.widget.MenuItem.prototype.DISABLED_CHECKED_IMAGE_ALT_TEXT = - "Checked. (Item disabled.)"; + YAHOO.widget.ContextMenu.superclass.initDefaultConfig.call(this); -// Private properties + /** + * @config trigger + * @description The HTML element(s) whose "contextmenu" event ("mousedown" + * for Opera) trigger the display of the context menu. Can be a string + * representing the id attribute of the HTML element, an object reference + * for the HTML element, or an array of strings or HTML element references. + * @default null + * @type String|HTMLElement|Array + */ + this.cfg.addProperty("trigger", { handler: this.configTrigger }); -/** -* Reference to the HTMLImageElement used to create the checked -* indicator for a MenuItem instance. -* @private -* @type {HTMLImageElement} -*/ -YAHOO.widget.MenuItem.prototype._checkImage = null; +}, -// Private event handlers - /** -* "keydown" Custom Event handler for a MenuItem instance. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuItem} p_oMenuModule The MenuModule instance that -* fired the event. +* @method destroy +* @description Removes the context menu's <div> element +* (and accompanying child nodes) from the document. */ -YAHOO.widget.MenuItem.prototype._onKeyDown = +destroy: function() { - function(p_sType, p_aArgs, p_oMenuItem) { + // Remove the DOM event handlers from the current trigger(s) - var Event = YAHOO.util.Event; - var oDOMEvent = p_aArgs[0]; - var oParent = this.parent; - var oConfig = this.cfg; - var oMenuItem; + this._removeEventHandlers(); - switch(oDOMEvent.keyCode) { + // Continue with the superclass implementation of this method - case 38: // Up arrow - case 40: // Down arrow + YAHOO.widget.ContextMenu.superclass.destroy.call(this); - if( - this == oParent.activeItem && - !oConfig.getProperty("selected") - ) { +}, - oConfig.setProperty("selected", true); +// Public event handlers for configuration properties - } - else { - - var oNextItem = (oDOMEvent.keyCode == 38) ? - this.getPreviousEnabledSibling() : - this.getNextEnabledSibling(); - - if(oNextItem) { - - oParent.clearActiveItem(); - - oNextItem.cfg.setProperty("selected", true); - - oNextItem.focus(); - - } - - } - - Event.preventDefault(oDOMEvent); - - break; - - - case 39: // Right arrow - - oParent.clearActiveItem(); - - oConfig.setProperty("selected", true); - - this.focus(); - - var oSubmenu = oConfig.getProperty("submenu"); - - if(oSubmenu) { - - oSubmenu.show(); - oSubmenu.setInitialSelection(); - - } - else if( - YAHOO.widget.MenuBarItem && - oParent.parent && - oParent.parent instanceof YAHOO.widget.MenuBarItem - ) { - - oParent.hide(); - - // Set focus to the parent MenuItem if one exists - - oMenuItem = oParent.parent; - - if(oMenuItem) { - - oMenuItem.focus(); - oMenuItem.cfg.setProperty("selected", true); - - } - - } - - Event.preventDefault(oDOMEvent); - - break; - - - case 37: // Left arrow - - // Only hide if this this is a MenuItem of a submenu - - if(oParent.parent) { - - oParent.hide(); - - // Set focus to the parent MenuItem if one exists - - oMenuItem = oParent.parent; - - if(oMenuItem) { - - oMenuItem.focus(); - oMenuItem.cfg.setProperty("selected", true); - - } - - } - - Event.preventDefault(oDOMEvent); - - break; - - } - - }; - /** -* "mouseover" Custom Event handler for a MenuItem instance. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event +* @method configTrigger +* @description Event handler for when the value of the "trigger" configuration +* property changes. +* @param {String} p_sType String representing the name of the event that * was fired. -* @param {YAHOO.widget.MenuItem} p_oMenuModule The MenuModule instance that -* fired the event. +* @param {Array} p_aArgs Array of arguments sent when the event was fired. +* @param {YAHOO.widget.ContextMenu} p_oMenu Object representing the context +* menu that fired the event. */ -YAHOO.widget.MenuItem.prototype._onMouseOver = +configTrigger: function(p_sType, p_aArgs, p_oMenu) { - function(p_sType, p_aArgs, p_oMenuItem) { + var Event = YAHOO.util.Event, + oTrigger = p_aArgs[0]; - var oParent = this.parent; - var oConfig = this.cfg; - var oActiveItem = oParent.activeItem; + if(oTrigger) { + /* + If there is a current "trigger" - remove the event handlers + from that element(s) before assigning new ones + */ - // Hide any other submenus that might be visible + if(this._oTrigger) { - if(oActiveItem && oActiveItem != this) { + this._removeEventHandlers(); - oParent.clearActiveItem(); - } + this._oTrigger = oTrigger; - // Select and focus the current MenuItem instance + /* + Listen for the "mousedown" event in Opera b/c it does not + support the "contextmenu" event + */ - oConfig.setProperty("selected", true); - this.focus(); + var bOpera = (this.browser == "opera"); + Event.addListener( + oTrigger, + (bOpera ? "mousedown" : "contextmenu"), + this._onTriggerContextMenu, + this, + true + ); - // Show the submenu for this instance + /* + Assign a "click" event handler to the trigger element(s) for + Opera to prevent default browser behaviors. + */ - var oSubmenu = oConfig.getProperty("submenu"); + if(bOpera) { - if(oSubmenu) { + Event.addListener( + oTrigger, + "click", + this._onTriggerClick, + this, + true + ); - oSubmenu.show(); - } - }; + } + else { -/** -* "mouseout" Custom Event handler for a MenuItem instance. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuItem} p_oMenuModule The MenuModule instance that -* fired the event. -*/ -YAHOO.widget.MenuItem.prototype._onMouseOut = + this._removeEventHandlers(); - function(p_sType, p_aArgs, p_oMenuItem) { + } - var oConfig = this.cfg; - var oSubmenu = oConfig.getProperty("submenu"); +} - oConfig.setProperty("selected", false); +}); // END YAHOO.extend - if(oSubmenu) { - - var oDOMEvent = p_aArgs[0]; - var oRelatedTarget = YAHOO.util.Event.getRelatedTarget(oDOMEvent); - - if( - !( - oRelatedTarget == oSubmenu.element || - YAHOO.util.Dom.isAncestor(oSubmenu.element, oRelatedTarget) - ) - ) { - - oSubmenu.hide(); - - } - - } - - }; - /** -* "click" Custom Event handler for a MenuItem instance. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuItem} p_oMenuModule The MenuModule instance that -* fired the event. +* Creates an item for a context menu. +* +* @param {String} p_oObject String specifying the text of the context menu item. +* @param {HTMLLIElement} p_oObject Object specifying the +* <li> element of the context menu item. +* @param {HTMLOptGroupElement} p_oObject Object +* specifying the <optgroup> element of the context +* menu item. +* @param {HTMLOptionElement} p_oObject Object specifying +* the <option> element of the context menu item. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the context menu item. See configuration class +* documentation for more details. +* @class ContextMenuItem +* @constructor +* @extends YAHOO.widget.MenuItem */ -YAHOO.widget.MenuItem.prototype._onClick = +YAHOO.widget.ContextMenuItem = function(p_oObject, p_oConfig) { - function(p_sType, p_aArgs, p_oMenuItem) { + YAHOO.widget.ContextMenuItem.superclass.constructor.call( + this, + p_oObject, + p_oConfig + ); - function findRoot(p_oMenu) { +}; - var oItem = p_oMenu.parent; // The parent MenuItem instance +YAHOO.extend(YAHOO.widget.ContextMenuItem, YAHOO.widget.MenuItem, { - if(oItem) { - - var oParentMenu = oItem.parent; - - if( - oParentMenu && - (oParentMenu instanceof YAHOO.widget.Menu) && - oParentMenu.cfg.getProperty("position") == "dynamic" - ) { - - return findRoot(oParentMenu); - - } - - } - - return p_oMenu; - - } - - - var oRoot = findRoot(this.parent); - var sURL = this.cfg.getProperty("url"); - - if( - (sURL.substr((sURL.length-1),1) == "#") && - oRoot && - oRoot.cfg.getProperty("position") == "dynamic" - ) { - - oRoot.hide(); - - } - - }; - - -// Event handlers for configuration properties - /** -* Event handler for when the "checked" configuration property of -* a MenuItem instance changes. -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the -* event was fired. -* @param {YAHOO.widget.MenuItem} p_oItem The MenuItem instance -* that fired the event. +* @method init +* @description The ContextMenuItem class's initialization method. This method +* is automatically called by the constructor, and sets up all DOM references +* for pre-existing markup, and creates required markup if it is not +* already present. +* @param {String} p_oObject String specifying the text of the context menu item. +* @param {HTMLLIElement} p_oObject Object specifying the +* <li> element of the context menu item. +* @param {HTMLOptGroupElement} p_oObject Object +* specifying the <optgroup> element of the context +* menu item. +* @param {HTMLOptionElement} p_oObject Object specifying +* the <option> element of the context menu item. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the context menu item. See configuration class +* documentation for more details. */ -YAHOO.widget.MenuItem.prototype.configChecked = +init: function(p_oObject, p_oConfig) { - function(p_sType, p_aArgs, p_oItem) { + if(!this.SUBMENU_TYPE) { - var Dom = YAHOO.util.Dom; - var bChecked = p_aArgs[0]; - var oEl = this.element; - var oConfig = this.cfg; - var oImg; + this.SUBMENU_TYPE = YAHOO.widget.ContextMenu; + } - if(bChecked) { + /* + Call the init of the superclass (YAHOO.widget.MenuItem) + Note: We don't pass the user config in here yet + because we only want it executed once, at the lowest + subclass level. + */ - var me = this; + YAHOO.widget.ContextMenuItem.superclass.init.call(this, p_oObject); - function preloadImage(p_sPath) { + var oConfig = this.cfg; - var sPath = me.imageRoot + p_sPath; + if(p_oConfig) { - if(!document.images[sPath]) { + oConfig.applyConfig(p_oConfig, true); - var oImage = document.createElement("img"); - oImage.src = sPath; - oImage.name = sPath; - oImage.id = sPath; - oImage.style.display = "none"; + } - document.body.appendChild(oImage); + oConfig.fireQueue(); - } +}, - } - - preloadImage(this.CHECKED_IMAGE_PATH); - preloadImage(this.SELECTED_CHECKED_IMAGE_PATH); - preloadImage(this.DISABLED_CHECKED_IMAGE_PATH); - - oImg = document.createElement("img"); - oImg.src = (this.imageRoot + this.CHECKED_IMAGE_PATH); - oImg.alt = this.CHECKED_IMAGE_ALT_TEXT; - - var oSubmenu = this.cfg.getProperty("submenu"); - - if(oSubmenu) { - - oEl.insertBefore(oImg, oSubmenu.element); - - } - else { - - oEl.appendChild(oImg); - - } - - Dom.addClass([oEl, oImg], "checked"); - - this._checkImage = oImg; - - if(oConfig.getProperty("disabled")) { - - oConfig.refireEvent("disabled"); - - } - - if(oConfig.getProperty("selected")) { - - oConfig.refireEvent("selected"); - - } - - } - else { - - oImg = this._checkImage; - - Dom.removeClass([oEl, oImg], "checked"); - - if(oImg) { - - oEl.removeChild(oImg); - - } - - this._checkImage = null; - - } - - }; - - -/** -* Event handler for when the "selected" configuration property of -* a MenuItem instance changes. -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the -* event was fired. -* @param {YAHOO.widget.MenuItem} p_oItem The MenuItem instance -* that fired the event. -*/ -YAHOO.widget.MenuItem.prototype.configSelected = - - function(p_sType, p_aArgs, p_oItem) { - - YAHOO.widget.MenuItem.superclass.configSelected.call( - this, p_sType, p_aArgs, p_oItem - ); - - var oConfig = this.cfg; - - if(!oConfig.getProperty("disabled") && oConfig.getProperty("checked")) { - - var bSelected = p_aArgs[0]; - - var sSrc = this.imageRoot + (bSelected ? - this.SELECTED_CHECKED_IMAGE_PATH : this.CHECKED_IMAGE_PATH); - - this._checkImage.src = document.images[sSrc].src; - - } - - }; - -/** -* Event handler for when the "disabled" configuration property of -* a MenuItem instance changes. -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the -* event was fired. -* @param {YAHOO.widget.MenuItem} p_oItem The MenuItem instance -* that fired the event. -*/ -YAHOO.widget.MenuItem.prototype.configDisabled = - - function(p_sType, p_aArgs, p_oItem) { - - YAHOO.widget.MenuItem.superclass.configDisabled.call( - this, p_sType, p_aArgs, p_oItem - ); - - if(this.cfg.getProperty("checked")) { - - var bDisabled = p_aArgs[0]; - var sAlt = this.CHECKED_IMAGE_ALT_TEXT; - var sSrc = this.CHECKED_IMAGE_PATH; - var oImg = this._checkImage; - - if(bDisabled) { - - sAlt = this.DISABLED_CHECKED_IMAGE_ALT_TEXT; - sSrc = this.DISABLED_CHECKED_IMAGE_PATH; - - } - - oImg.src = document.images[(this.imageRoot + sSrc)].src; - oImg.alt = sAlt; - - } - - }; - // Public methods /** -* Initializes the class's configurable properties which can be changed using -* the MenuModule's Config object (cfg). +* @method toString +* @description Returns a string representing the context menu item. +* @return {String} */ -YAHOO.widget.MenuItem.prototype.initDefaultConfig = function() { +toString: function() { - YAHOO.widget.MenuItem.superclass.initDefaultConfig.call(this); + return ("MenuBarItem: " + this.cfg.getProperty("text")); - // Add configuration properties +} - this.cfg.addProperty( - "checked", - { - value: false, - handler: this.configChecked, - validator: this.cfg.checkBoolean, - suppressEvent: true, - supercedes:["disabled"] - } - ); +}); // END YAHOO.extend -}; - /** -* @class Creates a list of options which vary depending on the context in -* which the menu is invoked. +* Horizontal collection of items, each of which can contain a submenu. +* +* @param {String} p_oElement String specifying the id attribute of the +* <div> element of the menu bar. +* @param {String} p_oElement String specifying the id attribute of the +* <select> element to be used as the data source for the +* menu bar. +* @param {HTMLDivElement} p_oElement Object specifying +* the <div> element of the menu bar. +* @param {HTMLSelectElement} p_oElement Object +* specifying the <select> element to be used as the data +* source for the menu bar. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the menu bar. See configuration class documentation for +* more details. +* @class Menubar * @constructor * @extends YAHOO.widget.Menu -* @base YAHOO.widget.Menu -* @param {String or HTMLElement} p_oElement String id or HTMLElement -* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node. -* @param {Object} p_oConfig Optional. The configuration object literal -* containing the configuration for a ContextMenu instance. See -* configuration class documentation for more details. +* @namespace YAHOO.widget */ -YAHOO.widget.ContextMenu = function(p_oElement, p_oConfig) { +YAHOO.widget.MenuBar = function(p_oElement, p_oConfig) { - YAHOO.widget.ContextMenu.superclass.constructor.call( + YAHOO.widget.MenuBar.superclass.constructor.call( this, p_oElement, p_oConfig ); }; -YAHOO.extend(YAHOO.widget.ContextMenu, YAHOO.widget.Menu); +YAHOO.extend(YAHOO.widget.MenuBar, YAHOO.widget.Menu, { -// Private properties - /** -* Array of ContextMenu instances -* @private -* @type {Array} +* @method init +* @description The MenuBar class's initialization method. This method is +* automatically called by the constructor, and sets up all DOM references for +* pre-existing markup, and creates required markup if it is not already present. +* @param {String} p_oElement String specifying the id attribute of the +* <div> element of the menu bar. +* @param {String} p_oElement String specifying the id attribute of the +* <select> element to be used as the data source for the +* menu bar. +* @param {HTMLDivElement} p_oElement Object specifying +* the <div> element of the menu bar. +* @param {HTMLSelectElement} p_oElement Object +* specifying the <select> element to be used as the data +* source for the menu bar. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the menu bar. See configuration class documentation for +* more details. */ -YAHOO.widget.ContextMenu._aMenus = []; +init: function(p_oElement, p_oConfig) { -/** -* The id(s) or element(s) that trigger the display of the ContextMenu instance -* @private -* @type {String/Array/HTMLElement} -*/ -YAHOO.widget.ContextMenu.prototype._oTrigger = null; - -// Public properties - -/** -* Returns the HTMLElement node that was the target of the "contextmenu" -* DOM event. -* @type HTMLElement -*/ -YAHOO.widget.ContextMenu.prototype.contextEventTarget = null; - -/** -* The ContextMenu class's initialization method. This method is automatically -* called by the constructor, and sets up all DOM references for pre-existing -* markup, and creates required markup if it is not already present. -* @param {String or HTMLElement} p_oElement String id or HTMLElement -* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node. -* @param {Object} p_oConfig Optional. The configuration object literal -* containing the configuration for a ContextMenu instance. See -* configuration class documentation for more details. -*/ -YAHOO.widget.ContextMenu.prototype.init = function(p_oElement, p_oConfig) { - if(!this.ITEM_TYPE) { - this.ITEM_TYPE = YAHOO.widget.ContextMenuItem; + this.ITEM_TYPE = YAHOO.widget.MenuBarItem; } // Call the init of the superclass (YAHOO.widget.Menu) - YAHOO.widget.ContextMenu.superclass.init.call(this, p_oElement); + YAHOO.widget.MenuBar.superclass.init.call(this, p_oElement); - this.beforeInitEvent.fire(YAHOO.widget.ContextMenu); + this.beforeInitEvent.fire(YAHOO.widget.MenuBar); if(p_oConfig) { this.cfg.applyConfig(p_oConfig, true); } + this.initEvent.fire(YAHOO.widget.MenuBar); - this.initEvent.fire(YAHOO.widget.ContextMenu); +}, - var aMenus = YAHOO.widget.ContextMenu._aMenus; +// Constants - aMenus[aMenus.length] = this; - -}; - -// Private event handlers - /** -* "click" event handler for the document object. -* @private -* @param {Event} p_oEvent Event object passed back by the -* event utility (YAHOO.util.Event). -* @param {YAHOO.widget.ContextMenu} p_oMenu The ContextMenu instance -* handling the event. +* @property CSS_CLASS_NAME +* @description String representing the CSS class(es) to be applied to the menu +* bar's <div> element. +* @default "yuimenubar" +* @final +* @type String */ -YAHOO.widget.ContextMenu.prototype._onDocumentClick = +CSS_CLASS_NAME: "yuimenubar", - function(p_oEvent, p_oMenu) { +// Protected event handlers - this.hide(); - - }; - /** -* "click" event handler for the HTMLElement node that triggered the event. -* Used to cancel default behaviors in Opera. +* @method _onKeyDown +* @description "keydown" Custom Event handler for the menu bar. * @private -* @param {Event} p_oEvent Event object passed back by the -* event utility (YAHOO.util.Event). -* @param {YAHOO.widget.ContextMenu} p_oMenu The ContextMenu instance -* handling the event. +* @param {String} p_sType String representing the name of the event that +* was fired. +* @param {Array} p_aArgs Array of arguments sent when the event was fired. +* @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar +* that fired the event. */ -YAHOO.widget.ContextMenu.prototype._onTriggerClick = +_onKeyDown: function(p_sType, p_aArgs, p_oMenuBar) { - function(p_oEvent, p_oMenu) { + var Event = YAHOO.util.Event, + oEvent = p_aArgs[0], + oItem = p_aArgs[1], + oSubmenu; - if(p_oEvent.ctrlKey) { + if(oItem && !oItem.cfg.getProperty("disabled")) { - YAHOO.util.Event.stopEvent(p_oEvent); + var oItemCfg = oItem.cfg; - } + switch(oEvent.keyCode) { - }; + case 37: // Left arrow + case 39: // Right arrow -/** -* "contextmenu" event handler ("mousedown" for Opera) for the HTMLElement -* node that triggered the event. -* @private -* @param {Event} p_oEvent Event object passed back by the -* event utility (YAHOO.util.Event). -* @param {YAHOO.widget.ContextMenu} p_oMenu The ContextMenu instance -* handling the event. -*/ -YAHOO.widget.ContextMenu.prototype._onTriggerContextMenu = + if( + oItem == this.activeItem && + !oItemCfg.getProperty("selected") + ) { - function(p_oEvent, p_oMenu) { + oItemCfg.setProperty("selected", true); - var Event = YAHOO.util.Event; - var oConfig = this.cfg; + } + else { - // Hide any other ContextMenu instances that might be visible + var oNextItem = (oEvent.keyCode == 37) ? + oItem.getPreviousEnabledSibling() : + oItem.getNextEnabledSibling(); - var aMenus = YAHOO.widget.ContextMenu._aMenus; - var i = aMenus.length - 1; + if(oNextItem) { - do { + this.clearActiveItem(); - aMenus[i].hide(); + oNextItem.cfg.setProperty("selected", true); - } - while(i--); + if(this.cfg.getProperty("autosubmenudisplay")) { - if(p_oEvent.type == "mousedown" && !p_oEvent.ctrlKey) { + oSubmenu = oNextItem.cfg.getProperty("submenu"); - return; + if(oSubmenu) { - } + oSubmenu.show(); + oSubmenu.activeItem.blur(); + oSubmenu.activeItem = null; - this.contextEventTarget = Event.getTarget(p_oEvent); + } + } - // Position and display the context menu + oNextItem.focus(); - var nX = Event.getPageX(p_oEvent); - var nY = Event.getPageY(p_oEvent); + } + } - oConfig.applyConfig( { xy:[nX, nY], visible:true } ); - oConfig.fireQueue(); + Event.preventDefault(oEvent); + break; - /* - Prevent the browser's default context menu from appearing and - stop the propagation of the "contextmenu" event so that - other ContextMenu instances are no displayed. - */ + case 40: // Down arrow - Event.stopEvent(p_oEvent); + if(this.activeItem != oItem) { - }; + this.clearActiveItem(); -// Public methods + oItemCfg.setProperty("selected", true); + oItem.focus(); -/** -* Initializes the class's configurable properties which can be changed using -* a ContextMenu instance's Config object (cfg). -*/ -YAHOO.widget.ContextMenu.prototype.initDefaultConfig = function() { + } - YAHOO.widget.ContextMenu.superclass.initDefaultConfig.call(this); + oSubmenu = oItemCfg.getProperty("submenu"); - // Add a configuration property + if(oSubmenu) { - this.cfg.addProperty("trigger", { handler: this.configTrigger }); + if(oSubmenu.cfg.getProperty("visible")) { -}; + oSubmenu.setInitialSelection(); + oSubmenu.setInitialFocus(); -// Event handlers for configuration properties + } + else { -/** -* Event handler for when the "trigger" configuration property of -* a MenuItem instance. -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the -* event was fired. -* @param {YAHOO.widget.ContextMenu} p_oMenu The ContextMenu that instance fired -* the event. -*/ -YAHOO.widget.ContextMenu.prototype.configTrigger = + oSubmenu.show(); - function(p_sType, p_aArgs, p_oMenu) { + } - var Event = YAHOO.util.Event; - var oTrigger = p_aArgs[0]; + } - if(oTrigger) { + Event.preventDefault(oEvent); + break; - /* - If there is a current "trigger" - remove the event handlers - from that element(s) before assigning new ones - */ - if(this._oTrigger) { + } - Event.purgeElement(this._oTrigger); + } - } + if(oEvent.keyCode == 27 && this.activeItem) { // Esc key - this._oTrigger = oTrigger; + oSubmenu = this.activeItem.cfg.getProperty("submenu"); - /* - Listen for the "mousedown" event in Opera b/c it does not - support the "contextmenu" event - */ + if(oSubmenu && oSubmenu.cfg.getProperty("visible")) { - var bOpera = (this.browser == "opera"); + oSubmenu.hide(); + this.activeItem.focus(); - Event.addListener( - oTrigger, - (bOpera ? "mousedown" : "contextmenu"), - this._onTriggerContextMenu, - this, - true - ); + } + else { + this.activeItem.cfg.setProperty("selected", false); + this.activeItem.blur(); - /* - Assign a "click" event handler to the trigger element(s) for - Opera to prevent default browser behaviors. - */ + } - if(bOpera) { + Event.preventDefault(oEvent); - Event.addListener( - oTrigger, - "click", - this._onTriggerClick, - this, - true - ); + } - } +}, - - // Assign a "mousedown" event handler to the document - - Event.addListener( - document, - "click", - this._onDocumentClick, - this, - true - ); - - } - - }; - /** -* @class Creates an item for a context menu instance. -* @constructor -* @extends YAHOO.widget.MenuItem -* @base YAHOO.widget.MenuItem -* @param {String or HTMLElement} p_oObject String or HTMLElement -* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the -* source HTMLElement node. -* @param {Object} p_oConfig The configuration object literal containing -* the configuration for a ContextMenuItem instance. See the configuration -* class documentation for more details. +* @method _onClick +* @description "click" event handler for the menu bar. +* @protected +* @param {String} p_sType String representing the name of the event that +* was fired. +* @param {Array} p_aArgs Array of arguments sent when the event was fired. +* @param {YAHOO.widget.MenuBar} p_oMenuBar Object representing the menu bar +* that fired the event. */ -YAHOO.widget.ContextMenuItem = function(p_oObject, p_oConfig) { +_onClick: function(p_sType, p_aArgs, p_oMenuBar) { - YAHOO.widget.ContextMenuItem.superclass.constructor.call( + YAHOO.widget.MenuBar.superclass._onClick.call( this, - p_oObject, - p_oConfig + p_sType, + p_aArgs, + p_oMenuBar ); -}; + var oItem = p_aArgs[1]; -YAHOO.extend(YAHOO.widget.ContextMenuItem, YAHOO.widget.MenuItem); + if(oItem && !oItem.cfg.getProperty("disabled")) { -/** -* The ContextMenuItem class's initialization method. This method is -* automatically called by the constructor, and sets up all DOM references for -* pre-existing markup, and creates required markup if it is not -* already present. -* @param {String or HTMLElement} p_oObject String or HTMLElement -* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the -* source HTMLElement node. -* @param {Object} p_oConfig The configuration object literal containing -* the configuration for a ContextMenuItem instance. See the configuration -* class documentation for more details. -*/ -YAHOO.widget.ContextMenuItem.prototype.init = + var Event = YAHOO.util.Event, + Dom = YAHOO.util.Dom, - function(p_oObject, p_oConfig) { + oEvent = p_aArgs[0], + oTarget = Event.getTarget(oEvent), - if(!this.SUBMENU_TYPE) { + oActiveItem = this.activeItem, + oConfig = this.cfg; - this.SUBMENU_TYPE = YAHOO.widget.ContextMenu; + // Hide any other submenus that might be visible + if(oActiveItem && oActiveItem != oItem) { + + this.clearActiveItem(); + } - if(!this.SUBMENU_ITEM_TYPE) { - this.SUBMENU_ITEM_TYPE = YAHOO.widget.ContextMenuItem; + // Select and focus the current item - } + oItem.cfg.setProperty("selected", true); + oItem.focus(); - /* - Call the init of the superclass (YAHOO.widget.MenuItem) - Note: We don't pass the user config in here yet - because we only want it executed once, at the lowest - subclass level. - */ + // Show the submenu for the item - YAHOO.widget.ContextMenuItem.superclass.init.call(this, p_oObject); + var oSubmenu = oItem.cfg.getProperty("submenu"); - var oConfig = this.cfg; + if(oSubmenu && oTarget != oItem.submenuIndicator) { - if(p_oConfig) { + if(oSubmenu.cfg.getProperty("visible")) { - oConfig.applyConfig(p_oConfig, true); + oSubmenu.hide(); - } + } + else { - oConfig.fireQueue(); + oSubmenu.show(); - }; + } -/** -* @class Horizontal collection of items, each of which can contain a submenu. -* Extends YAHOO.widget.MenuModule to provide a set of default mouse and -* key event behaviors. -* @constructor -* @extends YAHOO.widget.MenuModule -* @base YAHOO.widget.MenuModule -* @param {String or HTMLElement} p_oElement String id or HTMLElement -* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node. -* @param {Object} p_oConfig Optional. The configuration object literal -* containing the configuration for a MenuBar instance. See -* configuration class documentation for more details. -*/ -YAHOO.widget.MenuBar = function(p_oElement, p_oConfig) { + } - YAHOO.widget.MenuBar.superclass.constructor.call( - this, - p_oElement, - p_oConfig - ); + } -}; +}, -YAHOO.extend(YAHOO.widget.MenuBar, YAHOO.widget.MenuModule); +// Public methods /** -* The MenuBar class's initialization method. This method is automatically -* called by the constructor, and sets up all DOM references for pre-existing -* markup, and creates required markup if it is not already present. -* @param {String or HTMLElement} p_oElement String id or HTMLElement -* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node. -* @param {Object} p_oConfig Optional. The configuration object literal -* containing the configuration for a MenuBar instance. See -* configuration class documentation for more details. +* @method toString +* @description Returns a string representing the menu bar. +* @return {String} */ -YAHOO.widget.MenuBar.prototype.init = function(p_oElement, p_oConfig) { +toString: function() { - if(!this.ITEM_TYPE) { + return ("MenuBar " + this.id); - this.ITEM_TYPE = YAHOO.widget.MenuBarItem; +}, - } +/** +* @description Initializes the class's configurable properties which can be +* changed using the menu bar's Config object ("cfg"). +* @method initDefaultConfig +*/ +initDefaultConfig: function() { - // Call the init of the superclass (YAHOO.widget.MenuModule) + YAHOO.widget.MenuBar.superclass.initDefaultConfig.call(this); - YAHOO.widget.MenuBar.superclass.init.call(this, p_oElement); - - this.beforeInitEvent.fire(YAHOO.widget.MenuBar); - var oConfig = this.cfg; + // Add configuration properties + /* Set the default value for the "position" configuration property - to "static" + to "static" by re-adding the property. */ - if(!p_oConfig || (p_oConfig && !p_oConfig.position)) { - oConfig.queueProperty("position", "static"); + /** + * @config position + * @description String indicating how a menu bar should be positioned on the + * screen. Possible values are "static" and "dynamic." Static menu bars + * are visible by default and reside in the normal flow of the document + * (CSS position: static). Dynamic menu bars are hidden by default, reside + * out of the normal flow of the document (CSS position: absolute), and can + * overlay other elements on the screen. + * @default static + * @type String + */ + oConfig.addProperty( + "position", + { + value: "static", + handler: this.configPosition, + validator: this._checkPosition, + supercedes: ["visible"] + } + ); - } - /* Set the default value for the "submenualignment" configuration property - to "tl" and "bl" + to ["tl","bl"] by re-adding the property. */ - if(!p_oConfig || (p_oConfig && !p_oConfig.submenualignment)) { - oConfig.queueProperty("submenualignment", ["tl","bl"]); + /** + * @config submenualignment + * @description Array defining how submenus should be aligned to their + * parent menu bar item. The format is: [itemCorner, submenuCorner]. + * @default ["tl","bl"] + * @type Array + */ + oConfig.addProperty("submenualignment", { value: ["tl","bl"] } ); - } + /* + Change the default value for the "autosubmenudisplay" configuration + property to "false" by re-adding the property. + */ - if(p_oConfig) { + /** + * @config autosubmenudisplay + * @description Boolean indicating if submenus are automatically made + * visible when the user mouses over the menu bar's items. + * @default false + * @type Boolean + */ + oConfig.addProperty( + "autosubmenudisplay", + { value: false, validator: oConfig.checkBoolean } + ); - oConfig.applyConfig(p_oConfig, true); +} - } +}); // END YAHOO.extend - this.initEvent.fire(YAHOO.widget.MenuBar); - -}; - -// Constants - /** -* Constant representing the CSS class(es) to be applied to the root -* HTMLDivElement of the MenuBar instance. -* @final -* @type String -*/ -YAHOO.widget.MenuBar.prototype.CSS_CLASS_NAME = "yuimenubar"; - -/** -* @class The MenuBarItem class allows you to create and modify an item for a -* MenuBar instance. MenuBarItem extends YAHOO.widget.MenuModuleItem to provide -* a set of default mouse and key event behaviors. +* Creates an item for a menu bar. +* +* @param {String} p_oObject String specifying the text of the menu bar item. +* @param {HTMLLIElement} p_oObject Object specifying the +* <li> element of the menu bar item. +* @param {HTMLOptGroupElement} p_oObject Object +* specifying the <optgroup> element of the menu bar item. +* @param {HTMLOptionElement} p_oObject Object specifying +* the <option> element of the menu bar item. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the menu bar item. See configuration class documentation +* for more details. +* @class MenuBarItem * @constructor -* @extends YAHOO.widget.MenuModuleItem -* @base YAHOO.widget.MenuModuleItem -* @param {String or HTMLElement} p_oObject String or HTMLElement -* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the -* source HTMLElement node. -* @param {Object} p_oConfig The configuration object literal containing -* the configuration for a MenuBarItem instance. See the configuration -* class documentation for more details. +* @extends YAHOO.widget.MenuItem */ YAHOO.widget.MenuBarItem = function(p_oObject, p_oConfig) { @@ -5142,47 +10394,44 @@ }; -YAHOO.extend(YAHOO.widget.MenuBarItem, YAHOO.widget.MenuModuleItem); +YAHOO.extend(YAHOO.widget.MenuBarItem, YAHOO.widget.MenuItem, { /** -* The MenuBarItem class's initialization method. This method is automatically -* called by the constructor, and sets up all DOM references for -* pre-existing markup, and creates required markup if it is not -* already present. -* @param {String or HTMLElement} p_oObject String or HTMLElement -* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the -* source HTMLElement node. -* @param {Object} p_oConfig The configuration object literal containing -* the configuration for a MenuBarItem instance. See the configuration -* class documentation for more details. +* @method init +* @description The MenuBarItem class's initialization method. This method is +* automatically called by the constructor, and sets up all DOM references for +* pre-existing markup, and creates required markup if it is not already present. +* @param {String} p_oObject String specifying the text of the menu bar item. +* @param {HTMLLIElement} p_oObject Object specifying the +* <li> element of the menu bar item. +* @param {HTMLOptGroupElement} p_oObject Object +* specifying the <optgroup> element of the menu bar item. +* @param {HTMLOptionElement} p_oObject Object specifying +* the <option> element of the menu bar item. +* @param {Object} p_oConfig Optional. Object literal specifying the +* configuration for the menu bar item. See configuration class documentation +* for more details. */ -YAHOO.widget.MenuBarItem.prototype.init = function(p_oObject, p_oConfig) { +init: function(p_oObject, p_oConfig) { if(!this.SUBMENU_TYPE) { this.SUBMENU_TYPE = YAHOO.widget.Menu; } - if(!this.SUBMENU_ITEM_TYPE) { - - this.SUBMENU_ITEM_TYPE = YAHOO.widget.MenuItem; - - } - /* - Call the init of the superclass (YAHOO.widget.MenuModuleItem) + Call the init of the superclass (YAHOO.widget.MenuItem) Note: We don't pass the user config in here yet because we only want it executed once, at the lowest subclass level. */ YAHOO.widget.MenuBarItem.superclass.init.call(this, p_oObject); - // Add event handlers to each "MenuBarItem" instance - - this.keyDownEvent.subscribe(this._onKeyDown, this, true); - var oConfig = this.cfg; if(p_oConfig) { @@ -5193,121 +10442,61 @@ oConfig.fireQueue(); -}; +}, // Constants /** -* Constant representing the CSS class(es) to be applied to the root -* HTMLLIElement of the MenuBarItem. +* @property CSS_CLASS_NAME +* @description String representing the CSS class(es) to be applied to the +* <li> element of the menu bar item. +* @default "yuimenubaritem" * @final * @type String */ -YAHOO.widget.MenuBarItem.prototype.CSS_CLASS_NAME = "yuimenubaritem"; +CSS_CLASS_NAME: "yuimenubaritem", /** -* Constant representing the path to the image to be used for the submenu -* arrow indicator. +* @property SUBMENU_INDICATOR_IMAGE_PATH +* @description String representing the path to the image to be used for the +* menu bar item's submenu arrow indicator. +* @default "nt/ic/ut/alt1/menuarodwn8_nrm_1.gif" * @final * @type String */ -YAHOO.widget.MenuBarItem.prototype.SUBMENU_INDICATOR_IMAGE_PATH = - "nt/ic/ut/alt1/menuarodwn8_nrm_1.gif"; +SUBMENU_INDICATOR_IMAGE_PATH: "nt/ic/ut/alt1/menuarodwn8_nrm_1.gif", /** -* Constant representing the path to the image to be used for the submenu -* arrow indicator when a MenuBarItem instance is selected. +* @property SELECTED_SUBMENU_INDICATOR_IMAGE_PATH +* @description String representing the path to the image to be used for the +* submenu arrow indicator when the menu bar item is selected. +* @default "nt/ic/ut/alt1/menuarodwn8_hov_1.gif" * @final * @type String */ -YAHOO.widget.MenuBarItem.prototype.SELECTED_SUBMENU_INDICATOR_IMAGE_PATH = - "nt/ic/ut/alt1/menuarodwn8_hov_1.gif"; +SELECTED_SUBMENU_INDICATOR_IMAGE_PATH: "nt/ic/ut/alt1/menuarodwn8_hov_1.gif", /** -* Constant representing the path to the image to be used for the submenu -* arrow indicator when a MenuBarItem instance is disabled. +* @property DISABLED_SUBMENU_INDICATOR_IMAGE_PATH +* @description String representing the path to the image to be used for the +* submenu arrow indicator when the menu bar item is disabled. +* @default "nt/ic/ut/alt1/menuarodwn8_dim_1.gif" * @final * @type String */ -YAHOO.widget.MenuBarItem.prototype.DISABLED_SUBMENU_INDICATOR_IMAGE_PATH = - "nt/ic/ut/alt1/menuarodwn8_dim_1.gif"; +DISABLED_SUBMENU_INDICATOR_IMAGE_PATH: "nt/ic/ut/alt1/menuarodwn8_dim_1.gif", -// Private event handlers +// Public methods /** -* "keydown" Custom Event handler for a MenuBarItem instance. -* @private -* @param {String} p_sType The name of the event that was fired. -* @param {Array} p_aArgs Collection of arguments sent when the event -* was fired. -* @param {YAHOO.widget.MenuBarItem} p_oMenuModule The MenuModule instance that -* fired the event. +* @method toString +* @description Returns a string representing the menu bar item. +* @return {String} */ -YAHOO.widget.MenuBarItem.prototype._onKeyDown = +toString: function() { - function(p_sType, p_aArgs, p_oMenuItem) { + return ("MenuBarItem: " + this.cfg.getProperty("text")); - var Event = YAHOO.util.Event; - var oDOMEvent = p_aArgs[0]; - var oConfig = this.cfg; - var oParent = this.parent; +} - switch(oDOMEvent.keyCode) { - - case 37: // Left arrow - case 39: // Right arrow - - if( - this == oParent.activeItem && - !oConfig.getProperty("selected") - ) { - - oConfig.setProperty("selected", true); - - } - else { - - var oNextItem = (oDOMEvent.keyCode == 37) ? - this.getPreviousEnabledSibling() : - this.getNextEnabledSibling(); - - if(oNextItem) { - - oParent.clearActiveItem(); - - oNextItem.cfg.setProperty("selected", true); - - oNextItem.focus(); - - } - - } - - Event.preventDefault(oDOMEvent); - - break; - - case 40: // Down arrow - - oParent.clearActiveItem(); - - oConfig.setProperty("selected", true); - - this.focus(); - - var oSubmenu = oConfig.getProperty("submenu"); - - if(oSubmenu) { - - oSubmenu.show(); - oSubmenu.setInitialSelection(); - - } - - Event.preventDefault(oDOMEvent); - - break; - - } - - }; \ No newline at end of file +}); // END YAHOO.extend \ No newline at end of file