src/cm/media/js/lib/yui/yui_3.10.3/build/node-menunav/node-menunav-debug.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 Yahoo! Inc. All rights reserved.
       
     4 Licensed under the BSD License.
       
     5 http://yuilibrary.com/license/
       
     6 */
       
     7 
       
     8 YUI.add('node-menunav', function (Y, NAME) {
       
     9 
       
    10 /**
       
    11 * <p>The MenuNav Node Plugin makes it easy to transform existing list-based 
       
    12 * markup into traditional, drop down navigational menus that are both accessible 
       
    13 * and easy to customize, and only require a small set of dependencies.</p>
       
    14 * 
       
    15 * 
       
    16 * <p>To use the MenuNav Node Plugin, simply pass a reference to the plugin to a 
       
    17 * Node instance's <code>plug</code> method.</p>
       
    18 * 
       
    19 * <p>
       
    20 * <code>
       
    21 * &#60;script type="text/javascript"&#62; <br>
       
    22 * <br>
       
    23 * 		//	Call the "use" method, passing in "node-menunav".  This will <br>
       
    24 * 		//	load the script and CSS for the MenuNav Node Plugin and all of <br>
       
    25 * 		//	the required dependencies. <br>
       
    26 * <br>
       
    27 * 		YUI().use("node-menunav", function(Y) { <br>
       
    28 * <br>
       
    29 * 			//	Use the "contentready" event to initialize the menu when <br>
       
    30 * 			//	the subtree of element representing the root menu <br>
       
    31 * 			//	(&#60;div id="menu-1"&#62;) is ready to be scripted. <br>
       
    32 * <br>
       
    33 * 			Y.on("contentready", function () { <br>
       
    34 * <br>
       
    35 * 				//	The scope of the callback will be a Node instance <br>
       
    36 * 				//	representing the root menu (&#60;div id="menu-1"&#62;). <br>
       
    37 * 				//	Therefore, since "this" represents a Node instance, it <br>
       
    38 * 				//	is possible to just call "this.plug" passing in a <br>
       
    39 *				//	reference to the MenuNav Node Plugin. <br>
       
    40 * <br>
       
    41 * 				this.plug(Y.Plugin.NodeMenuNav); <br>
       
    42 * <br>
       
    43 * 			}, "#menu-1"); <br>
       
    44 * <br>		
       
    45 * 		}); <br>
       
    46 * <br>	
       
    47 * 	&#60;/script&#62; <br>
       
    48 * </code>
       
    49 * </p>
       
    50 *
       
    51 * <p>The MenuNav Node Plugin has several configuration properties that can be 
       
    52 * set via an object literal that is passed as a second argument to a Node 
       
    53 * instance's <code>plug</code> method.
       
    54 * </p>
       
    55 *
       
    56 * <p>
       
    57 * <code>
       
    58 * &#60;script type="text/javascript"&#62; <br>
       
    59 * <br>
       
    60 * 		//	Call the "use" method, passing in "node-menunav".  This will <br>
       
    61 * 		//	load the script and CSS for the MenuNav Node Plugin and all of <br>
       
    62 * 		//	the required dependencies. <br>
       
    63 * <br>
       
    64 * 		YUI().use("node-menunav", function(Y) { <br>
       
    65 * <br>
       
    66 * 			//	Use the "contentready" event to initialize the menu when <br>
       
    67 * 			//	the subtree of element representing the root menu <br>
       
    68 * 			//	(&#60;div id="menu-1"&#62;) is ready to be scripted. <br>
       
    69 * <br>
       
    70 * 			Y.on("contentready", function () { <br>
       
    71 * <br>
       
    72 * 				//	The scope of the callback will be a Node instance <br>
       
    73 * 				//	representing the root menu (&#60;div id="menu-1"&#62;). <br>
       
    74 * 				//	Therefore, since "this" represents a Node instance, it <br>
       
    75 * 				//	is possible to just call "this.plug" passing in a <br>
       
    76 *				//	reference to the MenuNav Node Plugin. <br>
       
    77 * <br>
       
    78 * 				this.plug(Y.Plugin.NodeMenuNav, { mouseOutHideDelay: 1000 });
       
    79 * <br><br>
       
    80 * 			}, "#menu-1"); <br>
       
    81 * <br>		
       
    82 * 		}); <br>
       
    83 * <br>	
       
    84 * 	&#60;/script&#62; <br>
       
    85 * </code>
       
    86 * </p>
       
    87 * 
       
    88 DEPRECATED. The MenuNav Node Plugin has been deprecated as of YUI 3.9.0. This module will be removed from the library in a future version. If you require functionality similar to the one provided by this module, consider taking a look at the various modules in the YUI Gallery <http://yuilibrary.com/gallery/>. 
       
    89 
       
    90 @module node-menunav
       
    91 @deprecated 3.9.0
       
    92 */
       
    93 
       
    94 
       
    95 	//	Util shortcuts
       
    96 
       
    97 var UA = Y.UA,
       
    98 	later = Y.later,
       
    99 	getClassName = Y.ClassNameManager.getClassName,
       
   100 
       
   101 
       
   102 
       
   103 	//	Frequently used strings
       
   104 
       
   105 	MENU = "menu",
       
   106 	MENUITEM = "menuitem",
       
   107 	HIDDEN = "hidden",
       
   108 	PARENT_NODE = "parentNode",
       
   109 	CHILDREN = "children",
       
   110 	OFFSET_HEIGHT = "offsetHeight",
       
   111 	OFFSET_WIDTH = "offsetWidth",
       
   112 	PX = "px",
       
   113 	ID = "id",
       
   114 	PERIOD = ".",
       
   115 	HANDLED_MOUSEOUT = "handledMouseOut",
       
   116 	HANDLED_MOUSEOVER = "handledMouseOver",
       
   117 	ACTIVE = "active",
       
   118 	LABEL = "label",
       
   119 	LOWERCASE_A = "a",
       
   120 	MOUSEDOWN = "mousedown",
       
   121 	KEYDOWN = "keydown",
       
   122 	CLICK = "click",
       
   123 	EMPTY_STRING = "",
       
   124 	FIRST_OF_TYPE = "first-of-type",
       
   125 	ROLE = "role",
       
   126 	PRESENTATION = "presentation",
       
   127 	DESCENDANTS = "descendants",
       
   128 	UI = "UI",
       
   129 	ACTIVE_DESCENDANT = "activeDescendant",
       
   130 	USE_ARIA = "useARIA",
       
   131 	ARIA_HIDDEN = "aria-hidden",
       
   132 	CONTENT = "content",
       
   133 	HOST = "host",
       
   134 	ACTIVE_DESCENDANT_CHANGE = ACTIVE_DESCENDANT + "Change",
       
   135 
       
   136 
       
   137 	//	Attribute keys
       
   138 	
       
   139 	AUTO_SUBMENU_DISPLAY = "autoSubmenuDisplay",
       
   140 	MOUSEOUT_HIDE_DELAY = "mouseOutHideDelay",
       
   141 
       
   142 
       
   143 	//	CSS class names
       
   144 
       
   145 	CSS_MENU = getClassName(MENU),
       
   146 	CSS_MENU_HIDDEN = getClassName(MENU, HIDDEN),
       
   147 	CSS_MENU_HORIZONTAL = getClassName(MENU, "horizontal"),
       
   148 	CSS_MENU_LABEL = getClassName(MENU, LABEL),
       
   149 	CSS_MENU_LABEL_ACTIVE = getClassName(MENU, LABEL, ACTIVE),
       
   150 	CSS_MENU_LABEL_MENUVISIBLE = getClassName(MENU, LABEL, (MENU + "visible")),
       
   151 	CSS_MENUITEM = getClassName(MENUITEM),
       
   152 	CSS_MENUITEM_ACTIVE = getClassName(MENUITEM, ACTIVE),
       
   153 
       
   154 
       
   155 	//	CSS selectors
       
   156 	
       
   157 	MENU_SELECTOR = PERIOD + CSS_MENU,
       
   158 	MENU_TOGGLE_SELECTOR = (PERIOD + getClassName(MENU, "toggle")),
       
   159     MENU_CONTENT_SELECTOR = PERIOD + getClassName(MENU, CONTENT),
       
   160     MENU_LABEL_SELECTOR = PERIOD + CSS_MENU_LABEL,
       
   161 
       
   162 	STANDARD_QUERY = ">" + MENU_CONTENT_SELECTOR + ">ul>li>a",
       
   163 	EXTENDED_QUERY = ">" + MENU_CONTENT_SELECTOR + ">ul>li>" + MENU_LABEL_SELECTOR + ">a:first-child";
       
   164 
       
   165 //	Utility functions
       
   166 
       
   167 
       
   168 var getPreviousSibling = function (node) {
       
   169 
       
   170 	var oPrevious = node.previous(),
       
   171 		oChildren;
       
   172 
       
   173 	if (!oPrevious) {
       
   174 		oChildren = node.get(PARENT_NODE).get(CHILDREN);
       
   175 		oPrevious = oChildren.item(oChildren.size() - 1);
       
   176 	}
       
   177 	
       
   178 	
       
   179 	return oPrevious;
       
   180 
       
   181 };
       
   182 
       
   183 
       
   184 var getNextSibling = function (node) {
       
   185 
       
   186 	var oNext = node.next();
       
   187 
       
   188 	if (!oNext) {
       
   189 		oNext = node.get(PARENT_NODE).get(CHILDREN).item(0);		
       
   190 	}
       
   191 	
       
   192 	return oNext;
       
   193 
       
   194 };
       
   195 
       
   196 
       
   197 var isAnchor = function (node) {
       
   198 	
       
   199 	var bReturnVal = false;
       
   200 	
       
   201 	if (node) {
       
   202 		bReturnVal = node.get("nodeName").toLowerCase() === LOWERCASE_A;
       
   203 	}
       
   204 	
       
   205 	return bReturnVal;
       
   206 	
       
   207 };
       
   208 
       
   209 
       
   210 var isMenuItem = function (node) {
       
   211 	
       
   212 	return node.hasClass(CSS_MENUITEM);
       
   213 
       
   214 };
       
   215 
       
   216 
       
   217 var isMenuLabel = function (node) {
       
   218 	
       
   219 	return node.hasClass(CSS_MENU_LABEL);
       
   220 
       
   221 };
       
   222 
       
   223 
       
   224 var isHorizontalMenu = function (menu) {
       
   225 	
       
   226 	return menu.hasClass(CSS_MENU_HORIZONTAL);
       
   227 
       
   228 };
       
   229 
       
   230 
       
   231 var hasVisibleSubmenu = function (menuLabel) {
       
   232 	
       
   233 	return menuLabel.hasClass(CSS_MENU_LABEL_MENUVISIBLE);
       
   234 
       
   235 };
       
   236 
       
   237 
       
   238 var getItemAnchor = function (node) {
       
   239 	
       
   240 	return isAnchor(node) ? node : node.one(LOWERCASE_A);
       
   241 
       
   242 };
       
   243 
       
   244 
       
   245 var getNodeWithClass = function (node, className, searchAncestors) {
       
   246 	
       
   247 	var oItem;
       
   248 	
       
   249 	if (node) {
       
   250 		
       
   251 		if (node.hasClass(className)) {
       
   252 			oItem = node;
       
   253 		}
       
   254 		
       
   255 		if (!oItem && searchAncestors) {
       
   256 			oItem = node.ancestor((PERIOD + className));
       
   257 		}
       
   258 	
       
   259 	}
       
   260 	
       
   261 	return oItem;
       
   262 
       
   263 };
       
   264 
       
   265 
       
   266 var getParentMenu = function (node) {
       
   267 	
       
   268 	return node.ancestor(MENU_SELECTOR);
       
   269 	
       
   270 };
       
   271 
       
   272 
       
   273 var getMenu = function (node, searchAncestors) {
       
   274 	
       
   275 	return getNodeWithClass(node, CSS_MENU, searchAncestors);
       
   276 
       
   277 };
       
   278 
       
   279 
       
   280 var getMenuItem = function (node, searchAncestors) {
       
   281 
       
   282 	var oItem;
       
   283 	
       
   284 	if (node) {
       
   285 		oItem = getNodeWithClass(node, CSS_MENUITEM, searchAncestors);
       
   286 	}
       
   287 	
       
   288 	return oItem;
       
   289 
       
   290 };
       
   291 
       
   292 
       
   293 var getMenuLabel = function (node, searchAncestors) {
       
   294 
       
   295 	var oItem;
       
   296 	
       
   297 	if (node) {
       
   298 	
       
   299 		if (searchAncestors) {
       
   300 			oItem = getNodeWithClass(node, CSS_MENU_LABEL, searchAncestors);
       
   301 		}
       
   302 		else {
       
   303 			oItem = getNodeWithClass(node, CSS_MENU_LABEL) || 
       
   304 				node.one((PERIOD + CSS_MENU_LABEL));
       
   305 		}
       
   306 		
       
   307 	}
       
   308 	
       
   309 	return oItem;
       
   310 
       
   311 };
       
   312 
       
   313 
       
   314 var getItem = function (node, searchAncestors) {
       
   315 
       
   316 	var oItem;
       
   317 	
       
   318 	if (node) {
       
   319 		oItem = getMenuItem(node, searchAncestors) || 
       
   320 			getMenuLabel(node, searchAncestors);
       
   321 	}
       
   322 	
       
   323 	return oItem;	
       
   324 
       
   325 };
       
   326 
       
   327 
       
   328 var getFirstItem = function (menu) {
       
   329 	
       
   330 	return getItem(menu.one("li"));
       
   331 
       
   332 };
       
   333 
       
   334 
       
   335 var getActiveClass = function (node) {
       
   336 	
       
   337 	return isMenuItem(node) ? CSS_MENUITEM_ACTIVE : CSS_MENU_LABEL_ACTIVE;
       
   338 
       
   339 };
       
   340 
       
   341 
       
   342 var handleMouseOverForNode = function (node, target) {
       
   343 	
       
   344 	return node && !node[HANDLED_MOUSEOVER] && 
       
   345 		(node.compareTo(target) || node.contains(target));
       
   346 
       
   347 };
       
   348 
       
   349 
       
   350 var handleMouseOutForNode = function (node, relatedTarget) {
       
   351 	
       
   352 	return node && !node[HANDLED_MOUSEOUT] && 
       
   353 		(!node.compareTo(relatedTarget) && !node.contains(relatedTarget));
       
   354 
       
   355 };
       
   356 
       
   357 /**
       
   358 * The NodeMenuNav class is a plugin for a Node instance.  The class is used via  
       
   359 * the <a href="Node.html#method_plug"><code>plug</code></a> method of Node and 
       
   360 * should not be instantiated directly.
       
   361 * @namespace plugin
       
   362 * @class NodeMenuNav
       
   363 */
       
   364 var NodeMenuNav = function () {
       
   365 
       
   366 	NodeMenuNav.superclass.constructor.apply(this, arguments);
       
   367 
       
   368 };
       
   369 
       
   370 NodeMenuNav.NAME = "nodeMenuNav";
       
   371 NodeMenuNav.NS = "menuNav";
       
   372 
       
   373 
       
   374 /** 
       
   375 * @property SHIM_TEMPLATE_TITLE
       
   376 * @description String representing the value for the <code>title</code> 
       
   377 * attribute for the shim used to prevent <code>&#60;select&#62;</code> elements 
       
   378 * from poking through menus in IE 6.
       
   379 * @default "Menu Stacking Shim"
       
   380 * @type String
       
   381 */
       
   382 NodeMenuNav.SHIM_TEMPLATE_TITLE = "Menu Stacking Shim";
       
   383 
       
   384 
       
   385 /** 
       
   386 * @property SHIM_TEMPLATE
       
   387 * @description String representing the HTML used to create the 
       
   388 * <code>&#60;iframe&#62;</code> shim used to prevent 
       
   389 * <code>&#60;select&#62;</code> elements from poking through menus in IE 6.
       
   390 * @default &#34;&#60;iframe frameborder=&#34;0&#34; tabindex=&#34;-1&#34; 
       
   391 * class=&#34;yui-shim&#34; title=&#34;Menu Stacking Shim&#34; 
       
   392 * src=&#34;javascript:false;&#34;&#62;&#60;/iframe&#62;&#34;
       
   393 * @type String
       
   394 */
       
   395 
       
   396 //	<iframe> shim notes:
       
   397 //
       
   398 //	1) Need to set the "frameBorder" property to 0 to suppress the default 
       
   399 //	<iframe> border in IE.  (Setting the CSS "border" property alone doesn't  
       
   400 //	suppress it.) 
       
   401 //
       
   402 //	2) The "src" attribute of the <iframe> is set to "javascript:false;" so 
       
   403 //	that it won't load a page inside it, preventing the secure/nonsecure 
       
   404 //	warning in IE when using HTTPS.
       
   405 //
       
   406 //	3) Since the role of the <iframe> shim is completely presentational, its 
       
   407 //	"tabindex" attribute is set to "-1" and its title attribute is set to 
       
   408 //	"Menu Stacking Shim".  Both strategies help users of screen readers to 
       
   409 //	avoid mistakenly interacting with the <iframe> shim.
       
   410 
       
   411 NodeMenuNav.SHIM_TEMPLATE = '<iframe frameborder="0" tabindex="-1" class="' + 
       
   412 							getClassName("shim") + 
       
   413 							'" title="' + NodeMenuNav.SHIM_TEMPLATE_TITLE + 
       
   414 							'" src="javascript:false;"></iframe>';
       
   415 
       
   416 
       
   417 NodeMenuNav.ATTRS = {
       
   418 
       
   419 	/**
       
   420 	* Boolean indicating if use of the WAI-ARIA Roles and States should be 
       
   421 	* enabled for the menu.
       
   422 	*
       
   423 	* @attribute useARIA
       
   424 	* @readOnly
       
   425 	* @writeOnce	
       
   426 	* @default true
       
   427 	* @type boolean
       
   428 	*/
       
   429 	useARIA: {
       
   430 		
       
   431 		value: true,
       
   432 		writeOnce: true,
       
   433 		lazyAdd: false,
       
   434 		setter: function (value) {
       
   435 
       
   436 			var oMenu = this.get(HOST),
       
   437 				oMenuLabel,
       
   438 				oMenuToggle,
       
   439 				oSubmenu,
       
   440 				sID;
       
   441 
       
   442 			if (value) {
       
   443 
       
   444 				oMenu.set(ROLE, MENU);
       
   445 
       
   446 				oMenu.all("ul,li," + MENU_CONTENT_SELECTOR).set(ROLE, PRESENTATION);
       
   447 
       
   448 				oMenu.all((PERIOD + getClassName(MENUITEM, CONTENT))).set(ROLE, MENUITEM);
       
   449 
       
   450 				oMenu.all((PERIOD + CSS_MENU_LABEL)).each(function (node) {
       
   451 
       
   452 					oMenuLabel = node;
       
   453 					oMenuToggle = node.one(MENU_TOGGLE_SELECTOR);
       
   454 
       
   455 					if (oMenuToggle) {
       
   456 						oMenuToggle.set(ROLE, PRESENTATION);
       
   457 						oMenuLabel = oMenuToggle.previous();
       
   458 					}
       
   459 
       
   460 					oMenuLabel.set(ROLE, MENUITEM);
       
   461 					oMenuLabel.set("aria-haspopup", true);
       
   462 
       
   463 					oSubmenu = node.next();
       
   464 
       
   465 					if (oSubmenu) {
       
   466 
       
   467 						oSubmenu.set(ROLE, MENU);
       
   468 
       
   469 						oMenuLabel = oSubmenu.previous();
       
   470 						oMenuToggle = oMenuLabel.one(MENU_TOGGLE_SELECTOR);
       
   471 
       
   472 						if (oMenuToggle) {
       
   473 							oMenuLabel = oMenuToggle;
       
   474 						}
       
   475 
       
   476 						sID = Y.stamp(oMenuLabel);
       
   477 
       
   478 						if (!oMenuLabel.get(ID)) {
       
   479 							oMenuLabel.set(ID, sID);
       
   480 						}
       
   481 
       
   482 						oSubmenu.set("aria-labelledby", sID);
       
   483 						oSubmenu.set(ARIA_HIDDEN, true);
       
   484 						
       
   485 					}
       
   486 
       
   487 				});
       
   488 				
       
   489 			}
       
   490 
       
   491 		}
       
   492 		
       
   493 	},
       
   494 
       
   495 
       
   496 	/**
       
   497 	* Boolean indicating if submenus are automatically made visible when the 
       
   498 	* user mouses over the menu's items.
       
   499 	*
       
   500 	* @attribute autoSubmenuDisplay
       
   501 	* @readOnly
       
   502 	* @writeOnce	
       
   503 	* @default true
       
   504 	* @type boolean
       
   505 	*/	
       
   506 	autoSubmenuDisplay: {
       
   507 		
       
   508 		value: true,
       
   509 		writeOnce: true
       
   510 		
       
   511 	},
       
   512 
       
   513 
       
   514 	/**
       
   515 	* Number indicating the time (in milliseconds) that should expire before a 
       
   516 	* submenu is made visible when the user mouses over the menu's label.
       
   517 	*
       
   518 	* @attribute submenuShowDelay
       
   519 	* @readOnly
       
   520 	* @writeOnce	
       
   521 	* @default 250
       
   522 	* @type Number
       
   523 	*/
       
   524 	submenuShowDelay: {
       
   525 		
       
   526 		value: 250,
       
   527 		writeOnce: true
       
   528 		
       
   529 	},
       
   530 
       
   531 
       
   532 	/**
       
   533 	* Number indicating the time (in milliseconds) that should expire before a 
       
   534 	* submenu is hidden when the user mouses out of a menu label heading in the 
       
   535 	* direction of a submenu.  
       
   536 	*
       
   537 	* @attribute submenuHideDelay
       
   538 	* @readOnly
       
   539 	* @writeOnce	
       
   540 	* @default 250
       
   541 	* @type Number
       
   542 	*/
       
   543 	submenuHideDelay: {
       
   544 		
       
   545 		value: 250,
       
   546 		writeOnce: true
       
   547 		
       
   548 	},
       
   549 
       
   550 
       
   551 	/**
       
   552 	* Number indicating the time (in milliseconds) that should expire before a 
       
   553 	* submenu is hidden when the user mouses out of it.
       
   554 	* 
       
   555 	* @attribute mouseOutHideDelay
       
   556 	* @readOnly
       
   557 	* @writeOnce	
       
   558 	* @default 750
       
   559 	* @type Number
       
   560 	*/	
       
   561 	mouseOutHideDelay: {
       
   562 		
       
   563 		value: 750,
       
   564 		writeOnce: true
       
   565 		
       
   566 	}
       
   567 
       
   568 };
       
   569 
       
   570 
       
   571 Y.extend(NodeMenuNav, Y.Plugin.Base, {
       
   572 
       
   573 	//	Protected properties
       
   574 
       
   575 	/** 
       
   576 	* @property _rootMenu
       
   577 	* @description Node instance representing the root menu in the menu.
       
   578 	* @default null
       
   579 	* @protected
       
   580 	* @type Node
       
   581 	*/
       
   582 	_rootMenu: null,	
       
   583 
       
   584 
       
   585 	/** 
       
   586 	* @property _activeItem
       
   587 	* @description Node instance representing the menu's active descendent: 
       
   588 	* the menuitem or menu label the user is currently interacting with.
       
   589 	* @default null
       
   590 	* @protected
       
   591 	* @type Node
       
   592 	*/
       
   593 	_activeItem: null, 
       
   594 
       
   595 
       
   596 	/** 
       
   597 	* @property _activeMenu
       
   598 	* @description Node instance representing the menu that is the parent of 
       
   599 	* the menu's active descendent.
       
   600 	* @default null
       
   601 	* @protected
       
   602 	* @type Node
       
   603 	*/
       
   604 	_activeMenu: null,
       
   605 
       
   606 
       
   607 	/** 
       
   608 	* @property _hasFocus
       
   609 	* @description Boolean indicating if the menu has focus.
       
   610 	* @default false
       
   611 	* @protected
       
   612 	* @type Boolean
       
   613 	*/
       
   614 	_hasFocus: false,
       
   615 
       
   616 
       
   617 	//	In gecko-based browsers a mouseover and mouseout event will fire even 
       
   618 	//	if a DOM element moves out from under the mouse without the user 
       
   619 	//	actually moving the mouse.  This bug affects NodeMenuNav because the  
       
   620 	//	user can hit the Esc key to hide a menu, and if the mouse is over the  
       
   621 	//	menu when the user presses Esc, the _onMenuMouseOut handler will be 
       
   622 	//	called.  To fix this bug the following flag (_blockMouseEvent) is used 
       
   623 	// to block the code in the _onMenuMouseOut handler from executing.
       
   624 
       
   625 	/** 
       
   626 	* @property _blockMouseEvent
       
   627 	* @description Boolean indicating whether or not to handle the 
       
   628 	* "mouseover" event.
       
   629 	* @default false
       
   630 	* @protected
       
   631 	* @type Boolean
       
   632 	*/
       
   633 	_blockMouseEvent: false,
       
   634 
       
   635 
       
   636 	/** 
       
   637 	* @property _currentMouseX
       
   638 	* @description Number representing the current x coordinate of the mouse 
       
   639 	* inside the menu.
       
   640 	* @default 0
       
   641 	* @protected
       
   642 	* @type Number
       
   643 	*/
       
   644 	_currentMouseX: 0,
       
   645 
       
   646 
       
   647 	/** 
       
   648 	* @property _movingToSubmenu
       
   649 	* @description Boolean indicating if the mouse is moving from a menu 
       
   650 	* label to its corresponding submenu.
       
   651 	* @default false
       
   652 	* @protected
       
   653 	* @type Boolean
       
   654 	*/
       
   655 	_movingToSubmenu: false,
       
   656 
       
   657 
       
   658 	/** 
       
   659 	* @property _showSubmenuTimer
       
   660 	* @description Timer used to show a submenu.
       
   661 	* @default null
       
   662 	* @protected
       
   663 	* @type Object
       
   664 	*/
       
   665 	_showSubmenuTimer: null,
       
   666 
       
   667 
       
   668 	/** 
       
   669 	* @property _hideSubmenuTimer
       
   670 	* @description Timer used to hide a submenu.
       
   671 	* @default null
       
   672 	* @protected
       
   673 	* @type Object
       
   674 	*/
       
   675 	_hideSubmenuTimer: null,
       
   676 
       
   677 
       
   678 	/** 
       
   679 	* @property _hideAllSubmenusTimer
       
   680 	* @description Timer used to hide a all submenus.
       
   681 	* @default null
       
   682 	* @protected
       
   683 	* @type Object
       
   684 	*/
       
   685 	_hideAllSubmenusTimer: null,
       
   686 
       
   687 
       
   688 	/** 
       
   689 	* @property _firstItem
       
   690 	* @description Node instance representing the first item (menuitem or menu 
       
   691 	* label) in the root menu of a menu.
       
   692 	* @default null
       
   693 	* @protected
       
   694 	* @type Node
       
   695 	*/
       
   696 	_firstItem: null,
       
   697 
       
   698 
       
   699 	//	Public methods
       
   700 
       
   701 
       
   702     initializer: function (config) {
       
   703 
       
   704 		var menuNav = this,
       
   705 			oRootMenu = this.get(HOST),
       
   706 			aHandlers = [],
       
   707 			oDoc;
       
   708 
       
   709 		Y.log("WARNING: Node-MenuNav is a deprecated module as of YUI 3.9.0. This module will be removed from a later version of the library.", "warn");
       
   710 
       
   711 		if (oRootMenu) {
       
   712 
       
   713 			menuNav._rootMenu = oRootMenu;
       
   714 
       
   715 			oRootMenu.all("ul:first-child").addClass(FIRST_OF_TYPE);
       
   716 
       
   717 			//	Hide all visible submenus
       
   718 
       
   719 			oRootMenu.all(MENU_SELECTOR).addClass(CSS_MENU_HIDDEN);
       
   720 
       
   721 
       
   722 			//	Wire up all event handlers
       
   723 
       
   724 			aHandlers.push(oRootMenu.on("mouseover", menuNav._onMouseOver, menuNav));
       
   725 			aHandlers.push(oRootMenu.on("mouseout", menuNav._onMouseOut, menuNav));
       
   726 			aHandlers.push(oRootMenu.on("mousemove", menuNav._onMouseMove, menuNav));
       
   727 			aHandlers.push(oRootMenu.on(MOUSEDOWN, menuNav._toggleSubmenuDisplay, menuNav));
       
   728 			aHandlers.push(Y.on("key", menuNav._toggleSubmenuDisplay, oRootMenu, "down:13", menuNav));
       
   729 			aHandlers.push(oRootMenu.on(CLICK, menuNav._toggleSubmenuDisplay, menuNav));
       
   730 			aHandlers.push(oRootMenu.on("keypress", menuNav._onKeyPress, menuNav));
       
   731 			aHandlers.push(oRootMenu.on(KEYDOWN, menuNav._onKeyDown, menuNav));
       
   732 
       
   733 			oDoc = oRootMenu.get("ownerDocument");
       
   734 
       
   735 		    aHandlers.push(oDoc.on(MOUSEDOWN, menuNav._onDocMouseDown, menuNav));
       
   736 			aHandlers.push(oDoc.on("focus", menuNav._onDocFocus, menuNav));
       
   737 
       
   738 			this._eventHandlers = aHandlers;
       
   739 
       
   740 			menuNav._initFocusManager();
       
   741 
       
   742 		}
       
   743 		
       
   744 
       
   745     },
       
   746 
       
   747 	destructor: function () {
       
   748 
       
   749 		var aHandlers = this._eventHandlers;
       
   750 
       
   751 		if (aHandlers) {
       
   752 
       
   753 			Y.Array.each(aHandlers, function (handle) {
       
   754 				handle.detach();
       
   755 			});
       
   756 
       
   757 			this._eventHandlers = null;
       
   758 
       
   759 		}
       
   760 		
       
   761 		this.get(HOST).unplug("focusManager");
       
   762 		
       
   763     },
       
   764 
       
   765 
       
   766 
       
   767 	//	Protected methods
       
   768 
       
   769 	/**
       
   770 	* @method _isRoot
       
   771 	* @description Returns a boolean indicating if the specified menu is the 
       
   772 	* root menu in the menu.
       
   773 	* @protected
       
   774 	* @param {Node} menu Node instance representing a menu.
       
   775 	* @return {Boolean} Boolean indicating if the specified menu is the root 
       
   776 	* menu in the menu.
       
   777 	*/
       
   778 	_isRoot: function (menu) {
       
   779 
       
   780 		return this._rootMenu.compareTo(menu);
       
   781 
       
   782 	},
       
   783 
       
   784 
       
   785 	/**
       
   786 	* @method _getTopmostSubmenu
       
   787 	* @description Returns the topmost submenu of a submenu hierarchy.
       
   788 	* @protected
       
   789 	* @param {Node} menu Node instance representing a menu.
       
   790 	* @return {Node} Node instance representing a menu.
       
   791 	*/
       
   792 	_getTopmostSubmenu: function (menu) {
       
   793 	
       
   794 		var menuNav = this,
       
   795 			oMenu = getParentMenu(menu),
       
   796 			returnVal;
       
   797 
       
   798 
       
   799 		if (!oMenu) {
       
   800 			returnVal = menu;
       
   801 		}
       
   802 		else if (menuNav._isRoot(oMenu)) {
       
   803 			returnVal = menu;
       
   804 		}
       
   805 		else {
       
   806 			returnVal = menuNav._getTopmostSubmenu(oMenu);
       
   807 		}
       
   808 	
       
   809 		return returnVal;
       
   810 	
       
   811 	},
       
   812 
       
   813 
       
   814 	/**
       
   815 	* @method _clearActiveItem
       
   816 	* @description Clears the menu's active descendent.
       
   817 	* @protected
       
   818 	*/
       
   819 	_clearActiveItem: function () {
       
   820 
       
   821 		var menuNav = this,
       
   822 			oActiveItem = menuNav._activeItem;
       
   823 		
       
   824 		if (oActiveItem) {
       
   825 			oActiveItem.removeClass(getActiveClass(oActiveItem));
       
   826 		}
       
   827 
       
   828 		menuNav._activeItem = null;
       
   829 	
       
   830 	},
       
   831 
       
   832 
       
   833 	/**
       
   834 	* @method _setActiveItem
       
   835 	* @description Sets the specified menuitem or menu label as the menu's 
       
   836 	* active descendent.
       
   837 	* @protected
       
   838 	* @param {Node} item Node instance representing a menuitem or menu label.
       
   839 	*/
       
   840 	_setActiveItem: function (item) {
       
   841 
       
   842 		var menuNav = this;
       
   843 	
       
   844 		if (item) {
       
   845 			
       
   846 			menuNav._clearActiveItem();
       
   847 	
       
   848 			item.addClass(getActiveClass(item));
       
   849 			
       
   850 			menuNav._activeItem = item;
       
   851 		
       
   852 		}
       
   853 	
       
   854 	},
       
   855 
       
   856 
       
   857 	/**
       
   858 	* @method _focusItem
       
   859 	* @description Focuses the specified menuitem or menu label.
       
   860 	* @protected
       
   861 	* @param {Node} item Node instance representing a menuitem or menu label.
       
   862 	*/
       
   863 	_focusItem: function (item) {
       
   864 	
       
   865 		var menuNav = this,
       
   866 			oMenu,
       
   867 			oItem;
       
   868 	
       
   869 		if (item && menuNav._hasFocus) {
       
   870 
       
   871 			oMenu = getParentMenu(item);
       
   872 			oItem = getItemAnchor(item);
       
   873 
       
   874 			if (oMenu && !oMenu.compareTo(menuNav._activeMenu)) {
       
   875 				menuNav._activeMenu = oMenu;
       
   876 				menuNav._initFocusManager();
       
   877 			}
       
   878 		
       
   879 			menuNav._focusManager.focus(oItem);
       
   880 
       
   881 		}
       
   882 	
       
   883 	},
       
   884 
       
   885 
       
   886 	/**
       
   887 	* @method _showMenu
       
   888 	* @description Shows the specified menu.
       
   889 	* @protected
       
   890 	* @param {Node} menu Node instance representing a menu.
       
   891 	*/
       
   892 	_showMenu: function (menu) {
       
   893 
       
   894 		var oParentMenu = getParentMenu(menu),
       
   895 			oLI = menu.get(PARENT_NODE),
       
   896 			aXY = oLI.getXY();
       
   897 
       
   898 
       
   899 		if (this.get(USE_ARIA)) {
       
   900 			menu.set(ARIA_HIDDEN, false);
       
   901 		}
       
   902 
       
   903 
       
   904 		if (isHorizontalMenu(oParentMenu)) {
       
   905 			aXY[1] = aXY[1] + oLI.get(OFFSET_HEIGHT);
       
   906 		}
       
   907 		else {
       
   908 			aXY[0] = aXY[0] + oLI.get(OFFSET_WIDTH);
       
   909 		}
       
   910 		
       
   911 		menu.setXY(aXY);
       
   912 
       
   913 		if (UA.ie < 8) {
       
   914 
       
   915 			if (UA.ie === 6 && !menu.hasIFrameShim) {
       
   916 	
       
   917 				menu.appendChild(Y.Node.create(NodeMenuNav.SHIM_TEMPLATE));
       
   918 				menu.hasIFrameShim = true;
       
   919 
       
   920 			}
       
   921 
       
   922 			//	Clear previous values for height and width
       
   923 
       
   924 			menu.setStyles({ height: EMPTY_STRING, width: EMPTY_STRING });
       
   925 
       
   926 			//	Set the width and height of the menu's bounding box - this is 
       
   927 			//	necessary for IE 6 so that the CSS for the <iframe> shim can 
       
   928 			//	simply set the <iframe>'s width and height to 100% to ensure 
       
   929 			//	that dimensions of an <iframe> shim are always sync'd to the 
       
   930 			//	that of its parent menu.  Specifying a width and height also 
       
   931 			//	helps when positioning decorator elements (for creating effects 
       
   932 			//	like rounded corners) inside a menu's bounding box in IE 7.
       
   933 			
       
   934 			menu.setStyles({ 
       
   935 				height: (menu.get(OFFSET_HEIGHT) + PX), 
       
   936 				width: (menu.get(OFFSET_WIDTH) + PX) });
       
   937 
       
   938 		}
       
   939 
       
   940 		menu.previous().addClass(CSS_MENU_LABEL_MENUVISIBLE);
       
   941 		menu.removeClass(CSS_MENU_HIDDEN);
       
   942 
       
   943 	},
       
   944 	
       
   945 
       
   946 	/**
       
   947 	* @method _hideMenu 
       
   948 	* @description Hides the specified menu.
       
   949 	* @protected
       
   950 	* @param {Node} menu Node instance representing a menu.
       
   951 	* @param {Boolean} activateAndFocusLabel Boolean indicating if the label 
       
   952 	* for the specified 
       
   953 	* menu should be focused and set as active.
       
   954 	*/
       
   955 	_hideMenu: function (menu, activateAndFocusLabel) {
       
   956 
       
   957 		var menuNav = this,
       
   958 			oLabel = menu.previous(),
       
   959 			oActiveItem;
       
   960 
       
   961 		oLabel.removeClass(CSS_MENU_LABEL_MENUVISIBLE);
       
   962 
       
   963 
       
   964 		if (activateAndFocusLabel) {
       
   965 			menuNav._focusItem(oLabel);
       
   966 			menuNav._setActiveItem(oLabel);			
       
   967 		}
       
   968 
       
   969 		oActiveItem = menu.one((PERIOD + CSS_MENUITEM_ACTIVE));
       
   970 
       
   971 		if (oActiveItem) {
       
   972 			oActiveItem.removeClass(CSS_MENUITEM_ACTIVE);
       
   973 		}
       
   974 
       
   975 		//	Clear the values for top and left that were set by the call to 
       
   976 		//	"setXY" when the menu was shown so that the hidden position 
       
   977 		//	specified in the core CSS file will take affect.
       
   978 
       
   979 		menu.setStyles({ left: EMPTY_STRING, top: EMPTY_STRING });
       
   980 		
       
   981 		menu.addClass(CSS_MENU_HIDDEN);
       
   982 
       
   983 		if (menuNav.get(USE_ARIA)) {
       
   984 			menu.set(ARIA_HIDDEN, true);
       
   985 		}	
       
   986 		
       
   987 	},
       
   988 
       
   989 
       
   990 	/**
       
   991 	* @method _hideAllSubmenus
       
   992 	* @description Hides all submenus of the specified menu.
       
   993 	* @protected
       
   994 	* @param {Node} menu Node instance representing a menu.
       
   995 	*/
       
   996 	_hideAllSubmenus: function (menu) {
       
   997 
       
   998 		var menuNav = this;
       
   999 
       
  1000 		menu.all(MENU_SELECTOR).each(Y.bind(function (submenuNode) {
       
  1001 		
       
  1002 			menuNav._hideMenu(submenuNode);
       
  1003 		
       
  1004 		}, menuNav));
       
  1005 	
       
  1006 	},
       
  1007 
       
  1008 
       
  1009 	/**
       
  1010 	* @method _cancelShowSubmenuTimer
       
  1011 	* @description Cancels the timer used to show a submenu.
       
  1012 	* @protected
       
  1013 	*/
       
  1014 	_cancelShowSubmenuTimer: function () {
       
  1015 
       
  1016 		var menuNav = this,
       
  1017 			oShowSubmenuTimer = menuNav._showSubmenuTimer;
       
  1018 
       
  1019 		if (oShowSubmenuTimer) {
       
  1020 			oShowSubmenuTimer.cancel();
       
  1021 			menuNav._showSubmenuTimer = null;
       
  1022 		}
       
  1023 	
       
  1024 	},
       
  1025 
       
  1026 
       
  1027 	/**
       
  1028 	* @method _cancelHideSubmenuTimer
       
  1029 	* @description Cancels the timer used to hide a submenu.
       
  1030 	* @protected
       
  1031 	*/
       
  1032 	_cancelHideSubmenuTimer: function () {
       
  1033 
       
  1034 		var menuNav = this,
       
  1035 			oHideSubmenuTimer = menuNav._hideSubmenuTimer;
       
  1036 
       
  1037 
       
  1038 		if (oHideSubmenuTimer) {
       
  1039 			oHideSubmenuTimer.cancel();
       
  1040 			menuNav._hideSubmenuTimer = null;
       
  1041 		}
       
  1042 	
       
  1043 	},
       
  1044 
       
  1045 
       
  1046 	/**
       
  1047 	* @method _initFocusManager
       
  1048 	* @description Initializes and updates the Focus Manager so that is is 
       
  1049 	* always managing descendants of the active menu.
       
  1050 	* @protected
       
  1051 	*/
       
  1052 	_initFocusManager: function () {
       
  1053 
       
  1054 		var menuNav = this,
       
  1055 			oRootMenu = menuNav._rootMenu,
       
  1056 			oMenu = menuNav._activeMenu || oRootMenu,
       
  1057 			sSelectorBase = 
       
  1058 				menuNav._isRoot(oMenu) ? EMPTY_STRING : ("#" + oMenu.get("id")),
       
  1059 			oFocusManager = menuNav._focusManager,
       
  1060 			sKeysVal,
       
  1061 			sDescendantSelector,
       
  1062 			sQuery;
       
  1063 
       
  1064 		if (isHorizontalMenu(oMenu)) {
       
  1065 
       
  1066 			sDescendantSelector = sSelectorBase + STANDARD_QUERY + "," + 
       
  1067 				sSelectorBase + EXTENDED_QUERY;
       
  1068 			
       
  1069 			sKeysVal = { next: "down:39", previous: "down:37" };
       
  1070 			
       
  1071 		}
       
  1072 		else {
       
  1073 
       
  1074 			sDescendantSelector = sSelectorBase + STANDARD_QUERY;
       
  1075 			sKeysVal = { next: "down:40", previous: "down:38" };
       
  1076 
       
  1077 		}
       
  1078 
       
  1079 
       
  1080 		if (!oFocusManager) {
       
  1081 
       
  1082 			oRootMenu.plug(Y.Plugin.NodeFocusManager, { 
       
  1083 				descendants: sDescendantSelector,
       
  1084 				keys: sKeysVal,
       
  1085 				circular: true
       
  1086 			});
       
  1087 
       
  1088 			oFocusManager = oRootMenu.focusManager;
       
  1089 
       
  1090 			sQuery = "#" + oRootMenu.get("id") + MENU_SELECTOR + " a," + 
       
  1091 							MENU_TOGGLE_SELECTOR;
       
  1092 
       
  1093 			oRootMenu.all(sQuery).set("tabIndex", -1);
       
  1094 
       
  1095 			oFocusManager.on(ACTIVE_DESCENDANT_CHANGE, 
       
  1096 				this._onActiveDescendantChange, oFocusManager, this);
       
  1097 
       
  1098 			oFocusManager.after(ACTIVE_DESCENDANT_CHANGE, 
       
  1099 				this._afterActiveDescendantChange, oFocusManager, this);
       
  1100 			
       
  1101 			menuNav._focusManager = oFocusManager;
       
  1102 			
       
  1103 		}
       
  1104 		else {
       
  1105 
       
  1106 			oFocusManager.set(ACTIVE_DESCENDANT, -1);
       
  1107 			oFocusManager.set(DESCENDANTS, sDescendantSelector);
       
  1108 			oFocusManager.set("keys", sKeysVal);
       
  1109 			
       
  1110 		}
       
  1111 
       
  1112 	},
       
  1113 
       
  1114 
       
  1115 	//	Event handlers for discrete pieces of pieces of the menu
       
  1116 
       
  1117 
       
  1118 	/**
       
  1119 	* @method _onActiveDescendantChange
       
  1120 	* @description "activeDescendantChange" event handler for menu's 
       
  1121 	* Focus Manager.
       
  1122 	* @protected
       
  1123 	* @param {Object} event Object representing the Attribute change event.
       
  1124 	* @param {NodeMenuNav} menuNav Object representing the NodeMenuNav instance.
       
  1125 	*/
       
  1126 	_onActiveDescendantChange: function (event, menuNav) {
       
  1127 
       
  1128 		if (event.src === UI && menuNav._activeMenu && 
       
  1129 				!menuNav._movingToSubmenu) {
       
  1130 
       
  1131 			menuNav._hideAllSubmenus(menuNav._activeMenu);
       
  1132 
       
  1133 		}
       
  1134 		
       
  1135 	},
       
  1136 
       
  1137 
       
  1138 	/**
       
  1139 	* @method _afterActiveDescendantChange
       
  1140 	* @description "activeDescendantChange" event handler for menu's 
       
  1141 	* Focus Manager.
       
  1142 	* @protected
       
  1143 	* @param {Object} event Object representing the Attribute change event.
       
  1144 	* @param {NodeMenuNav} menuNav Object representing the NodeMenuNav instance.
       
  1145 	*/
       
  1146 	_afterActiveDescendantChange: function (event, menuNav) {
       
  1147 
       
  1148 		var oItem;
       
  1149 
       
  1150 		if (event.src === UI) {
       
  1151 			oItem = getItem(this.get(DESCENDANTS).item(event.newVal), true);
       
  1152 			menuNav._setActiveItem(oItem);
       
  1153 		}
       
  1154 	
       
  1155 	},
       
  1156 
       
  1157 
       
  1158 	/**
       
  1159 	* @method _onDocFocus
       
  1160 	* @description "focus" event handler for the owner document of the MenuNav.
       
  1161 	* @protected
       
  1162 	* @param {Object} event Object representing the DOM event.
       
  1163 	*/
       
  1164 	_onDocFocus: function (event) {
       
  1165 	
       
  1166 		var menuNav = this,
       
  1167 			oActiveItem = menuNav._activeItem,
       
  1168 			oTarget = event.target,
       
  1169 			oMenu;
       
  1170 	
       
  1171 
       
  1172 		if (menuNav._rootMenu.contains(oTarget)) {	//	The menu has focus
       
  1173 
       
  1174 			if (menuNav._hasFocus) {	
       
  1175 
       
  1176 				oMenu = getParentMenu(oTarget);
       
  1177 
       
  1178 				//	If the element that was focused is a descendant of the 
       
  1179 				//	root menu, but is in a submenu not currently being 
       
  1180 				//	managed by the Focus Manager, update the Focus Manager so 
       
  1181 				//	that it is now managing the submenu that is the parent of  
       
  1182 				//	the element that was focused.
       
  1183 				
       
  1184 				if (!menuNav._activeMenu.compareTo(oMenu)) {
       
  1185 
       
  1186 					menuNav._activeMenu = oMenu;
       
  1187 					menuNav._initFocusManager();
       
  1188 					menuNav._focusManager.set(ACTIVE_DESCENDANT, oTarget);
       
  1189 					menuNav._setActiveItem(getItem(oTarget, true));
       
  1190 					
       
  1191 				}
       
  1192 			
       
  1193 			}
       
  1194 			else { //	Initial focus
       
  1195 
       
  1196 				//	First time the menu has been focused, need to setup focused 
       
  1197 				//	state and established active active descendant
       
  1198 	
       
  1199 				menuNav._hasFocus = true;
       
  1200 	
       
  1201 				oActiveItem = getItem(oTarget, true);
       
  1202 	
       
  1203 				if (oActiveItem) {	
       
  1204 					menuNav._setActiveItem(oActiveItem);
       
  1205 				}
       
  1206 				
       
  1207 			}
       
  1208 		
       
  1209 		}
       
  1210 		else {	//	The menu has lost focus
       
  1211 
       
  1212 			menuNav._clearActiveItem();
       
  1213 
       
  1214 			menuNav._cancelShowSubmenuTimer();
       
  1215 			menuNav._hideAllSubmenus(menuNav._rootMenu);
       
  1216 
       
  1217 			menuNav._activeMenu = menuNav._rootMenu;
       
  1218 			menuNav._initFocusManager();
       
  1219 			
       
  1220 			menuNav._focusManager.set(ACTIVE_DESCENDANT, 0);
       
  1221 			
       
  1222 			menuNav._hasFocus = false;
       
  1223 
       
  1224 		}
       
  1225 	
       
  1226 	},
       
  1227 
       
  1228 
       
  1229 	/**
       
  1230 	* @method _onMenuMouseOver
       
  1231 	* @description "mouseover" event handler for a menu.
       
  1232 	* @protected
       
  1233 	* @param {Node} menu Node instance representing a menu.
       
  1234 	* @param {Object} event Object representing the DOM event.
       
  1235 	*/
       
  1236 	_onMenuMouseOver: function (menu, event) {
       
  1237 
       
  1238 		var menuNav = this,
       
  1239 			oHideAllSubmenusTimer = menuNav._hideAllSubmenusTimer;
       
  1240 
       
  1241 		if (oHideAllSubmenusTimer) {
       
  1242 			oHideAllSubmenusTimer.cancel();
       
  1243 			menuNav._hideAllSubmenusTimer = null;
       
  1244 		}
       
  1245 
       
  1246 		menuNav._cancelHideSubmenuTimer();
       
  1247 
       
  1248 		//	Need to update the FocusManager in advance of focus a new 
       
  1249 		//	Menu in order to avoid the FocusManager thinking that 
       
  1250 		//	it has lost focus
       
  1251 		
       
  1252 		if (menu && !menu.compareTo(menuNav._activeMenu)) {
       
  1253 			menuNav._activeMenu = menu;
       
  1254 
       
  1255 			if (menuNav._hasFocus) {
       
  1256 				menuNav._initFocusManager();
       
  1257 			}
       
  1258 
       
  1259 		}
       
  1260 
       
  1261 		if (menuNav._movingToSubmenu && isHorizontalMenu(menu)) {
       
  1262 			menuNav._movingToSubmenu = false;
       
  1263 		}
       
  1264 
       
  1265 	},
       
  1266 
       
  1267 
       
  1268 	/**
       
  1269 	* @method _hideAndFocusLabel
       
  1270 	* @description Hides all of the submenus of the root menu and focuses the 
       
  1271 	* label of the topmost submenu
       
  1272 	* @protected
       
  1273 	*/
       
  1274 	_hideAndFocusLabel: function () {
       
  1275 
       
  1276 		var	menuNav = this,
       
  1277 			oActiveMenu = menuNav._activeMenu,
       
  1278 			oSubmenu;
       
  1279 	
       
  1280 		menuNav._hideAllSubmenus(menuNav._rootMenu);
       
  1281 
       
  1282 		if (oActiveMenu) {
       
  1283 
       
  1284 			//	Focus the label element for the topmost submenu
       
  1285 			oSubmenu = menuNav._getTopmostSubmenu(oActiveMenu);
       
  1286 			menuNav._focusItem(oSubmenu.previous());
       
  1287 
       
  1288 		}
       
  1289 	
       
  1290 	},
       
  1291 
       
  1292 
       
  1293 	/**
       
  1294 	* @method _onMenuMouseOut
       
  1295 	* @description "mouseout" event handler for a menu.
       
  1296 	* @protected
       
  1297 	* @param {Node} menu Node instance representing a menu.
       
  1298 	* @param {Object} event Object representing the DOM event.
       
  1299 	*/
       
  1300 	_onMenuMouseOut: function (menu, event) {
       
  1301 
       
  1302 		var menuNav = this,
       
  1303 			oActiveMenu = menuNav._activeMenu,
       
  1304 			oRelatedTarget = event.relatedTarget,
       
  1305 			oActiveItem = menuNav._activeItem,
       
  1306 			oParentMenu,
       
  1307 			oMenu;
       
  1308 
       
  1309 
       
  1310 		if (oActiveMenu && !oActiveMenu.contains(oRelatedTarget)) {
       
  1311 		
       
  1312 			oParentMenu = getParentMenu(oActiveMenu);
       
  1313 			
       
  1314 
       
  1315 			if (oParentMenu && !oParentMenu.contains(oRelatedTarget)) {
       
  1316 
       
  1317 				if (menuNav.get(MOUSEOUT_HIDE_DELAY) > 0) {
       
  1318 
       
  1319 					menuNav._cancelShowSubmenuTimer();
       
  1320 
       
  1321 					menuNav._hideAllSubmenusTimer = 
       
  1322 
       
  1323 						later(menuNav.get(MOUSEOUT_HIDE_DELAY), 
       
  1324 							menuNav, menuNav._hideAndFocusLabel);
       
  1325 						
       
  1326 				}
       
  1327 			
       
  1328 			}
       
  1329 			else {
       
  1330 			
       
  1331 				if (oActiveItem) {
       
  1332 				
       
  1333 					oMenu = getParentMenu(oActiveItem);
       
  1334 
       
  1335 					if (!menuNav._isRoot(oMenu)) { 
       
  1336 						menuNav._focusItem(oMenu.previous());
       
  1337 					}
       
  1338 				
       
  1339 				}
       
  1340 			
       
  1341 			}
       
  1342 
       
  1343 		}
       
  1344 
       
  1345 	},
       
  1346 
       
  1347 
       
  1348 	/**
       
  1349 	* @method _onMenuLabelMouseOver
       
  1350 	* @description "mouseover" event handler for a menu label.
       
  1351 	* @protected
       
  1352 	* @param {Node} menuLabel Node instance representing a menu label.
       
  1353 	* @param {Object} event Object representing the DOM event.
       
  1354 	*/
       
  1355 	_onMenuLabelMouseOver: function (menuLabel, event) {
       
  1356 
       
  1357 		var menuNav = this,
       
  1358 			oActiveMenu = menuNav._activeMenu,
       
  1359 			bIsRoot = menuNav._isRoot(oActiveMenu),
       
  1360 			bUseAutoSubmenuDisplay = 
       
  1361 				(menuNav.get(AUTO_SUBMENU_DISPLAY) && bIsRoot || !bIsRoot),
       
  1362             submenuShowDelay = menuNav.get("submenuShowDelay"),	
       
  1363 			oSubmenu;
       
  1364 				
       
  1365 
       
  1366         var showSubmenu = function (delay) {
       
  1367 
       
  1368 			menuNav._cancelHideSubmenuTimer();
       
  1369 			menuNav._cancelShowSubmenuTimer();
       
  1370 
       
  1371 			if (!hasVisibleSubmenu(menuLabel)) {
       
  1372 
       
  1373 				oSubmenu = menuLabel.next();
       
  1374 
       
  1375 				if (oSubmenu) {
       
  1376 					menuNav._hideAllSubmenus(oActiveMenu);
       
  1377 					menuNav._showSubmenuTimer = later(delay, menuNav, menuNav._showMenu, oSubmenu);
       
  1378 				}
       
  1379 
       
  1380 			}
       
  1381             
       
  1382         };
       
  1383 
       
  1384 
       
  1385 		menuNav._focusItem(menuLabel);
       
  1386 		menuNav._setActiveItem(menuLabel);
       
  1387 
       
  1388 
       
  1389 		if (bUseAutoSubmenuDisplay) {
       
  1390 	
       
  1391 	        if (menuNav._movingToSubmenu) {
       
  1392 	            
       
  1393 	            //  If the user is moving diagonally from a submenu to 
       
  1394 	            //  another submenu and they then stop and pause on a
       
  1395 	            //  menu label for an amount of time equal to the amount of 
       
  1396 	            //  time defined for the display of a submenu then show the 
       
  1397 	            //  submenu immediately.
       
  1398 	            //  http://yuilibrary.com/projects/yui3/ticket/2528316
       
  1399 	            
       
  1400 	            //Y.message("Pause path");
       
  1401 	            
       
  1402 	            menuNav._hoverTimer = later(submenuShowDelay, menuNav, function () {
       
  1403                     showSubmenu(0);
       
  1404 	            });
       
  1405 	            
       
  1406 	        }
       
  1407 	        else {
       
  1408                 showSubmenu(submenuShowDelay);
       
  1409 	        }
       
  1410 		
       
  1411 		}
       
  1412 
       
  1413 	},
       
  1414 
       
  1415 
       
  1416 	/**
       
  1417 	* @method _onMenuLabelMouseOut
       
  1418 	* @description "mouseout" event handler for a menu label.
       
  1419 	* @protected
       
  1420 	* @param {Node} menuLabel Node instance representing a menu label.
       
  1421 	* @param {Object} event Object representing the DOM event.
       
  1422 	*/
       
  1423 	_onMenuLabelMouseOut: function (menuLabel, event) {
       
  1424 
       
  1425 		var menuNav = this,
       
  1426 			bIsRoot = menuNav._isRoot(menuNav._activeMenu),
       
  1427 			bUseAutoSubmenuDisplay = 
       
  1428 				(menuNav.get(AUTO_SUBMENU_DISPLAY) && bIsRoot || !bIsRoot),
       
  1429 
       
  1430 			oRelatedTarget = event.relatedTarget,
       
  1431 			oSubmenu = menuLabel.next(),
       
  1432 			hoverTimer = menuNav._hoverTimer;
       
  1433 
       
  1434         if (hoverTimer) {
       
  1435             hoverTimer.cancel();
       
  1436         }
       
  1437 
       
  1438 		menuNav._clearActiveItem();
       
  1439 
       
  1440 		if (bUseAutoSubmenuDisplay) {
       
  1441 
       
  1442 			if (menuNav._movingToSubmenu && 
       
  1443 					!menuNav._showSubmenuTimer && oSubmenu) {
       
  1444 
       
  1445 				//	If the mouse is moving diagonally toward the submenu and 
       
  1446 				//	another submenu isn't in the process of being displayed 
       
  1447 				//	(via a timer), then hide the submenu via a timer to give
       
  1448 				//	the user some time to reach the submenu.
       
  1449 			
       
  1450 				menuNav._hideSubmenuTimer = 
       
  1451 					later(menuNav.get("submenuHideDelay"), menuNav, 
       
  1452 						menuNav._hideMenu, oSubmenu);
       
  1453 			
       
  1454 			}
       
  1455 			else if (!menuNav._movingToSubmenu && oSubmenu && (!oRelatedTarget || 
       
  1456 			        (oRelatedTarget && 
       
  1457 			            !oSubmenu.contains(oRelatedTarget) && 
       
  1458 			            !oRelatedTarget.compareTo(oSubmenu)))) {
       
  1459 
       
  1460 				//	If the mouse is not moving toward the submenu, cancel any 
       
  1461 				//	submenus that might be in the process of being displayed 
       
  1462 				//	(via a timer) and hide this submenu immediately.
       
  1463 
       
  1464 				menuNav._cancelShowSubmenuTimer();
       
  1465 
       
  1466 				menuNav._hideMenu(oSubmenu);
       
  1467 
       
  1468 			}
       
  1469 
       
  1470 		}
       
  1471 
       
  1472 	},
       
  1473 	
       
  1474 
       
  1475 	/**
       
  1476 	* @method _onMenuItemMouseOver
       
  1477 	* @description "mouseover" event handler for a menuitem.
       
  1478 	* @protected
       
  1479 	* @param {Node} menuItem Node instance representing a menuitem.
       
  1480 	* @param {Object} event Object representing the DOM event.
       
  1481 	*/
       
  1482 	_onMenuItemMouseOver: function (menuItem, event) {
       
  1483 
       
  1484 		var menuNav = this,
       
  1485 			oActiveMenu = menuNav._activeMenu,
       
  1486 			bIsRoot = menuNav._isRoot(oActiveMenu),
       
  1487 			bUseAutoSubmenuDisplay = 
       
  1488 				(menuNav.get(AUTO_SUBMENU_DISPLAY) && bIsRoot || !bIsRoot);
       
  1489 
       
  1490 
       
  1491 		menuNav._focusItem(menuItem);
       
  1492 		menuNav._setActiveItem(menuItem);
       
  1493 
       
  1494 
       
  1495 		if (bUseAutoSubmenuDisplay && !menuNav._movingToSubmenu) {
       
  1496 
       
  1497 			menuNav._hideAllSubmenus(oActiveMenu);
       
  1498 
       
  1499 		}
       
  1500 
       
  1501 	},
       
  1502 	
       
  1503 
       
  1504 	/**
       
  1505 	* @method _onMenuItemMouseOut
       
  1506 	* @description "mouseout" event handler for a menuitem.
       
  1507 	* @protected
       
  1508 	* @param {Node} menuItem Node instance representing a menuitem.
       
  1509 	* @param {Object} event Object representing the DOM event.
       
  1510 	*/
       
  1511 	_onMenuItemMouseOut: function (menuItem, event) {
       
  1512 
       
  1513 		this._clearActiveItem();
       
  1514 
       
  1515 	},
       
  1516 
       
  1517 
       
  1518 	/**
       
  1519 	* @method _onVerticalMenuKeyDown
       
  1520 	* @description "keydown" event handler for vertical menus.
       
  1521 	* @protected
       
  1522 	* @param {Object} event Object representing the DOM event.
       
  1523 	*/
       
  1524 	_onVerticalMenuKeyDown: function (event) {
       
  1525 
       
  1526 		var menuNav = this,
       
  1527 			oActiveMenu = menuNav._activeMenu,
       
  1528 			oRootMenu = menuNav._rootMenu,
       
  1529 			oTarget = event.target,
       
  1530 			bPreventDefault = false,
       
  1531 			nKeyCode = event.keyCode,
       
  1532 			oSubmenu,
       
  1533 			oParentMenu,
       
  1534 			oLI,
       
  1535 			oItem;
       
  1536 
       
  1537 
       
  1538 		switch (nKeyCode) {
       
  1539 
       
  1540 			case 37:	//	left arrow
       
  1541 
       
  1542 				oParentMenu = getParentMenu(oActiveMenu);
       
  1543 
       
  1544 				if (oParentMenu && isHorizontalMenu(oParentMenu)) {
       
  1545 				
       
  1546 					menuNav._hideMenu(oActiveMenu);
       
  1547 					oLI = getPreviousSibling(oActiveMenu.get(PARENT_NODE));
       
  1548 					oItem = getItem(oLI);
       
  1549 					
       
  1550 					if (oItem) {
       
  1551 
       
  1552 						if (isMenuLabel(oItem)) {	//	Menu label
       
  1553 						
       
  1554 							oSubmenu = oItem.next();
       
  1555 						
       
  1556 
       
  1557 							if (oSubmenu) {
       
  1558 
       
  1559 								menuNav._showMenu(oSubmenu);
       
  1560 								menuNav._focusItem(getFirstItem(oSubmenu));
       
  1561 								menuNav._setActiveItem(getFirstItem(oSubmenu));
       
  1562 
       
  1563 							}
       
  1564 							else {
       
  1565 	
       
  1566 								menuNav._focusItem(oItem);
       
  1567 								menuNav._setActiveItem(oItem);
       
  1568 	
       
  1569 							}
       
  1570 						
       
  1571 						}
       
  1572 						else {	//	MenuItem
       
  1573 
       
  1574 							menuNav._focusItem(oItem);
       
  1575 							menuNav._setActiveItem(oItem);
       
  1576 
       
  1577 						}
       
  1578 					
       
  1579 					}
       
  1580 
       
  1581 				}
       
  1582 				else if (!menuNav._isRoot(oActiveMenu)) {
       
  1583 					menuNav._hideMenu(oActiveMenu, true);
       
  1584 				}
       
  1585 
       
  1586 
       
  1587 				bPreventDefault = true;
       
  1588 
       
  1589 			break;
       
  1590 
       
  1591 			case 39:	//	right arrow
       
  1592 
       
  1593 				if (isMenuLabel(oTarget)) {
       
  1594 					
       
  1595 					oSubmenu = oTarget.next();
       
  1596 
       
  1597 					if (oSubmenu) {
       
  1598 
       
  1599 						menuNav._showMenu(oSubmenu);
       
  1600 						menuNav._focusItem(getFirstItem(oSubmenu));
       
  1601 						menuNav._setActiveItem(getFirstItem(oSubmenu));
       
  1602 
       
  1603 					}
       
  1604 				
       
  1605 				}
       
  1606 				else if (isHorizontalMenu(oRootMenu)) {
       
  1607 
       
  1608 					oSubmenu = menuNav._getTopmostSubmenu(oActiveMenu);
       
  1609 					oLI = getNextSibling(oSubmenu.get(PARENT_NODE));
       
  1610 					oItem = getItem(oLI);
       
  1611 
       
  1612 					menuNav._hideAllSubmenus(oRootMenu);
       
  1613 
       
  1614 					if (oItem) {
       
  1615 
       
  1616 						if (isMenuLabel(oItem)) {	//	Menu label
       
  1617 
       
  1618 							oSubmenu = oItem.next();
       
  1619 
       
  1620 							if (oSubmenu) {
       
  1621 
       
  1622 								menuNav._showMenu(oSubmenu);
       
  1623 								menuNav._focusItem(getFirstItem(oSubmenu));
       
  1624 								menuNav._setActiveItem(getFirstItem(oSubmenu));
       
  1625 
       
  1626 							}
       
  1627 							else {
       
  1628 
       
  1629 								menuNav._focusItem(oItem);
       
  1630 								menuNav._setActiveItem(oItem);	
       
  1631 
       
  1632 							}
       
  1633 						
       
  1634 						}
       
  1635 						else {	//	MenuItem
       
  1636 
       
  1637 							menuNav._focusItem(oItem);
       
  1638 							menuNav._setActiveItem(oItem);
       
  1639 
       
  1640 						}							
       
  1641 
       
  1642 					}
       
  1643 				
       
  1644 				}
       
  1645 
       
  1646 				bPreventDefault = true;
       
  1647 
       
  1648 			break;
       
  1649 
       
  1650 		}	
       
  1651 
       
  1652 
       
  1653 		if (bPreventDefault) {
       
  1654 
       
  1655 			//	Prevent the browser from scrolling the window
       
  1656 
       
  1657 			event.preventDefault();			
       
  1658 
       
  1659 		}
       
  1660 	
       
  1661 	},
       
  1662 	
       
  1663 
       
  1664 	/**
       
  1665 	* @method _onHorizontalMenuKeyDown
       
  1666 	* @description "keydown" event handler for horizontal menus.
       
  1667 	* @protected
       
  1668 	* @param {Object} event Object representing the DOM event.
       
  1669 	*/
       
  1670 	_onHorizontalMenuKeyDown: function (event) {
       
  1671 
       
  1672 		var menuNav = this,
       
  1673 			oActiveMenu = menuNav._activeMenu,
       
  1674 			oTarget = event.target,
       
  1675 			oFocusedItem = getItem(oTarget, true),
       
  1676 			bPreventDefault = false,
       
  1677 			nKeyCode = event.keyCode,
       
  1678 			oSubmenu;
       
  1679 
       
  1680 
       
  1681 		if (nKeyCode === 40) {
       
  1682 
       
  1683 			menuNav._hideAllSubmenus(oActiveMenu);
       
  1684 
       
  1685 			if (isMenuLabel(oFocusedItem)) {
       
  1686 			
       
  1687 				oSubmenu = oFocusedItem.next();
       
  1688 
       
  1689 				if (oSubmenu) {
       
  1690 
       
  1691 					menuNav._showMenu(oSubmenu);
       
  1692 					menuNav._focusItem(getFirstItem(oSubmenu));
       
  1693 					menuNav._setActiveItem(getFirstItem(oSubmenu));
       
  1694 
       
  1695 				}
       
  1696 
       
  1697 				bPreventDefault = true;
       
  1698 			
       
  1699 			}
       
  1700 
       
  1701 		}		
       
  1702 
       
  1703 
       
  1704 		if (bPreventDefault) {
       
  1705 
       
  1706 			//	Prevent the browser from scrolling the window
       
  1707 
       
  1708 			event.preventDefault();			
       
  1709 
       
  1710 		}
       
  1711 	
       
  1712 	},
       
  1713 
       
  1714 
       
  1715 	//	Generic DOM Event handlers
       
  1716 
       
  1717 
       
  1718 	/**
       
  1719 	* @method _onMouseMove
       
  1720 	* @description "mousemove" event handler for the menu.
       
  1721 	* @protected
       
  1722 	* @param {Object} event Object representing the DOM event.
       
  1723 	*/
       
  1724 	_onMouseMove: function (event) {
       
  1725 
       
  1726 		var menuNav = this;
       
  1727 
       
  1728 		//	Using a timer to set the value of the "_currentMouseX" property 
       
  1729 		//	helps improve the reliability of the calculation used to set the 
       
  1730 		//	value of the "_movingToSubmenu" property - especially in Opera.
       
  1731 
       
  1732 		later(10, menuNav, function () {
       
  1733 
       
  1734 			menuNav._currentMouseX = event.pageX;
       
  1735 		
       
  1736 		});
       
  1737 	
       
  1738 	},
       
  1739 
       
  1740 
       
  1741 	/**
       
  1742 	* @method _onMouseOver
       
  1743 	* @description "mouseover" event handler for the menu.
       
  1744 	* @protected
       
  1745 	* @param {Object} event Object representing the DOM event.
       
  1746 	*/
       
  1747 	_onMouseOver: function (event) {
       
  1748 
       
  1749 		var menuNav = this,
       
  1750 			oTarget,
       
  1751 			oMenu,
       
  1752 			oMenuLabel,
       
  1753 			oParentMenu,
       
  1754 			oMenuItem;
       
  1755 
       
  1756 
       
  1757 		if (menuNav._blockMouseEvent) {
       
  1758 			menuNav._blockMouseEvent = false;
       
  1759 		}
       
  1760 		else {
       
  1761 
       
  1762 			oTarget = event.target;
       
  1763 			oMenu = getMenu(oTarget, true);
       
  1764 			oMenuLabel = getMenuLabel(oTarget, true);
       
  1765 			oMenuItem = getMenuItem(oTarget, true);
       
  1766 
       
  1767 
       
  1768 			if (handleMouseOverForNode(oMenu, oTarget)) {
       
  1769 
       
  1770 				menuNav._onMenuMouseOver(oMenu, event);
       
  1771 
       
  1772 				oMenu[HANDLED_MOUSEOVER] = true;
       
  1773 				oMenu[HANDLED_MOUSEOUT] = false;
       
  1774 
       
  1775 				oParentMenu = getParentMenu(oMenu);
       
  1776 
       
  1777 				if (oParentMenu) {
       
  1778 
       
  1779 					oParentMenu[HANDLED_MOUSEOUT] = true;
       
  1780 					oParentMenu[HANDLED_MOUSEOVER] = false;
       
  1781 		
       
  1782 				}
       
  1783 			
       
  1784 			}
       
  1785 
       
  1786 			if (handleMouseOverForNode(oMenuLabel, oTarget)) {
       
  1787 
       
  1788 				menuNav._onMenuLabelMouseOver(oMenuLabel, event);
       
  1789 
       
  1790 				oMenuLabel[HANDLED_MOUSEOVER] = true;
       
  1791 				oMenuLabel[HANDLED_MOUSEOUT] = false;
       
  1792 	
       
  1793 			}
       
  1794 
       
  1795 			if (handleMouseOverForNode(oMenuItem, oTarget)) {
       
  1796 	
       
  1797 				menuNav._onMenuItemMouseOver(oMenuItem, event);
       
  1798 
       
  1799 				oMenuItem[HANDLED_MOUSEOVER] = true;
       
  1800 				oMenuItem[HANDLED_MOUSEOUT] = false;
       
  1801 				
       
  1802 			}
       
  1803 
       
  1804 		}
       
  1805 
       
  1806 	},
       
  1807 
       
  1808 
       
  1809 	/**
       
  1810 	* @method _onMouseOut
       
  1811 	* @description "mouseout" event handler for the menu.
       
  1812 	* @protected
       
  1813 	* @param {Object} event Object representing the DOM event.
       
  1814 	*/
       
  1815 	_onMouseOut: function (event) {
       
  1816 			
       
  1817 		var menuNav = this,
       
  1818 			oActiveMenu = menuNav._activeMenu,
       
  1819 			bMovingToSubmenu = false,
       
  1820 			oTarget,
       
  1821 			oRelatedTarget,
       
  1822 			oMenu,
       
  1823 			oMenuLabel,
       
  1824 			oSubmenu,
       
  1825 			oMenuItem;
       
  1826 
       
  1827 
       
  1828 		menuNav._movingToSubmenu = 
       
  1829 					(oActiveMenu && !isHorizontalMenu(oActiveMenu) && 
       
  1830 						((event.pageX - 5) > menuNav._currentMouseX));
       
  1831 		
       
  1832 		oTarget = event.target;
       
  1833 		oRelatedTarget = event.relatedTarget;
       
  1834 		oMenu = getMenu(oTarget, true);
       
  1835 		oMenuLabel = getMenuLabel(oTarget, true);
       
  1836 		oMenuItem = getMenuItem(oTarget, true);
       
  1837 
       
  1838 
       
  1839 		if (handleMouseOutForNode(oMenuLabel, oRelatedTarget)) {
       
  1840 
       
  1841 			menuNav._onMenuLabelMouseOut(oMenuLabel, event);
       
  1842 
       
  1843 			oMenuLabel[HANDLED_MOUSEOUT] = true;
       
  1844 			oMenuLabel[HANDLED_MOUSEOVER] = false;
       
  1845 
       
  1846 		}
       
  1847 
       
  1848 		if (handleMouseOutForNode(oMenuItem, oRelatedTarget)) {
       
  1849 
       
  1850 			menuNav._onMenuItemMouseOut(oMenuItem, event);
       
  1851 
       
  1852 			oMenuItem[HANDLED_MOUSEOUT] = true;
       
  1853 			oMenuItem[HANDLED_MOUSEOVER] = false;
       
  1854 			
       
  1855 		}
       
  1856 
       
  1857 
       
  1858 		if (oMenuLabel) {
       
  1859 
       
  1860 			oSubmenu = oMenuLabel.next();
       
  1861 
       
  1862 			if (oSubmenu && oRelatedTarget && 
       
  1863 				(oRelatedTarget.compareTo(oSubmenu) || 
       
  1864 					oSubmenu.contains(oRelatedTarget))) {
       
  1865 
       
  1866 				bMovingToSubmenu = true;
       
  1867 
       
  1868 			}
       
  1869 		
       
  1870 		}
       
  1871 		
       
  1872 
       
  1873 		if (handleMouseOutForNode(oMenu, oRelatedTarget) || bMovingToSubmenu) {
       
  1874 
       
  1875 			menuNav._onMenuMouseOut(oMenu, event);				
       
  1876 
       
  1877 			oMenu[HANDLED_MOUSEOUT] = true;
       
  1878 			oMenu[HANDLED_MOUSEOVER] = false;
       
  1879 		
       
  1880 		}
       
  1881 	
       
  1882 	},
       
  1883 
       
  1884 
       
  1885 	/**
       
  1886 	* @method _toggleSubmenuDisplay
       
  1887 	* @description "mousedown," "keydown," and "click" event handler for the 
       
  1888 	* menu used to toggle the display of a submenu.
       
  1889 	* @protected
       
  1890 	* @param {Object} event Object representing the DOM event.
       
  1891 	*/
       
  1892 	_toggleSubmenuDisplay: function (event) {
       
  1893 
       
  1894 		var menuNav = this,
       
  1895 			oTarget = event.target,
       
  1896 			oMenuLabel = getMenuLabel(oTarget, true),
       
  1897 			sType = event.type,
       
  1898 			oAnchor,
       
  1899 			oSubmenu,
       
  1900 			sHref,
       
  1901 			nHashPos,
       
  1902 			nLen,
       
  1903 			sId;
       
  1904 
       
  1905 
       
  1906 		if (oMenuLabel) {
       
  1907 
       
  1908 			oAnchor = isAnchor(oTarget) ? oTarget : oTarget.ancestor(isAnchor);
       
  1909 			
       
  1910 
       
  1911 			if (oAnchor) {
       
  1912 
       
  1913 				//	Need to pass "2" as a second argument to "getAttribute" for 
       
  1914 				//	IE otherwise IE will return a fully qualified URL for the 
       
  1915 				//	value of the "href" attribute.
       
  1916 				//	http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
       
  1917 
       
  1918 				sHref = oAnchor.getAttribute("href", 2);
       
  1919 				nHashPos = sHref.indexOf("#");
       
  1920 				nLen = sHref.length;
       
  1921 
       
  1922 				if (nHashPos === 0 && nLen > 1) {
       
  1923 
       
  1924 					sId = sHref.substr(1, nLen);
       
  1925 					oSubmenu = oMenuLabel.next();
       
  1926 
       
  1927 					if (oSubmenu && (oSubmenu.get(ID) === sId)) {
       
  1928 
       
  1929 						if (sType === MOUSEDOWN || sType === KEYDOWN) {
       
  1930 							
       
  1931 							if ((UA.opera || UA.gecko || UA.ie) && sType === KEYDOWN && !menuNav._preventClickHandle) {
       
  1932 
       
  1933 								//	Prevent the browser from following the URL of 
       
  1934 								//	the anchor element
       
  1935 
       
  1936 								menuNav._preventClickHandle = menuNav._rootMenu.on("click", function (event) {
       
  1937 
       
  1938 									event.preventDefault();
       
  1939 
       
  1940 									menuNav._preventClickHandle.detach();
       
  1941 									menuNav._preventClickHandle = null;
       
  1942 
       
  1943 								});
       
  1944 
       
  1945 							}
       
  1946 							
       
  1947 							if (sType == MOUSEDOWN) {
       
  1948 
       
  1949 								//	Prevent the target from getting focused by 
       
  1950 								//	default, since the element to be focused will
       
  1951 								//	be determined by weather or not the submenu
       
  1952 								//	is visible.
       
  1953 								event.preventDefault();
       
  1954 
       
  1955 								//	FocusManager will attempt to focus any 
       
  1956 								//	descendant that is the target of the mousedown
       
  1957 								//	event.  Since we want to explicitly control 
       
  1958 	 							//	where focus is going, we need to call 
       
  1959 								//	"stopImmediatePropagation" to stop the 
       
  1960 								//	FocusManager from doing its thing.
       
  1961 								event.stopImmediatePropagation();	
       
  1962 
       
  1963 								//	The "_focusItem" method relies on the 
       
  1964 								//	"_hasFocus" property being set to true.  The
       
  1965 								//	"_hasFocus" property is normally set via a 
       
  1966 								//	"focus" event listener, but since we've 
       
  1967 								//	blocked focus from happening, we need to set 
       
  1968 								//	this property manually.
       
  1969 								menuNav._hasFocus = true;
       
  1970 
       
  1971 							}
       
  1972 
       
  1973 								
       
  1974 							if (menuNav._isRoot(getParentMenu(oTarget))) {	//	Event target is a submenu label in the root menu
       
  1975 							
       
  1976 								//	Menu label toggle functionality
       
  1977 							
       
  1978 								if (hasVisibleSubmenu(oMenuLabel)) {
       
  1979 							
       
  1980 									menuNav._hideMenu(oSubmenu);
       
  1981 									menuNav._focusItem(oMenuLabel);	
       
  1982 									menuNav._setActiveItem(oMenuLabel);
       
  1983 									
       
  1984 								}
       
  1985 								else {
       
  1986 							
       
  1987 									menuNav._hideAllSubmenus(menuNav._rootMenu);
       
  1988 									menuNav._showMenu(oSubmenu);
       
  1989 
       
  1990 									menuNav._focusItem(getFirstItem(oSubmenu));
       
  1991 									menuNav._setActiveItem(getFirstItem(oSubmenu));
       
  1992 									
       
  1993 								}
       
  1994 							
       
  1995 							}
       
  1996 							else {	//	Event target is a submenu label within a submenu
       
  1997 							
       
  1998 								if (menuNav._activeItem == oMenuLabel) {
       
  1999 							
       
  2000 									menuNav._showMenu(oSubmenu);
       
  2001 									menuNav._focusItem(getFirstItem(oSubmenu));
       
  2002 									menuNav._setActiveItem(getFirstItem(oSubmenu));										
       
  2003 							
       
  2004 								}
       
  2005 								else {
       
  2006 							
       
  2007 									if (!oMenuLabel._clickHandle) {
       
  2008 
       
  2009 										oMenuLabel._clickHandle = oMenuLabel.on("click", function () {
       
  2010 
       
  2011 											menuNav._hideAllSubmenus(menuNav._rootMenu);
       
  2012 
       
  2013 											menuNav._hasFocus = false;
       
  2014 											menuNav._clearActiveItem();
       
  2015 
       
  2016 
       
  2017 											oMenuLabel._clickHandle.detach();
       
  2018 											
       
  2019 											oMenuLabel._clickHandle = null;
       
  2020 
       
  2021 										});
       
  2022 										
       
  2023 									}
       
  2024 									
       
  2025 								}
       
  2026 								
       
  2027 							}
       
  2028 
       
  2029 						}
       
  2030 
       
  2031 
       
  2032 						if (sType === CLICK) {
       
  2033 						
       
  2034 							//	Prevent the browser from following the URL of 
       
  2035 							//	the anchor element
       
  2036 							
       
  2037 							event.preventDefault();
       
  2038 						
       
  2039 						}
       
  2040 					
       
  2041 					}
       
  2042 				
       
  2043 				}				
       
  2044 
       
  2045 
       
  2046 			}
       
  2047 		
       
  2048 		}
       
  2049 	
       
  2050 	},
       
  2051 	
       
  2052 
       
  2053 	/**
       
  2054 	* @method _onKeyPress
       
  2055 	* @description "keypress" event handler for the menu.
       
  2056 	* @protected
       
  2057 	* @param {Object} event Object representing the DOM event.
       
  2058 	*/
       
  2059 	_onKeyPress: function (event) {
       
  2060 	
       
  2061 		switch (event.keyCode) {
       
  2062 
       
  2063 			case 37:	//	left arrow
       
  2064 			case 38:	//	up arrow
       
  2065 			case 39:	//	right arrow
       
  2066 			case 40:	//	down arrow
       
  2067 
       
  2068 				//	Prevent the browser from scrolling the window
       
  2069 
       
  2070 				event.preventDefault();
       
  2071 
       
  2072 			break;
       
  2073 
       
  2074 		}						
       
  2075 
       
  2076 	},	
       
  2077 
       
  2078 
       
  2079 	/**
       
  2080 	* @method _onKeyDown
       
  2081 	* @description "keydown" event handler for the menu.
       
  2082 	* @protected
       
  2083 	* @param {Object} event Object representing the DOM event.
       
  2084 	*/
       
  2085 	_onKeyDown: function (event) {
       
  2086 
       
  2087 		var menuNav = this,
       
  2088 			oActiveItem = menuNav._activeItem,
       
  2089 			oTarget = event.target,
       
  2090 			oActiveMenu = getParentMenu(oTarget),
       
  2091 			oSubmenu;
       
  2092 
       
  2093 		if (oActiveMenu) {
       
  2094 
       
  2095 			menuNav._activeMenu = oActiveMenu;
       
  2096 
       
  2097 			if (isHorizontalMenu(oActiveMenu)) {
       
  2098 				menuNav._onHorizontalMenuKeyDown(event);
       
  2099 			}
       
  2100 			else {
       
  2101 				menuNav._onVerticalMenuKeyDown(event);
       
  2102 			}
       
  2103 
       
  2104 
       
  2105 			if (event.keyCode === 27) {
       
  2106 
       
  2107 				if (!menuNav._isRoot(oActiveMenu)) {
       
  2108 
       
  2109 					if (UA.opera) {
       
  2110 						later(0, menuNav, function () {
       
  2111 							menuNav._hideMenu(oActiveMenu, true);
       
  2112 						});						
       
  2113 					}
       
  2114 					else {
       
  2115 						menuNav._hideMenu(oActiveMenu, true);						
       
  2116 					}
       
  2117 
       
  2118 					event.stopPropagation();
       
  2119 					menuNav._blockMouseEvent = UA.gecko ? true : false;
       
  2120 
       
  2121 				}
       
  2122 				else if (oActiveItem) {
       
  2123 
       
  2124 					if (isMenuLabel(oActiveItem) && 
       
  2125 							hasVisibleSubmenu(oActiveItem)) {
       
  2126 					
       
  2127 						oSubmenu = oActiveItem.next();
       
  2128 
       
  2129 						if (oSubmenu) {
       
  2130 							menuNav._hideMenu(oSubmenu);
       
  2131 						}
       
  2132 
       
  2133 					}
       
  2134 					else {
       
  2135 
       
  2136 						menuNav._focusManager.blur();
       
  2137 
       
  2138 						//	This is necessary for Webkit since blurring the 
       
  2139 						//	active menuitem won't result in the document 
       
  2140 						//	gaining focus, meaning the that _onDocFocus 
       
  2141 						//	listener won't clear the active menuitem.
       
  2142 
       
  2143 						menuNav._clearActiveItem();	
       
  2144 						
       
  2145 						menuNav._hasFocus = false;
       
  2146 
       
  2147 					}
       
  2148 
       
  2149 				}
       
  2150 			
       
  2151 			}
       
  2152 		
       
  2153 		}
       
  2154 	
       
  2155 	},
       
  2156 	
       
  2157 	/**
       
  2158 	* @method _onDocMouseDown
       
  2159 	* @description "mousedown" event handler for the owner document of 
       
  2160 	* the menu.
       
  2161 	* @protected
       
  2162 	* @param {Object} event Object representing the DOM event.
       
  2163 	*/
       
  2164 	_onDocMouseDown: function (event) {
       
  2165 
       
  2166 		var menuNav = this,
       
  2167 			oRoot = menuNav._rootMenu,
       
  2168 			oTarget = event.target;
       
  2169 
       
  2170 
       
  2171 		if (!(oRoot.compareTo(oTarget) || oRoot.contains(oTarget))) {
       
  2172 
       
  2173 			menuNav._hideAllSubmenus(oRoot);
       
  2174 
       
  2175 			//	Document doesn't receive focus in Webkit when the user mouses 
       
  2176 			//	down on it, so the "_hasFocus" property won't get set to the 
       
  2177 			//	correct value.  The following line corrects the problem.
       
  2178 
       
  2179 			if (UA.webkit) {
       
  2180 				menuNav._hasFocus = false;
       
  2181 				menuNav._clearActiveItem();
       
  2182 			}
       
  2183 
       
  2184 		}
       
  2185 
       
  2186 	}
       
  2187 	
       
  2188 });
       
  2189 
       
  2190 
       
  2191 Y.namespace('Plugin');
       
  2192 
       
  2193 Y.Plugin.NodeMenuNav = NodeMenuNav;
       
  2194 
       
  2195 
       
  2196 }, '3.10.3', {"requires": ["node", "classnamemanager", "plugin", "node-focusmanager"], "skinnable": true});