Index: openacs-4/packages/ajaxhelper/www/resources/yui/menu/menu-debug.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/yui/menu/menu-debug.js,v diff -u -r1.3 -r1.4 --- openacs-4/packages/ajaxhelper/www/resources/yui/menu/menu-debug.js 8 Sep 2007 14:22:07 -0000 1.3 +++ openacs-4/packages/ajaxhelper/www/resources/yui/menu/menu-debug.js 9 Apr 2009 23:15:49 -0000 1.4 @@ -1,8 +1,8 @@ /* -Copyright (c) 2007, Yahoo! Inc. All rights reserved. +Copyright (c) 2009, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt -version: 2.3.0 +version: 2.7.0 */ @@ -14,7 +14,6 @@ * context menus, or application-style menu bars with just a small amount of * scripting.
The Menu family of controls features:
*<div>
element.
-* @private
-*/
-_getOffsetWidth: function () {
-
- var oClone = this.element.cloneNode(true);
-
- Dom.removeClass(oClone, "visible");
-
- Dom.setStyle(oClone, "width", "");
-
- document.body.appendChild(oClone);
-
- var sWidth = oClone.offsetWidth;
-
- document.body.removeChild(oClone);
-
- return sWidth;
-
-},
-
-
-/**
-* @method _setWidth
-* @description Sets the width of the menu's root <div>
-* element to its offsetWidth.
-* @private
-*/
-_setWidth: function () {
-
- var oElement = this.element,
- bVisible = false,
- sWidth;
-
- if (oElement.parentNode.tagName.toUpperCase() == "BODY") {
-
- if (YAHOO.env.ua.opera) {
-
- sWidth = this._getOffsetWidth();
-
- }
- else {
-
- if (Dom.hasClass(oElement, "visible")) {
-
- bVisible = true;
-
- Dom.removeClass(oElement, "visible");
-
- }
-
- Dom.setStyle(oElement, "width", "auto");
-
- sWidth = oElement.offsetWidth;
-
- }
-
- }
- else {
-
- sWidth = this._getOffsetWidth();
-
- }
-
- this.cfg.setProperty("width", (sWidth + "px"));
-
-
- if (bVisible) {
-
- Dom.addClass(oElement, "visible");
-
- }
-
-},
-
-
-/**
-* @method _onWidthChange
-* @description Change event handler for the the menu's "width" configuration
-* property.
-* @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.
-*/
-_onWidthChange: function (p_sType, p_aArgs) {
-
- var sWidth = p_aArgs[0];
-
- if (sWidth && !this._hasSetWidthHandlers) {
-
- this.itemAddedEvent.subscribe(this._setWidth);
- this.itemRemovedEvent.subscribe(this._setWidth);
-
- this._hasSetWidthHandlers = true;
-
- }
- else if (this._hasSetWidthHandlers) {
-
- this.itemAddedEvent.unsubscribe(this._setWidth);
- this.itemRemovedEvent.unsubscribe(this._setWidth);
-
- this._hasSetWidthHandlers = false;
-
- }
-
-},
-
-
-/**
* @method _onVisibleChange
* @description Change event handler for the the menu's "visible" configuration
* property.
@@ -2319,12 +2406,12 @@
if (bVisible) {
- Dom.addClass(this.element, "visible");
+ Dom.addClass(this.element, _VISIBLE);
}
else {
- Dom.removeClass(this.element, "visible");
+ Dom.removeClass(this.element, _VISIBLE);
}
@@ -2338,11 +2425,11 @@
*/
_cancelHideDelay: function () {
- var oRoot = this.getRoot();
+ var oTimer = this.getRoot()._hideDelayTimer;
- if (oRoot._nHideDelayId) {
+ if (oTimer) {
- window.clearTimeout(oRoot._nHideDelayId);
+ oTimer.cancel();
}
@@ -2359,30 +2446,31 @@
this._cancelHideDelay();
- var oRoot = this.getRoot(),
- me = this;
-
- function hideMenu() {
+ var oRoot = this.getRoot();
+
+ oRoot._hideDelayTimer = Lang.later(oRoot.cfg.getProperty(_HIDE_DELAY), this, function () {
if (oRoot.activeItem) {
+ if (oRoot.hasFocus()) {
+
+ oRoot.activeItem.focus();
+
+ }
+
oRoot.clearActiveItem();
}
- if (oRoot == me && !(me instanceof YAHOO.widget.MenuBar) &&
- me.cfg.getProperty("position") == "dynamic") {
+ if (oRoot == this && !(this instanceof YAHOO.widget.MenuBar) &&
+ this.cfg.getProperty(_POSITION) == _DYNAMIC) {
- me.hide();
+ this.hide();
}
- }
+ });
-
- oRoot._nHideDelayId =
- window.setTimeout(hideMenu, oRoot.cfg.getProperty("hidedelay"));
-
},
@@ -2393,47 +2481,18 @@
*/
_cancelShowDelay: function () {
- var oRoot = this.getRoot();
+ var oTimer = this.getRoot()._showDelayTimer;
- if (oRoot._nShowDelayId) {
+ if (oTimer) {
- window.clearTimeout(oRoot._nShowDelayId);
+ oTimer.cancel();
}
},
/**
-* @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() {
-
- if (p_oMenu.parent.cfg.getProperty("selected")) {
-
- p_oMenu.show();
-
- }
-
- }
-
-
- oRoot._nShowDelayId =
- window.setTimeout(showMenu, oRoot.cfg.getProperty("showdelay"));
-
-},
-
-
-/**
* @method _execSubmenuHideDelay
* @description Hides a submenu after the number of milliseconds specified by
* the "submenuhidedelay" configuration property have ellapsed.
@@ -2447,27 +2506,25 @@
*/
_execSubmenuHideDelay: function (p_oSubmenu, p_nMouseX, p_nHideDelay) {
- var me = this;
+ p_oSubmenu._submenuHideDelayTimer = Lang.later(50, this, function () {
- p_oSubmenu._nSubmenuHideDelayId = window.setTimeout(function () {
+ if (this._nCurrentMouseX > (p_nMouseX + 10)) {
- if (me._nCurrentMouseX > (p_nMouseX + 10)) {
-
- p_oSubmenu._nSubmenuHideDelayId = window.setTimeout(function () {
+ p_oSubmenu._submenuHideDelayTimer = Lang.later(p_nHideDelay, p_oSubmenu, function () {
- p_oSubmenu.hide();
+ this.hide();
- }, p_nHideDelay);
+ });
}
else {
p_oSubmenu.hide();
}
+
+ });
- }, 50);
-
},
@@ -2484,7 +2541,7 @@
if (!this._bHeaderDisabled) {
- Dom.addClass(this.header, "topscrollbar_disabled");
+ Dom.addClass(this.header, _TOP_SCROLLBAR_DISABLED);
this._bHeaderDisabled = true;
}
@@ -2501,7 +2558,7 @@
if (!this._bFooterDisabled) {
- Dom.addClass(this.footer, "bottomscrollbar_disabled");
+ Dom.addClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
this._bFooterDisabled = true;
}
@@ -2518,7 +2575,7 @@
if (this._bHeaderDisabled) {
- Dom.removeClass(this.header, "topscrollbar_disabled");
+ Dom.removeClass(this.header, _TOP_SCROLLBAR_DISABLED);
this._bHeaderDisabled = false;
}
@@ -2535,7 +2592,7 @@
if (this._bFooterDisabled) {
- Dom.removeClass(this.footer, "bottomscrollbar_disabled");
+ Dom.removeClass(this.footer, _BOTTOM_SCROLLBAR_DISABLED);
this._bFooterDisabled = false;
}
@@ -2553,16 +2610,11 @@
*/
_onMouseOver: function (p_sType, p_aArgs) {
- if (this._bStopMouseEventHandlers) {
-
- return false;
-
- }
-
-
var oEvent = p_aArgs[0],
oItem = p_aArgs[1],
oTarget = Event.getTarget(oEvent),
+ oRoot = this.getRoot(),
+ oSubmenuHideDelayTimer = this._submenuHideDelayTimer,
oParentMenu,
nShowDelay,
bShowDelay,
@@ -2571,105 +2623,135 @@
oSubmenu;
- if (!this._bHandledMouseOverEvent && (oTarget == this.element ||
- Dom.isAncestor(this.element, oTarget))) {
+ var showSubmenu = function () {
- // Menu mouseover logic
+ if (this.parent.cfg.getProperty(_SELECTED)) {
- this._nCurrentMouseX = 0;
+ this.show();
- Event.on(this.element, "mousemove", this._onMouseMove, this, true);
-
-
- this.clearActiveItem();
-
-
- if (this.parent && this._nSubmenuHideDelayId) {
-
- window.clearTimeout(this._nSubmenuHideDelayId);
-
- this.parent.cfg.setProperty("selected", true);
-
- oParentMenu = this.parent.parent;
-
- oParentMenu._bHandledMouseOutEvent = true;
- oParentMenu._bHandledMouseOverEvent = false;
-
}
+ };
- this._bHandledMouseOverEvent = true;
- this._bHandledMouseOutEvent = false;
-
- }
-
- if (oItem && !oItem.handledMouseOverEvent &&
- !oItem.cfg.getProperty("disabled") &&
- (oTarget == oItem.element || Dom.isAncestor(oItem.element, oTarget))) {
-
- // Menu Item mouseover logic
-
- nShowDelay = this.cfg.getProperty("showdelay");
- bShowDelay = (nShowDelay > 0);
-
-
- if (bShowDelay) {
-
- this._cancelShowDelay();
-
- }
-
-
- oActiveItem = this.activeItem;
+ if (!this._bStopMouseEventHandlers) {
- if (oActiveItem) {
-
- oActiveItem.cfg.setProperty("selected", false);
-
- }
+ if (!this._bHandledMouseOverEvent && (oTarget == this.element ||
+ Dom.isAncestor(this.element, oTarget))) {
+
+ // Menu mouseover logic
+ if (this._useHideDelay) {
+ this._cancelHideDelay();
+ }
+
+ this._nCurrentMouseX = 0;
+
+ Event.on(this.element, _MOUSEMOVE, this._onMouseMove, this, true);
- oItemCfg = oItem.cfg;
-
- // Select and focus the current menu item
-
- oItemCfg.setProperty("selected", true);
+ /*
+ If the mouse is moving from the submenu back to its corresponding menu item,
+ don't hide the submenu or clear the active MenuItem.
+ */
- if (this.hasFocus()) {
-
- oItem.focus();
-
- }
+ if (!(oItem && Dom.isAncestor(oItem.element, Event.getRelatedTarget(oEvent)))) {
+ this.clearActiveItem();
- if (this.cfg.getProperty("autosubmenudisplay")) {
+ }
+
- // Show the submenu this menu item
-
- oSubmenu = oItemCfg.getProperty("submenu");
-
- if (oSubmenu) {
-
- if (bShowDelay) {
-
- this._execShowDelay(oSubmenu);
-
- }
- else {
-
- oSubmenu.show();
-
- }
-
- }
-
- }
-
- oItem.handledMouseOverEvent = true;
- oItem.handledMouseOutEvent = false;
-
+ if (this.parent && oSubmenuHideDelayTimer) {
+
+ oSubmenuHideDelayTimer.cancel();
+
+ this.parent.cfg.setProperty(_SELECTED, true);
+
+ oParentMenu = this.parent.parent;
+
+ oParentMenu._bHandledMouseOutEvent = true;
+ oParentMenu._bHandledMouseOverEvent = false;
+
+ }
+
+
+ this._bHandledMouseOverEvent = true;
+ this._bHandledMouseOutEvent = false;
+
+ }
+
+
+ if (oItem && !oItem.handledMouseOverEvent && !oItem.cfg.getProperty(_DISABLED) &&
+ (oTarget == oItem.element || Dom.isAncestor(oItem.element, oTarget))) {
+
+ // Menu Item mouseover logic
+
+ nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
+ bShowDelay = (nShowDelay > 0);
+
+
+ if (bShowDelay) {
+
+ this._cancelShowDelay();
+
+ }
+
+
+ oActiveItem = this.activeItem;
+
+ if (oActiveItem) {
+
+ oActiveItem.cfg.setProperty(_SELECTED, false);
+
+ }
+
+
+ oItemCfg = oItem.cfg;
+
+ // Select and focus the current menu item
+
+ oItemCfg.setProperty(_SELECTED, true);
+
+
+ if (this.hasFocus() || oRoot._hasFocus) {
+
+ oItem.focus();
+
+ oRoot._hasFocus = false;
+
+ }
+
+
+ if (this.cfg.getProperty(_AUTO_SUBMENU_DISPLAY)) {
+
+ // Show the submenu this menu item
+
+ oSubmenu = oItemCfg.getProperty(_SUBMENU);
+
+ if (oSubmenu) {
+
+ if (bShowDelay) {
+
+ oRoot._showDelayTimer =
+ Lang.later(oRoot.cfg.getProperty(_SHOW_DELAY), oSubmenu, showSubmenu);
+
+ }
+ else {
+
+ oSubmenu.show();
+
+ }
+
+ }
+
+ }
+
+ oItem.handledMouseOverEvent = true;
+ oItem.handledMouseOutEvent = false;
+
+ }
+
}
},
@@ -2685,13 +2767,6 @@
*/
_onMouseOut: function (p_sType, p_aArgs) {
- if (this._bStopMouseEventHandlers) {
-
- return false;
-
- }
-
-
var oEvent = p_aArgs[0],
oItem = p_aArgs[1],
oRelatedTarget = Event.getRelatedTarget(oEvent),
@@ -2702,80 +2777,84 @@
nShowDelay;
- if (oItem && !oItem.cfg.getProperty("disabled")) {
+ if (!this._bStopMouseEventHandlers) {
+
+ if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
+
+ 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)) {
+
+ // Menu Item mouseout logic
+
+ if (!bMovingToSubmenu) {
+
+ oItem.cfg.setProperty(_SELECTED, false);
+
+
+ if (oSubmenu) {
+
+ nSubmenuHideDelay = this.cfg.getProperty(_SUBMENU_HIDE_DELAY);
+
+ nShowDelay = this.cfg.getProperty(_SHOW_DELAY);
+
+ if (!(this instanceof YAHOO.widget.MenuBar) && nSubmenuHideDelay > 0 &&
+ nShowDelay >= nSubmenuHideDelay) {
+
+ this._execSubmenuHideDelay(oSubmenu, Event.getPageX(oEvent),
+ nSubmenuHideDelay);
+
+ }
+ else {
+
+ oSubmenu.hide();
+
+ }
+
+ }
+
+ }
+
+
+ oItem.handledMouseOutEvent = true;
+ oItem.handledMouseOverEvent = false;
+
+ }
+
+ }
- oItemCfg = oItem.cfg;
- oSubmenu = oItemCfg.getProperty("submenu");
+ if (!this._bHandledMouseOutEvent && ((oRelatedTarget != this.element &&
+ !Dom.isAncestor(this.element, oRelatedTarget)) || bMovingToSubmenu)) {
+
+ // Menu mouseout logic
- if (oSubmenu && (oRelatedTarget == oSubmenu.element ||
- Dom.isAncestor(oSubmenu.element, oRelatedTarget))) {
+ if (this._useHideDelay) {
+ this._execHideDelay();
+ }
- bMovingToSubmenu = true;
-
- }
-
-
- if (!oItem.handledMouseOutEvent && ((oRelatedTarget != oItem.element &&
- !Dom.isAncestor(oItem.element, oRelatedTarget)) ||
- bMovingToSubmenu)) {
-
- // Menu Item mouseout logic
-
- if (!bMovingToSubmenu) {
-
- oItem.cfg.setProperty("selected", false);
-
-
- if (oSubmenu) {
-
- nSubmenuHideDelay =
- this.cfg.getProperty("submenuhidedelay");
-
- nShowDelay = this.cfg.getProperty("showdelay");
-
- if (!(this instanceof YAHOO.widget.MenuBar) &&
- nSubmenuHideDelay > 0 &&
- nShowDelay >= nSubmenuHideDelay) {
-
- this._execSubmenuHideDelay(oSubmenu,
- Event.getPageX(oEvent),
- nSubmenuHideDelay);
-
- }
- else {
-
- oSubmenu.hide();
-
- }
-
- }
-
- }
-
-
- oItem.handledMouseOutEvent = true;
- oItem.handledMouseOverEvent = false;
+ Event.removeListener(this.element, _MOUSEMOVE, this._onMouseMove);
+
+ this._nCurrentMouseX = Event.getPageX(oEvent);
+
+ this._bHandledMouseOutEvent = true;
+ this._bHandledMouseOverEvent = false;
+
+ }
- }
-
}
-
- if (!this._bHandledMouseOutEvent && ((oRelatedTarget != this.element &&
- !Dom.isAncestor(this.element, oRelatedTarget)) || bMovingToSubmenu)) {
-
- // Menu mouseout logic
-
- Event.removeListener(this.element, "mousemove", this._onMouseMove);
-
- this._nCurrentMouseX = Event.getPageX(oEvent);
-
- this._bHandledMouseOutEvent = true;
- this._bHandledMouseOverEvent = false;
-
- }
-
},
@@ -2790,14 +2869,12 @@
*/
_onMouseMove: function (p_oEvent, p_oMenu) {
- if (this._bStopMouseEventHandlers) {
+ if (!this._bStopMouseEventHandlers) {
- return false;
+ this._nCurrentMouseX = Event.getPageX(p_oEvent);
}
- this._nCurrentMouseX = Event.getPageX(p_oEvent);
-
},
@@ -2811,88 +2888,148 @@
*/
_onClick: function (p_sType, p_aArgs) {
- var oEvent = p_aArgs[0],
- oItem = p_aArgs[1],
- oTarget,
- oItemCfg,
- oSubmenu,
- sURL,
- oRoot;
+ var oEvent = p_aArgs[0],
+ oItem = p_aArgs[1],
+ bInMenuAnchor = false,
+ oSubmenu,
+ oMenu,
+ oRoot,
+ sId,
+ sURL,
+ nHashPos,
+ nLen;
- if (oItem && !oItem.cfg.getProperty("disabled")) {
+ var hide = function () {
- oTarget = Event.getTarget(oEvent);
- oItemCfg = oItem.cfg;
- oSubmenu = oItemCfg.getProperty("submenu");
+ /*
+ There is an inconsistency between Firefox for Mac OS X and Firefox Windows
+ regarding the triggering of the display of the browser's context menu and the
+ subsequent firing of the "click" event. In Firefox for Windows, when the user
+ triggers the display of the browser's context menu the "click" event also fires
+ for the document object, even though the "click" event did not fire for the
+ element that was the original target of the "contextmenu" event. This is unique
+ to Firefox on Windows. For all other A-Grade browsers, including Firefox for
+ Mac OS X, the "click" event doesn't fire for the document object.
+ This bug in Firefox for Windows affects Menu as Menu instances listen for
+ events at the document level and have an internal "click" event handler they
+ use to hide themselves when clicked. As a result, in Firefox for Windows a
+ Menu will hide when the user right clicks on a MenuItem to raise the browser's
+ default context menu, because its internal "click" event handler ends up
+ getting called. The following line fixes this bug.
+ */
- /*
- ACCESSIBILITY FEATURE FOR SCREEN READERS:
- Expand/collapse the submenu when the user clicks
- on the submenu indicator image.
- */
+ if (!((UA.gecko && this.platform == _WINDOWS) && oEvent.button > 0)) {
+
+ oRoot = this.getRoot();
- if (oTarget == oItem.submenuIndicator && oSubmenu) {
+ if (oRoot instanceof YAHOO.widget.MenuBar ||
+ oRoot.cfg.getProperty(_POSITION) == _STATIC) {
- if (oSubmenu.cfg.getProperty("visible")) {
+ oRoot.clearActiveItem();
- oSubmenu.hide();
-
- oSubmenu.parent.focus();
-
- }
- else {
+ }
+ else {
- this.clearActiveItem();
+ oRoot.hide();
+
+ }
+
+ }
+
+ };
- oItemCfg.setProperty("selected", true);
- oSubmenu.show();
-
- oSubmenu.setInitialFocus();
-
- }
+ if (oItem) {
+
+ if (oItem.cfg.getProperty(_DISABLED)) {
+
+ Event.preventDefault(oEvent);
- Event.preventDefault(oEvent);
-
- }
- else {
+ hide.call(this);
- sURL = oItemCfg.getProperty("url");
+ }
+ else {
- // Prevent the browser from following links equal to "#"
-
- if ((sURL.substr((sURL.length-1),1) == "#")) {
+ oSubmenu = oItem.cfg.getProperty(_SUBMENU);
+
+
+ /*
+ Check if the URL of the anchor is pointing to an element that is
+ a child of the menu.
+ */
+
+ sURL = oItem.cfg.getProperty(_URL);
- Event.preventDefault(oEvent);
+
+ if (sURL) {
+
+ nHashPos = sURL.indexOf(_HASH);
+
+ nLen = sURL.length;
+
+
+ if (nHashPos != -1) {
+
+ sURL = sURL.substr(nHashPos, nLen);
+
+ nLen = sURL.length;
+
+
+ if (nLen > 1) {
+
+ sId = sURL.substr(1, nLen);
+
+ oMenu = YAHOO.widget.MenuManager.getMenu(sId);
+
+ if (oMenu) {
- oItem.focus();
-
- }
+ bInMenuAnchor =
+ (this.getRoot() === oMenu.getRoot());
+ }
+
+ }
+ else if (nLen === 1) {
+
+ bInMenuAnchor = true;
+
+ }
+
+ }
+
+ }
- if (!oSubmenu) {
-
- oRoot = this.getRoot();
-
- if (oRoot instanceof YAHOO.widget.MenuBar ||
- oRoot.cfg.getProperty("position") == "static") {
-
- oRoot.clearActiveItem();
-
- }
- else if (oRoot.cfg.getProperty("clicktohide")) {
+
+ if (bInMenuAnchor && !oItem.cfg.getProperty(_TARGET)) {
+
+ Event.preventDefault(oEvent);
+
- oRoot.hide();
-
- }
-
- }
+ if (UA.webkit) {
+
+ oItem.focus();
+
+ }
+ else {
- }
-
- }
+ oItem.focusEvent.fire();
+
+ }
+
+ }
+
+
+ if (!oSubmenu && !this.cfg.getProperty(_KEEP_OPEN)) {
+
+ hide.call(this);
+
+ }
+
+ }
+
+ }
},
@@ -2909,7 +3046,6 @@
var oEvent = p_aArgs[0],
oItem = p_aArgs[1],
- me = this,
oSubmenu,
oItemCfg,
oParentItem,
@@ -2925,6 +3061,11 @@
oParentMenu;
+ if (this._useHideDelay) {
+ this._cancelHideDelay();
+ }
+
+
/*
This function is called to prevent a bug in Firefox. In Firefox,
moving a DOM element into a stationary mouse pointer will cause the
@@ -2935,18 +3076,18 @@
*/
function stopMouseEventHandlers() {
- me._bStopMouseEventHandlers = true;
+ this._bStopMouseEventHandlers = true;
- window.setTimeout(function () {
+ Lang.later(10, this, function () {
+
+ this._bStopMouseEventHandlers = false;
- me._bStopMouseEventHandlers = false;
-
- }, 10);
+ });
}
- if (oItem && !oItem.cfg.getProperty("disabled")) {
+ if (oItem && !oItem.cfg.getProperty(_DISABLED)) {
oItemCfg = oItem.cfg;
oParentItem = this.parent;
@@ -2964,11 +3105,11 @@
this.clearActiveItem();
- oNextItem.cfg.setProperty("selected", true);
+ oNextItem.cfg.setProperty(_SELECTED, true);
oNextItem.focus();
- if (this.cfg.getProperty("maxheight") > 0) {
+ if (this.cfg.getProperty(_MAX_HEIGHT) > 0) {
oBody = this.body;
nBodyScrollTop = oBody.scrollTop;
@@ -3058,13 +3199,13 @@
case 39: // Right arrow
- oSubmenu = oItemCfg.getProperty("submenu");
+ oSubmenu = oItemCfg.getProperty(_SUBMENU);
if (oSubmenu) {
- if (!oItemCfg.getProperty("selected")) {
+ if (!oItemCfg.getProperty(_SELECTED)) {
- oItemCfg.setProperty("selected", true);
+ oItemCfg.setProperty(_SELECTED, true);
}
@@ -3085,17 +3226,21 @@
oRoot.clearActiveItem();
- oNextItem.cfg.setProperty("selected", true);
+ oNextItem.cfg.setProperty(_SELECTED, true);
- oSubmenu = oNextItem.cfg.getProperty("submenu");
+ oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
if (oSubmenu) {
oSubmenu.show();
+ oSubmenu.setInitialFocus();
}
+ else {
- oNextItem.focus();
+ oNextItem.focus();
+
+ }
}
@@ -3126,17 +3271,21 @@
oParentMenu.clearActiveItem();
- oNextItem.cfg.setProperty("selected", true);
+ oNextItem.cfg.setProperty(_SELECTED, true);
- oSubmenu = oNextItem.cfg.getProperty("submenu");
+ oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
if (oSubmenu) {
oSubmenu.show();
+ oSubmenu.setInitialFocus();
}
+ else {
- oNextItem.focus();
+ oNextItem.focus();
+
+ }
}
@@ -3165,7 +3314,7 @@
if (oEvent.keyCode == 27) { // Esc key
- if (this.cfg.getProperty("position") == "dynamic") {
+ if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
this.hide();
@@ -3178,9 +3327,9 @@
}
else if (this.activeItem) {
- oSubmenu = this.activeItem.cfg.getProperty("submenu");
+ oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
- if (oSubmenu && oSubmenu.cfg.getProperty("visible")) {
+ if (oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
oSubmenu.hide();
this.activeItem.focus();
@@ -3189,7 +3338,7 @@
else {
this.activeItem.blur();
- this.activeItem.cfg.setProperty("selected", false);
+ this.activeItem.cfg.setProperty(_SELECTED, false);
}
@@ -3226,31 +3375,61 @@
/**
-* @method _onTextResize
-* @description "textresize" event handler for the menu.
+* @method _onBlur
+* @description "blur" event handler for a Menu instance.
* @protected
-* @param {String} p_sType String representing the name of the event that
+* @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_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) {
+_onBlur: function (p_sType, p_aArgs) {
+
+ if (this._hasFocus) {
+ this._hasFocus = false;
+ }
- if (YAHOO.env.ua.gecko && !this._handleResize) {
+},
- this._handleResize = true;
- return;
-
- }
+/**
+* @method _onYChange
+* @description "y" event handler for a Menu instance.
+* @protected
+* @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.
+*/
+_onYChange: function (p_sType, p_aArgs) {
+ var oParent = this.parent,
+ nScrollTop,
+ oIFrame,
+ nY;
- var oConfig = this.cfg;
- if (oConfig.getProperty("position") == "dynamic") {
+ if (oParent) {
- oConfig.setProperty("width", (this._getOffsetWidth() + "px"));
+ nScrollTop = oParent.parent.body.scrollTop;
+
+ if (nScrollTop > 0) {
+
+ nY = (this.cfg.getProperty(_Y) - nScrollTop);
+
+ Dom.setY(this.element, nY);
+
+ oIFrame = this.iframe;
+
+
+ if (oIFrame) {
+
+ Dom.setY(oIFrame, nY);
+
+ }
+
+ this.cfg.setProperty(_Y, nY, true);
+
+ }
+
}
},
@@ -3269,11 +3448,22 @@
*/
_onScrollTargetMouseOver: function (p_oEvent, p_oMenu) {
- this._cancelHideDelay();
+ var oBodyScrollTimer = this._bodyScrollTimer;
+
+ if (oBodyScrollTimer) {
+
+ oBodyScrollTimer.cancel();
+
+ }
+
+
+ this._cancelHideDelay();
+
+
var oTarget = Event.getTarget(p_oEvent),
oBody = this.body,
- me = this,
+ nScrollIncrement = this.cfg.getProperty(_SCROLL_INCREMENT),
nScrollTarget,
fnScrollFunction;
@@ -3285,19 +3475,19 @@
if (nScrollTop < nScrollTarget) {
- oBody.scrollTop = (nScrollTop + 1);
+ oBody.scrollTop = (nScrollTop + nScrollIncrement);
- me._enableScrollHeader();
+ this._enableScrollHeader();
}
else {
oBody.scrollTop = nScrollTarget;
-
- window.clearInterval(me._nBodyScrollId);
- me._disableScrollFooter();
+ this._bodyScrollTimer.cancel();
+ this._disableScrollFooter();
+
}
}
@@ -3310,25 +3500,25 @@
if (nScrollTop > 0) {
- oBody.scrollTop = (nScrollTop - 1);
+ oBody.scrollTop = (nScrollTop - nScrollIncrement);
- me._enableScrollFooter();
+ this._enableScrollFooter();
}
else {
oBody.scrollTop = 0;
-
- window.clearInterval(me._nBodyScrollId);
- me._disableScrollHeader();
+ this._bodyScrollTimer.cancel();
+ this._disableScrollHeader();
+
}
}
- if (Dom.hasClass(oTarget, "hd")) {
+ if (Dom.hasClass(oTarget, _HD)) {
fnScrollFunction = scrollBodyUp;
@@ -3340,10 +3530,10 @@
fnScrollFunction = scrollBodyDown;
}
+
+ this._bodyScrollTimer = Lang.later(10, this, fnScrollFunction, null, true);
- this._nBodyScrollId = window.setInterval(fnScrollFunction, 10);
-
},
@@ -3360,8 +3550,14 @@
*/
_onScrollTargetMouseOut: function (p_oEvent, p_oMenu) {
- window.clearInterval(this._nBodyScrollId);
+ var oBodyScrollTimer = this._bodyScrollTimer;
+ if (oBodyScrollTimer) {
+
+ oBodyScrollTimer.cancel();
+
+ }
+
this._cancelHideDelay();
},
@@ -3381,8 +3577,7 @@
*/
_onInit: function (p_sType, p_aArgs) {
- this.cfg.subscribeToConfigEvent("width", this._onWidthChange);
- this.cfg.subscribeToConfigEvent("visible", this._onVisibleChange);
+ this.cfg.subscribeToConfigEvent(_VISIBLE, this._onVisibleChange);
var bRootMenu = !this.parent,
bLazyLoad = this.lazyLoad;
@@ -3402,8 +3597,8 @@
if (((bRootMenu && !bLazyLoad) ||
- (bRootMenu && (this.cfg.getProperty("visible") ||
- this.cfg.getProperty("position") == "static")) ||
+ (bRootMenu && (this.cfg.getProperty(_VISIBLE) ||
+ this.cfg.getProperty(_POSITION) == _STATIC)) ||
(!bRootMenu && !bLazyLoad)) && this.getItemGroups().length === 0) {
if (this.srcElement) {
@@ -3441,8 +3636,7 @@
*/
_onBeforeRender: function (p_sType, p_aArgs) {
- var oConfig = this.cfg,
- oEl = this.element,
+ var oEl = this.element,
nListElements = this._aListElements.length,
bFirstList = true,
i = 0,
@@ -3459,7 +3653,7 @@
if (bFirstList) {
- Dom.addClass(oUL, "first-of-type");
+ Dom.addClass(oUL, _FIRST_OF_TYPE);
bFirstList = false;
}
@@ -3483,7 +3677,7 @@
}
- Dom.addClass(oUL, "hastitle");
+ Dom.addClass(oUL, _HAS_TITLE);
}
@@ -3492,7 +3686,7 @@
i++;
}
- while(i < nListElements);
+ while (i < nListElements);
}
@@ -3509,16 +3703,22 @@
*/
_onRender: function (p_sType, p_aArgs) {
- if (this.cfg.getProperty("position") == "dynamic" &&
- !this.cfg.getProperty("width")) {
+ if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
- this._setWidth();
+ if (!this.cfg.getProperty(_VISIBLE)) {
+
+ this.positionOffScreen();
+
+ }
}
},
+
+
+
/**
* @method _onBeforeShow
* @description "beforeshow" event handler for the menu.
@@ -3531,11 +3731,8 @@
var nOptions,
n,
- nViewportHeight,
- oRegion,
- nMaxHeight,
- oBody,
- oSrcElement;
+ oSrcElement,
+ oContainer = this.cfg.getProperty(_CONTAINER);
if (this.lazyLoad && this.getItemGroups().length === 0) {
@@ -3552,7 +3749,7 @@
if (this.parent && this.parent.parent &&
this.parent.parent.srcElement &&
this.parent.parent.srcElement.tagName.toUpperCase() ==
- "SELECT") {
+ _SELECT) {
nOptions = this.itemData.length;
@@ -3580,7 +3777,7 @@
if (oSrcElement) {
- if (oSrcElement.tagName.toUpperCase() == "SELECT") {
+ if (oSrcElement.tagName.toUpperCase() == _SELECT) {
if (Dom.inDocument(oSrcElement)) {
@@ -3589,7 +3786,7 @@
}
else {
- this.render(this.cfg.getProperty("container"));
+ this.render(oContainer);
}
@@ -3605,13 +3802,12 @@
if (this.parent) {
- this.render(this.parent.element);
+ this.render(this.parent.element);
}
else {
- this.render(this.cfg.getProperty("container"));
- this.cfg.refireEvent("xy");
+ this.render(oContainer);
}
@@ -3620,59 +3816,324 @@
}
- if (!(this instanceof YAHOO.widget.MenuBar) &&
- this.cfg.getProperty("position") == "dynamic") {
- nViewportHeight = Dom.getViewportHeight();
+ var oParent = this.parent,
+ aAlignment;
- if (this.parent && this.parent.parent instanceof YAHOO.widget.MenuBar) {
-
- oRegion = YAHOO.util.Region.getRegion(this.parent.element);
-
- nViewportHeight = (nViewportHeight - oRegion.bottom);
+ if (!oParent && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
- }
+ this.cfg.refireEvent(_XY);
+
+ }
- if (this.element.offsetHeight >= nViewportHeight) {
-
- nMaxHeight = this.cfg.getProperty("maxheight");
+ if (oParent) {
- /*
- Cache the original value for the "maxheight" configuration
- property so that we can set it back when the menu is hidden.
- */
-
- this._nMaxHeight = nMaxHeight;
+ aAlignment = oParent.parent.cfg.getProperty(_SUBMENU_ALIGNMENT);
+
+ this.cfg.setProperty(_CONTEXT, [oParent.element, aAlignment[0], aAlignment[1]]);
+ this.align();
+
+ }
- this.cfg.setProperty("maxheight", (nViewportHeight - 20));
-
- }
-
-
- if (this.cfg.getProperty("maxheight") > 0) {
-
- oBody = this.body;
-
- if (oBody.scrollTop > 0) {
-
- oBody.scrollTop = 0;
-
- }
+},
- this._disableScrollHeader();
- this._enableScrollFooter();
-
- }
- }
+getConstrainedY: function (y) {
+ var oMenu = this,
+
+ aContext = oMenu.cfg.getProperty(_CONTEXT),
+ nInitialMaxHeight = oMenu.cfg.getProperty(_MAX_HEIGHT),
+ nMaxHeight,
+
+ oOverlapPositions = {
+
+ "trbr": true,
+ "tlbl": true,
+ "bltl": true,
+ "brtr": true
+
+ },
+
+ bPotentialContextOverlap = (aContext && oOverlapPositions[aContext[1] + aContext[2]]),
+
+ oMenuEl = oMenu.element,
+ nMenuOffsetHeight = oMenuEl.offsetHeight,
+
+ nViewportOffset = Overlay.VIEWPORT_OFFSET,
+ viewPortHeight = Dom.getViewportHeight(),
+ scrollY = Dom.getDocumentScrollTop(),
+
+ bCanConstrain =
+ (oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) + nViewportOffset < viewPortHeight),
+
+ nAvailableHeight,
+
+ oContextEl,
+ nContextElY,
+ nContextElHeight,
+
+ bFlipped = false,
+
+ nTopRegionHeight,
+ nBottomRegionHeight,
+
+ topConstraint = scrollY + nViewportOffset,
+ bottomConstraint = scrollY + viewPortHeight - nMenuOffsetHeight - nViewportOffset,
+
+ yNew = y;
+
+
+ var flipVertical = function () {
+
+ var nNewY;
+
+ // The Menu is below the context element, flip it above
+ if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
+ nNewY = (nContextElY - nMenuOffsetHeight);
+ }
+ else { // The Menu is above the context element, flip it below
+ nNewY = (nContextElY + nContextElHeight);
+ }
+
+ oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
+
+ return nNewY;
+
+ };
+
+
+ /*
+ Uses the context element's position to calculate the availble height
+ above and below it to display its corresponding Menu.
+ */
+
+ var getDisplayRegionHeight = function () {
+
+ // The Menu is below the context element
+ if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
+ return (nBottomRegionHeight - nViewportOffset);
+ }
+ else { // The Menu is above the context element
+ return (nTopRegionHeight - nViewportOffset);
+ }
+
+ };
+
+
+ /*
+ Sets the Menu's "y" configuration property to the correct value based on its
+ current orientation.
+ */
+
+ var alignY = function () {
+
+ var nNewY;
+
+ if ((oMenu.cfg.getProperty(_Y) - scrollY) > nContextElY) {
+ nNewY = (nContextElY + nContextElHeight);
+ }
+ else {
+ nNewY = (nContextElY - oMenuEl.offsetHeight);
+ }
+
+ oMenu.cfg.setProperty(_Y, (nNewY + scrollY), true);
+
+ };
+
+
+ // Resets the maxheight of the Menu to the value set by the user
+
+ var resetMaxHeight = function () {
+
+ oMenu._setScrollHeight(this.cfg.getProperty(_MAX_HEIGHT));
+
+ oMenu.hideEvent.unsubscribe(resetMaxHeight);
+
+ };
+
+
+ /*
+ Trys to place the Menu in the best possible position (either above or
+ below its corresponding context element).
+ */
+
+ var setVerticalPosition = function () {
+
+ var nDisplayRegionHeight = getDisplayRegionHeight(),
+ bMenuHasItems = (oMenu.getItems().length > 0),
+ nMenuMinScrollHeight,
+ fnReturnVal;
+
+
+ if (nMenuOffsetHeight > nDisplayRegionHeight) {
+
+ nMenuMinScrollHeight =
+ bMenuHasItems ? oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT) : nMenuOffsetHeight;
+
+
+ if ((nDisplayRegionHeight > nMenuMinScrollHeight) && bMenuHasItems) {
+ nMaxHeight = nDisplayRegionHeight;
+ }
+ else {
+ nMaxHeight = nInitialMaxHeight;
+ }
+
+
+ oMenu._setScrollHeight(nMaxHeight);
+ oMenu.hideEvent.subscribe(resetMaxHeight);
+
+
+ // Re-align the Menu since its height has just changed
+ // as a result of the setting of the maxheight property.
+
+ alignY();
+
+
+ if (nDisplayRegionHeight < nMenuMinScrollHeight) {
+
+ if (bFlipped) {
+
+ /*
+ All possible positions and values for the "maxheight"
+ configuration property have been tried, but none were
+ successful, so fall back to the original size and position.
+ */
+
+ flipVertical();
+
+ }
+ else {
+
+ flipVertical();
+
+ bFlipped = true;
+
+ fnReturnVal = setVerticalPosition();
+
+ }
+
+ }
+
+ }
+ else if (nMaxHeight && (nMaxHeight !== nInitialMaxHeight)) {
+
+ oMenu._setScrollHeight(nInitialMaxHeight);
+ oMenu.hideEvent.subscribe(resetMaxHeight);
+
+ // Re-align the Menu since its height has just changed
+ // as a result of the setting of the maxheight property.
+
+ alignY();
+
+ }
+
+ return fnReturnVal;
+
+ };
+
+
+ // Determine if the current value for the Menu's "y" configuration property will
+ // result in the Menu being positioned outside the boundaries of the viewport
+
+ if (y < topConstraint || y > bottomConstraint) {
+
+ // The current value for the Menu's "y" configuration property WILL
+ // result in the Menu being positioned outside the boundaries of the viewport
+
+ if (bCanConstrain) {
+
+ if (oMenu.cfg.getProperty(_PREVENT_CONTEXT_OVERLAP) && bPotentialContextOverlap) {
+
+ // SOLUTION #1:
+ // If the "preventcontextoverlap" configuration property is set to "true",
+ // try to flip and/or scroll the Menu to both keep it inside the boundaries of the
+ // viewport AND from overlaping its context element (MenuItem or MenuBarItem).
+
+ oContextEl = aContext[0];
+ nContextElHeight = oContextEl.offsetHeight;
+ nContextElY = (Dom.getY(oContextEl) - scrollY);
+
+ nTopRegionHeight = nContextElY;
+ nBottomRegionHeight = (viewPortHeight - (nContextElY + nContextElHeight));
+
+ setVerticalPosition();
+
+ yNew = oMenu.cfg.getProperty(_Y);
+
+ }
+ else if (!(oMenu instanceof YAHOO.widget.MenuBar) &&
+ nMenuOffsetHeight >= viewPortHeight) {
+
+ // SOLUTION #2:
+ // If the Menu exceeds the height of the viewport, introduce scroll bars
+ // to keep the Menu inside the boundaries of the viewport
+
+ nAvailableHeight = (viewPortHeight - (nViewportOffset * 2));
+
+ if (nAvailableHeight > oMenu.cfg.getProperty(_MIN_SCROLL_HEIGHT)) {
+
+ oMenu._setScrollHeight(nAvailableHeight);
+ oMenu.hideEvent.subscribe(resetMaxHeight);
+
+ alignY();
+
+ yNew = oMenu.cfg.getProperty(_Y);
+
+ }
+
+ }
+ else {
+
+ // SOLUTION #3:
+
+ if (y < topConstraint) {
+ yNew = topConstraint;
+ } else if (y > bottomConstraint) {
+ yNew = bottomConstraint;
+ }
+
+ }
+
+ }
+ else {
+ // The "y" configuration property cannot be set to a value that will keep
+ // entire Menu inside the boundary of the viewport. Therefore, set
+ // the "y" configuration property to scrollY to keep as much of the
+ // Menu inside the viewport as possible.
+ yNew = nViewportOffset + scrollY;
+ }
+
+ }
+
+ return yNew;
+
},
/**
+* @method _onHide
+* @description "hide" 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.
+*/
+_onHide: function (p_sType, p_aArgs) {
+
+ if (this.cfg.getProperty(_POSITION) === _DYNAMIC) {
+
+ this.positionOffScreen();
+
+ }
+
+},
+
+
+/**
* @method _onShow
* @description "show" event handler for the menu.
* @private
@@ -3684,16 +4145,16 @@
var oParent = this.parent,
oParentMenu,
- aParentAlignment,
- aAlignment;
+ oElement,
+ nOffsetWidth,
+ sWidth;
function disableAutoSubmenuDisplay(p_oEvent) {
var oTarget;
- if (p_oEvent.type == "mousedown" || (p_oEvent.type == "keydown" &&
- p_oEvent.keyCode == 27)) {
+ if (p_oEvent.type == _MOUSEDOWN || (p_oEvent.type == _KEYDOWN && p_oEvent.keyCode == 27)) {
/*
Set the "autosubmenudisplay" to "false" if the user
@@ -3702,51 +4163,72 @@
oTarget = Event.getTarget(p_oEvent);
- if (oTarget != oParentMenu.element ||
- !Dom.isAncestor(oParentMenu.element, oTarget)) {
+ if (oTarget != oParentMenu.element || !Dom.isAncestor(oParentMenu.element, oTarget)) {
- oParentMenu.cfg.setProperty("autosubmenudisplay", false);
+ oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
- Event.removeListener(document, "mousedown",
- disableAutoSubmenuDisplay);
+ Event.removeListener(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
+ Event.removeListener(document, _KEYDOWN, disableAutoSubmenuDisplay);
- Event.removeListener(document, "keydown",
- disableAutoSubmenuDisplay);
-
}
}
}
+ function onSubmenuHide(p_sType, p_aArgs, p_sWidth) {
+
+ this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
+ this.hideEvent.unsubscribe(onSubmenuHide, p_sWidth);
+
+ }
+
+
if (oParent) {
oParentMenu = oParent.parent;
- aParentAlignment = oParentMenu.cfg.getProperty("submenualignment");
- aAlignment = this.cfg.getProperty("submenualignment");
- if ((aParentAlignment[0] != aAlignment[0]) &&
- (aParentAlignment[1] != aAlignment[1])) {
+ if (!oParentMenu.cfg.getProperty(_AUTO_SUBMENU_DISPLAY) &&
+ (oParentMenu instanceof YAHOO.widget.MenuBar ||
+ oParentMenu.cfg.getProperty(_POSITION) == _STATIC)) {
- this.cfg.setProperty("submenualignment",
- [aParentAlignment[0], aParentAlignment[1]]);
-
- }
+ oParentMenu.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, true);
+ Event.on(document, _MOUSEDOWN, disableAutoSubmenuDisplay);
+ Event.on(document, _KEYDOWN, disableAutoSubmenuDisplay);
- if (!oParentMenu.cfg.getProperty("autosubmenudisplay") &&
- (oParentMenu instanceof YAHOO.widget.MenuBar ||
- oParentMenu.cfg.getProperty("position") == "static")) {
+ }
- oParentMenu.cfg.setProperty("autosubmenudisplay", true);
- Event.on(document, "mousedown", disableAutoSubmenuDisplay);
- Event.on(document, "keydown", disableAutoSubmenuDisplay);
+ // The following fixes an issue with the selected state of a MenuItem
+ // not rendering correctly when a submenu is aligned to the left of
+ // its parent Menu instance.
- }
+ if ((this.cfg.getProperty("x") < oParentMenu.cfg.getProperty("x")) &&
+ (UA.gecko && UA.gecko < 1.9) && !this.cfg.getProperty(_WIDTH)) {
+ oElement = this.element;
+ nOffsetWidth = oElement.offsetWidth;
+
+ /*
+ Measuring the difference of the offsetWidth before and after
+ setting the "width" style attribute allows us to compute the
+ about of padding and borders applied to the element, which in
+ turn allows us to set the "width" property correctly.
+ */
+
+ oElement.style.width = nOffsetWidth + _PX;
+
+ sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
+
+ this.cfg.setProperty(_WIDTH, sWidth);
+
+ this.hideEvent.subscribe(onSubmenuHide, sWidth);
+
+ }
+
}
},
@@ -3763,16 +4245,18 @@
_onBeforeHide: function (p_sType, p_aArgs) {
var oActiveItem = this.activeItem,
+ oRoot = this.getRoot(),
oConfig,
oSubmenu;
+
if (oActiveItem) {
oConfig = oActiveItem.cfg;
- oConfig.setProperty("selected", false);
+ oConfig.setProperty(_SELECTED, false);
- oSubmenu = oConfig.getProperty("submenu");
+ oSubmenu = oConfig.getProperty(_SUBMENU);
if (oSubmenu) {
@@ -3782,31 +4266,25 @@
}
- if (this.getRoot() == this) {
- this.blur();
-
- }
+ /*
+ Focus can get lost in IE when the mouse is moving from a submenu back to its parent Menu.
+ For this reason, it is necessary to maintain the focused state in a private property
+ so that the _onMouseOver event handler is able to determined whether or not to set focus
+ to MenuItems as the user is moving the mouse.
+ */
-},
+ if (UA.ie && this.cfg.getProperty(_POSITION) === _DYNAMIC && this.parent) {
+ oRoot._hasFocus = this.hasFocus();
+
+ }
-/**
-* @method _onHide
-* @description "hide" 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.
-*/
-_onHide: function (p_sType, p_aArgs) {
- if (this._nMaxHeight != -1) {
+ if (oRoot == this) {
- this.cfg.setProperty("maxheight", this._nMaxHeight);
-
- this._nMaxHeight = -1;
-
+ oRoot.blur();
+
}
},
@@ -3829,19 +4307,35 @@
switch(sPropertyName) {
- case "iframe":
- case "constraintoviewport":
- case "hidedelay":
- case "showdelay":
- case "submenuhidedelay":
- case "clicktohide":
- case "effect":
- case "classname":
+ case _IFRAME:
+ case _CONSTRAIN_TO_VIEWPORT:
+ case _HIDE_DELAY:
+ case _SHOW_DELAY:
+ case _SUBMENU_HIDE_DELAY:
+ case _CLICK_TO_HIDE:
+ case _EFFECT:
+ case _CLASSNAME:
+ case _SCROLL_INCREMENT:
+ case _MAX_HEIGHT:
+ case _MIN_SCROLL_HEIGHT:
+ case _MONITOR_RESIZE:
+ case _SHADOW:
+ case _PREVENT_CONTEXT_OVERLAP:
p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
- break;
+ break;
+ case _SUBMENU_ALIGNMENT:
+
+ if (!(this.parent.parent instanceof YAHOO.widget.MenuBar)) {
+
+ p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
+
+ }
+
+ break;
+
}
},
@@ -3861,44 +4355,53 @@
_onParentMenuRender: function (p_sType, p_aArgs, p_oSubmenu) {
var oParentMenu = p_oSubmenu.parent.parent,
+ oParentCfg = oParentMenu.cfg,
oConfig = {
- constraintoviewport:
- oParentMenu.cfg.getProperty("constraintoviewport"),
+ constraintoviewport: oParentCfg.getProperty(_CONSTRAIN_TO_VIEWPORT),
xy: [0,0],
+
+ clicktohide: oParentCfg.getProperty(_CLICK_TO_HIDE),
- clicktohide: oParentMenu.cfg.getProperty("clicktohide"),
-
- effect: oParentMenu.cfg.getProperty("effect"),
+ effect: oParentCfg.getProperty(_EFFECT),
- showdelay: oParentMenu.cfg.getProperty("showdelay"),
+ showdelay: oParentCfg.getProperty(_SHOW_DELAY),
- hidedelay: oParentMenu.cfg.getProperty("hidedelay"),
+ hidedelay: oParentCfg.getProperty(_HIDE_DELAY),
- submenuhidedelay: oParentMenu.cfg.getProperty("submenuhidedelay"),
+ submenuhidedelay: oParentCfg.getProperty(_SUBMENU_HIDE_DELAY),
- classname: oParentMenu.cfg.getProperty("classname")
+ classname: oParentCfg.getProperty(_CLASSNAME),
+
+ scrollincrement: oParentCfg.getProperty(_SCROLL_INCREMENT),
+
+ maxheight: oParentCfg.getProperty(_MAX_HEIGHT),
+ minscrollheight: oParentCfg.getProperty(_MIN_SCROLL_HEIGHT),
+
+ iframe: oParentCfg.getProperty(_IFRAME),
+
+ shadow: oParentCfg.getProperty(_SHADOW),
+
+ preventcontextoverlap: oParentCfg.getProperty(_PREVENT_CONTEXT_OVERLAP),
+
+ monitorresize: oParentCfg.getProperty(_MONITOR_RESIZE)
+
},
oLI;
- /*
- Only sync the "iframe" configuration property if the parent
- menu's "position" configuration is the same.
- */
+
+ if (!(oParentMenu instanceof YAHOO.widget.MenuBar)) {
- if (this.cfg.getProperty("position") ==
- oParentMenu.cfg.getProperty("position")) {
+ oConfig[_SUBMENU_ALIGNMENT] = oParentCfg.getProperty(_SUBMENU_ALIGNMENT);
- oConfig.iframe = oParentMenu.cfg.getProperty("iframe");
-
- }
-
+ }
+
p_oSubmenu.cfg.applyConfig(oConfig);
@@ -3923,89 +4426,18 @@
/**
-* @method _onSubmenuBeforeShow
-* @description "beforeshow" event handler for a submenu.
+* @method _onMenuItemDestroy
+* @description "destroy" event handler for the menu's items.
* @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.
-*/
-_onSubmenuBeforeShow: function (p_sType, p_aArgs) {
-
- var oParent = this.parent,
- aAlignment = oParent.parent.cfg.getProperty("submenualignment");
-
- this.cfg.setProperty("context",
- [oParent.element, aAlignment[0], aAlignment[1]]);
-
-
- var nScrollTop = oParent.parent.body.scrollTop;
-
- if ((YAHOO.env.ua.gecko || YAHOO.env.ua.webkit) && nScrollTop > 0) {
-
- this.cfg.setProperty("y", (this.cfg.getProperty("y") - nScrollTop));
-
- }
-
-},
-
-
-/**
-* @method _onSubmenuShow
-* @description "show" event handler for a submenu.
-* @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.
-*/
-_onSubmenuShow: function (p_sType, p_aArgs) {
-
- this.submenuIndicator.innerHTML = this.EXPANDED_SUBMENU_INDICATOR_TEXT;
-
-},
-
-
-/**
-* @method _onSubmenuHide
-* @description "hide" Custom Event handler for a submenu.
-* @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.
-*/
-_onSubmenuHide: function (p_sType, p_aArgs) {
-
- this.submenuIndicator.innerHTML = this.COLLAPSED_SUBMENU_INDICATOR_TEXT;
-
-},
-
-
-/**
-* @method _onMenuItemFocus
-* @description "focus" event handler for the menu's items.
-* @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.
-*/
-_onMenuItemFocus: function (p_sType, p_aArgs) {
-
- this.parent.focusEvent.fire(this);
-
-},
-
-
-/**
-* @method _onMenuItemBlur
-* @description "blur" event handler for the menu's items.
-* @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.
*/
-_onMenuItemBlur: function (p_sType, p_aArgs) {
+_onMenuItemDestroy: function (p_sType, p_aArgs, p_oItem) {
- this.parent.blurEvent.fire(this);
+ this._removeItemFromGroupByValue(p_oItem.groupIndex, p_oItem);
},
@@ -4024,12 +4456,12 @@
var sPropertyName = p_aArgs[0][0],
oPropertyValue = p_aArgs[0][1],
- sWidth,
oSubmenu;
+
switch(sPropertyName) {
- case "selected":
+ case _SELECTED:
if (oPropertyValue === true) {
@@ -4039,7 +4471,7 @@
break;
- case "submenu":
+ case _SUBMENU:
oSubmenu = p_aArgs[0][1];
@@ -4051,25 +4483,6 @@
break;
- case "text":
- case "helptext":
-
- /*
- A change to an item's "text" or "helptext"
- configuration properties requires the width of the parent
- menu to be recalculated.
- */
-
- if (this.element.style.width) {
-
- sWidth = this._getOffsetWidth() + "px";
-
- Dom.setStyle(this.element, "width", sWidth);
-
- }
-
- break;
-
}
},
@@ -4080,126 +4493,6 @@
/**
-* @method enforceConstraints
-* @description The default event handler executed when the moveEvent is fired,
-* if the "constraintoviewport" configuration property is set to true.
-* @param {String} type The name of the event that was fired.
-* @param {Array} args Collection of arguments sent when the
-* event was fired.
-* @param {Array} obj Array containing the current Menu instance
-* and the item that fired the event.
-*/
-enforceConstraints: function (type, args, obj) {
-
- var oParentMenuItem = this.parent,
- oElement,
- oConfig,
- pos,
- x,
- y,
- offsetHeight,
- offsetWidth,
- viewPortWidth,
- viewPortHeight,
- scrollX,
- scrollY,
- nPadding,
- topConstraint,
- leftConstraint,
- bottomConstraint,
- rightConstraint,
- aContext,
- oContextElement;
-
-
- if (oParentMenuItem &&
- !(oParentMenuItem.parent instanceof YAHOO.widget.MenuBar)) {
-
- oElement = this.element;
-
- oConfig = this.cfg;
- pos = args[0];
-
- x = pos[0];
- y = pos[1];
-
- offsetHeight = oElement.offsetHeight;
- offsetWidth = oElement.offsetWidth;
-
- viewPortWidth = Dom.getViewportWidth();
- viewPortHeight = Dom.getViewportHeight();
-
- scrollX = Dom.getDocumentScrollLeft();
- scrollY = Dom.getDocumentScrollTop();
-
- nPadding =
- (oParentMenuItem.parent instanceof YAHOO.widget.MenuBar) ? 0 : 10;
-
- topConstraint = scrollY + nPadding;
- leftConstraint = scrollX + nPadding;
-
- bottomConstraint = scrollY + viewPortHeight - offsetHeight - nPadding;
- rightConstraint = scrollX + viewPortWidth - offsetWidth - nPadding;
-
- aContext = oConfig.getProperty("context");
- oContextElement = aContext ? aContext[0] : null;
-
-
- if (x < 10) {
-
- x = leftConstraint;
-
- } else if ((x + offsetWidth) > 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);
-
- }
- else if (this == this.getRoot() &&
- this.cfg.getProperty("position") == "dynamic") {
-
- Menu.superclass.enforceConstraints.call(this, type, args, obj);
-
- }
-
-},
-
-
-/**
* @method configVisible
* @description Event handler for when the "visible" configuration property
* the menu changes.
@@ -4214,30 +4507,32 @@
var bVisible,
sDisplay;
- if (this.cfg.getProperty("position") == "dynamic") {
+ if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
Menu.superclass.configVisible.call(this, p_sType, p_aArgs, p_oMenu);
}
else {
bVisible = p_aArgs[0];
- sDisplay = Dom.getStyle(this.element, "display");
+ sDisplay = Dom.getStyle(this.element, _DISPLAY);
+ Dom.setStyle(this.element, _VISIBILITY, _VISIBLE);
+
if (bVisible) {
- if (sDisplay != "block") {
+ if (sDisplay != _BLOCK) {
this.beforeShowEvent.fire();
- Dom.setStyle(this.element, "display", "block");
+ Dom.setStyle(this.element, _DISPLAY, _BLOCK);
this.showEvent.fire();
}
}
else {
- if (sDisplay == "block") {
+ if (sDisplay == _BLOCK) {
this.beforeHideEvent.fire();
- Dom.setStyle(this.element, "display", "none");
+ Dom.setStyle(this.element, _DISPLAY, _NONE);
this.hideEvent.fire();
}
@@ -4261,40 +4556,25 @@
configPosition: function (p_sType, p_aArgs, p_oMenu) {
var oElement = this.element,
- sCSSPosition = p_aArgs[0] == "static" ? "static" : "absolute",
- sCurrentPosition = Dom.getStyle(oElement, "position"),
+ sCSSPosition = p_aArgs[0] == _STATIC ? _STATIC : _ABSOLUTE,
oCfg = this.cfg,
nZIndex;
- Dom.setStyle(this.element, "position", sCSSPosition);
+ Dom.setStyle(oElement, _POSITION, sCSSPosition);
- if (sCSSPosition == "static") {
+ 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");
+ Dom.setStyle(oElement, _DISPLAY, _BLOCK);
- oCfg.setProperty("visible", true);
+ oCfg.setProperty(_VISIBLE, true);
}
else {
- if (sCurrentPosition != "absolute") {
-
- oCfg.setProperty("iframe", (YAHOO.env.ua.ie == 6 ? true : false));
-
- }
-
/*
Even though the "visible" property is queued to
"false" by default, we need to set the "visibility" property to
@@ -4303,26 +4583,23 @@
or not to show an Overlay instance.
*/
- Dom.setStyle(this.element, "visibility", "hidden");
+ Dom.setStyle(oElement, _VISIBILITY, _HIDDEN);
}
+
+ if (sCSSPosition == _ABSOLUTE) {
+
+ nZIndex = oCfg.getProperty(_ZINDEX);
+
+ if (!nZIndex || nZIndex === 0) {
+
+ oCfg.setProperty(_ZINDEX, 1);
+
+ }
+
+ }
- if (sCSSPosition == "absolute") {
-
- nZIndex = oCfg.getProperty("zindex");
-
- if (!nZIndex || nZIndex === 0) {
-
- nZIndex = this.parent ?
- (this.parent.parent.cfg.getProperty("zindex") + 1) : 1;
-
- oCfg.setProperty("zindex", nZIndex);
-
- }
-
- }
-
},
@@ -4338,7 +4615,7 @@
*/
configIframe: function (p_sType, p_aArgs, p_oMenu) {
- if (this.cfg.getProperty("position") == "dynamic") {
+ if (this.cfg.getProperty(_POSITION) == _DYNAMIC) {
Menu.superclass.configIframe.call(this, p_sType, p_aArgs, p_oMenu);
@@ -4359,46 +4636,17 @@
*/
configHideDelay: function (p_sType, p_aArgs, p_oMenu) {
- var nHideDelay = p_aArgs[0],
- oMouseOutEvent = this.mouseOutEvent,
- oMouseOverEvent = this.mouseOverEvent,
- oKeyDownEvent = this.keyDownEvent;
+ var nHideDelay = p_aArgs[0];
- if (nHideDelay > 0) {
+ this._useHideDelay = (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._bHideDelayEventHandlersAssigned) {
-
- oMouseOutEvent.subscribe(this._execHideDelay);
- oMouseOverEvent.subscribe(this._cancelHideDelay);
- oKeyDownEvent.subscribe(this._cancelHideDelay);
-
- this._bHideDelayEventHandlersAssigned = true;
-
- }
-
- }
- else {
-
- oMouseOutEvent.unsubscribe(this._execHideDelay);
- oMouseOverEvent.unsubscribe(this._cancelHideDelay);
- oKeyDownEvent.unsubscribe(this._cancelHideDelay);
-
- this._bHideDelayEventHandlersAssigned = false;
-
- }
-
},
/**
* @method configContainer
* @description Event handler for when the "container" configuration property
-of the menu changes.
+* 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.
@@ -4409,135 +4657,298 @@
var oElement = p_aArgs[0];
- if (typeof oElement == 'string') {
+ if (Lang.isString(oElement)) {
- this.cfg.setProperty("container", document.getElementById(oElement),
- true);
+ this.cfg.setProperty(_CONTAINER, Dom.get(oElement), true);
}
},
/**
-* @method _setMaxHeight
-* @description "renderEvent" handler used to defer the setting of the
-* "maxheight" configuration property until the menu is rendered in lazy
-* load scenarios.
-* @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 {Number} p_nMaxHeight Number representing the value to set for the
-* "maxheight" configuration property.
+* @method _clearSetWidthFlag
+* @description Change event listener for the "width" configuration property. This listener is
+* added when a Menu's "width" configuration property is set by the "_setScrollHeight" method, and
+* is used to set the "_widthSetForScroll" property to "false" if the "width" configuration property
+* is changed after it was set by the "_setScrollHeight" method. If the "_widthSetForScroll"
+* property is set to "false", and the "_setScrollHeight" method is in the process of tearing down
+* scrolling functionality, it will maintain the Menu's new width rather than reseting it.
* @private
*/
-_setMaxHeight: function (p_sType, p_aArgs, p_nMaxHeight) {
+_clearSetWidthFlag: function () {
- this.cfg.setProperty("maxheight", p_nMaxHeight);
- this.renderEvent.unsubscribe(this._setMaxHeight);
+ this._widthSetForScroll = false;
+
+ this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
},
/**
-* @method configMaxHeight
-* @description Event handler for when the "maxheight" configuration property of
-* a Menu 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.Menu} p_oMenu The Menu instance fired
-* the event.
+* @method _setScrollHeight
+* @description
+* @param {String} p_nScrollHeight Number representing the scrolling height of the Menu.
+* @private
*/
-configMaxHeight: function (p_sType, p_aArgs, p_oMenu) {
+_setScrollHeight: function (p_nScrollHeight) {
- var nMaxHeight = p_aArgs[0],
- oBody = this.body,
- oHeader = this.header,
- oFooter = this.footer,
- fnMouseOver = this._onScrollTargetMouseOver,
- fnMouseOut = this._onScrollTargetMouseOut,
- nHeight;
+ var nScrollHeight = p_nScrollHeight,
+ bRefireIFrameAndShadow = false,
+ bSetWidth = false,
+ oElement,
+ oBody,
+ oHeader,
+ oFooter,
+ fnMouseOver,
+ fnMouseOut,
+ nMinScrollHeight,
+ nHeight,
+ nOffsetWidth,
+ sWidth;
- if (this.lazyLoad && !oBody) {
+ if (this.getItems().length > 0) {
+
+ oElement = this.element;
+ oBody = this.body;
+ oHeader = this.header;
+ oFooter = this.footer;
+ fnMouseOver = this._onScrollTargetMouseOver;
+ fnMouseOut = this._onScrollTargetMouseOut;
+ nMinScrollHeight = this.cfg.getProperty(_MIN_SCROLL_HEIGHT);
- this.renderEvent.unsubscribe(this._setMaxHeight);
-
- if (nMaxHeight > 0) {
- this.renderEvent.subscribe(this._setMaxHeight, nMaxHeight, this);
+ if (nScrollHeight > 0 && nScrollHeight < nMinScrollHeight) {
+
+ nScrollHeight = nMinScrollHeight;
+
+ }
- }
- return;
-
- }
+ Dom.setStyle(oBody, _HEIGHT, _EMPTY_STRING);
+ Dom.removeClass(oBody, _YUI_MENU_BODY_SCROLLED);
+ oBody.scrollTop = 0;
- Dom.setStyle(oBody, "height", "auto");
- Dom.setStyle(oBody, "overflow", "visible");
+ // Need to set a width for the Menu to fix the following problems in
+ // Firefox 2 and IE:
- if ((nMaxHeight > 0) && (oBody.offsetHeight > nMaxHeight)) {
+ // #1) Scrolled Menus will render at 1px wide in Firefox 2
- if (!this.cfg.getProperty("width")) {
+ // #2) There is a bug in gecko-based browsers where an element whose
+ // "position" property is set to "absolute" and "overflow" property is
+ // set to "hidden" will not render at the correct width when its
+ // offsetParent's "position" property is also set to "absolute." It is
+ // possible to work around this bug by specifying a value for the width
+ // property in addition to overflow.
- this._setWidth();
+ // #3) In IE it is necessary to give the Menu a width before the
+ // scrollbars are rendered to prevent the Menu from rendering with a
+ // width that is 100% of the browser viewport.
+
+ bSetWidth = ((UA.gecko && UA.gecko < 1.9) || UA.ie);
- }
+ if (nScrollHeight > 0 && bSetWidth && !this.cfg.getProperty(_WIDTH)) {
- if (!oHeader && !oFooter) {
+ nOffsetWidth = oElement.offsetWidth;
+
+ /*
+ Measuring the difference of the offsetWidth before and after
+ setting the "width" style attribute allows us to compute the
+ about of padding and borders applied to the element, which in
+ turn allows us to set the "width" property correctly.
+ */
+
+ oElement.style.width = nOffsetWidth + _PX;
+
+ sWidth = (nOffsetWidth - (oElement.offsetWidth - nOffsetWidth)) + _PX;
- this.setHeader(" ");
- this.setFooter(" ");
- oHeader = this.header;
- oFooter = this.footer;
+ this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
- Dom.addClass(oHeader, "topscrollbar");
- Dom.addClass(oFooter, "bottomscrollbar");
-
- this.element.insertBefore(oHeader, oBody);
- this.element.appendChild(oFooter);
+ YAHOO.log("Setting the \"width\" configuration property to " + sWidth + " for srolling.",
+ "info", this.toString());
- Event.on(oHeader, "mouseover", fnMouseOver, this, true);
- Event.on(oHeader, "mouseout", fnMouseOut, this, true);
- Event.on(oFooter, "mouseover", fnMouseOver, this, true);
- Event.on(oFooter, "mouseout", fnMouseOut, this, true);
-
- }
+ this.cfg.setProperty(_WIDTH, sWidth);
- nHeight = (nMaxHeight - (this.footer.offsetHeight +
- this.header.offsetHeight));
- Dom.setStyle(oBody, "height", (nHeight + "px"));
- Dom.setStyle(oBody, "overflow", "hidden");
+ /*
+ Set a flag (_widthSetForScroll) to maintain some history regarding how the
+ "width" configuration property was set. If the "width" configuration property
+ is set by something other than the "_setScrollHeight" method, it will be
+ necessary to maintain that new value and not clear the width if scrolling
+ is turned off.
+ */
- }
- else if (oHeader && oFooter) {
+ this._widthSetForScroll = true;
- Dom.setStyle(oBody, "height", "auto");
- Dom.setStyle(oBody, "overflow", "visible");
+ this.cfg.subscribeToConfigEvent(_WIDTH, this._clearSetWidthFlag);
+
+ }
+
+
+ if (nScrollHeight > 0 && (!oHeader && !oFooter)) {
+
+ YAHOO.log("Creating header and footer for scrolling.", "info", this.toString());
+
+ this.setHeader(_NON_BREAKING_SPACE);
+ this.setFooter(_NON_BREAKING_SPACE);
+
+ oHeader = this.header;
+ oFooter = this.footer;
+
+ Dom.addClass(oHeader, _TOP_SCROLLBAR);
+ Dom.addClass(oFooter, _BOTTOM_SCROLLBAR);
+
+ oElement.insertBefore(oHeader, oBody);
+ oElement.appendChild(oFooter);
+
+ }
+
+
+ nHeight = nScrollHeight;
+
+
+ if (oHeader && oFooter) {
+ nHeight = (nHeight - (oHeader.offsetHeight + oFooter.offsetHeight));
+ }
+
+
+ if ((nHeight > 0) && (oBody.offsetHeight > nScrollHeight)) {
- Event.removeListener(oHeader, "mouseover", fnMouseOver);
- Event.removeListener(oHeader, "mouseout", fnMouseOut);
- Event.removeListener(oFooter, "mouseover", fnMouseOver);
- Event.removeListener(oFooter, "mouseout", fnMouseOut);
+ YAHOO.log("Setting up styles and event handlers for scrolling.",
+ "info", this.toString());
+
+ Dom.addClass(oBody, _YUI_MENU_BODY_SCROLLED);
+ Dom.setStyle(oBody, _HEIGHT, (nHeight + _PX));
- this.element.removeChild(oHeader);
- this.element.removeChild(oFooter);
-
- this.header = null;
- this.footer = null;
-
- }
+ if (!this._hasScrollEventHandlers) {
+
+ Event.on(oHeader, _MOUSEOVER, fnMouseOver, this, true);
+ Event.on(oHeader, _MOUSEOUT, fnMouseOut, this, true);
+ Event.on(oFooter, _MOUSEOVER, fnMouseOver, this, true);
+ Event.on(oFooter, _MOUSEOUT, fnMouseOut, this, true);
+
+ this._hasScrollEventHandlers = true;
+
+ }
+
+ this._disableScrollHeader();
+ this._enableScrollFooter();
+
+ bRefireIFrameAndShadow = true;
+
+ }
+ else if (oHeader && oFooter) {
- this.cfg.refireEvent("iframe");
+ YAHOO.log("Removing styles and event handlers for scrolling.", "info", this.toString());
+
+ /*
+ Only clear the the "width" configuration property if it was set the
+ "_setScrollHeight" method and wasn't changed by some other means after it was set.
+ */
+
+ if (this._widthSetForScroll) {
+
+ YAHOO.log("Clearing width used for scrolling.", "info", this.toString());
+
+ this._widthSetForScroll = false;
+
+ this.cfg.unsubscribeFromConfigEvent(_WIDTH, this._clearSetWidthFlag);
+
+ this.cfg.setProperty(_WIDTH, _EMPTY_STRING);
+
+ }
+
+
+ this._enableScrollHeader();
+ this._enableScrollFooter();
+
+ if (this._hasScrollEventHandlers) {
+
+ Event.removeListener(oHeader, _MOUSEOVER, fnMouseOver);
+ Event.removeListener(oHeader, _MOUSEOUT, fnMouseOut);
+ Event.removeListener(oFooter, _MOUSEOVER, fnMouseOver);
+ Event.removeListener(oFooter, _MOUSEOUT, fnMouseOut);
+
+ this._hasScrollEventHandlers = false;
+
+ }
+
+ oElement.removeChild(oHeader);
+ oElement.removeChild(oFooter);
+
+ this.header = null;
+ this.footer = null;
+
+ bRefireIFrameAndShadow = true;
+
+ }
+
+
+ if (bRefireIFrameAndShadow) {
+
+ this.cfg.refireEvent(_IFRAME);
+ this.cfg.refireEvent(_SHADOW);
+
+ }
+
+ }
+
},
/**
+* @method _setMaxHeight
+* @description "renderEvent" handler used to defer the setting of the
+* "maxheight" configuration property until the menu is rendered in lazy
+* load scenarios.
+* @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 {Number} p_nMaxHeight Number representing the value to set for the
+* "maxheight" configuration property.
+* @private
+*/
+_setMaxHeight: function (p_sType, p_aArgs, p_nMaxHeight) {
+
+ this._setScrollHeight(p_nMaxHeight);
+ this.renderEvent.unsubscribe(this._setMaxHeight);
+
+},
+
+
+/**
+* @method configMaxHeight
+* @description Event handler for when the "maxheight" configuration property of
+* a Menu 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.Menu} p_oMenu The Menu instance fired
+* the event.
+*/
+configMaxHeight: function (p_sType, p_aArgs, p_oMenu) {
+
+ var nMaxHeight = p_aArgs[0];
+
+ if (this.lazyLoad && !this.body && nMaxHeight > 0) {
+
+ this.renderEvent.subscribe(this._setMaxHeight, nMaxHeight, this);
+
+ }
+ else {
+
+ this._setScrollHeight(nMaxHeight);
+
+ }
+
+},
+
+
+/**
* @method configClassName
* @description Event handler for when the "classname" configuration property of
* a menu changes.
@@ -4575,7 +4986,7 @@
if (oItem) {
- oItem.cfg.setProperty("disabled", true);
+ oItem.cfg.setProperty(_DISABLED, true);
}
@@ -4593,93 +5004,119 @@
configDisabled: function (p_sType, p_aArgs, p_oMenu) {
var bDisabled = p_aArgs[0],
- aItems,
+ aItems = this.getItems(),
nItems,
i;
- if (this._bDisabled != bDisabled) {
+ if (Lang.isArray(aItems)) {
- aItems = this.getItems();
nItems = aItems.length;
-
+
if (nItems > 0) {
i = nItems - 1;
do {
- aItems[i].cfg.setProperty("disabled", bDisabled);
+ aItems[i].cfg.setProperty(_DISABLED, bDisabled);
}
while (i--);
}
-
- Dom[(bDisabled ? "addClass" : "removeClass")](this.element, "disabled");
- this.itemAddedEvent[(bDisabled ? "subscribe" : "unsubscribe")](
- this._onItemAdded);
-
- this._bDisabled = bDisabled;
-
+
+ if (bDisabled) {
+
+ this.clearActiveItem(true);
+
+ Dom.addClass(this.element, _DISABLED);
+
+ this.itemAddedEvent.subscribe(this._onItemAdded);
+
+ }
+ else {
+
+ Dom.removeClass(this.element, _DISABLED);
+
+ this.itemAddedEvent.unsubscribe(this._onItemAdded);
+
+ }
+
}
},
/**
-* @method onRender
-* @description "render" event handler for the menu.
-* @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.
+* @method configShadow
+* @description Event handler for when the "shadow" configuration property of
+* a menu 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.Menu} p_oMenu The Menu instance fired the event.
*/
-onRender: function (p_sType, p_aArgs) {
+configShadow: function (p_sType, p_aArgs, p_oMenu) {
- function sizeShadow() {
+ var sizeShadow = function () {
var oElement = this.element,
oShadow = this._shadow;
- if (oShadow) {
+ if (oShadow && oElement) {
- oShadow.style.width = (oElement.offsetWidth + 6) + "px";
- oShadow.style.height = (oElement.offsetHeight + 1) + "px";
+ // Clear the previous width
+
+ if (oShadow.style.width && oShadow.style.height) {
+
+ oShadow.style.width = _EMPTY_STRING;
+ oShadow.style.height = _EMPTY_STRING;
+
+ }
+
+ oShadow.style.width = (oElement.offsetWidth + 6) + _PX;
+ oShadow.style.height = (oElement.offsetHeight + 1) + _PX;
}
- }
+ };
- function addShadowVisibleClass() {
+ var replaceShadow = function () {
+
+ this.element.appendChild(this._shadow);
+
+ };
+
+
+ var addShadowVisibleClass = function () {
- Dom.addClass(this._shadow, "yui-menu-shadow-visible");
+ Dom.addClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
- }
+ };
- function removeShadowVisibleClass() {
+ var removeShadowVisibleClass = function () {
- Dom.removeClass(this._shadow, "yui-menu-shadow-visible");
+ Dom.removeClass(this._shadow, _YUI_MENU_SHADOW_VISIBLE);
- }
+ };
- function createShadow() {
+ var createShadow = function () {
var oShadow = this._shadow,
- oElement,
- me;
+ oElement;
if (!oShadow) {
oElement = this.element;
- me = this;
+
if (!m_oShadowTemplate) {
- m_oShadowTemplate = document.createElement("div");
- m_oShadowTemplate.className = "yui-menu-shadow";
+ m_oShadowTemplate = document.createElement(_DIV_LOWERCASE);
+ m_oShadowTemplate.className = _YUI_MENU_SHADOW_YUI_MENU_SHADOW_VISIBLE;
}
@@ -4689,12 +5126,11 @@
this._shadow = oShadow;
- addShadowVisibleClass.call(this);
-
this.beforeShowEvent.subscribe(addShadowVisibleClass);
this.beforeHideEvent.subscribe(removeShadowVisibleClass);
- if (YAHOO.env.ua.ie) {
+
+ if (UA.ie) {
/*
Need to call sizeShadow & syncIframe via setTimeout for
@@ -4703,46 +5139,81 @@
positioned properly.
*/
- window.setTimeout(function () {
-
- sizeShadow.call(me);
- me.syncIframe();
-
- }, 0);
+ Lang.later(0, this, function () {
- this.cfg.subscribeToConfigEvent("width", sizeShadow);
- this.cfg.subscribeToConfigEvent("height", sizeShadow);
+ sizeShadow.call(this);
+ this.syncIframe();
+
+ });
+
+
+ this.cfg.subscribeToConfigEvent(_WIDTH, sizeShadow);
+ this.cfg.subscribeToConfigEvent(_HEIGHT, sizeShadow);
+ this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, sizeShadow);
this.changeContentEvent.subscribe(sizeShadow);
- Module.textResizeEvent.subscribe(sizeShadow, me, true);
+ Module.textResizeEvent.subscribe(sizeShadow, this, true);
this.destroyEvent.subscribe(function () {
- Module.textResizeEvent.unsubscribe(sizeShadow, me);
+ Module.textResizeEvent.unsubscribe(sizeShadow, this);
});
}
-
+
+ this.cfg.subscribeToConfigEvent(_MAX_HEIGHT, replaceShadow);
+
}
- }
+ };
- function onBeforeShow() {
+ var onBeforeShow = function () {
+
+ if (this._shadow) {
+
+ // If called because the "shadow" event was refired - just append again and resize
+
+ replaceShadow.call(this);
+
+ if (UA.ie) {
+ sizeShadow.call(this);
+ }
+
+ }
+ else {
- createShadow.call(this);
+ createShadow.call(this);
+
+ }
this.beforeShowEvent.unsubscribe(onBeforeShow);
- }
+ };
- if (this.cfg.getProperty("position") == "dynamic") {
+ var bShadow = p_aArgs[0];
- if (this.cfg.getProperty("visible")) {
- createShadow.call(this);
+ if (bShadow && this.cfg.getProperty(_POSITION) == _DYNAMIC) {
+
+ if (this.cfg.getProperty(_VISIBLE)) {
+
+ if (this._shadow) {
+
+ // If the "shadow" event was refired - just append again and resize
+
+ replaceShadow.call(this);
+
+ if (UA.ie) {
+ sizeShadow.call(this);
+ }
+
+ }
+ else {
+ createShadow.call(this);
+ }
}
else {
@@ -4752,10 +5223,11 @@
}
}
-
+
},
+
// Public methods
@@ -4769,43 +5241,47 @@
// Create custom events
- var SIGNATURE = CustomEvent.LIST;
+ var i = EVENT_TYPES.length - 1,
+ aEventData,
+ oCustomEvent;
- this.mouseOverEvent = this.createEvent(EVENT_TYPES.MOUSE_OVER);
- this.mouseOverEvent.signature = SIGNATURE;
- this.mouseOutEvent = this.createEvent(EVENT_TYPES.MOUSE_OUT);
- this.mouseOutEvent.signature = SIGNATURE;
-
- this.mouseDownEvent = this.createEvent(EVENT_TYPES.MOUSE_DOWN);
- this.mouseDownEvent.signature = SIGNATURE;
+ do {
- this.mouseUpEvent = this.createEvent(EVENT_TYPES.MOUSE_UP);
- this.mouseUpEvent.signature = SIGNATURE;
+ aEventData = EVENT_TYPES[i];
+
+ oCustomEvent = this.createEvent(aEventData[1]);
+ oCustomEvent.signature = CustomEvent.LIST;
+
+ this[aEventData[0]] = oCustomEvent;
+
+ }
+ while (i--);
+
+},
+
+
+/**
+* @method positionOffScreen
+* @description Positions the menu outside of the boundaries of the browser's
+* viewport. Called automatically when a menu is hidden to ensure that
+* it doesn't force the browser to render uncessary scrollbars.
+*/
+positionOffScreen: function () {
+
+ var oIFrame = this.iframe,
+ oElement = this.element,
+ sPos = this.OFF_SCREEN_POSITION;
- this.clickEvent = this.createEvent(EVENT_TYPES.CLICK);
- this.clickEvent.signature = SIGNATURE;
+ oElement.style.top = _EMPTY_STRING;
+ oElement.style.left = _EMPTY_STRING;
- this.keyPressEvent = this.createEvent(EVENT_TYPES.KEY_PRESS);
- this.keyPressEvent.signature = SIGNATURE;
+ if (oIFrame) {
+
+ oIFrame.style.top = sPos;
+ oIFrame.style.left = sPos;
- this.keyDownEvent = this.createEvent(EVENT_TYPES.KEY_DOWN);
- this.keyDownEvent.signature = SIGNATURE;
-
- this.keyUpEvent = this.createEvent(EVENT_TYPES.KEY_UP);
- this.keyUpEvent.signature = SIGNATURE;
-
- this.focusEvent = this.createEvent(EVENT_TYPES.FOCUS);
- this.focusEvent.signature = SIGNATURE;
-
- this.blurEvent = this.createEvent(EVENT_TYPES.BLUR);
- this.blurEvent.signature = SIGNATURE;
-
- this.itemAddedEvent = this.createEvent(EVENT_TYPES.ITEM_ADDED);
- this.itemAddedEvent.signature = SIGNATURE;
-
- this.itemRemovedEvent = this.createEvent(EVENT_TYPES.ITEM_REMOVED);
- this.itemRemovedEvent.signature = SIGNATURE;
+ }
},
@@ -4817,20 +5293,23 @@
getRoot: function () {
var oItem = this.parent,
- oParentMenu;
+ oParentMenu,
+ returnVal;
if (oItem) {
oParentMenu = oItem.parent;
- return oParentMenu ? oParentMenu.getRoot() : this;
+ returnVal = oParentMenu ? oParentMenu.getRoot() : this;
}
else {
- return this;
+ returnVal = this;
}
+
+ return returnVal;
},
@@ -4842,12 +5321,12 @@
*/
toString: function () {
- var sReturnVal = "Menu",
+ var sReturnVal = _MENU,
sId = this.id;
if (sId) {
- sReturnVal += (" " + sId);
+ sReturnVal += (_SPACE + sId);
}
@@ -4870,9 +5349,9 @@
i,
nFirstIndex;
- if (typeof p_sGroupTitle == "string" && p_sGroupTitle.length > 0) {
+ if (Lang.isString(p_sGroupTitle) && p_sGroupTitle.length > 0) {
- nGroupIndex = typeof p_nGroupIndex == "number" ? p_nGroupIndex : 0;
+ nGroupIndex = Lang.isNumber(p_nGroupIndex) ? p_nGroupIndex : 0;
oTitle = this._aGroupTitleElements[nGroupIndex];
@@ -4898,20 +5377,20 @@
if (this._aGroupTitleElements[i]) {
- Dom.removeClass(this._aGroupTitleElements[i], "first-of-type");
+ Dom.removeClass(this._aGroupTitleElements[i], _FIRST_OF_TYPE);
nFirstIndex = i;
}
}
- while(i--);
+ while (i--);
if (nFirstIndex !== null) {
Dom.addClass(this._aGroupTitleElements[nFirstIndex],
- "first-of-type");
+ _FIRST_OF_TYPE);
}
@@ -4938,12 +5417,8 @@
*/
addItem: function (p_oItem, p_nGroupIndex) {
- if (p_oItem) {
+ return this._addItemToGroup(p_nGroupIndex, p_oItem);
- return this._addItemToGroup(p_nGroupIndex, p_oItem);
-
- }
-
},
@@ -4963,8 +5438,10 @@
var nItems,
aItems,
oItem,
- i;
+ i,
+ returnVal;
+
if (Lang.isArray(p_aItems)) {
nItems = p_aItems.length;
@@ -4983,8 +5460,7 @@
}
else {
- aItems[aItems.length] =
- this._addItemToGroup(p_nGroupIndex, oItem);
+ aItems[aItems.length] = this._addItemToGroup(p_nGroupIndex, oItem);
}
@@ -4995,12 +5471,14 @@
if (aItems.length) {
- return aItems;
+ returnVal = aItems;
}
}
+ return returnVal;
+
},
@@ -5021,12 +5499,8 @@
*/
insertItem: function (p_oItem, p_nItemIndex, p_nGroupIndex) {
- if (p_oItem) {
+ return this._addItemToGroup(p_nGroupIndex, p_oItem, p_nItemIndex);
- return this._addItemToGroup(p_nGroupIndex, p_oItem, p_nItemIndex);
-
- }
-
},
@@ -5043,16 +5517,17 @@
*/
removeItem: function (p_oObject, p_nGroupIndex) {
- var oItem;
+ var oItem,
+ returnVal;
- if (typeof p_oObject != "undefined") {
+ if (!Lang.isUndefined(p_oObject)) {
if (p_oObject instanceof YAHOO.widget.MenuItem) {
oItem = this._removeItemFromGroupByValue(p_nGroupIndex, p_oObject);
}
- else if (typeof p_oObject == "number") {
+ else if (Lang.isNumber(p_oObject)) {
oItem = this._removeItemFromGroupByIndex(p_nGroupIndex, p_oObject);
@@ -5062,17 +5537,19 @@
oItem.destroy();
- this.logger.log("Item removed." +
+ YAHOO.log("Item removed." +
" Text: " + oItem.cfg.getProperty("text") + ", " +
" Index: " + oItem.index + ", " +
- " Group Index: " + oItem.groupIndex);
+ " Group Index: " + oItem.groupIndex, "info", this.toString());
- return oItem;
+ returnVal = oItem;
}
}
+ return returnVal;
+
},
@@ -5084,11 +5561,21 @@
getItems: function () {
var aGroups = this._aItemGroups,
+ nGroups,
+ returnVal,
+ aItems = [];
+
+
+ if (Lang.isArray(aGroups)) {
+
nGroups = aGroups.length;
- return ((nGroups == 1) ? aGroups[0] :
- (Array.prototype.concat.apply([], aGroups)));
+ returnVal = ((nGroups == 1) ? aGroups[0] : (Array.prototype.concat.apply(aItems, aGroups)));
+ }
+
+ return returnVal;
+
},
@@ -5116,20 +5603,23 @@
*/
getItem: function (p_nItemIndex, p_nGroupIndex) {
- var aGroup;
+ var aGroup,
+ returnVal;
- if (typeof p_nItemIndex == "number") {
+ if (Lang.isNumber(p_nItemIndex)) {
aGroup = this._getItemGroup(p_nGroupIndex);
if (aGroup) {
- return aGroup[p_nItemIndex];
+ returnVal = aGroup[p_nItemIndex];
}
}
+ return returnVal;
+
},
@@ -5159,7 +5649,7 @@
if (oItem) {
- oSubmenu = oItem.cfg.getProperty("submenu");
+ oSubmenu = oItem.cfg.getProperty(_SUBMENU);
if (oSubmenu) {
@@ -5177,6 +5667,7 @@
},
+
/**
* @method clearContent
* @description Removes all of the content from the menu, including the menu
@@ -5205,7 +5696,7 @@
if (oItem) {
- oSubmenu = oItem.cfg.getProperty("submenu");
+ oSubmenu = oItem.cfg.getProperty(_SUBMENU);
if (oSubmenu) {
@@ -5217,12 +5708,12 @@
}
- this.removeItem(oItem);
+ this.removeItem(oItem, oItem.groupIndex);
}
}
- while(i--);
+ while (i--);
}
@@ -5246,17 +5737,18 @@
Event.purgeElement(oBody);
- oBody.innerHTML = "";
+ oBody.innerHTML = _EMPTY_STRING;
}
+ this.activeItem = null;
this._aItemGroups = [];
this._aListElements = [];
this._aGroupTitleElements = [];
-
- this.cfg.setProperty("width", null);
+ this.cfg.setProperty(_WIDTH, null);
+
},
@@ -5267,9 +5759,6 @@
*/
destroy: function () {
- Module.textResizeEvent.unsubscribe(this._onTextResize, this);
-
-
// Remove all items
this.clearContent();
@@ -5283,7 +5772,7 @@
Menu.superclass.destroy.call(this);
- this.logger.log("Destroyed.");
+ YAHOO.log("Destroyed.", "info", this.toString());
},
@@ -5316,7 +5805,7 @@
if (oItem) {
- oItem.cfg.setProperty("selected", true);
+ oItem.cfg.setProperty(_SELECTED, true);
}
},
@@ -5331,7 +5820,7 @@
*/
clearActiveItem: function (p_bBlur) {
- if (this.cfg.getProperty("showdelay") > 0) {
+ if (this.cfg.getProperty(_SHOW_DELAY) > 0) {
this._cancelShowDelay();
@@ -5349,20 +5838,23 @@
if (p_bBlur) {
oActiveItem.blur();
+
+ this.getRoot()._hasFocus = true;
}
- oConfig.setProperty("selected", false);
+ oConfig.setProperty(_SELECTED, false);
- oSubmenu = oConfig.getProperty("submenu");
+ oSubmenu = oConfig.getProperty(_SUBMENU);
+
if (oSubmenu) {
oSubmenu.hide();
}
- this.activeItem = null;
+ this.activeItem = null;
}
@@ -5435,7 +5927,7 @@
function onItemAdded(p_sType, p_aArgs, p_oObject) {
var oItem = p_aArgs[0],
- oSubmenu = oItem.cfg.getProperty("submenu");
+ oSubmenu = oItem.cfg.getProperty(_SUBMENU);
if (oSubmenu) {
@@ -5446,34 +5938,60 @@
}
+ function onSubmenuAdded(p_sType, p_aArgs, p_oObject) {
+
+ var oSubmenu = this.cfg.getProperty(_SUBMENU);
+
+ if (oSubmenu) {
+
+ oSubmenu.subscribe.apply(oSubmenu, p_oObject);
+
+ }
+
+ }
+
+
Menu.superclass.subscribe.apply(this, arguments);
- Menu.superclass.subscribe.call(this, "itemAdded", onItemAdded, arguments);
+ Menu.superclass.subscribe.call(this, _ITEM_ADDED, onItemAdded, arguments);
- var aSubmenus = this.getSubmenus(),
- nSubmenus,
+ var aItems = this.getItems(),
+ nItems,
+ oItem,
oSubmenu,
i;
+
- if (aSubmenus) {
+ if (aItems) {
- nSubmenus = aSubmenus.length;
-
- if (nSubmenus > 0) {
+ nItems = aItems.length;
- i = nSubmenus - 1;
+ if (nItems > 0) {
+
+ i = nItems - 1;
do {
-
- oSubmenu = aSubmenus[i];
+
+ oItem = aItems[i];
- oSubmenu.subscribe.apply(oSubmenu, arguments);
-
+ oSubmenu = oItem.cfg.getProperty(_SUBMENU);
+
+ if (oSubmenu) {
+
+ oSubmenu.subscribe.apply(oSubmenu, arguments);
+
+ }
+ else {
+
+ oItem.cfg.subscribeToConfigEvent(_SUBMENU, onSubmenuAdded, arguments);
+
+ }
+
}
- while(i--);
+ while (i--);
}
-
+
}
},
@@ -5490,6 +6008,88 @@
var oConfig = this.cfg;
+
+ // Module documentation overrides
+
+ /**
+ * @config effect
+ * @description Object or array of objects representing the ContainerEffect
+ * classes that are active for animating the container. When set this
+ * property is automatically applied to all submenus.
+ * @type Object
+ * @default null
+ */
+
+ // Overlay documentation overrides
+
+
+ /**
+ * @config x
+ * @description Number representing the absolute x-coordinate position of
+ * the Menu. This property is only applied when the "position"
+ * configuration property is set to dynamic.
+ * @type Number
+ * @default null
+ */
+
+
+ /**
+ * @config y
+ * @description Number representing the absolute y-coordinate position of
+ * the Menu. This property is only applied when the "position"
+ * configuration property is set to dynamic.
+ * @type Number
+ * @default null
+ */
+
+
+ /**
+ * @description Array of the absolute x and y positions of the Menu. This
+ * property is only applied when the "position" configuration property is
+ * set to dynamic.
+ * @config xy
+ * @type Number[]
+ * @default null
+ */
+
+
+ /**
+ * @config context
+ * @description Array of context arguments for context-sensitive positioning.
+ * The format is: [id or element, element corner, context corner].
+ * For example, setting this property to ["img1", "tl", "bl"] would
+ * align the Mnu's top left corner to the context element's
+ * bottom left corner. This property is only applied when the "position"
+ * configuration property is set to dynamic.
+ * @type Array
+ * @default null
+ */
+
+
+ /**
+ * @config fixedcenter
+ * @description Boolean indicating if the Menu should be anchored to the
+ * center of the viewport. This property is only applied when the
+ * "position" configuration property is set to dynamic.
+ * @type Boolean
+ * @default false
+ */
+
+
+ /**
+ * @config iframe
+ * @description Boolean indicating whether or not the Menu should
+ * have an IFRAME shim; used to prevent SELECT elements from
+ * poking through an Overlay instance in IE6. When set to "true",
+ * the iframe shim is created when the Menu instance is intially
+ * made visible. This property is only applied when the "position"
+ * configuration property is set to dynamic and is automatically applied
+ * to all submenus.
+ * @type Boolean
+ * @default true for IE6 and below, false for all other browsers.
+ */
+
+
// Add configuration attributes
/*
@@ -5511,38 +6111,61 @@
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.VISIBLE.key,
+ VISIBLE_CONFIG.key,
{
handler: this.configVisible,
- value: DEFAULT_CONFIG.VISIBLE.value,
- validator: DEFAULT_CONFIG.VISIBLE.validator
- }
+ value: VISIBLE_CONFIG.value,
+ validator: VISIBLE_CONFIG.validator
+ }
);
/*
Change the default value for the "constraintoviewport" configuration
- property to "true" by re-adding the property.
+ property (inherited by YAHOO.widget.Overlay) 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.
+ * the boundaries of the size of viewport. This property is only applied
+ * when the "position" configuration property is set to dynamic and is
+ * automatically applied to all submenus.
* @default true
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.key,
+ CONSTRAIN_TO_VIEWPORT_CONFIG.key,
{
handler: this.configConstrainToViewport,
- value: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.value,
- validator: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.validator,
- supercedes: DEFAULT_CONFIG.CONSTRAIN_TO_VIEWPORT.supercedes
+ value: CONSTRAIN_TO_VIEWPORT_CONFIG.value,
+ validator: CONSTRAIN_TO_VIEWPORT_CONFIG.validator,
+ supercedes: CONSTRAIN_TO_VIEWPORT_CONFIG.supercedes
}
);
+ /*
+ Change the default value for the "preventcontextoverlap" configuration
+ property (inherited by YAHOO.widget.Overlay) to "true" by re-adding the property.
+ */
+
+ /**
+ * @config preventcontextoverlap
+ * @description Boolean indicating whether or not a submenu should overlap its parent MenuItem
+ * when the "constraintoviewport" configuration property is set to "true".
+ * @type Boolean
+ * @default true
+ */
+ oConfig.addProperty(PREVENT_CONTEXT_OVERLAP_CONFIG.key, {
+
+ value: PREVENT_CONTEXT_OVERLAP_CONFIG.value,
+ validator: PREVENT_CONTEXT_OVERLAP_CONFIG.validator,
+ supercedes: PREVENT_CONTEXT_OVERLAP_CONFIG.supercedes
+
+ });
+
+
/**
* @config position
* @description String indicating how a menu should be positioned on the
@@ -5555,12 +6178,12 @@
* @type String
*/
oConfig.addProperty(
- DEFAULT_CONFIG.POSITION.key,
+ POSITION_CONFIG.key,
{
handler: this.configPosition,
- value: DEFAULT_CONFIG.POSITION.value,
- validator: DEFAULT_CONFIG.POSITION.validator,
- supercedes: DEFAULT_CONFIG.POSITION.supercedes
+ value: POSITION_CONFIG.value,
+ validator: POSITION_CONFIG.validator,
+ supercedes: POSITION_CONFIG.supercedes
}
);
@@ -5575,9 +6198,10 @@
* @type Array
*/
oConfig.addProperty(
- DEFAULT_CONFIG.SUBMENU_ALIGNMENT.key,
+ SUBMENU_ALIGNMENT_CONFIG.key,
{
- value: DEFAULT_CONFIG.SUBMENU_ALIGNMENT.value
+ value: SUBMENU_ALIGNMENT_CONFIG.value,
+ suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
}
);
@@ -5590,10 +6214,11 @@
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.AUTO_SUBMENU_DISPLAY.key,
+ AUTO_SUBMENU_DISPLAY_CONFIG.key,
{
- value: DEFAULT_CONFIG.AUTO_SUBMENU_DISPLAY.value,
- validator: DEFAULT_CONFIG.AUTO_SUBMENU_DISPLAY.validator
+ value: AUTO_SUBMENU_DISPLAY_CONFIG.value,
+ validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
+ suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
}
);
@@ -5602,33 +6227,38 @@
* @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.
+ * the menu's items. This property is only applied when the "position"
+ * configuration property is set to dynamic and is automatically applied
+ * to all submenus.
* @default 250
* @type Number
*/
oConfig.addProperty(
- DEFAULT_CONFIG.SHOW_DELAY.key,
+ SHOW_DELAY_CONFIG.key,
{
- value: DEFAULT_CONFIG.SHOW_DELAY.value,
- validator: DEFAULT_CONFIG.SHOW_DELAY.validator
+ value: SHOW_DELAY_CONFIG.value,
+ validator: SHOW_DELAY_CONFIG.validator,
+ suppressEvent: SHOW_DELAY_CONFIG.suppressEvent
}
);
/**
* @config hidedelay
* @description Number indicating the time (in milliseconds) that should
- * expire before the menu is hidden.
+ * expire before the menu is hidden. This property is only applied when
+ * the "position" configuration property is set to dynamic and is
+ * automatically applied to all submenus.
* @default 0
* @type Number
*/
oConfig.addProperty(
- DEFAULT_CONFIG.HIDE_DELAY.key,
+ HIDE_DELAY_CONFIG.key,
{
handler: this.configHideDelay,
- value: DEFAULT_CONFIG.HIDE_DELAY.value,
- validator: DEFAULT_CONFIG.HIDE_DELAY.validator,
- suppressEvent: DEFAULT_CONFIG.HIDE_DELAY.suppressEvent
+ value: HIDE_DELAY_CONFIG.value,
+ validator: HIDE_DELAY_CONFIG.validator,
+ suppressEvent: HIDE_DELAY_CONFIG.suppressEvent
}
);
@@ -5639,30 +6269,36 @@
* expire before a submenu is hidden when the user mouses out of a menu item
* heading in the direction of a submenu. The value must be greater than or
* equal to the value specified for the "showdelay" configuration property.
+ * This property is only applied when the "position" configuration property
+ * is set to dynamic and is automatically applied to all submenus.
* @default 250
* @type Number
*/
oConfig.addProperty(
- DEFAULT_CONFIG.SUBMENU_HIDE_DELAY.key,
+ SUBMENU_HIDE_DELAY_CONFIG.key,
{
- value: DEFAULT_CONFIG.SUBMENU_HIDE_DELAY.value,
- validator: DEFAULT_CONFIG.SUBMENU_HIDE_DELAY.validator
+ value: SUBMENU_HIDE_DELAY_CONFIG.value,
+ validator: SUBMENU_HIDE_DELAY_CONFIG.validator,
+ suppressEvent: SUBMENU_HIDE_DELAY_CONFIG.suppressEvent
}
);
/**
* @config clicktohide
* @description Boolean indicating if the menu will automatically be
- * hidden if the user clicks outside of it.
+ * hidden if the user clicks outside of it. This property is only
+ * applied when the "position" configuration property is set to dynamic
+ * and is automatically applied to all submenus.
* @default true
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.CLICK_TO_HIDE.key,
+ CLICK_TO_HIDE_CONFIG.key,
{
- value: DEFAULT_CONFIG.CLICK_TO_HIDE.value,
- validator: DEFAULT_CONFIG.CLICK_TO_HIDE.validator
+ value: CLICK_TO_HIDE_CONFIG.value,
+ validator: CLICK_TO_HIDE_CONFIG.validator,
+ suppressEvent: CLICK_TO_HIDE_CONFIG.suppressEvent
}
);
@@ -5677,46 +6313,93 @@
* @default document.body
*/
oConfig.addProperty(
- DEFAULT_CONFIG.CONTAINER.key,
+ CONTAINER_CONFIG.key,
{
handler: this.configContainer,
- value: document.body
+ value: document.body,
+ suppressEvent: CONTAINER_CONFIG.suppressEvent
}
);
/**
+ * @config scrollincrement
+ * @description Number used to control the scroll speed of a menu. Used to
+ * increment the "scrollTop" property of the menu's body by when a menu's
+ * content is scrolling. When set this property is automatically applied
+ * to all submenus.
+ * @default 1
+ * @type Number
+ */
+ oConfig.addProperty(
+ SCROLL_INCREMENT_CONFIG.key,
+ {
+ value: SCROLL_INCREMENT_CONFIG.value,
+ validator: SCROLL_INCREMENT_CONFIG.validator,
+ supercedes: SCROLL_INCREMENT_CONFIG.supercedes,
+ suppressEvent: SCROLL_INCREMENT_CONFIG.suppressEvent
+ }
+ );
+
+
+ /**
+ * @config minscrollheight
+ * @description Number defining the minimum threshold for the "maxheight"
+ * configuration property. When set this property is automatically applied
+ * to all submenus.
+ * @default 90
+ * @type Number
+ */
+ oConfig.addProperty(
+ MIN_SCROLL_HEIGHT_CONFIG.key,
+ {
+ value: MIN_SCROLL_HEIGHT_CONFIG.value,
+ validator: MIN_SCROLL_HEIGHT_CONFIG.validator,
+ supercedes: MIN_SCROLL_HEIGHT_CONFIG.supercedes,
+ suppressEvent: MIN_SCROLL_HEIGHT_CONFIG.suppressEvent
+ }
+ );
+
+
+ /**
* @config maxheight
- * @description Defines the maximum height (in pixels) for a menu before the
- * contents of the body are scrolled.
+ * @description Number defining the maximum height (in pixels) for a menu's
+ * body element (<div class="bd"<
). Once a menu's body
+ * exceeds this height, the contents of the body are scrolled to maintain
+ * this value. This value cannot be set lower than the value of the
+ * "minscrollheight" configuration property.
* @default 0
* @type Number
*/
oConfig.addProperty(
- DEFAULT_CONFIG.MAX_HEIGHT.key,
+ MAX_HEIGHT_CONFIG.key,
{
handler: this.configMaxHeight,
- value: DEFAULT_CONFIG.MAX_HEIGHT.value,
- validator: DEFAULT_CONFIG.MAX_HEIGHT.validator
+ value: MAX_HEIGHT_CONFIG.value,
+ validator: MAX_HEIGHT_CONFIG.validator,
+ suppressEvent: MAX_HEIGHT_CONFIG.suppressEvent,
+ supercedes: MAX_HEIGHT_CONFIG.supercedes
}
);
/**
* @config classname
- * @description CSS class to be applied to the menu's root
- * <div>
element. The specified class(es) are
- * appended in addition to the default class as specified by the menu's
- * CSS_CLASS_NAME constant.
+ * @description String representing the CSS class to be applied to the
+ * menu's root <div>
element. The specified class(es)
+ * are appended in addition to the default class as specified by the menu's
+ * CSS_CLASS_NAME constant. When set this property is automatically
+ * applied to all submenus.
* @default null
* @type String
*/
oConfig.addProperty(
- DEFAULT_CONFIG.CLASS_NAME.key,
+ CLASS_NAME_CONFIG.key,
{
handler: this.configClassName,
- value: DEFAULT_CONFIG.CLASS_NAME.value,
- validator: DEFAULT_CONFIG.CLASS_NAME.validator
+ value: CLASS_NAME_CONFIG.value,
+ validator: CLASS_NAME_CONFIG.validator,
+ supercedes: CLASS_NAME_CONFIG.supercedes
}
);
@@ -5732,14 +6415,46 @@
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.DISABLED.key,
+ DISABLED_CONFIG.key,
{
handler: this.configDisabled,
- value: DEFAULT_CONFIG.DISABLED.value,
- validator: DEFAULT_CONFIG.DISABLED.validator
+ value: DISABLED_CONFIG.value,
+ validator: DISABLED_CONFIG.validator,
+ suppressEvent: DISABLED_CONFIG.suppressEvent
}
);
+
+ /**
+ * @config shadow
+ * @description Boolean indicating if the menu should have a shadow.
+ * @default true
+ * @type Boolean
+ */
+ oConfig.addProperty(
+ SHADOW_CONFIG.key,
+ {
+ handler: this.configShadow,
+ value: SHADOW_CONFIG.value,
+ validator: SHADOW_CONFIG.validator
+ }
+ );
+
+
+ /**
+ * @config keepopen
+ * @description Boolean indicating if the menu should remain open when clicked.
+ * @default false
+ * @type Boolean
+ */
+ oConfig.addProperty(
+ KEEP_OPEN_CONFIG.key,
+ {
+ value: KEEP_OPEN_CONFIG.value,
+ validator: KEEP_OPEN_CONFIG.validator
+ }
+ );
+
}
}); // END YAHOO.lang.extend
@@ -5748,9 +6463,8 @@
-(function() {
+(function () {
-
/**
* Creates an item for a menu.
*
@@ -5770,11 +6484,11 @@
* @class MenuItem
* @constructor
*/
-YAHOO.widget.MenuItem = function(p_oObject, p_oConfig) {
+YAHOO.widget.MenuItem = function (p_oObject, p_oConfig) {
- if(p_oObject) {
+ if (p_oObject) {
- if(p_oConfig) {
+ if (p_oConfig) {
this.parent = p_oConfig.parent;
this.value = p_oConfig.value;
@@ -5788,191 +6502,230 @@
};
+
var Dom = YAHOO.util.Dom,
Module = YAHOO.widget.Module,
Menu = YAHOO.widget.Menu,
MenuItem = YAHOO.widget.MenuItem,
CustomEvent = YAHOO.util.CustomEvent,
+ UA = YAHOO.env.ua,
Lang = YAHOO.lang,
- m_oMenuItemTemplate,
+ // Private string constants
- /**
- * Constant representing the name of the MenuItem's events
- * @property EVENT_TYPES
- * @private
- * @final
- * @type Object
- */
- EVENT_TYPES = {
-
- "MOUSE_OVER": "mouseover",
- "MOUSE_OUT": "mouseout",
- "MOUSE_DOWN": "mousedown",
- "MOUSE_UP": "mouseup",
- "CLICK": "click",
- "KEY_PRESS": "keypress",
- "KEY_DOWN": "keydown",
- "KEY_UP": "keyup",
- "ITEM_ADDED": "itemAdded",
- "ITEM_REMOVED": "itemRemoved",
- "FOCUS": "focus",
- "BLUR": "blur",
- "DESTROY": "destroy"
-
- },
+ _TEXT = "text",
+ _HASH = "#",
+ _HYPHEN = "-",
+ _HELP_TEXT = "helptext",
+ _URL = "url",
+ _TARGET = "target",
+ _EMPHASIS = "emphasis",
+ _STRONG_EMPHASIS = "strongemphasis",
+ _CHECKED = "checked",
+ _SUBMENU = "submenu",
+ _DISABLED = "disabled",
+ _SELECTED = "selected",
+ _HAS_SUBMENU = "hassubmenu",
+ _CHECKED_DISABLED = "checked-disabled",
+ _HAS_SUBMENU_DISABLED = "hassubmenu-disabled",
+ _HAS_SUBMENU_SELECTED = "hassubmenu-selected",
+ _CHECKED_SELECTED = "checked-selected",
+ _ONCLICK = "onclick",
+ _CLASSNAME = "classname",
+ _EMPTY_STRING = "",
+ _OPTION = "OPTION",
+ _OPTGROUP = "OPTGROUP",
+ _LI_UPPERCASE = "LI",
+ _HREF = "href",
+ _SELECT = "SELECT",
+ _DIV = "DIV",
+ _START_HELP_TEXT = "",
+ _START_EM = "",
+ _END_EM = "",
+ _START_STRONG = "",
+ _END_STRONG = "",
+ _PREVENT_CONTEXT_OVERLAP = "preventcontextoverlap",
+ _OBJ = "obj",
+ _SCOPE = "scope",
+ _NONE = "none",
+ _VISIBLE = "visible",
+ _SPACE = " ",
+ _MENUITEM = "MenuItem",
+ _CLICK = "click",
+ _SHOW = "show",
+ _HIDE = "hide",
+ _LI_LOWERCASE = "li",
+ _ANCHOR_TEMPLATE = "",
- /**
- * Constant representing the MenuItem's configuration properties
- * @property DEFAULT_CONFIG
- * @private
- * @final
- * @type Object
- */
- DEFAULT_CONFIG = {
+ EVENT_TYPES = [
- "TEXT": {
- key: "text",
- value: "",
- validator: Lang.isString,
- suppressEvent: true
- },
+ ["mouseOverEvent", "mouseover"],
+ ["mouseOutEvent", "mouseout"],
+ ["mouseDownEvent", "mousedown"],
+ ["mouseUpEvent", "mouseup"],
+ ["clickEvent", _CLICK],
+ ["keyPressEvent", "keypress"],
+ ["keyDownEvent", "keydown"],
+ ["keyUpEvent", "keyup"],
+ ["focusEvent", "focus"],
+ ["blurEvent", "blur"],
+ ["destroyEvent", "destroy"]
- "HELP_TEXT": {
- key: "helptext",
- supercedes: ["text"]
- },
-
- "URL": {
- key: "url",
- value: "#",
- suppressEvent: true
- },
-
- "TARGET": {
- key: "target",
- suppressEvent: true
- },
-
- "EMPHASIS": {
- key: "emphasis",
- value: false,
- validator: Lang.isBoolean,
- suppressEvent: true,
- supercedes: ["text"]
- },
-
- "STRONG_EMPHASIS": {
- key: "strongemphasis",
- value: false,
- validator: Lang.isBoolean,
- suppressEvent: true,
- supercedes: ["text"]
- },
-
- "CHECKED": {
- key: "checked",
- value: false,
- validator: Lang.isBoolean,
- suppressEvent: true,
- supercedes: ["text"]
- },
-
- "DISABLED": {
- key: "disabled",
- value: false,
- validator: Lang.isBoolean,
- suppressEvent: true,
- supercedes: ["text"]
- },
-
- "SELECTED": {
- key: "selected",
- value: false,
- validator: Lang.isBoolean,
- suppressEvent: true
- },
-
- "SUBMENU": {
- key: "submenu",
- supercedes: ["text"]
- },
-
- "ONCLICK": {
- key: "onclick"
- },
-
- "CLASS_NAME": {
- key: "classname",
- value: null,
- validator: Lang.isString
- }
-
- };
+ ],
+ TEXT_CONFIG = {
+ key: _TEXT,
+ value: _EMPTY_STRING,
+ validator: Lang.isString,
+ suppressEvent: true
+ },
-MenuItem.prototype = {
+ HELP_TEXT_CONFIG = {
+ key: _HELP_TEXT,
+ supercedes: [_TEXT],
+ suppressEvent: true
+ },
- // Constants
+ URL_CONFIG = {
+ key: _URL,
+ value: _HASH,
+ suppressEvent: true
+ },
- /**
- * @property COLLAPSED_SUBMENU_INDICATOR_TEXT
- * @description String representing the text for the <em>
- * element used for the submenu arrow indicator.
- * @default "Submenu collapsed. Click to expand submenu."
- * @final
- * @type String
- */
- COLLAPSED_SUBMENU_INDICATOR_TEXT:
- "Submenu collapsed. Click to expand submenu.",
+ TARGET_CONFIG = {
+ key: _TARGET,
+ suppressEvent: true
+ },
+ EMPHASIS_CONFIG = {
+ key: _EMPHASIS,
+ value: false,
+ validator: Lang.isBoolean,
+ suppressEvent: true,
+ supercedes: [_TEXT]
+ },
- /**
- * @property EXPANDED_SUBMENU_INDICATOR_TEXT
- * @description String representing the text for the submenu arrow indicator
- * element (<em>
) when the submenu is visible.
- * @default "Submenu expanded. Click to collapse submenu."
- * @final
- * @type String
- */
- EXPANDED_SUBMENU_INDICATOR_TEXT:
- "Submenu expanded. Click to collapse submenu.",
+ STRONG_EMPHASIS_CONFIG = {
+ key: _STRONG_EMPHASIS,
+ value: false,
+ validator: Lang.isBoolean,
+ suppressEvent: true,
+ supercedes: [_TEXT]
+ },
+ CHECKED_CONFIG = {
+ key: _CHECKED,
+ value: false,
+ validator: Lang.isBoolean,
+ suppressEvent: true,
+ supercedes: [_DISABLED, _SELECTED]
+ },
- /**
- * @property DISABLED_SUBMENU_INDICATOR_TEXT
- * @description String representing the text for the submenu arrow indicator
- * element (<em>
) when the menu item is disabled.
- * @default "Submenu collapsed. (Item disabled.)."
- * @final
- * @type String
- */
- DISABLED_SUBMENU_INDICATOR_TEXT: "Submenu collapsed. (Item disabled.)",
+ SUBMENU_CONFIG = {
+ key: _SUBMENU,
+ suppressEvent: true,
+ supercedes: [_DISABLED, _SELECTED]
+ },
+ DISABLED_CONFIG = {
+ key: _DISABLED,
+ value: false,
+ validator: Lang.isBoolean,
+ suppressEvent: true,
+ supercedes: [_TEXT, _SELECTED]
+ },
- /**
- * @property CHECKED_TEXT
- * @description String representing the text to be used for the checked
- * indicator element (<em>
).
- * @default "Checked."
- * @final
- * @type String
- */
- CHECKED_TEXT: "Menu item checked.",
+ SELECTED_CONFIG = {
+ key: _SELECTED,
+ value: false,
+ validator: Lang.isBoolean,
+ suppressEvent: true
+ },
+
+ ONCLICK_CONFIG = {
+ key: _ONCLICK,
+ suppressEvent: true
+ },
+
+ CLASS_NAME_CONFIG = {
+ key: _CLASSNAME,
+ value: null,
+ validator: Lang.isString,
+ suppressEvent: true
+ },
-
- /**
- * @property DISABLED_CHECKED_TEXT
- * @description String representing the text to be used for the checked
- * indicator element (<em>
) when the menu item
- * is disabled.
- * @default "Checked. (Item disabled.)"
- * @final
- * @type String
- */
- DISABLED_CHECKED_TEXT: "Checked. (Item disabled.)",
+ KEY_LISTENER_CONFIG = {
+ key: "keylistener",
+ value: null,
+ suppressEvent: true
+ },
+ m_oMenuItemTemplate = null,
+ CLASS_NAMES = {};
+
+
+/**
+* @method getClassNameForState
+* @description Returns a class name for the specified prefix and state. If the class name does not
+* yet exist, it is created and stored in the CLASS_NAMES object to increase performance.
+* @private
+* @param {String} prefix String representing the prefix for the class name
+* @param {String} state String representing a state - "disabled," "checked," etc.
+*/
+var getClassNameForState = function (prefix, state) {
+
+ var oClassNames = CLASS_NAMES[prefix];
+
+ if (!oClassNames) {
+ CLASS_NAMES[prefix] = {};
+ oClassNames = CLASS_NAMES[prefix];
+ }
+
+
+ var sClassName = oClassNames[state];
+
+ if (!sClassName) {
+ sClassName = prefix + _HYPHEN + state;
+ oClassNames[state] = sClassName;
+ }
+
+ return sClassName;
+
+};
+
+
+/**
+* @method addClassNameForState
+* @description Applies a class name to a MenuItem instance's <LI> and <A> elements
+* that represents a MenuItem's state - "disabled," "checked," etc.
+* @private
+* @param {String} state String representing a state - "disabled," "checked," etc.
+*/
+var addClassNameForState = function (state) {
+
+ Dom.addClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
+ Dom.addClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
+
+};
+
+/**
+* @method removeClassNameForState
+* @description Removes a class name from a MenuItem instance's <LI> and <A> elements
+* that represents a MenuItem's state - "disabled," "checked," etc.
+* @private
+* @param {String} state String representing a state - "disabled," "checked," etc.
+*/
+var removeClassNameForState = function (state) {
+
+ Dom.removeClass(this.element, getClassNameForState(this.CSS_CLASS_NAME, state));
+ Dom.removeClass(this._oAnchor, getClassNameForState(this.CSS_LABEL_CLASS_NAME, state));
+
+};
+
+
+MenuItem.prototype = {
+
/**
* @property CSS_CLASS_NAME
* @description String representing the CSS class(es) to be applied to the
@@ -6041,20 +6794,8 @@
* @type YAHOO.widget.Menu
*/
_oSubmenu: null,
-
- /**
- * @property _oCheckedIndicator
- * @description Object reference to the menu item's checkmark image.
- * @default HTMLElement
- * @private
- * @type HTMLElement
- */
- _oCheckedIndicator: null,
-
/**
* @property _oOnclickAttributeValue
* @description Object reference to the menu item's current value for the
@@ -6158,18 +6899,6 @@
value: null,
- /**
- * @property submenuIndicator
- * @description Object reference to the <em>
element
- * used to create the submenu indicator for the menu item.
- * @default HTMLElement
- * @type HTMLElement
- */
- submenuIndicator: null,
-
-
/**
* @property browser
* @deprecated Use YAHOO.env.ua
@@ -6201,7 +6930,6 @@
* element is removed from its parent <ul>
element.
* @type YAHOO.util.CustomEvent
*/
- destroyEvent: null,
/**
@@ -6210,7 +6938,6 @@
* back the DOM Event object as an argument.
* @type YAHOO.util.CustomEvent
*/
- mouseOverEvent: null,
/**
@@ -6219,7 +6946,6 @@
* the DOM Event object as an argument.
* @type YAHOO.util.CustomEvent
*/
- mouseOutEvent: null,
/**
@@ -6228,7 +6954,6 @@
* back the DOM Event object as an argument.
* @type YAHOO.util.CustomEvent
*/
- mouseDownEvent: null,
/**
@@ -6237,7 +6962,6 @@
* is over the menu item. Passes back the DOM Event object as an argument.
* @type YAHOO.util.CustomEvent
*/
- mouseUpEvent: null,
/**
@@ -6246,7 +6970,6 @@
* back the DOM Event object as an argument.
* @type YAHOO.util.CustomEvent
*/
- clickEvent: null,
/**
@@ -6255,7 +6978,6 @@
* menu item has focus. Passes back the DOM Event object as an argument.
* @type YAHOO.util.CustomEvent
*/
- keyPressEvent: null,
/**
@@ -6264,7 +6986,6 @@
* focus. Passes back the DOM Event object as an argument.
* @type YAHOO.util.CustomEvent
*/
- keyDownEvent: null,
/**
@@ -6273,23 +6994,20 @@
* focus. Passes back the DOM Event object as an argument.
* @type YAHOO.util.CustomEvent
*/
- keyUpEvent: null,
/**
* @event focusEvent
* @description Fires when the menu item receives focus.
* @type YAHOO.util.CustomEvent
*/
- focusEvent: null,
/**
* @event blurEvent
* @description Fires when the menu item loses the input focus.
* @type YAHOO.util.CustomEvent
*/
- blurEvent: null,
/**
@@ -6312,10 +7030,10 @@
* configuration for the menu item. See configuration class documentation
* for more details.
*/
- init: function(p_oObject, p_oConfig) {
+ init: function (p_oObject, p_oConfig) {
- if(!this.SUBMENU_TYPE) {
+ if (!this.SUBMENU_TYPE) {
this.SUBMENU_TYPE = Menu;
@@ -6328,49 +7046,55 @@
this.initDefaultConfig();
- var SIGNATURE = CustomEvent.LIST,
- oConfig = this.cfg,
- sURL = "#",
+ var oConfig = this.cfg,
+ sURL = _HASH,
+ oCustomEvent,
+ aEventData,
oAnchor,
sTarget,
sText,
- sId;
+ sId,
+ i;
- if(Lang.isString(p_oObject)) {
+ if (Lang.isString(p_oObject)) {
this._createRootNodeStructure();
- oConfig.queueProperty("text", p_oObject);
+ oConfig.queueProperty(_TEXT, p_oObject);
}
- else if(p_oObject && p_oObject.tagName) {
+ else if (p_oObject && p_oObject.tagName) {
switch(p_oObject.tagName.toUpperCase()) {
- case "OPTION":
+ case _OPTION:
this._createRootNodeStructure();
- oConfig.queueProperty("text", p_oObject.text);
+ oConfig.queueProperty(_TEXT, p_oObject.text);
+ oConfig.queueProperty(_DISABLED, p_oObject.disabled);
+ this.value = p_oObject.value;
+
this.srcElement = p_oObject;
break;
- case "OPTGROUP":
+ case _OPTGROUP:
this._createRootNodeStructure();
- oConfig.queueProperty("text", p_oObject.label);
+ oConfig.queueProperty(_TEXT, p_oObject.label);
+ oConfig.queueProperty(_DISABLED, p_oObject.disabled);
this.srcElement = p_oObject;
this._initSubTree();
break;
- case "LI":
+ case _LI_UPPERCASE:
// Get the anchor node (if it exists)
@@ -6379,10 +7103,11 @@
// Capture the "text" and/or the "URL"
- if(oAnchor) {
+ if (oAnchor) {
- sURL = oAnchor.getAttribute("href");
- sTarget = oAnchor.getAttribute("target");
+ sURL = oAnchor.getAttribute(_HREF, 2);
+ sTarget = oAnchor.getAttribute(_TARGET);
+
sText = oAnchor.innerHTML;
}
@@ -6397,9 +7122,9 @@
element's DOM
*/
- oConfig.setProperty("text", sText, true);
- oConfig.setProperty("url", sURL, true);
- oConfig.setProperty("target", sTarget, true);
+ oConfig.setProperty(_TEXT, sText, true);
+ oConfig.setProperty(_URL, sURL, true);
+ oConfig.setProperty(_TARGET, sTarget, true);
this._initSubTree();
@@ -6410,11 +7135,11 @@
}
- if(this.element) {
+ if (this.element) {
- sId = this.element.id;
+ sId = (this.srcElement || this.element).id;
- if(!sId) {
+ if (!sId) {
sId = this.id || Dom.generateId();
@@ -6429,42 +7154,22 @@
Dom.addClass(this._oAnchor, this.CSS_LABEL_CLASS_NAME);
- // Create custom events
+ i = EVENT_TYPES.length - 1;
- this.mouseOverEvent = this.createEvent(EVENT_TYPES.MOUSE_OVER);
- this.mouseOverEvent.signature = SIGNATURE;
+ do {
- this.mouseOutEvent = this.createEvent(EVENT_TYPES.MOUSE_OUT);
- this.mouseOutEvent.signature = SIGNATURE;
+ aEventData = EVENT_TYPES[i];
- this.mouseDownEvent = this.createEvent(EVENT_TYPES.MOUSE_DOWN);
- this.mouseDownEvent.signature = SIGNATURE;
+ oCustomEvent = this.createEvent(aEventData[1]);
+ oCustomEvent.signature = CustomEvent.LIST;
+
+ this[aEventData[0]] = oCustomEvent;
- this.mouseUpEvent = this.createEvent(EVENT_TYPES.MOUSE_UP);
- this.mouseUpEvent.signature = SIGNATURE;
+ }
+ while (i--);
- this.clickEvent = this.createEvent(EVENT_TYPES.CLICK);
- this.clickEvent.signature = SIGNATURE;
- this.keyPressEvent = this.createEvent(EVENT_TYPES.KEY_PRESS);
- this.keyPressEvent.signature = SIGNATURE;
-
- this.keyDownEvent = this.createEvent(EVENT_TYPES.KEY_DOWN);
- this.keyDownEvent.signature = SIGNATURE;
-
- this.keyUpEvent = this.createEvent(EVENT_TYPES.KEY_UP);
- this.keyUpEvent.signature = SIGNATURE;
-
- this.focusEvent = this.createEvent(EVENT_TYPES.FOCUS);
- this.focusEvent.signature = SIGNATURE;
-
- this.blurEvent = this.createEvent(EVENT_TYPES.BLUR);
- this.blurEvent.signature = SIGNATURE;
-
- this.destroyEvent = this.createEvent(EVENT_TYPES.DESTROY);
- this.destroyEvent.signature = SIGNATURE;
-
- if(p_oConfig) {
+ if (p_oConfig) {
oConfig.applyConfig(p_oConfig);
@@ -6480,7 +7185,6 @@
// Private methods
-
/**
* @method _createRootNodeStructure
* @description Creates the core DOM structure for the menu item.
@@ -6491,10 +7195,10 @@
var oElement,
oAnchor;
- if(!m_oMenuItemTemplate) {
+ if (!m_oMenuItemTemplate) {
- m_oMenuItemTemplate = document.createElement("li");
- m_oMenuItemTemplate.innerHTML = "";
+ m_oMenuItemTemplate = document.createElement(_LI_LOWERCASE);
+ m_oMenuItemTemplate.innerHTML = _ANCHOR_TEMPLATE;
}
@@ -6503,7 +7207,7 @@
oAnchor = oElement.firstChild;
oAnchor.className = this.CSS_LABEL_CLASS_NAME;
-
+
this.element = oElement;
this._oAnchor = oAnchor;
@@ -6516,7 +7220,7 @@
* the child nodes to instantiate other menus.
* @private
*/
- _initSubTree: function() {
+ _initSubTree: function () {
var oSrcEl = this.srcElement,
oConfig = this.cfg,
@@ -6527,13 +7231,13 @@
n;
- if(oSrcEl.childNodes.length > 0) {
+ if (oSrcEl.childNodes.length > 0) {
- if(this.parent.lazyLoad && this.parent.srcElement &&
- this.parent.srcElement.tagName.toUpperCase() == "SELECT") {
+ if (this.parent.lazyLoad && this.parent.srcElement &&
+ this.parent.srcElement.tagName.toUpperCase() == _SELECT) {
oConfig.setProperty(
- "submenu",
+ _SUBMENU,
{ id: Dom.generateId(), itemdata: oSrcEl.childNodes }
);
@@ -6545,17 +7249,17 @@
do {
- if(oNode && oNode.tagName) {
+ if (oNode && oNode.tagName) {
switch(oNode.tagName.toUpperCase()) {
- case "DIV":
+ case _DIV:
- oConfig.setProperty("submenu", oNode);
+ oConfig.setProperty(_SUBMENU, oNode);
break;
- case "OPTION":
+ case _OPTION:
aOptions[aOptions.length] = oNode;
@@ -6571,11 +7275,11 @@
nOptions = aOptions.length;
- if(nOptions > 0) {
+ if (nOptions > 0) {
oMenu = new this.SUBMENU_TYPE(Dom.generateId());
- oConfig.setProperty("submenu", oMenu);
+ oConfig.setProperty(_SUBMENU, oMenu);
for(n=0; noMenuItem.cfg.setProperty("text", "Copy <em
- * class=\"helptext\">Ctrl + C</em<");
+ * class=\"helptext\">Ctrl + C</em>");
* @default null
* @type String|
* HTMLElement
*/
oConfig.addProperty(
- DEFAULT_CONFIG.HELP_TEXT.key,
- { handler: this.configHelpText }
+ HELP_TEXT_CONFIG.key,
+ {
+ handler: this.configHelpText,
+ supercedes: HELP_TEXT_CONFIG.supercedes,
+ suppressEvent: HELP_TEXT_CONFIG.suppressEvent
+ }
);
@@ -7155,11 +8100,11 @@
* @type String
*/
oConfig.addProperty(
- DEFAULT_CONFIG.URL.key,
+ URL_CONFIG.key,
{
handler: this.configURL,
- value: DEFAULT_CONFIG.URL.value,
- suppressEvent: DEFAULT_CONFIG.URL.suppressEvent
+ value: URL_CONFIG.value,
+ suppressEvent: URL_CONFIG.suppressEvent
}
);
@@ -7176,10 +8121,10 @@
* @type String
*/
oConfig.addProperty(
- DEFAULT_CONFIG.TARGET.key,
+ TARGET_CONFIG.key,
{
handler: this.configTarget,
- suppressEvent: DEFAULT_CONFIG.TARGET.suppressEvent
+ suppressEvent: TARGET_CONFIG.suppressEvent
}
);
@@ -7188,19 +8133,20 @@
* @config emphasis
* @description Boolean indicating if the text of the menu item will be
* rendered with emphasis.
- * @deprecated Use "text" configuration property to add emphasis.
+ * @deprecated Use the "text" configuration property to add emphasis.
* For example: oMenuItem.cfg.setProperty("text", "<em>Some
- * Text</em<");
+ * Text</em>");
* @default false
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.EMPHASIS.key,
+ EMPHASIS_CONFIG.key,
{
handler: this.configEmphasis,
- value: DEFAULT_CONFIG.EMPHASIS.value,
- validator: DEFAULT_CONFIG.EMPHASIS.validator,
- suppressEvent: DEFAULT_CONFIG.EMPHASIS.suppressEvent
+ value: EMPHASIS_CONFIG.value,
+ validator: EMPHASIS_CONFIG.validator,
+ suppressEvent: EMPHASIS_CONFIG.suppressEvent,
+ supercedes: EMPHASIS_CONFIG.supercedes
}
);
@@ -7209,19 +8155,20 @@
* @config strongemphasis
* @description Boolean indicating if the text of the menu item will be
* rendered with strong emphasis.
- * @deprecated Use "text" configuration property to add strong emphasis.
+ * @deprecated Use the "text" configuration property to add strong emphasis.
* For example: oMenuItem.cfg.setProperty("text", "<strong>
- * Some Text</strong<");
+ * Some Text</strong>");
* @default false
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.STRONG_EMPHASIS.key,
+ STRONG_EMPHASIS_CONFIG.key,
{
handler: this.configStrongEmphasis,
- value: DEFAULT_CONFIG.STRONG_EMPHASIS.value,
- validator: DEFAULT_CONFIG.STRONG_EMPHASIS.validator,
- suppressEvent: DEFAULT_CONFIG.STRONG_EMPHASIS.suppressEvent
+ value: STRONG_EMPHASIS_CONFIG.value,
+ validator: STRONG_EMPHASIS_CONFIG.validator,
+ suppressEvent: STRONG_EMPHASIS_CONFIG.suppressEvent,
+ supercedes: STRONG_EMPHASIS_CONFIG.supercedes
}
);
@@ -7234,13 +8181,13 @@
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.CHECKED.key,
+ CHECKED_CONFIG.key,
{
handler: this.configChecked,
- value: DEFAULT_CONFIG.CHECKED.value,
- validator: DEFAULT_CONFIG.CHECKED.validator,
- suppressEvent: DEFAULT_CONFIG.CHECKED.suppressEvent,
- supercedes: DEFAULT_CONFIG.CHECKED.supercedes
+ value: CHECKED_CONFIG.value,
+ validator: CHECKED_CONFIG.validator,
+ suppressEvent: CHECKED_CONFIG.suppressEvent,
+ supercedes: CHECKED_CONFIG.supercedes
}
);
@@ -7254,12 +8201,12 @@
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.DISABLED.key,
+ DISABLED_CONFIG.key,
{
handler: this.configDisabled,
- value: DEFAULT_CONFIG.DISABLED.value,
- validator: DEFAULT_CONFIG.DISABLED.validator,
- suppressEvent: DEFAULT_CONFIG.DISABLED.suppressEvent
+ value: DISABLED_CONFIG.value,
+ validator: DISABLED_CONFIG.validator,
+ suppressEvent: DISABLED_CONFIG.suppressEvent
}
);
@@ -7272,12 +8219,12 @@
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.SELECTED.key,
+ SELECTED_CONFIG.key,
{
handler: this.configSelected,
- value: DEFAULT_CONFIG.SELECTED.value,
- validator: DEFAULT_CONFIG.SELECTED.validator,
- suppressEvent: DEFAULT_CONFIG.SELECTED.suppressEvent
+ value: SELECTED_CONFIG.value,
+ validator: SELECTED_CONFIG.validator,
+ suppressEvent: SELECTED_CONFIG.suppressEvent
}
);
@@ -7299,8 +8246,12 @@
* HTMLElement
*/
oConfig.addProperty(
- DEFAULT_CONFIG.SUBMENU.key,
- { handler: this.configSubmenu }
+ SUBMENU_CONFIG.key,
+ {
+ handler: this.configSubmenu,
+ supercedes: SUBMENU_CONFIG.supercedes,
+ suppressEvent: SUBMENU_CONFIG.suppressEvent
+ }
);
@@ -7317,8 +8268,11 @@
* @default null
*/
oConfig.addProperty(
- DEFAULT_CONFIG.ONCLICK.key,
- { handler: this.configOnClick }
+ ONCLICK_CONFIG.key,
+ {
+ handler: this.configOnClick,
+ suppressEvent: ONCLICK_CONFIG.suppressEvent
+ }
);
@@ -7332,14 +8286,34 @@
* @type String
*/
oConfig.addProperty(
- DEFAULT_CONFIG.CLASS_NAME.key,
+ CLASS_NAME_CONFIG.key,
{
handler: this.configClassName,
- value: DEFAULT_CONFIG.CLASS_NAME.value,
- validator: DEFAULT_CONFIG.CLASS_NAME.validator
+ value: CLASS_NAME_CONFIG.value,
+ validator: CLASS_NAME_CONFIG.validator,
+ suppressEvent: CLASS_NAME_CONFIG.suppressEvent
}
);
+
+ /**
+ * @config keylistener
+ * @description Object literal representing the key(s) that can be used
+ * to trigger the MenuItem's "click" event. Possible attributes are
+ * shift (boolean), alt (boolean), ctrl (boolean) and keys (either an int
+ * or an array of ints representing keycodes).
+ * @default null
+ * @type Object
+ */
+ oConfig.addProperty(
+ KEY_LISTENER_CONFIG.key,
+ {
+ handler: this.configKeyListener,
+ value: KEY_LISTENER_CONFIG.value,
+ suppressEvent: KEY_LISTENER_CONFIG.suppressEvent
+ }
+ );
+
},
@@ -7348,36 +8322,36 @@
* @description Finds the menu item's next enabled sibling.
* @return YAHOO.widget.MenuItem
*/
- getNextEnabledSibling: function() {
+ getNextEnabledSibling: function () {
var nGroupIndex,
aItemGroups,
oNextItem,
nNextGroupIndex,
- aNextGroup;
+ aNextGroup,
+ returnVal;
function getNextArrayItem(p_aArray, p_nStartIndex) {
- return p_aArray[p_nStartIndex] ||
- getNextArrayItem(p_aArray, (p_nStartIndex+1));
+ return p_aArray[p_nStartIndex] || getNextArrayItem(p_aArray, (p_nStartIndex+1));
}
- if(this.parent instanceof Menu) {
+ if (this.parent instanceof Menu) {
nGroupIndex = this.groupIndex;
aItemGroups = this.parent.getItemGroups();
- if(this.index < (aItemGroups[nGroupIndex].length - 1)) {
+ if (this.index < (aItemGroups[nGroupIndex].length - 1)) {
oNextItem = getNextArrayItem(aItemGroups[nGroupIndex],
(this.index+1));
}
else {
- if(nGroupIndex < (aItemGroups.length - 1)) {
+ if (nGroupIndex < (aItemGroups.length - 1)) {
nNextGroupIndex = nGroupIndex + 1;
@@ -7396,11 +8370,13 @@
}
- return (oNextItem.cfg.getProperty("disabled") ||
- oNextItem.element.style.display == "none") ?
+ returnVal = (oNextItem.cfg.getProperty(_DISABLED) ||
+ oNextItem.element.style.display == _NONE) ?
oNextItem.getNextEnabledSibling() : oNextItem;
}
+
+ return returnVal;
},
@@ -7410,18 +8386,18 @@
* @description Finds the menu item's previous enabled sibling.
* @return {YAHOO.widget.MenuItem}
*/
- getPreviousEnabledSibling: function() {
+ getPreviousEnabledSibling: function () {
var nGroupIndex,
aItemGroups,
oPreviousItem,
nPreviousGroupIndex,
- aPreviousGroup;
+ aPreviousGroup,
+ returnVal;
function getPreviousArrayItem(p_aArray, p_nStartIndex) {
- return p_aArray[p_nStartIndex] ||
- getPreviousArrayItem(p_aArray, (p_nStartIndex-1));
+ return p_aArray[p_nStartIndex] || getPreviousArrayItem(p_aArray, (p_nStartIndex-1));
}
@@ -7432,21 +8408,21 @@
}
- if(this.parent instanceof Menu) {
+ if (this.parent instanceof Menu) {
nGroupIndex = this.groupIndex;
aItemGroups = this.parent.getItemGroups();
- if(this.index > getFirstItemIndex(aItemGroups[nGroupIndex], 0)) {
+ if (this.index > getFirstItemIndex(aItemGroups[nGroupIndex], 0)) {
oPreviousItem = getPreviousArrayItem(aItemGroups[nGroupIndex],
(this.index-1));
}
else {
- if(nGroupIndex > getFirstItemIndex(aItemGroups, 0)) {
+ if (nGroupIndex > getFirstItemIndex(aItemGroups, 0)) {
nPreviousGroupIndex = nGroupIndex - 1;
@@ -7465,11 +8441,13 @@
}
- return (oPreviousItem.cfg.getProperty("disabled") ||
- oPreviousItem.element.style.display == "none") ?
+ returnVal = (oPreviousItem.cfg.getProperty(_DISABLED) ||
+ oPreviousItem.element.style.display == _NONE) ?
oPreviousItem.getPreviousEnabledSibling() : oPreviousItem;
}
+
+ return returnVal;
},
@@ -7479,26 +8457,31 @@
* @description Causes the menu item to receive the focus and fires the
* focus event.
*/
- focus: function() {
+ focus: function () {
var oParent = this.parent,
oAnchor = this._oAnchor,
- oActiveItem = oParent.activeItem,
- me = this;
+ oActiveItem = oParent.activeItem;
function setFocus() {
try {
- if (YAHOO.env.ua.ie && !document.hasFocus()) {
+ if (!(UA.ie && !document.hasFocus())) {
- return;
+ if (oActiveItem) {
+
+ oActiveItem.blurEvent.fire();
+
+ }
+
+ oAnchor.focus();
+
+ this.focusEvent.fire();
}
- oAnchor.focus();
-
}
catch(e) {
@@ -7507,26 +8490,17 @@
}
- if(!this.cfg.getProperty("disabled") && oParent &&
- oParent.cfg.getProperty("visible") &&
- this.element.style.display != "none") {
+ if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE) &&
+ this.element.style.display != _NONE) {
- if(oActiveItem) {
- oActiveItem.blur();
-
- }
-
-
/*
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();
+ Lang.later(0, this, setFocus);
}
@@ -7538,17 +8512,26 @@
* @description Causes the menu item to lose focus and fires the
* blur event.
*/
- blur: function() {
+ blur: function () {
var oParent = this.parent;
- if(!this.cfg.getProperty("disabled") && oParent &&
- oParent.cfg.getProperty("visible")) {
+ if (!this.cfg.getProperty(_DISABLED) && oParent && oParent.cfg.getProperty(_VISIBLE)) {
- this._oAnchor.blur();
+ Lang.later(0, this, function () {
- this.blurEvent.fire();
+ try {
+
+ this._oAnchor.blur();
+ this.blurEvent.fire();
+ }
+ catch (e) {
+
+ }
+
+ }, 0);
+
}
},
@@ -7560,7 +8543,7 @@
* has focus.
* @return {Boolean}
*/
- hasFocus: function() {
+ hasFocus: function () {
return (YAHOO.widget.MenuManager.getFocusedMenuItem() == this);
@@ -7572,55 +8555,58 @@
* @description Removes the menu item's <li>
element
* from its parent <ul>
element.
*/
- destroy: function() {
+ destroy: function () {
var oEl = this.element,
oSubmenu,
- oParentNode;
+ oParentNode,
+ aEventData,
+ i;
- if(oEl) {
+ if (oEl) {
+
// If the item has a submenu, destroy it first
- oSubmenu = this.cfg.getProperty("submenu");
+ oSubmenu = this.cfg.getProperty(_SUBMENU);
- if(oSubmenu) {
+ if (oSubmenu) {
oSubmenu.destroy();
}
- // Remove CustomEvent 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.focusEvent.unsubscribeAll();
- this.blurEvent.unsubscribeAll();
- this.cfg.configChangedEvent.unsubscribeAll();
-
-
// Remove the element from the parent node
oParentNode = oEl.parentNode;
- if(oParentNode) {
+ if (oParentNode) {
oParentNode.removeChild(oEl);
this.destroyEvent.fire();
}
- this.destroyEvent.unsubscribeAll();
+ // Remove CustomEvent listeners
+
+ i = EVENT_TYPES.length - 1;
+
+ do {
+
+ aEventData = EVENT_TYPES[i];
+
+ this[aEventData[0]].unsubscribeAll();
+
+ }
+ while (i--);
+
+
+ this.cfg.configChangedEvent.unsubscribeAll();
+
}
},
@@ -7631,14 +8617,14 @@
* @description Returns a string representing the menu item.
* @return {String}
*/
- toString: function() {
+ toString: function () {
- var sReturnVal = "MenuItem",
+ var sReturnVal = _MENUITEM,
sId = this.id;
- if(sId) {
+ if (sId) {
- sReturnVal += (" " + sId);
+ sReturnVal += (_SPACE + sId);
}
@@ -7653,6 +8639,10 @@
})();
(function () {
+ var _XY = "xy",
+ _MOUSEDOWN = "mousedown",
+ _CONTEXTMENU = "ContextMenu",
+ _SPACE = " ";
/**
* Creates a list of options or commands which are made visible in response to
@@ -7680,25 +8670,28 @@
*/
YAHOO.widget.ContextMenu = function(p_oElement, p_oConfig) {
- YAHOO.widget.ContextMenu.superclass.constructor.call(this,
- p_oElement, p_oConfig);
+ YAHOO.widget.ContextMenu.superclass.constructor.call(this, p_oElement, p_oConfig);
};
+
var Event = YAHOO.util.Event,
+ UA = YAHOO.env.ua,
ContextMenu = YAHOO.widget.ContextMenu,
-/**
-* Constant representing the name of the ContextMenu's events
-* @property EVENT_TYPES
-* @private
-* @final
-* @type Object
-*/
+
+
+ /**
+ * Constant representing the name of the ContextMenu's events
+ * @property EVENT_TYPES
+ * @private
+ * @final
+ * @type Object
+ */
EVENT_TYPES = {
"TRIGGER_CONTEXT_MENU": "triggerContextMenu",
- "CONTEXT_MENU": (YAHOO.env.ua.opera ? "mousedown" : "contextmenu"),
+ "CONTEXT_MENU": (UA.opera ? _MOUSEDOWN : "contextmenu"),
"CLICK": "click"
},
@@ -7711,15 +8704,30 @@
* @final
* @type Object
*/
- DEFAULT_CONFIG = {
-
- "TRIGGER": {
- key: "trigger"
- }
-
+ TRIGGER_CONFIG = {
+ key: "trigger",
+ suppressEvent: true
};
+/**
+* @method position
+* @description "beforeShow" event handler used to position the contextmenu.
+* @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 {Array} p_aPos Array representing the xy position for the context menu.
+*/
+function position(p_sType, p_aArgs, p_aPos) {
+
+ this.cfg.setProperty(_XY, p_aPos);
+
+ this.beforeShowEvent.unsubscribe(position, p_aPos);
+
+}
+
+
YAHOO.lang.extend(ContextMenu, YAHOO.widget.Menu, {
@@ -7803,13 +8811,7 @@
*/
init: function(p_oElement, p_oConfig) {
- if(!this.ITEM_TYPE) {
- this.ITEM_TYPE = YAHOO.widget.ContextMenuItem;
-
- }
-
-
// Call the init of the superclass (YAHOO.widget.Menu)
ContextMenu.superclass.init.call(this, p_oElement);
@@ -7818,13 +8820,12 @@
this.beforeInitEvent.fire(ContextMenu);
- if(p_oConfig) {
+ if (p_oConfig) {
this.cfg.applyConfig(p_oConfig, true);
}
-
this.initEvent.fire(ContextMenu);
},
@@ -7840,8 +8841,7 @@
// Create custom events
- this.triggerContextMenuEvent =
- this.createEvent(EVENT_TYPES.TRIGGER_CONTEXT_MENU);
+ this.triggerContextMenuEvent = this.createEvent(EVENT_TYPES.TRIGGER_CONTEXT_MENU);
this.triggerContextMenuEvent.signature = YAHOO.util.CustomEvent.LIST;
@@ -7879,13 +8879,11 @@
if (oTrigger) {
- Event.removeListener(oTrigger, EVENT_TYPES.CONTEXT_MENU,
- this._onTriggerContextMenu);
+ Event.removeListener(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu);
- if(YAHOO.env.ua.opera) {
+ if (UA.opera) {
- Event.removeListener(oTrigger, EVENT_TYPES.CLICK,
- this._onTriggerClick);
+ Event.removeListener(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick);
}
@@ -7898,6 +8896,7 @@
// Private event handlers
+
/**
* @method _onTriggerClick
* @description "click" event handler for the HTML element(s) identified as the
@@ -7910,7 +8909,7 @@
*/
_onTriggerClick: function(p_oEvent, p_oMenu) {
- if(p_oEvent.ctrlKey) {
+ if (p_oEvent.ctrlKey) {
Event.stopEvent(p_oEvent);
@@ -7931,44 +8930,57 @@
*/
_onTriggerContextMenu: function(p_oEvent, p_oMenu) {
- if(p_oEvent.type == "mousedown" && !p_oEvent.ctrlKey) {
+ var aXY;
- return;
+ if (!(p_oEvent.type == _MOUSEDOWN && !p_oEvent.ctrlKey)) {
+
+ this.contextEventTarget = Event.getTarget(p_oEvent);
+
+ this.triggerContextMenuEvent.fire(p_oEvent);
+
+
+ if (!this._bCancelled) {
- }
+ /*
+ 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.
+ */
+ Event.stopEvent(p_oEvent);
- /*
- 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.
- */
- Event.stopEvent(p_oEvent);
+ // Hide any other Menu instances that might be visible
+ YAHOO.widget.MenuManager.hideVisible();
+
+
- // Hide any other ContextMenu instances that might be visible
+ // Position and display the context menu
+
+ aXY = Event.getXY(p_oEvent);
+
+
+ if (!YAHOO.util.Dom.inDocument(this.element)) {
+
+ this.beforeShowEvent.subscribe(position, aXY);
+
+ }
+ else {
+
+ this.cfg.setProperty(_XY, aXY);
+
+ }
+
+
+ this.show();
+
+ }
+
+ this._bCancelled = false;
- YAHOO.widget.MenuManager.hideVisible();
-
-
- this.contextEventTarget = Event.getTarget(p_oEvent);
-
- this.triggerContextMenuEvent.fire(p_oEvent);
-
-
- if(!this._bCancelled) {
-
- // Position and display the context menu
-
- this.cfg.setProperty("xy", Event.getXY(p_oEvent));
-
- this.show();
-
}
- this._bCancelled = false;
-
},
@@ -7983,12 +8995,12 @@
*/
toString: function() {
- var sReturnVal = "ContextMenu",
+ var sReturnVal = _CONTEXTMENU,
sId = this.id;
- if(sId) {
+ if (sId) {
- sReturnVal += (" " + sId);
+ sReturnVal += (_SPACE + sId);
}
@@ -8016,8 +9028,12 @@
* @type String|HTMLElement|Array
*/
- this.cfg.addProperty(DEFAULT_CONFIG.TRIGGER.key,
- { handler: this.configTrigger });
+ this.cfg.addProperty(TRIGGER_CONFIG.key,
+ {
+ handler: this.configTrigger,
+ suppressEvent: TRIGGER_CONFIG.suppressEvent
+ }
+ );
},
@@ -8032,8 +9048,8 @@
// Remove the DOM event handlers from the current trigger(s)
this._removeEventHandlers();
-
+
// Continue with the superclass implementation of this method
ContextMenu.superclass.destroy.call(this);
@@ -8059,14 +9075,14 @@
var oTrigger = p_aArgs[0];
- if(oTrigger) {
+ if (oTrigger) {
/*
If there is a current "trigger" - remove the event handlers
from that element(s) before assigning new ones
*/
- if(this._oTrigger) {
+ if (this._oTrigger) {
this._removeEventHandlers();
@@ -8080,19 +9096,17 @@
support the "contextmenu" event
*/
- Event.on(oTrigger, EVENT_TYPES.CONTEXT_MENU,
- this._onTriggerContextMenu, this, true);
+ Event.on(oTrigger, EVENT_TYPES.CONTEXT_MENU, this._onTriggerContextMenu, this, true);
/*
Assign a "click" event handler to the trigger element(s) for
Opera to prevent default browser behaviors.
*/
- if(YAHOO.env.ua.opera) {
+ if (UA.opera) {
- Event.on(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick,
- this, true);
+ Event.on(oTrigger, EVENT_TYPES.CLICK, this._onTriggerClick, this, true);
}
@@ -8131,97 +9145,28 @@
* @class ContextMenuItem
* @constructor
* @extends YAHOO.widget.MenuItem
+* @deprecated As of version 2.4.0 items for YAHOO.widget.ContextMenu instances
+* are of type YAHOO.widget.MenuItem.
*/
-YAHOO.widget.ContextMenuItem = function(p_oObject, p_oConfig) {
+YAHOO.widget.ContextMenuItem = YAHOO.widget.MenuItem;
+(function () {
- YAHOO.widget.ContextMenuItem.superclass.constructor.call(this,
- p_oObject, p_oConfig);
+ var Lang = YAHOO.lang,
-};
+ // String constants
+
+ _STATIC = "static",
+ _DYNAMIC_STATIC = "dynamic," + _STATIC,
+ _DISABLED = "disabled",
+ _SELECTED = "selected",
+ _AUTO_SUBMENU_DISPLAY = "autosubmenudisplay",
+ _SUBMENU = "submenu",
+ _VISIBLE = "visible",
+ _SPACE = " ",
+ _SUBMENU_TOGGLE_REGION = "submenutoggleregion",
+ _MENUBAR = "MenuBar";
-YAHOO.lang.extend(YAHOO.widget.ContextMenuItem, YAHOO.widget.MenuItem, {
-
-
/**
-* @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.
-*/
-init: function(p_oObject, p_oConfig) {
-
- if(!this.SUBMENU_TYPE) {
-
- this.SUBMENU_TYPE = YAHOO.widget.ContextMenu;
-
- }
-
-
- /*
- 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.ContextMenuItem.superclass.init.call(this, p_oObject);
-
- var oConfig = this.cfg;
-
- if(p_oConfig) {
-
- oConfig.applyConfig(p_oConfig, true);
-
- }
-
- oConfig.fireQueue();
-
-},
-
-
-
-// Public methods
-
-
-/**
-* @method toString
-* @description Returns a string representing the context menu item.
-* @return {String}
-*/
-toString: function() {
-
- var sReturnVal = "ContextMenuItem";
-
- if(this.cfg && this.cfg.getProperty("text")) {
-
- sReturnVal += (": " + this.cfg.getProperty("text"));
-
- }
-
- return sReturnVal;
-
-}
-
-}); // END YAHOO.lang.extend
-(function () {
-
-
-/**
* Horizontal collection of items, each of which can contain a submenu.
*
* @param {String} p_oElement String specifying the id attribute of the
@@ -8246,8 +9191,7 @@
*/
YAHOO.widget.MenuBar = function(p_oElement, p_oConfig) {
- YAHOO.widget.MenuBar.superclass.constructor.call(this,
- p_oElement, p_oConfig);
+ YAHOO.widget.MenuBar.superclass.constructor.call(this, p_oElement, p_oConfig);
};
@@ -8262,52 +9206,51 @@
*/
function checkPosition(p_sPosition) {
- if (typeof p_sPosition == "string") {
+ var returnVal = false;
- return ("dynamic,static".indexOf((p_sPosition.toLowerCase())) != -1);
+ if (Lang.isString(p_sPosition)) {
+ returnVal = (_DYNAMIC_STATIC.indexOf((p_sPosition.toLowerCase())) != -1);
+
}
+
+ return returnVal;
}
var Event = YAHOO.util.Event,
- Dom = YAHOO.util.Dom,
MenuBar = YAHOO.widget.MenuBar,
- /**
- * Constant representing the MenuBar's configuration properties
- * @property DEFAULT_CONFIG
- * @private
- * @final
- * @type Object
- */
- DEFAULT_CONFIG = {
-
- "POSITION": {
- key: "position",
- value: "static",
- validator: checkPosition,
- supercedes: ["visible"]
- },
-
- "SUBMENU_ALIGNMENT": {
- key: "submenualignment",
- value: ["tl","bl"]
- },
-
- "AUTO_SUBMENU_DISPLAY": {
- key: "autosubmenudisplay",
- value: false,
- validator: YAHOO.lang.isBoolean
- }
-
- };
+ POSITION_CONFIG = {
+ key: "position",
+ value: _STATIC,
+ validator: checkPosition,
+ supercedes: [_VISIBLE]
+ },
+ SUBMENU_ALIGNMENT_CONFIG = {
+ key: "submenualignment",
+ value: ["tl","bl"]
+ },
+ AUTO_SUBMENU_DISPLAY_CONFIG = {
+ key: _AUTO_SUBMENU_DISPLAY,
+ value: false,
+ validator: Lang.isBoolean,
+ suppressEvent: true
+ },
+
+ SUBMENU_TOGGLE_REGION_CONFIG = {
+ key: _SUBMENU_TOGGLE_REGION,
+ value: false,
+ validator: Lang.isBoolean
+ };
-YAHOO.lang.extend(MenuBar, YAHOO.widget.Menu, {
+
+Lang.extend(MenuBar, YAHOO.widget.Menu, {
+
/**
* @method init
* @description The MenuBar class's initialization method. This method is
@@ -8372,7 +9315,17 @@
CSS_CLASS_NAME: "yuimenubar",
+/**
+* @property SUBMENU_TOGGLE_REGION_WIDTH
+* @description Width (in pixels) of the area of a MenuBarItem that, when pressed, will toggle the
+* display of the MenuBarItem's submenu.
+* @default 20
+* @final
+* @type Number
+*/
+SUBMENU_TOGGLE_REGION_WIDTH: 20,
+
// Protected event handlers
@@ -8395,7 +9348,7 @@
oNextItem;
- if(oItem && !oItem.cfg.getProperty("disabled")) {
+ if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
oItemCfg = oItem.cfg;
@@ -8404,10 +9357,9 @@
case 37: // Left arrow
case 39: // Right arrow
- if(oItem == this.activeItem &&
- !oItemCfg.getProperty("selected")) {
+ if(oItem == this.activeItem && !oItemCfg.getProperty(_SELECTED)) {
- oItemCfg.setProperty("selected", true);
+ oItemCfg.setProperty(_SELECTED, true);
}
else {
@@ -8420,23 +9372,20 @@
this.clearActiveItem();
- oNextItem.cfg.setProperty("selected", true);
-
-
- if(this.cfg.getProperty("autosubmenudisplay")) {
+ oNextItem.cfg.setProperty(_SELECTED, true);
- oSubmenu = oNextItem.cfg.getProperty("submenu");
-
- if(oSubmenu) {
-
- oSubmenu.show();
-
- }
-
- }
+ oSubmenu = oNextItem.cfg.getProperty(_SUBMENU);
+
+ if(oSubmenu) {
+
+ oSubmenu.show();
+ oSubmenu.setInitialFocus();
+
+ }
+ else {
+ oNextItem.focus();
+ }
- oNextItem.focus();
-
}
}
@@ -8451,16 +9400,16 @@
this.clearActiveItem();
- oItemCfg.setProperty("selected", true);
+ oItemCfg.setProperty(_SELECTED, true);
oItem.focus();
}
- oSubmenu = oItemCfg.getProperty("submenu");
+ oSubmenu = oItemCfg.getProperty(_SUBMENU);
if(oSubmenu) {
- if(oSubmenu.cfg.getProperty("visible")) {
+ if(oSubmenu.cfg.getProperty(_VISIBLE)) {
oSubmenu.setInitialSelection();
oSubmenu.setInitialFocus();
@@ -8469,6 +9418,7 @@
else {
oSubmenu.show();
+ oSubmenu.setInitialFocus();
}
@@ -8485,17 +9435,17 @@
if(oEvent.keyCode == 27 && this.activeItem) { // Esc key
- oSubmenu = this.activeItem.cfg.getProperty("submenu");
+ oSubmenu = this.activeItem.cfg.getProperty(_SUBMENU);
- if(oSubmenu && oSubmenu.cfg.getProperty("visible")) {
+ if(oSubmenu && oSubmenu.cfg.getProperty(_VISIBLE)) {
oSubmenu.hide();
this.activeItem.focus();
}
else {
- this.activeItem.cfg.setProperty("selected", false);
+ this.activeItem.cfg.setProperty(_SELECTED, false);
this.activeItem.blur();
}
@@ -8522,14 +9472,34 @@
MenuBar.superclass._onClick.call(this, p_sType, p_aArgs, p_oMenuBar);
var oItem = p_aArgs[1],
+ bReturnVal = true,
+ oItemEl,
oEvent,
oTarget,
oActiveItem,
oConfig,
- oSubmenu;
+ oSubmenu,
+ nMenuItemX,
+ nToggleRegion;
+
+
+ var toggleSubmenuDisplay = function () {
+
+ if(oSubmenu.cfg.getProperty(_VISIBLE)) {
+
+ oSubmenu.hide();
+
+ }
+ else {
+
+ oSubmenu.show();
+
+ }
+
+ };
- if(oItem && !oItem.cfg.getProperty("disabled")) {
+ if(oItem && !oItem.cfg.getProperty(_DISABLED)) {
oEvent = p_aArgs[0];
oTarget = Event.getTarget(oEvent);
@@ -8546,51 +9516,89 @@
}
- oItem.cfg.setProperty("selected", true);
+ oItem.cfg.setProperty(_SELECTED, true);
// Show the submenu for the item
- oSubmenu = oItem.cfg.getProperty("submenu");
+ oSubmenu = oItem.cfg.getProperty(_SUBMENU);
- if(oSubmenu && oTarget != oItem.submenuIndicator) {
+ if(oSubmenu) {
+
+ oItemEl = oItem.element;
+ nMenuItemX = YAHOO.util.Dom.getX(oItemEl);
+ nToggleRegion = nMenuItemX + (oItemEl.offsetWidth - this.SUBMENU_TOGGLE_REGION_WIDTH);
+
+ if (oConfig.getProperty(_SUBMENU_TOGGLE_REGION)) {
+
+ if (Event.getPageX(oEvent) > nToggleRegion) {
+
+ toggleSubmenuDisplay();
+
+ Event.preventDefault(oEvent);
+
+ /*
+ Return false so that other click event handlers are not called when the
+ user clicks inside the toggle region.
+ */
+ bReturnVal = false;
+
+ }
- if(oSubmenu.cfg.getProperty("visible")) {
+ }
+ else {
+
+ toggleSubmenuDisplay();
- oSubmenu.hide();
-
}
- else {
-
- oSubmenu.show();
-
- }
}
}
+
+ return bReturnVal;
+
},
// Public methods
+/**
+* @method configSubmenuToggle
+* @description Event handler for when the "submenutoggleregion" configuration property of
+* a MenuBar 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.
+*/
+configSubmenuToggle: function (p_sType, p_aArgs) {
+ var bSubmenuToggle = p_aArgs[0];
+
+ if (bSubmenuToggle) {
+
+ this.cfg.setProperty(_AUTO_SUBMENU_DISPLAY, false);
+
+ }
+
+},
+
+
/**
* @method toString
* @description Returns a string representing the menu bar.
* @return {String}
*/
toString: function() {
- var sReturnVal = "MenuBar",
+ var sReturnVal = _MENUBAR,
sId = this.id;
if(sId) {
- sReturnVal += (" " + sId);
+ sReturnVal += (_SPACE + sId);
}
@@ -8631,12 +9639,12 @@
* @type String
*/
oConfig.addProperty(
- DEFAULT_CONFIG.POSITION.key,
+ POSITION_CONFIG.key,
{
handler: this.configPosition,
- value: DEFAULT_CONFIG.POSITION.value,
- validator: DEFAULT_CONFIG.POSITION.validator,
- supercedes: DEFAULT_CONFIG.POSITION.supercedes
+ value: POSITION_CONFIG.value,
+ validator: POSITION_CONFIG.validator,
+ supercedes: POSITION_CONFIG.supercedes
}
);
@@ -8654,9 +9662,10 @@
* @type Array
*/
oConfig.addProperty(
- DEFAULT_CONFIG.SUBMENU_ALIGNMENT.key,
+ SUBMENU_ALIGNMENT_CONFIG.key,
{
- value: DEFAULT_CONFIG.SUBMENU_ALIGNMENT.value
+ value: SUBMENU_ALIGNMENT_CONFIG.value,
+ suppressEvent: SUBMENU_ALIGNMENT_CONFIG.suppressEvent
}
);
@@ -8674,13 +9683,36 @@
* @type Boolean
*/
oConfig.addProperty(
- DEFAULT_CONFIG.AUTO_SUBMENU_DISPLAY.key,
+ AUTO_SUBMENU_DISPLAY_CONFIG.key,
{
- value: DEFAULT_CONFIG.AUTO_SUBMENU_DISPLAY.value,
- validator: DEFAULT_CONFIG.AUTO_SUBMENU_DISPLAY.validator
+ value: AUTO_SUBMENU_DISPLAY_CONFIG.value,
+ validator: AUTO_SUBMENU_DISPLAY_CONFIG.validator,
+ suppressEvent: AUTO_SUBMENU_DISPLAY_CONFIG.suppressEvent
}
);
+
+ /**
+ * @config submenutoggleregion
+ * @description Boolean indicating if only a specific region of a MenuBarItem should toggle the
+ * display of a submenu. The default width of the region is determined by the value of the
+ * SUBMENU_TOGGLE_REGION_WIDTH property. If set to true, the autosubmenudisplay
+ * configuration property will be set to false, and any click event listeners will not be
+ * called when the user clicks inside the submenu toggle region of a MenuBarItem. If the
+ * user clicks outside of the submenu toggle region, the MenuBarItem will maintain its
+ * standard behavior.
+ * @default false
+ * @type Boolean
+ */
+ oConfig.addProperty(
+ SUBMENU_TOGGLE_REGION_CONFIG.key,
+ {
+ value: SUBMENU_TOGGLE_REGION_CONFIG.value,
+ validator: SUBMENU_TOGGLE_REGION_CONFIG.validator,
+ handler: this.configSubmenuToggle
+ }
+ );
+
}
}); // END YAHOO.lang.extend
@@ -8711,8 +9743,7 @@
*/
YAHOO.widget.MenuBarItem = function(p_oObject, p_oConfig) {
- YAHOO.widget.MenuBarItem.superclass.constructor.call(this,
- p_oObject, p_oConfig);
+ YAHOO.widget.MenuBarItem.superclass.constructor.call(this, p_oObject, p_oConfig);
};
@@ -8821,4 +9852,4 @@
}
}); // END YAHOO.lang.extend
-YAHOO.register("menu", YAHOO.widget.Menu, {version: "2.3.0", build: "442"});
+YAHOO.register("menu", YAHOO.widget.Menu, {version: "2.7.0", build: "1799"});