Source: src/main/javascript/oracle/oj/ojmenu/ojmenu.js

Oracle® JavaScript Extension Toolkit (JET)
1.1.2

E65298-01

/**
 * All rights reserved.
 */

/**
 * @preserve Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

(function() {

/**
 * @ojcomponent oj.ojMenu
 * @augments oj.baseComponent
 * @since 0.6
 *
 * @classdesc
 * <h3 id="menuOverview-section">
 *   JET Menu Component
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#menuOverview-section"></a>
 * </h3>
 *
 * <p>Description: Themeable, WAI-ARIA-compliant popup menu with mouse and keyboard interactions for navigation.
 *
 * <p>A JET Menu can be created from any valid markup as long as the elements have a strict parent/child relationship
 * and each menu item has an anchor. The most commonly used element is the unordered list ( <code class="prettyprint"><ul></code> ):
 *
 * <pre class="prettyprint">
 * <code><ul id="menu" style="display:none">
 *   <li><a href="#">Item 1</a></li>
 *   <li><a href="#">Item 2</a></li>
 *   <li><a href="#">Item 3</a>
 *     <ul>
 *       <li><a href="#">Item 3-1</a></li>
 *       <li><a href="#">Item 3-2</a></li>
 *       <li><a href="#">Item 3-3</a></li>
 *       <li><a href="#">Item 3-4</a></li>
 *       <li><a href="#">Item 3-5</a></li>
 *     </ul>
 *   </li>
 *   <li><a href="#">Item 4</a></li>
 *   <li><a href="#">Item 5</a></li>
 * </ul>
 * </code></pre>
 *
 * <p>If you use a structure other than <code class="prettyprint"><ul></code>/<code class="prettyprint"><li></code>, including using the same element for the menu and the menu items, use the
 * <code class="prettyprint">menuSelector</code> option to specify a way to differentiate the two elements, e.g., <code class="prettyprint">menuSelector: "div.menuElement"</code>.
 *
 * <p>Any menu item can be disabled by adding the <code class="prettyprint">oj-disabled</code> class to that element.  As with any DOM change, doing so post-init
 * requires a <code class="prettyprint">refresh()</code> of the component.
 * 
 * <p>JET Menus are not intended to be scrollable, as large, unwieldy menus are not good UX.  Ideally menus should have a manageable number of items; if this is not 
 * possible, then it is preferable to organize contents into submenus, rather than introducing scrolling. 
 *
 *
 * <h3 id="popup-section">
 *   Popup Menus
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#popup-section"></a>
 * </h3>
 *
 * <p>JET Menu is a popup component, for use with [context menu]{@link oj.baseComponent#contextMenu}, [menu button]{@link oj.ojButton#menu},
 * or similar functionality.  It is not intended to sit inline on the page.  See also the [JET NavigationList]{@link oj.ojNavigationList} component.
 *
 * <p>For this reason, the component is automatically hidden until it is opened.  However, this styling is not applied until the component is initialized.
 * To avoid a FOUC (flash of unstyled content), applications are encouraged to apply <code class="prettyprint">style="display:none"</code> to the menu markup,
 * as shown in the above code sample.
 *
 *
 * <h3 id="icons-section">
 *   Icons
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#icons-section"></a>
 * </h3>
 *
 * <p>Submenu icons are inserted automatically.  To add other icons to menu items, include them in the markup and include the <code class="prettyprint">oj-menu-item-icon</code> class, as follows:
 *
 * <pre class="prettyprint">
 * <code><ul id="menu">
 *   <li id="foo"><a href="#"><span class="oj-menu-item-icon demo-icon-font demo-palette-icon-24"></span>Foo</a></li>
 * </ul>
 * </code></pre>
 *
 *
 * <h3 id="dividers-section">
 *   Dividers
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#dividers-section"></a>
 * </h3>
 *
 * <p>Divider elements can be created by including unlinked menu items that contain only spaces and/or dashes, or nothing at all:
 *
 * <pre class="prettyprint">
 * <code><ul id="menu">
 *   <li><a href="#">Item 1</a></li>
 *   <li>---</li>
 *   <li><a href="#">Item 2</a></li>
 * </ul>
 * </code></pre>
 *
 * <p>For WAI-ARIA compliance, JET automatically adds <code class="prettyprint">role="separator"</code> to the divider element.
 *
 *
 * <h3 id="touch-section">
 *   Touch End User Information
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#touch-section"></a>
 * </h3>
 *
 * {@ojinclude "name":"touchDoc"}
 *
 *
 * <h3 id="keyboard-section">
 *   Keyboard End User Information
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#keyboard-section"></a>
 * </h3>
 *
 * {@ojinclude "name":"keyboardDoc"}
 *
 *
 * <h3 id="a11y-section">
 *   Accessibility
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#a11y-section"></a>
 * </h3>
 *
 * <p>Disabled content: JET supports an accessible luminosity contrast ratio,
 * as specified in <a href="http://www.w3.org/TR/WCAG20/#visual-audio-contrast-contrast">WCAG 2.0 - Section 1.4.3 "Contrast"</a>,
 * in the themes that are accessible.  (See the "Theming" chapter of the JET Developer Guide for more information on which
 * themes are accessible.)  Note that Section 1.4.3 says that text or images of text that are part of an inactive user
 * interface component have no contrast requirement.  Because disabled content may not meet the minimum contrast ratio
 * required of enabled content, it cannot be used to convey meaningful information.<p>
 *
 *
 * <h3 id="reparenting-section">
 *   Reparenting
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#reparenting-section"></a>
 * </h3>
 *
 *  <p id="reparenting-strategy">
 *     When a menu is opened, it will be reparented in the document and reparented back when closed.
 *     The goal of this design is to maintain as much of the page author's document structure as possible, while
 *     avoiding most of the clipping and positioning issues of a completely inline design.
 *  </p>
 *  <p>
 *     If opened from another popup, the menu will be reparented to the nearest parent popup.
 *     Otherwise, the menu will be reparented to a container in the document body.
 *  </p>
 *  <p>
 *     The context of opening is defined by the resolved <code class="prettyprint">openOptions.launcher</code> value,
 *     which can be set via the <a href="#openOptions.launcher">option</a>, via the argument to the <a href="#open">open()</a>
 *     method, or via a <a href="#event:beforeOpen">beforeOpen</a> listener.
 *  <p>
 *     All menus are assigned the same z-index values. The layering between peer popups reflects the opening order.
 *     In addition, the page author has control over z-index weights by way of the menu's layer.
 *     The menu's layer defines the "stacking context" and assignd the "oj-menu-layer" style.
 *  </p>
 *  <p>
 *     Some notable consequences of this design:
 *  </p>
 *  <ul>
 *    <li>Events raised within the menu will not bubble up to the menu's original ancestors.  Instead, listeners for menu events should
 *        be applied to either the menu's root element, or the document.</li>
 *    <li>Likewise, developers should not use CSS descendant selectors, or similar logic, that assumes that the menu will remain a child
 *        of its original parent.</li>
 *  </ul>
 *
 * <h3 id="rtl-section">
 *   Reading direction
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#rtl-section"></a>
 * </h3>
 *
 * <p>The only supported way to set the reading direction (LTR or RTL) is to set the <code class="prettyprint">"dir"</code> attribute on the
 * <code class="prettyprint"><html></code> element of the page.  As with any JET component, in the unusual case that the reading direction
 * is changed post-init, the menu must be <code class="prettyprint">refresh()</code>ed, or the page must be reloaded.
 *
 *
 * <h3 id="pseudos-section">
 *   Pseudo-selectors
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#pseudos-section"></a>
 * </h3>
 *
 * <p>The <code class="prettyprint">:oj-menu</code> pseudo-selector can be used in jQuery expressions to select JET Menus.  For example:
 *
 * <pre class="prettyprint">
 * <code>$( ":oj-menu" ) // selects all JET Menus on the page
 * $myEventTarget.closest( ":oj-menu" ) // selects the closest ancestor that is a JET Menu
 * </code></pre>
 *
 *
 * <h3 id="binding-section">
 *   Declarative Binding
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#binding-section"></a>
 * </h3>
 *
 * <p>For components like Menu and Buttonset that contain a number of like items, applications may wish to use a <code class="prettyprint">foreach</code> Knockout binding
 * to stamp out the contents.  This binding cannot live on the same node as the JET <code class="prettyprint">ojComponent</code> binding, and must instead live on a nested
 * virtual element as follows:
 *
 * <pre class="prettyprint">
 * <code><ul id="menu" data-bind="ojComponent: {component: 'ojMenu'}">
 *     <!-- ko foreach: menuItems -->
 *         <li data-bind="attr: {id: id}, css: {'oj-disabled': disabled}">
 *             <a href="#" data-bind="text: label"></a>
 *         </li>
 *     <!-- /ko -->
 * </ul>
 * </code></pre>
 *
 *
 * <h3 id="jqui2jet-section">
 *   JET for jQuery UI developers
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#jqui2jet-section"></a>
 * </h3>
 *
 * <ol>
 *   <li>All JQUI and JET components inherit <code class="prettyprint">disable()</code> and <code class="prettyprint">enable()</code> methods from the base class.  This API
 *       duplicates the functionality of the <code class="prettyprint">disabled</code> option.  In JET, to keep the API as lean as possible, we
 *       have chosen not to document these methods outside of this section.</li>
 *   <li>JET Menus are popup menus, and are not intended to sit statically on the page.</li>
 *   <li>For clarity, JQUI Menu's <code class="prettyprint">menus</code> option has been renamed to <code class="prettyprint">menuSelector</code> in JET Menu.</li>
 *   <li>JQUI Menu's <code class="prettyprint">position</code> option is now a field of the <code class="prettyprint">submenuOpenOptions</code> option in JET Menu.</li>
 *   <li>JQUI Menu has a <code class="prettyprint">role</code> option, which defaults to <code class="prettyprint">"menu"</code>.  This option was removed in JET Menu.  Reason:
 *       JET Menu is a menu component; thus we feel that the only appropriate WAI-ARIA role for our component is <code class="prettyprint">"menu"</code>.</li>
 *   <li>JQUI Menu has <code class="prettyprint">isFirstItem()</code> and <code class="prettyprint">isLastItem()</code> methods, which were removed in JET Menu.  Reason:  To
 *       keep the API lean, we prefer to avoid methods with such specific functionality.</li>
 *   <li>JQUI Menu has a number of "programmatic navigation" methods, and <code class="prettyprint">focus</code> / <code class="prettyprint">blur</code> events, that were
 *       removed in JET Menu due to lack of a use case.</li>
 *   <li>JET Menu swaps the functionality of the left and right arrow keys in RTL.</li>
 *   <li>JET Menu creates WAI-ARIA compliant separator elements, by applying <code class="prettyprint">role="separator"</code> to them.</li>
 * </ol>
 *
 * <p>Also, event names for all JET components are prefixed with "oj", instead of component-specific prefixes like "menu" or "button".
 * E.g. the JQUI <code class="prettyprint">menucreate</code> event is <code class="prettyprint">ojcreate</code> in JET, as shown in the doc for that event.
 * Reason:  This makes the API more powerful.  It allows apps to listen to "foo" events from <em>all</em> JET components via:
 *
 * <pre class="prettyprint">
 * <code>$( document ).on( "ojfoo", myFunc);
 * </code></pre>
 *
 * or to "foo" events only from JET Menus (the JQUI functionality) via:
 *
 * <pre class="prettyprint">
 * <code>$( document ).on( "ojfoo", ":oj-menu", myFunc);
 * </code></pre>
 *
 *
 * <!-- - - - - Above this point, the tags are for the class.
 *              Below this point, the tags are for the constructor (initializer). - - - - - - -->
 *
 *
 * @desc Creates a JET Menu.
 *
 * @param {Object=} options a map of option-value pairs to set on the component
 *
 * @example <caption>Initialize the menu with no options specified:</caption>
 * $( ".selector" ).ojMenu();
 *
 * @example <caption>Initialize the menu with some options and callbacks specified:</caption>
 * $( ".selector" ).ojMenu( { "disabled": true, "create": function( event, ui ) {} } );
 *
 * @example <caption>Initialize the menu via the JET <code class="prettyprint">ojComponent</code> binding:</caption>
 * <ul id="menu" data-bind="ojComponent: { component: 'ojMenu',
 *                                         disabled: true,
 *                                         select: menuItemSelect }">
 */
oj.__registerWidget("oj.ojMenu", $['oj']['baseComponent'], {
    defaultElement: "<ul>", // added to externs.js, since this is an override of a superclass member.  (That's the rule for public methods, what about protected fields?)  TODO: Would @override do the job and be better than externing?
    delay: 300, // Doesn't get renamed even when unquoted and not in (our) externs.js file, so I'm leaving it unquoted for now.  TBD: This is private, but do NOT rename to _delay since there's an inherited instance method by that name, so rename so something else prefixed with _.
    role: "menu", // private.  I moved from options to here since no longer public option.  Leave unquoted so gets renamed by GCC as desired.
    widgetEventPrefix : "oj",
    options: { // options is in externs.js, so no need for quotes
        /**
         * Disables the menu if set to <code class="prettyprint">true</code>.
         *
         * @member
         * @name disabled
         * @memberof oj.ojMenu
         * @instance
         * @type {boolean}
         * @default <code class="prettyprint">false</code>
         *
         * @example <caption>Initialize the menu with the <code class="prettyprint">disabled</code> option specified:</caption>
         * $( ".selector" ).ojMenu( { "disabled": true } );
         *
         * @example <caption>Get or set the <code class="prettyprint">disabled</code> option, after initialization:</caption>
         * // getter
         * var disabled = $( ".selector" ).ojMenu( "option", "disabled" );
         *
         * // setter
         * $( ".selector" ).ojMenu( "option", "disabled", true );
         */
        // disabled option declared in superclass, but we still want the above API doc

        /**
         * Selector for the elements that serve as the menu container, including submenus.
         *
         * <p>Note: The <code class="prettyprint">menuSelector</code> option should not be changed after initialization. Existing submenus will not be updated.
         *
         * @expose
         * @memberof oj.ojMenu
         * @instance
         * @type {string}
         * @default <code class="prettyprint">"ul"</code>
         *
         * @example <caption>Initialize the menu with the <code class="prettyprint">menuSelector</code> option specified:</caption>
         * $( ".selector" ).ojMenu({ menuSelector: "div" });
         *
         * @example <caption>Get the <code class="prettyprint">menuSelector</code> option, after initialization:</caption>
         * // getter
         * var menuSelector = $( ".selector" ).ojMenu( "option", "menuSelector" );
         */
        menuSelector: "ul",

        /**
         * <p>A collection of settings impacting the launch of a popup menu.  These <code class="prettyprint">openOptions</code>
         * may be accessed and overridden individually or collectively, as seen in the examples.
         *
         * <p>This option affects the top-level menu, while <code class="prettyprint">submenuOpenOptions</code> affects submenus.
         *
         * <p>The values set here can be overridden on a per-launch basis by passing the corresponding params into the
         * <code class="prettyprint">open()</code> method.  Those per-launch values can be further customized by a
         * <code class="prettyprint">beforeOpen</code> listener.
         * 
         * <p>The built-in [menu button]{@link oj.ojButton#menu} and [context menu]{@link oj.baseComponent#contextMenu} functionality 
         * overrides some of the Menu's <code class="prettyprint">openOptions</code>, for WAI-ARIA compliance and other reasons.  
         * Thus, if the app really wants to customize 
         * those values, it must do so in a <code class="prettyprint">beforeOpen</code> listener.  If the built-in menu button 
         * or context menu functionality is modified in this way, it is the app's responsibility to ensure that the result is 
         * both correct and accessible.  
         * 
         * @expose 
         * @memberof oj.ojMenu
         * @instance
         * @type {Object}
         *
         * @example <caption>Initialize the menu, setting some <code class="prettyprint">openOptions</code>.  This syntax leaves the
         * other <code class="prettyprint">openOptions</code> intact at create time, but not if called after create time:</caption>
         * $( ".selector" ).ojMenu({ openOptions: { "initialFocus": "none", "launcher": "#myLauncher" } });
         *
         * @example <caption>Get or set the <code class="prettyprint">openOptions</code> option, after initialization:</caption>
         * // Get one
         * var value = $( ".selector" ).ojMenu( "option", "openOptions.launcher" );
         *
         * // Get all
         * var values = $( ".selector" ).ojMenu( "option", "openOptions" );
         *
         * // Set one, leaving the others intact
         * $( ".selector" ).ojMenu( "option", "openOptions.initialFocus", "none" );
         *
         * // Set many.  Any existing openOptions not listed are lost
         * $( ".selector" ).ojMenu( "option", "openOptions", { launcher: "#myLauncher",
         *                                                     initialFocus: "firstItem",
         *                                                     position: myPositionObj } );
         */
        openOptions: {
            /**
             * Determines focus behavior when the popup menu is initially opened.
             *
             * @expose
             * @alias openOptions.initialFocus
             * @memberof! oj.ojMenu
             * @instance
             * @type {string}
             * @default <code class="prettyprint">"menu"</code>
             * @ojvalue {string} "none" Leaves focus where it is, e.g. on the launching component.
             * @ojvalue {string} "menu" Focuses the menu itself, with no menu item focused (e.g. typical Context Menu behavior).
             * @ojvalue {string} "firstItem": Focuses the first menu item (e.g. MenuButton <kbd>DownArrow</kbd> behavior).
             *
             * @example <caption>Initialize the menu with the <code class="prettyprint">openOptions.initialFocus</code> sub-option specified:</caption>
             * $( ".selector" ).ojMenu({ openOptions: { initialFocus: "firstItem" } });
             *
             * @example <caption>Get or set the <code class="prettyprint">openOptions.initialFocus</code> sub-option, after initialization:</caption>
             * // getter
             * var initialFocus = $( ".selector" ).ojMenu( "option", "openOptions.initialFocus" );
             *
             * // setter:
             * $( ".selector" ).ojMenu( "option", "openOptions.initialFocus", "none" );
             */
            initialFocus : "menu",

            /**
             * <p>The DOM node (which may or may not be a JET component) that launches this popup menu.
             * This node must be focusable, as focus is returned to it upon menu dismissal.
             *
             * <p>Can be a <code class="prettyprint">string</code> JQ selector indicating the DOM node, or a <code class="prettyprint">jQuery</code>
             * object containing the node.
             *
             * <p>The launcher must either be specified in this component option, or on each menu launch -- see <code class="prettyprint">open()</code>
             * and <code class="prettyprint">beforeOpen</code>.
             *
             * @expose
             * @alias openOptions.launcher
             * @memberof! oj.ojMenu
             * @instance
             * @type {string|jQuery}
             * @default <code class="prettyprint">null</code>
             *
             * @example <caption>Initialize the menu with the <code class="prettyprint">openOptions.launcher</code> sub-option specified:</caption>
             * $( ".selector" ).ojMenu({ openOptions: { launcher: "#myLauncher" } });
             *
             * @example <caption>Get or set the <code class="prettyprint">openOptions.launcher</code> sub-option, after initialization:</caption>
             * // getter
             * var launcher = $( ".selector" ).ojMenu( "option", "openOptions.launcher" );
             *
             * // setter:
             * $( ".selector" ).ojMenu( "option", "openOptions.launcher", "#myLauncher" );
             */
            launcher: null,

            /**
             * <p>Determines the position of this menu when launched via the <code class="prettyprint">open()</code> method or via menu button or
             * context menu functionality.
             * 
             * <p>Please refer to the jQuery UI [Position]{@link http://api.jqueryui.com/position/} utility for details about the various choices.
             * In addition to that syntax, note that JET supports the following reading direction-aware extended syntax in the 
             * <code class="prettyprint">my</code> and <code class="prettyprint">at</code> fields:
             * 
             * <ul>
             * <li>JET supports <code class="prettyprint">start</code> and <code class="prettyprint">end</code> values wherever <code class="prettyprint">left</code> 
             * and <code class="prettyprint">right</code> are supported.  The <code class="prettyprint">start</code> value means "left in LTR; right in RTL", 
             * while the <code class="prettyprint">end</code> value means "right in LTR; left in RTL."</li>
             *
             * <li>Similarly, JET supports <code class="prettyprint">></code> and <code class="prettyprint"><</code> operators wherever <code class="prettyprint">+</code> 
             * and <code class="prettyprint">-</code> are supported.  The <code class="prettyprint">></code> value means "+ in LTR; - in RTL", 
             * while the <code class="prettyprint"><</code> value means "- in LTR; + in RTL."  E.g. a <code class="prettyprint">my</code> value 
             * of <code class="prettyprint">"start>40"</code> shifts the menu 40px "endward," while a <code class="prettyprint">my</code> value 
             * of <code class="prettyprint">"start<40"</code> shifts the menu 40px "startward."</li>
             * </ul>
             * 
             * <p>Menu also supports the following extended syntax for the <code class="prettyprint">of</code> field:
             * 
             * <ul>
             * <li>The <code class="prettyprint">"event"</code> keyword means "position the menu relative to the UI event that opened the menu."</li>
             * <li>The <code class="prettyprint">"launcher"</code> keyword means "position the menu relative to the launcher element."</li>
             * </ul>
             * 
             * <p>By default, when the <code class="prettyprint">of</code> field is not set, the menu is positioned relative to the launcher.
             * 
             * @expose
             * @alias openOptions.position
             * @memberof! oj.ojMenu
             * @instance
             * @type {Object}
             * @default <code class="prettyprint">{ "my": "start top", "at": "start bottom" }</code>
             *
             * @example <caption>Initialize the menu with the <code class="prettyprint">openOptions.position</code> option specified:</caption>
             * $( ".selector" ).ojMenu({ openOptions: { position: { "my": "start top", "at": "end<5 top+5" } } });
             *
             * @example <caption>Get or set the <code class="prettyprint">openOptions.position</code> sub-option, after initialization:</caption>
             * // getter
             * var position = $( ".selector" ).ojMenu( "option", "openOptions.position" );
             *
             * // setter:
             * $( ".selector" ).ojMenu( "option", "openOptions.position", { "my": "start top", "at": "end<5 top+5" } );
             */
            position: {
                /** @expose */
                my: "start top",
                /** @expose */
                at: "start bottom"
            }
        },

        // Omitting the usual verbiage about whether the "other" sub-options are clobbered by a given setter syntax,
        // since only one sub-option currently.
        // TBD: restore that verbiage (copy from openOptions) if gain 2nd sub-option.
        /**
         * <p>A collection of settings impacting the launch of submenus.
         *
         * <p>This option affects submenus, while the similar <code class="prettyprint">openOptions</code> affects the top-level menu.
         *
         * @expose
         * @memberof oj.ojMenu
         * @instance
         * @type {Object}
         *
         * @example <caption>Initialize the menu with the <code class="prettyprint">submenuOpenOptions</code> option specified:</caption>
         * $( ".selector" ).ojMenu({ submenuOpenOptions: { "position": { "my": "start top", "at": "end<5 top+5" } } });
         *
         * @example <caption>Get or set the <code class="prettyprint">submenuOpenOptions</code> option, after initialization:</caption>
         * // Get one
         * var value = $( ".selector" ).ojMenu( "option", "submenuOpenOptions.position" );
         *
         * // Get all (currently only one)
         * var values = $( ".selector" ).ojMenu( "option", "submenuOpenOptions" );
         *
         * // Set one
         * $( ".selector" ).ojMenu( "option", "submenuOpenOptions.position", { "my": "start top", "at": "start bottom" } );
         *
         * // Set many (currently only one)
         * $( ".selector" ).ojMenu( "option", "submenuOpenOptions", { position: { "my": "start top", "at": "start bottom" } } );
         */
        submenuOpenOptions: {
            /**
             * <p>Determines the position of submenus.
             * 
             * <p>Please refer to the jQuery UI [Position]{@link http://api.jqueryui.com/position/} utility for details about the various choices.
             * In addition to that syntax, note that JET supports the following reading direction-aware extended syntax in the 
             * <code class="prettyprint">my</code> and <code class="prettyprint">at</code> fields:
             * 
             * <ul>
             * <li>JET supports <code class="prettyprint">start</code> and <code class="prettyprint">end</code> values wherever <code class="prettyprint">left</code> 
             * and <code class="prettyprint">right</code> are supported.  The <code class="prettyprint">start</code> value means "left in LTR; right in RTL", 
             * values in the <code class="prettyprint">my</code> and <code class="prettyprint">at</code> fields wherever <code class="prettyprint">left</code>
             * and <code class="prettyprint">right</code> are supported.  The <code class="prettyprint">start</code> value means "left in LTR; right in RTL",
             * while the <code class="prettyprint">end</code> value means "right in LTR; left in RTL."</li>
             *
             * <li>Similarly, JET supports <code class="prettyprint">></code> and <code class="prettyprint"><</code> operators wherever <code class="prettyprint">+</code> 
             * and <code class="prettyprint">-</code> are supported.  The <code class="prettyprint">></code> value means "+ in LTR; - in RTL", 
             * while the <code class="prettyprint"><</code> value means "- in LTR; + in RTL."  E.g. a <code class="prettyprint">my</code> value 
             * of <code class="prettyprint">"start>40"</code> shifts the submenu 40px "endward," while a <code class="prettyprint">my</code> value 
             * of <code class="prettyprint">"start<40"</code> shifts the submenu 40px "startward."</li>
             * </ul>
             * 
             * <p>By default, the submenu is positioned relative to the parent menu item, but if a value is set on 
             * the <code class="prettyprint">of</code> field, then the submenu is positioned relative to that element or position instead.  
             * 
             * @expose
             * @alias submenuOpenOptions.position
             * @memberof! oj.ojMenu
             * @instance
             * @type {Object}
             * @default <code class="prettyprint">{ "my": "start top", "at": "end top" }</code>
             *
             * @example <caption>Initialize the menu with the <code class="prettyprint">submenuOpenOptions.position</code> option specified:</caption>
             * $( ".selector" ).ojMenu({ openOptions: { position: { "my": "start top", "at": "end<5 top+5" } } });
             *
             * @example <caption>Get or set the <code class="prettyprint">submenuOpenOptions.position</code> sub-option, after initialization:</caption>
             * // getter
             * var position = $( ".selector" ).ojMenu( "option", "submenuOpenOptions.position" );
             *
             * // setter:
             * $( ".selector" ).ojMenu( "option", "submenuOpenOptions.position", { "my": "start top", "at": "end<5 top+5" } );
             */
            position: {
                /** @expose */
                my: "start top",
                /** @expose */
                at: "end top"
            }
        },

        // Events

        // Benefit of making openOptions live is this:
        //
        // - For MenuButton and ContextMenu, the app doesn't control the call to Menu.open().
        // - Our internal call to this method may pass in overrides to things like "initialFocus", in cases where the Right Thing for (say) MenuButtons differs
        //   from Menu's default option value (which may be tailored to, say, contextMenus).
        //     - This way, we don't have to rely on the app to set these things correctly, and we don't have to permanently set the Menu's options, which may be
        //       shared between (say) a MenuButton, a ContextMenu, and some custom app usage of the menu.
        // - The remaining piece of the puzzle is to give the app a way to override the values set in our internal call to open().  A live payload field handles this.
        //
        // If ever needed, we can add a "submenuOpenOptions" payload field alongside the "openOptions" field.
        /**
         * <p>Triggered before this menu is launched via the <code class="prettyprint">open()</code> method or via menu button or context menu functionality.
         * The launch can be cancelled by calling <code class="prettyprint">event.preventDefault()</code>.
         *
         * <p>The <code class="prettyprint">ui.openOptions</code> payload field contains the settings being used for this menu launch,
         * resulting from merging the <code class="prettyprint">openOptions</code> passed to <code class="prettyprint">open()</code>, if any,
         * with the <code class="prettyprint">openOptions</code> component option.
         *
         * <p>This field is "live", meaning that the listener can alter fields such as <code class="prettyprint">position</code> to affect this launch without
         * affecting the component option.  Since these changes are applied to the merged object, they supersede both the <code class="prettyprint">openOptions</code>
         * passed to <code class="prettyprint">open()</code> and the <code class="prettyprint">openOptions</code> component option.
         * 
         * <p>If any of the above techniques are used to alter the built-in [menu button]{@link oj.ojButton#menu} or [context menu]{@link oj.baseComponent#contextMenu} 
         * functionality, it is the app's responsibility to ensure that the result is both correct and accessible.  
         *
         * @expose
         * @event
         * @memberof oj.ojMenu
         * @instance
         * @property {Event} event <code class="prettyprint">jQuery</code> event object
         * @property {Object} ui Parameters
         * @property {Object} ui.openOptions Settings in use for this menu launch.
         *
         * @example <caption>Initialize the menu with the <code class="prettyprint">beforeOpen</code> callback specified:</caption>
         * $( ".selector" ).ojMenu({
         *     "beforeOpen": function( event, ui ) {}
         * });
         *
         * @example <caption>Bind an event listener to the <code class="prettyprint">ojbeforeopen</code> event:</caption>
         * // $( ".selector" ) must select either the menu root, or the document, due to reparenting
         * $( ".selector" ).on( "ojbeforeopen", function( event, ui ) {} );
         */
        beforeOpen: null,

        /**
         * Triggered when the menu is created.
         *
         * @event
         * @name create
         * @memberof oj.ojMenu
         * @instance
         * @property {Event} event <code class="prettyprint">jQuery</code> event object
         * @property {Object} ui Currently empty
         *
         * @example <caption>Initialize the menu with the <code class="prettyprint">create</code> callback specified:</caption>
         * $( ".selector" ).ojMenu({
         *     "create": function( event, ui ) {}
         * });
         *
         * @example <caption>Bind an event listener to the <code class="prettyprint">ojcreate</code> event:</caption>
         * $( ".selector" ).on( "ojcreate", function( event, ui ) {} );
         */
        // create event declared in superclass, but we still want the above API doc

        /**
         * <p>Triggered when the active menu item changes.  Private; do not use.
         *
         * <p>Internal notes:
         *
         * <p>We've replaced JQUI's focus/blur events with this internal event, and made their focus/blur methods internal.
         * It's been agreed with the architects that if we ever need any of this API
         * to be public, we'll have a focusedItem option, read-only or R/W, with an optionChange event, instead
         * of the removed API.  (Exact name TBD, but they favored focusedRow, with "ed",  for Table if it had an option rather than
         * a method.)  If for some reason we keep a separate event instead of an optionChange event, do NOT call this event
         * "focusedItem", since that will prevent ever having an "focusedItem" option since same namespace.  Instead, call this
         * "focusedItemChange" in that case.
         *
         * <p>In the meantime, we'll keep firing this private event, since it's used so extensively and usefully in the unit tests to make sure
         * other stuff works, and since keeping this working and tested means that we can just change the name to optionChange if
         * we ever need the public event.
         *
         * <p>The difference between this method and JQUI's focus event is that it fires for blurs too, it doesn't fire if the old
         * and new active item are the same, and we fire a single event, not both a blur and focus, when the active state moves from item A to
         * item B.
         *
         * @event
         * @name _activeItem
         * @memberof oj.ojMenu
         * @instance
         * @private
         * @property {Event} event <code class="prettyprint">jQuery</code> event object
         * @property {Object} ui Parameters
         * @property {jQuery} ui.previousItem the previously focused menu item
         * @property {jQuery} ui.item the currently focused menu item
         *
         * @example <caption>Initialize the menu with the <code class="prettyprint">_activeItem</code> callback specified:</caption>
         * $( ".selector" ).ojMenu({
         *     "_activeItem": function( event, ui ) {}
         * });
         *
         * @example <caption>Bind an event listener to the <code class="prettyprint">oj_activeitem</code> event:</caption>
         * // $( ".selector" ) must select either the menu root, or the document, due to reparenting
         * $( ".selector" ).on( "oj_activeitem", function( event, ui ) {} );
         */

        /**
         * Triggered when a menu item is selected.  The only correct, supported way to react to the selection of a
         * menu item is to listen for this event.  Click listeners and <code class="prettyprint">href</code> navigation should not be used.
         *
         * @expose
         * @event
         * @memberof oj.ojMenu
         * @instance
         * @property {Event} event <code class="prettyprint">jQuery</code> event object
         * @property {Object} ui Parameters
         * @property {jQuery} ui.item the selected menu item
         *
         * @example <caption>Initialize the menu with the <code class="prettyprint">select</code> callback specified:</caption>
         * $( ".selector" ).ojMenu({
         *     "select": function( event, ui ) {}
         * });
         *
         * @example <caption>Bind an event listener to the <code class="prettyprint">ojselect</code> event:</caption>
         * // $( ".selector" ) must select either the menu root, or the document, due to reparenting
         * $( ".selector" ).on( "ojselect", function( event, ui ) {} );
         */
        select: null
    },

    _ComponentCreate: function() { // Override of protected base class method.  Method name needn't be quoted since is in externs.js.
        this._super();

        // Create aliases, that won't be renamed, for the private methods that are called by unit tests.  These unit tests come
        // from JQUI, in which these methods were actually public.  With these aliases, we don't have to @expose private method names
        // (which prevents renaming and bloats minified code), and our internal calls to these methods can be this._focus rather than this["_focus"].
        // TBD: perhaps the unit tests could simulate keyboard events rather than calling these methods.
        this["_focusForTesting"] = this._focus;
        this["_nextForTesting"] = this._next;
        this["_selectForTesting"] = this._select;

        this.activeMenu = this.element;
        // flag used to prevent firing of the click handler
        // as the event bubbles up through nested menus
        this.mouseHandled = false;
        this.element
            .uniqueId()
            .addClass( "oj-menu oj-component" )
            .hide()
            .attr({
                "role": this.role,
                "tabIndex": "0"
            });
            // pass true to catch these events on all menus, not just enabled menus
            this._on(true, {
                //Required to stick the focus on disabled menu.
                "mousedown .oj-menu-item": function(event) {
                    if (this.options.disabled) {
                        event.preventDefault();
                    }
                },
                "click": function(event) {
                    if (this.options.disabled) {
                        event.preventDefault();
                    }
                },
                //On Esc key focus should be shifted to launcher and dismiss menu.
                //the TAB key should also implicitly dismiss the menu
                "keydown": function(event) {
                    if (this.options.disabled) {
                        if (event.keyCode === $.ui.keyCode.ESCAPE || event.keyCode === $.ui.keyCode.TAB) {

                            if (event.keyCode === $.ui.keyCode.TAB) {
                              event.preventDefault();
                            }

                            if (this._launcher) { // if this is a popup menu that's currently shown
                                this._focusLauncherAndDismiss(event);
                            }
                        }
                    }
                }
            });

        // needed since _setOption() is not automatically called at create time.
        // TBD: Would be a little better to toggle these 2 things rather than only setting them if true, as in superclass _setOption().
        if ( this.options.disabled ) {
            this.element
                .addClass( "oj-disabled" )
                .attr( "aria-disabled", "true" );
        }

        var handleMouseEnterMenuItem = function( event ) {
            var target = $( event.currentTarget );
            // Remove oj-focus-ancestor class from siblings of the newly focused menu item
            // to avoid a jump caused by adjacent elements both having a class with a border
            target.siblings().children( ".oj-focus-ancestor" ).removeClass( "oj-focus-ancestor" );
            this._focus( event, target );
        }.bind(this);
            
        this._on({
            // Prevent focus from sticking to links inside menu after clicking
            // them (focus should always stay on UL during navigation).
            "mousedown .oj-menu-item > a": function( event ) {
                event.preventDefault();
            },
            "click .oj-disabled > a": function( event ) {
                event.preventDefault();
            },
            "click": function(event) {
                // when the click event bubbles out of the root menu element, we're done with it, so
                // reset this flag to its initial value of false in preparation for the next click
                this.mouseHandled = false;
            },
            "touchstart": function(event) {
                // when the touchstart event bubbles out of the root menu element, we're done with it, so 
                // reset this flag to its initial value of false in preparation for the next touch
                this.touchHandled = false;
            },
            "click .oj-menu-item:has(a)": function( event ) {
                var target = $( event.target ).closest( ".oj-menu-item" );
                // the mouseHandled var ensures that the click is handled only for the originally clicked
                // menu item, not for the parent menu items to which it bubbles.
                if ( !this.mouseHandled && target.not( ".oj-disabled" ).length ) {
                    this.mouseHandled = true;

                    // prevent page scrolling and appending # to page URL, which can interfere with routing, etc.
                    // Do this before the bailout so these things are prevented when user clicks a 2nd time on parent menu item.
                    // No need to additionally do this for Enter/Space handler, because menu root, not the anchor, has browser focus
                    // in that case, so anchor click behavior doesn't happen, so doesn't need to be prevented.
                    event.preventDefault();

                    if (this.active && this.active.closest(target).length && this.active.get(0) != target.get(0)) {
                        //If current active menu item  is decendent of (and not equal to) target menu item then
                        //sub menu of the curent target is already open and hence no need to
                        //1. expand the sub menu
                        //2. as current target is a menu item having sub menu no need to invoke this._select(event).
                        return;
                    }
                    // Open submenu on click
                    if ( target.has( ".oj-menu" ).length ) {
                        this._expand( event );
                    }
                    else {
                        //Invoke _select() only for leaf menu items
                        this._select(event);
                        if (!this.element.is(":focus")) {
                            // Redirect focus to the menu
                            this.element.trigger("focus", [true]);

                            // If the active item is on the top level, let it stay active.
                            // Otherwise, blur the active item since it is no longer visible.
                            if (this.active && this.active.parents(".oj-menu").length === 1) {
                                clearTimeout(this.timer);
                            }
                        }
                    }
                }
            },
            "mouseenter .oj-menu-item": handleMouseEnterMenuItem,
            
            // Bug 19462004: Bad touch device behavior because the JQUI code relies on the above mouseenter handler to call _focus(), 
            // but for parent menu items on touch devices, mouseenter is called only if the previous tap was somewhere outside the 
            // parent menu item, not if it was in the submenu.  So call that mouseenter handler on touchstart:
            "touchstart .oj-menu-item": function( event ) {
                // the touchHandled var ensures that this handler only runs for the originally touched
                // menu item, not for the parent menu items to which it bubbles.  Without it, get flakiness 
                // where sometimes a tap on a menu item inside the submenu doesn't "take".
                if ( this.touchHandled )
                    return;
                
                this.touchHandled = true;
                handleMouseEnterMenuItem(event);
            },
            "mouseleave": function( event ) {
                this._collapse( event, "eventSubtree" );
            },
            "mouseleave .oj-menu": function( event ) {
                this._collapse( event, "eventSubtree" );
            },
            "focus": function( event, keepActiveItem ) {
                if ( !keepActiveItem ) {
                    // If there's already an active item, keep it active
                    // If not, make the first item active
                    // TBD: is there a reason that JQUI needed to redundantly call _focus() on this.active when this.active was already set?
                    //      Or should we only call it when it's not set and we're calling it on the first menu item?
                    var item = this.active || this.element.children( ".oj-menu-item" ).eq( 0 );
                    this._focus( event, item );
                }
            },
            "keydown": this._keydown,
            "keyup": function( event ) {
                if (event.keyCode == $.ui.keyCode.ENTER || event.keyCode == $.ui.keyCode.SPACE)
                    this.__spaceEnterDownInMenu = false;
            }
        });

        // callback that overrides the positon['using'] for auto dismissal when aligning element is cropped.
        this._usingCallback = $.proxy(this._usingHandler, this);
        this._setup();
    },

    // Resolves a Mobile Safari issue that occurs because mousedown fires after the touchend.  
    // To be called only by baseComponent's contextMenu logic, which explains the issue more fully.  
    // Gets/sets a static var, since the listener that needs to know whether to bail out is static
    // (shared by all menu instances).
    __contextMenuPressHoldJustEnded: function(val) {
        if (arguments.length)
            _contextMenuPressHoldJustEnded = val;
        else
            return _contextMenuPressHoldJustEnded;
    },

   /**
    * @instance
    * @private
    * @param {!jQuery.Event|Event} event
    */
    _clickAwayHandler: function(event) {
                //Focus event needs to be captured because, in case of menu button (where focus is still on menu button instead of open menu), if user does
                //a taboff to another element then menu should be closed. With this we also no need to have additional "blur" handler on menu to close the menu popup/submenus.

                //Despite of focus/mousedown, still keydown listener is required for contextmenu events especially for menubutton with browser default context menu
                //and user pressed contextmenu keyboard key(not right mouse click).

                //Checking event.KeyCode along with event.which as currently event created by jquery-simulate.js is setting only event.keyCode for chrome/IE.
                //This avoids test failures. This can be removed after jquery simulates event properly.

                if (event.type === "focus" || event.type === "mousedown" || event.type === "touchstart" || event.which == 93 || (event.which == 121 && event.shiftKey) || event.keyCode == 93) { // Windows contextMenu key (93) or Shift-F10 (121)                    // Resolves a Mobile Safari issue that occurs because mousedown fires after the touchend.  
                    // baseComponent's contextMenu logic explains the issue more fully.  
                    if (event.type === "mousedown" && _contextMenuPressHoldJustEnded) {
                        return;
                    }

                    //Clone _openPopupMenus as __dismiss() will remove the open menu from _openPopupMenus list
                    var openPopupMenus = _openPopupMenus.slice(0, _openPopupMenus.length);
                    $.each(openPopupMenus , function(index, menu) {
                        // This logic dismisses/collapses the menu if event is outside the menu and any of the following are true:
                        // - Event is a touchstart (which may or may not become a pressHold) or left/middle mousedown, unless (event is in launcher and this is not a context menu).  "Unless" clause needed for menuButton.
                        // - Event is focusing something outside of both the menu and launcher.
                        // - Event is a context-menu-launching event other than pressHold.  (i.e. right-click or CM keys)
                        if (!$(event.target).closest(menu.element).length &&  // if event target is outside of menu element AND one of the following is true then close the menu.
                            (event.type === "keydown" || (event.type === "mousedown" && event.which === 3) ||  // 1. if it's a context-menu-launching event other than pressHold (see event.which on outer if)
                             !$(event.target).closest(menu._launcher).length ||  // 2. When focus is moved on to other than launcher or left/middle mousedown or touchstart on element other than launcher
                             (menu._launcherClickShouldDismiss && ((event.type === "mousedown" && event.which !== 3) || event.type === "touchstart" ))))  // 3. If event is a (left/middle-mousedown or touchstart) on launcher and current menu is contextmenu (see bug 18745414)
                        {
                            menu._collapse(event, "eventSubtree"); // "eventSubtree" is effectively "all" since we check that event is outside menu.  "all" would be clearer, but just in case, leaving it as is.
                            if (menu._launcher)
                                menu.__dismiss(event);
                        }
                    });
                };
    },


    _setOption: function( key, value ) { // Override of protected base class method.  Method name needn't be quoted since is in externs.js.
        this._superApply( arguments ); // TBD: consider calling super at end, so that optionChange (fired at end of super) is fired at very end

        // this._submenuPosition is used every time a *sub*menu is opened.
        // For non-popup menus, this is set only here and in _setup().
        // For popup menus, this is set in each call to open(), and not changed by the following code while the popup is still open,
        // since while it is still open it should keep using the merged value from open()/beforeOpen, not the new value of the component option.
        if (!this._launcher) { // if this is not a popup menu that's currently shown
            if (key === "submenuOpenOptions")
                this._submenuPosition = oj.PositionUtils.normalizeHorizontalAlignment(value.position, this.isRtl);
            else if (key === "submenuOpenOptions.position")
                this._submenuPosition = oj.PositionUtils.normalizeHorizontalAlignment(value, this.isRtl);
        }
    },

    _destroy: function() { // Override of protected base class method.  Method name needn't be quoted since is in externs.js.
      if (this.element.is(":visible"))
        this.__dismiss();

      clearTimeout( this.timer );
        delete this.timer;

      // Destroy (sub)menus
        this.element
            .removeAttr( "aria-activedescendant" )
            .removeClass( "oj-component oj-menu-icons" )
            .find( ".oj-menu" ).addBack()
                .removeClass( "oj-menu" )
                .removeAttr( "role" )
                .removeAttr( "tabIndex" )
                .removeAttr( "aria-labelledby" )
                .removeAttr( "aria-hidden" )
                .removeAttr( "aria-disabled" )
                .removeUniqueId()
                .show();

        // Destroy menu items
        this.element.find( ".oj-menu-item" )
            .removeClass( "oj-menu-item" )
            .removeAttr( "role" )
            .children( "a" )
                .removeAttr( "aria-disabled" )
                .removeUniqueId()
                .removeClass( "oj-hover" )
                .removeAttr( "tabIndex" )
                .removeAttr( "role" )
                .removeAttr( "aria-haspopup" )
                .children().each( function() {
                    var elem = $( this );
                    if ( elem.data( "oj-ojMenu-submenu-icon" ) ) {
                        elem.remove();
                    }
                });

        // Destroy anchors
        this.element.find( "a" ).removeAttr( "aria-expanded" );

        // Destroy menu dividers
        this.element.find( ".oj-menu-divider" )
            .removeClass( "oj-menu-divider" )
            .removeAttr( "role" );

        // Remove the menu from openPopupMenus list if it is still added.
        if(_openPopupMenus.indexOf(this) >= 0)
            _openPopupMenus.splice(_openPopupMenus.indexOf(this),1);

        delete this._popupServiceEvents;
        delete this._usingCallback;

        var closeDelayTimer = this._closeDelayTimer;
        if (!isNaN(closeDelayTimer))
        {
          delete this._closeDelayTimer;
          window.clearTimeout(closeDelayTimer);
        }

        this._super();
    },

    _keydown: function( event ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        /*jshint maxcomplexity:20*/
        var match, prev, character, skip, regex,
            preventDefault = true;

        function escape( value ) {
            return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
        }

        switch ( event.keyCode ) {
        case $.ui.keyCode.HOME:
            this._move( "first", "first", event );
            break;
        case $.ui.keyCode.END:
            this._move( "last", "last", event );
            break;
        case $.ui.keyCode.UP:
            this._previous( event );
            break;
        case $.ui.keyCode.DOWN:
            this._next( event );
            break;
        case $.ui.keyCode.LEFT:
        case $.ui.keyCode.RIGHT:
            var isExpand = (event.keyCode === $.ui.keyCode.RIGHT) ^ this.isRtl;
            if (isExpand) {
                if ( this.active && !this.active.is( ".oj-disabled" ) ) {
                    this._expand( event );
                }
            } else {
                this._collapse( event, "active" );
            }
            break;
        case $.ui.keyCode.ENTER:
        case $.ui.keyCode.SPACE:
            this._handleEnterSpace( event );

            this.__spaceEnterDownInMenu = true;
            var self = this;

            // The spaceEnterDelay and __spaceEnterDownInMenu code addresses an issue where closing a menu, from within the menu via
            // Space or Enter, can immediately reopen the menu, because the keyUp can happen after focus has jumped to the button,
            // which clicks the button, which reopens the menu.  Repros most readily (only??) in Firefox.
            // TODO: try calling preventDefault() on the event in Menu (which is good practice anyway since it's handling the event), and
            // checking isDefaultPrevented() in Button.  If works, should be cleaner / more reliable than this existing fix.
            var spaceEnterDelay = 100; // 1 not enough in FF; 100 seems to do it.  If continued problems, try increasing this value.

            setTimeout(function () {
                self.__spaceEnterDownInMenu = false;
            }, spaceEnterDelay);

            break;
        // tab within a menu will implicitly dismiss
        case $.ui.keyCode.TAB:
          event.preventDefault();
          if (this._launcher) {
            this._focusLauncherAndDismiss( event );
          }
          break;
        // this handles enabled menus.  For disabled menus, see this handler: this._on(true, {...});
        case $.ui.keyCode.ESCAPE:
            if (this._launcher) { // if this is a popup menu that's currently shown
                var activeItemId = this.element.attr("aria-activedescendant"); // <a> or nothing.  Always the same as this.active now that we change them in lockstep.
                var topLevelAnchorSelector = "#" + this.element.attr("id") + ">*>a"; // * is typically <li>
                var submenuOpen = activeItemId && !$("#" + activeItemId).is( topLevelAnchorSelector );

                if (submenuOpen)
                    this._collapse( event, "active" );
                else
                    this._focusLauncherAndDismiss( event );
            } else {
                this._collapse( event, "active" );
            }
            break;
        default:
            preventDefault = false;
            prev = this.previousFilter || "";
            character = String.fromCharCode( event.keyCode );
            skip = false;

            clearTimeout( this.filterTimer );

            if ( character === prev ) {
                skip = true;
            } else {
                character = prev + character;
            }

            regex = new RegExp( "^" + escape( character ), "i" );
            match = this.activeMenu.children( ".oj-menu-item" ).filter(function() {
                return regex.test( $( this ).children( "a" ).text() );
            });
            match = skip && match.index( this.active.next() ) !== -1 ?
                this.active.nextAll( ".oj-menu-item" ) :
                match;

            // If no matches on the current filter, reset to the last character pressed
            // to move down the menu to the first item that starts with that character
            if ( !match.length ) {
                character = String.fromCharCode( event.keyCode );
                regex = new RegExp( "^" + escape( character ), "i" );
                match = this.activeMenu.children( ".oj-menu-item" ).filter(function() {
                    return regex.test( $( this ).children( "a" ).text() );
                });
            }

            if ( match.length ) {
                this._focus( event, match );
                if ( match.length > 1 ) {
                    this.previousFilter = character;
                    this.filterTimer = this._delay(function() {
                        delete this.previousFilter;
                    }, 1000 );
                } else {
                    delete this.previousFilter;
                }
            } else {
                delete this.previousFilter;
            }
        }

        if ( preventDefault ) {
            event.preventDefault();
        }
    },

    /*
     * Called for Space and Enter
     */
    _handleEnterSpace: function( event ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        if ( this.active && !this.active.is( ".oj-disabled" ) ) {
            if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
                this._expand( event );
            } else {
                this._select( event );
            }
        }
    },

    /**
     * Refreshes the visual state of the menu. JET components require a <code class="prettyprint">refresh()</code> after the DOM is
     * programmatically changed underneath the component.  For Menu, this includes:
     *
     * <ul>
     *   <li>After menu items or submenus are added or removed.</li>
     *   <li>After a change to a menu item's disabled status (which is set by applying or removing the <code class="prettyprint">oj-disabled</code>
     *       class from the menu item).</li>
     *   <li>After the reading direction (LTR vs. RTL) changes.</li>
     * </ul>
     *
     * <p>This method does not accept any arguments.
     *
     * @expose
     * @memberof oj.ojMenu
     * @instance
     *
     * @example <caption>Invoke the <code class="prettyprint">refresh</code> method:</caption>
     * $( ".selector" ).ojMenu( "refresh" );
     */
    refresh: function() { // Override of public base class method (unlike JQUI).  Method name needn't be quoted since is in externs.js.
        this._super();
        this._setup();


        var element = this.element;
        if (!element.is(":visible"))
          return;

        // reevaluate open menu positions
        var position = element.data(_POSITION_DATA);
        if (position)
          element.position(position);

        var openMenus = element.find(".oj-menu");
        openMenus.each(function()
        {
            var menu = $(this);
            if (menu.is(":visible"))
            {
              position = menu.data(_POSITION_DATA);
              if (position)
                menu['position'](position);
            }
        });
    },

    _setup: function() { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        this.isRtl = this._GetReadingDirection() === "rtl";

        // Used every time a *sub*menu is opened.
        // For non-popup menus, this is set only here and in _setOption().
        // For popup menus, this is set in each call to open().
        this._submenuPosition = oj.PositionUtils.normalizeHorizontalAlignment(this.options.submenuOpenOptions.position, this.isRtl);

        var self=this,
            menus, // <ul>'s including root <ul>
            submenus = this.element.find( this.options.menuSelector ); // <ul>'s except root <ul>

        this.element.toggleClass( "oj-menu-icons", !!this.element.find( ".oj-menu-item-icon" ).length )

        // Initialize nested menus
        submenus.filter( ":not(.oj-menu)" )
            .addClass( "oj-menu" )
            .hide()
            .attr({
                "role": this.role,
                "aria-hidden": "true"
            })
            .each(function() {
                var menu = $( this ), // <ul>
                    item = self._getSubmenuAnchor( menu ), // <a>
                    submenuIcon = $( "<span>" );

                submenuIcon   // separate stmt rather than chaining, since GCC can't tell that this is the setter overload of .data().
                    .addClass( "oj-menu-submenu-icon oj-component-icon" )
                    .data( "oj-ojMenu-submenu-icon", true ); // TODO: can't we just look for the class at destroy time rather than adding this data?

                item
                    .attr( "aria-haspopup", "true" )
                    .attr( "aria-expanded", "false" ) // per a11y team, live on <a>, not <ul> like JQUI

                    // @HTMLUpdateOK prepend trusted new DOM to menu item
                    .prepend( submenuIcon );
                var itemId = /** @type {string|undefined}  tell GCC is getter, not setter, overload of attr() */
                             (item.attr( "id" ));

                // itemId is undefined if id attr not present, in which case following stmt is a chainable no-op (returns
                // "this" and doesn't set anything).
                menu.attr( "aria-labelledby", itemId );
            });

        menus = submenus.add( this.element );
        var children = menus.children(); // <li>'s

        // Anything that used to be a divider, but now has an "a", should become a menu element.
        children.filter( ".oj-menu-divider" ).has("a")
            .removeClass("oj-menu-divider oj-menu-item") // remove oj-menu-item if somehow present to ensure that it enters following block
            .removeAttr("role");

        // Don't refresh list items that are already adapted
        // TBD: .has prob has better perf than :has
        children.filter( ":not(.oj-menu-item):has(a)" )
            .addClass( "oj-menu-item" )
            .attr( "role", "presentation" )
            .children( "a" )
                .uniqueId()
                .attr({
                    "tabIndex": "-1",
                    "role": this._itemRole()
                });

        // Initialize unlinked menu-items containing spaces and/or dashes only as dividers
        children.filter( ":not(.oj-menu-item)" ).each(function() {
            var item = $( this );
            // hyphen, em dash, en dash
            if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) {
                item.addClass( "oj-menu-divider" )
                    .attr( "role", "separator" );
            }
        });

        // Add aria-disabled to any disabled menu item, and remove it from any recently enabled menu item
        children.filter( ".oj-disabled" ).children( "a" ).attr( "aria-disabled", "true" );
        children.filter( ":not(.oj-disabled)" ).children( "a" ).removeAttr( "aria-disabled" );

        // If the active item has been removed, blur the menu
        if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
            this._blur();
        }
    },

    /*
     * Given a list of one or more submenus (typically <ul>'s), finds the <a>'s that are their labels.
     */
    _getSubmenuAnchor: function(submenu) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        return submenu.prev( "a" );
    },

    _itemRole: function() { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        return "menuitem";
//        {
//            "menu": "menuitem",
//            "listbox": "option"
//        }[ this.role ];
    },

    /**
     * Focuses the specified menu item and triggers the menu's <code class="prettyprint">_activeItem</code> event.
     *
     * @memberof oj.ojMenu
     * @instance
     * @private
     * @param {Event} event - What triggered the menu item to gain focus.  May be <code class="prettyprint">null</code>, but may not be omitted.
     * @param {!jQuery} item - The menu item to focus.  Its containing submenu, if any, must already be expanded.
     */
    _focus: function( event, item ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        // JQUI called blur() here.  This "if blah clearTimeout" is the only thing from that call that we (presumably) still want to do here.
        if ( !(event && event.type === "focus") )
            clearTimeout( this.timer );

        item = item.first();
        this._makeActive(item, event);

        // Highlight active parent menu item, if any
        item // li
            .parent() // ul
            .closest( ".oj-menu-item" ) // li
            .children( "a:first" ) // a
            .addClass( "oj-focus-ancestor" );

        if ( event && event.type === "keydown" ) {
            this._close();
        } else {
            this.timer = this._delay(function() {
                delete this.timer;
                this._close();
            }, this.delay );
        }

        var nested = item.children( ".oj-menu" ); // immediately nested submenu.  length 0 or 1.
        if ( nested.length && event && ( /^mouse/.test( event.type ) && !this.active.hasClass( "oj-disabled" ) ) ) {
            this._startOpening(nested);
        }
        this.activeMenu = item.parent();
    },

    /*
     * Sets this.active (<li>), aria-activedescendant (<a>), and oj-focus (<a>) in lockstep.  
     * Never set those things outside of _makeActive() and _removeActive(), so they stay in synch!
     *
     * param item length-1 JQ object containing the <li> to focus
     */
    _makeActive: function( item, event ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        // don't need to check for "both items null/empty", and don't need to null-check item, since item required to be length-1 JQ object
        var same = item.is(this.active);
        if (same) {
            return;
        }

        var previousItem = this.active ? this.active : $();
        var anchor = item.children( "a" );

        this.active = item;
        this.element.attr( "aria-activedescendant", anchor.attr( "id" ) );

        previousItem.children( "a" ).removeClass( "oj-focus" );
        anchor.addClass( "oj-focus" );

        // see private API doc on the private _activeItem event declaration in this file
        this._trigger( "_activeItem", event, { "previousItem": previousItem , "item": item, "privateNotice": "The _activeItem event is private.  Do not use." } );
    },

    /*
     * Unsets this.active (<li>), aria-activedescendant (<a>), and oj-focus (<a>) in lockstep.
     * Never set those things outside of _makeActive() and _removeActive(), so they stay in synch!
     *
     * Don't call this if you are immediately going to call _makeActive, to avoid firing the event twice (and redundant work).
     */
    _removeActive: function(event) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        if ( this.active ) { // then there is definitely a change, from "something focused" to "nothing focused", so proceed.
            var previousItem = this.active; // non-null, so don't need null-check

            this.active = null;
            this.element.removeAttr( "aria-activedescendant");

            previousItem.children( "a" ).removeClass( "oj-focus" );

        // see private API doc on the private _activeItem event declaration in this file
            this._trigger( "_activeItem", event, { "previousItem": previousItem, "item": $(), "privateNotice": "The _activeItem event is private.  Do not use." } );
        }
    },

    /**
     * @memberof oj.ojMenu
     * @instance
     * @private
     * @param {Event=} event - What triggered the menu item to blur.  May be <code class="prettyprint">null</code> or omitted.
     */
    _blur: function( event ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        clearTimeout( this.timer );
        this._removeActive(event);
    },

    _focusLauncherAndDismiss: function( event ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        this._launcher.focus();
        this.__dismiss( event );
    },

    /*
     * TODO: JSDoc, including making it private-but-actually-internal, then add 2nd star above
     * Could make this method, and the event, public, if ever needed.
     *
     */
    __dismiss: function(event) { // Internal visibility; called by Button's MenuButton functionality.  Not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        //this.element.hide().attr( "aria-hidden", "true" );

        /** @type {!Object.<oj.PopupService.OPTION, ?>} */
        var psOptions = {};
        psOptions[oj.PopupService.OPTION.POPUP] = this.element;
        oj.PopupService.getInstance().close(psOptions);
        this.element.removeData(_POSITION_DATA);

        this._launcher = undefined;

        // TODO: if keep this, check whether actually open first, to avoid spurious events
        this._trigger( "__dismiss", event, {} ); // internal event

        //Remove menu from openPopupMenus list
        if(_openPopupMenus.indexOf(this) >= 0)
            _openPopupMenus.splice(_openPopupMenus.indexOf(this),1);
    },

    // TODO: push up to Popup Fmwk, so all popups get this fix.
    // TODO: link to the JQ bug when I file it.
    /**
     * On iOS and Android, the JQ Event object wrapping touch* events lacks pageX and pageY properties, which is contrary to the
     * contract [1].  This breaks JQ's position() API [2], which assumes that the contract is obeyed.  Specifically, it 
     * relies on the pageX/Y fields of the Event object passed as the "of" field (and publicly docs that it does so).
     * 
     * Per W3C [3], pageX/Y are found in originalEvent.touches[i] or originalEvent.changedTouches[i], where originalEvent is 
     * the native (not JQ) event, and i is 0 for us.  In practice, for touchstart at least, iOS7 and 8 Mobile Safari, but 
     * apparently not Android Chrome, also put pageX and pageY on the top-level native event, and the values seem to be the 
     * same as those in the touches array.  We'll use the cross-platform W3C location.
     *
     * To workaround the JQ bug, we copy the properties ourselves in this method.
     * 
     * [1] http://api.jquery.com/category/events/event-object/
     * [2] http://api.jqueryui.com/position/
     * [3] http://www.w3.org/TR/touch-events/#touch-interface et. seq.
     * 
     * @param event
     * @private
     */
    _normalizeEventForPosition: function( event ) {
        $.each(["pageX", "pageY"], function (index, pagePos) {
            if (event && event[pagePos] === undefined && event.originalEvent) {
                var originalEvent = event.originalEvent;
                var type = originalEvent.type;
                var touchList = (type === "touchstart" || type === "touchmove")
                    ? "touches"
                    : (type === "touchend") ? "changedTouches" : null;

                if (touchList) {
                    var firstTouch = originalEvent[touchList][0];
                    if (firstTouch) {
                        event[pagePos] = firstTouch[pagePos];
                    }
                }
            }
        });
    },

    /**
     * <p>Launches this menu as a popup, after firing the <code class="prettyprint">beforeOpen</code> event.  Listeners to that event can cancel the launch
     * via <code class="prettyprint">event.preventDefault()</code>.
     *
     * <p>This method's optional <code class="prettyprint">openOptions</code> and <code class="prettyprint">submenuOpenOptions</code> params can be used to specify
     * per-launch values for the settings in the corresponding component options, without altering those options.  Those per-launch values can
     * be further customized by a <code class="prettyprint">beforeOpen</code> listener.
     *
     * @expose
     * @memberof oj.ojMenu
     * @instance
     *
     * @param {jQuery.Event=} event What triggered the menu launch.  May be <code class="prettyprint">null</code>.  May be omitted if subsequent params are omitted.
     * @param {Object=} openOptions Options to merge with the <code class="prettyprint">openOptions</code> option.  May be <code class="prettyprint">null</code>.  May be omitted if subsequent params are omitted.
     * @param {Object=} submenuOpenOptions Options to merge with the <code class="prettyprint">submenuOpenOptions</code> option.  May be <code class="prettyprint">null</code> or omitted.
     *
     * @example <caption>Invoke the <code class="prettyprint">open</code> method:</caption>
     * // override the launcher for this launch only, without affecting the other
     * // openOptions, and without affecting the component's openOptions option
     * $( ".selector" ).ojMenu( "open", myEvent, {launcher: "#myLauncher"} );
     */
    open: function( event, openOptions, submenuOpenOptions ) { // Public, not an override (not in base class), so use @expose with unquoted method name.
        // Important:  Merge [submenu]openOptions *before* calling _trigger(), and don't use the merged values until *after* the call.
        // Reason:  Per doc on open() and beforeOpen event, we pass the merged openOptions to beforeOpen listeners as a "live" object, 
        // so the listener can both read and write the values used for this launch.  We may eventually pass submenuOpenOptions too, either to 
        // beforeOpen or to beforeSubmenuOpen, if we ever have that.
        // 
        // Merge needs 2 steps:
        // 1) Shallow merge (i.e. don't pass true as first arg to extend) of the 2 openOptions objects, into a new object.  Shallow so that the per-launch position object completely overrides the 
        // component option's position object rather than merging with it.
        // 2) Then a deep copy of all object-valued fields in the merged object.  Position is the only such field, and it doesn't contain any objects of its own, 
        // so this is actually just a shallow copy of position.  This is so that if beforeOpen listener mutates the position object, the position object in the component option remains unchanged.
        // Step 2 isn't needed for submenuOptions, since it isn't passed to beforeOpen.  
        // $.fn.position copies the object passed to it before modifying it, so Step 2 isn't needed for that reason.  
        if (this.element.is(":visible"))
          this.__dismiss();

        openOptions = $.extend({}, this.options.openOptions, openOptions);
        openOptions.position = $.extend({}, openOptions.position);
        submenuOpenOptions = $.extend({}, this.options.submenuOpenOptions, submenuOpenOptions);

        this._normalizeEventForPosition(event); // see callee doc
        
        // Hack:  __openingContextMenu is set and unset by baseComponent._OpenContextMenu(), since Menu needs to know whether the 
        // menu is open as a context menu vs. some other kind of menu including menu button, 
        // as this affects whether subsequent mousedown/touchstart on launcher should dismiss menu.  IIRC, the upcoming Popup Fmwk 
        // will address this need, but if not, fix it separately, perhaps by adding a new openOptions sub-option so it can be passed to menu.open().
        this._launcherClickShouldDismiss = this.__openingContextMenu;

        // TBD: if we ever pass submenuOpenOptions to a listener, must copy its position object first like we do for openOptions, above.        // Important:  Do the merging *before* calling _trigger(), and don't use the merged values until *after* the call.
        var cancelled = !this._trigger( "beforeOpen", event, {openOptions: openOptions});

        if (cancelled)
            return;

        var launcher = openOptions.launcher;
        launcher = $.type(launcher) === "string"
                   ? $(launcher)
                   : launcher;

        if (!launcher || !launcher.length) {
          // need launcher so can return focus to it.
          oj.Logger.warn("When calling Menu.open(), must specify openOptions.launcher via the component option, method param, or beforeOpen listener.  Ignoring the call.");
          return;
        }

        var position = oj.PositionUtils.normalizeHorizontalAlignment(openOptions.position, this.isRtl);
        position.of = oj.PositionUtils.normalizePositionOf(position.of, launcher, event);
        
        // since already checked for null launcher above, this is only possible if "of" was "event" but the event was null.  Caller error.
        if (position.of == null) {
            oj.Logger.warn("position.of passed to Menu.open() is 'event', but the event is null.  Ignoring the call.");
            return;
        }
        
        //Close all other open menus
        var currentMenu = this.element[0];
        //Clone _openPopupMenus as __dismiss() will remove the open menu from _openPopupMenus list
        var openPopupMenus = _openPopupMenus.slice(0, _openPopupMenus.length);
        $.each(openPopupMenus , function(index, menu) {
            if (menu.element[0] !== currentMenu) {
                menu._collapse( event, "eventSubtree"); // TBD: should this be "all"?
                if (menu._launcher)
                    menu.__dismiss(event);
            }
        });

        // cache the merged value for use while the (outer) menu is still open
        this._submenuPosition = oj.PositionUtils.normalizeHorizontalAlignment(submenuOpenOptions.position, this.isRtl);

        var usingCallback = this._usingCallback;

        // if they provided a using function that is not our callback, stash it
        // away so that we can delegate to it in our proxy.
        if ($.isFunction(position["using"]) && position["using"] !== usingCallback)
          position["origUsing"] = position["using"];

        // override with our proxy to handle positioning of the tail
        position["using"] = usingCallback;

        /** @type {!Object.<oj.PopupService.OPTION, ?>} */
        var psOptions = {};
        psOptions[oj.PopupService.OPTION.POPUP] = this.element;
        psOptions[oj.PopupService.OPTION.LAUNCHER] = launcher;
        psOptions[oj.PopupService.OPTION.POSITION] = position;
        psOptions[oj.PopupService.OPTION.EVENTS] = this._getPopupServiceEvents();
        psOptions[oj.PopupService.OPTION.LAYER_SELECTORS] = "oj-menu-layer";
        oj.PopupService.getInstance().open(psOptions);
        this.element.data(_POSITION_DATA, position);

        var initialFocus = openOptions.initialFocus;

        var focusFirstItem = initialFocus === "firstItem";
        var focusMenu = focusFirstItem || initialFocus === "menu" ;

        if (focusMenu)
            this.element.focus();

        if (focusFirstItem) {
            this._focus(event, this.element.children().first());
        } else {
            this._blur(event);
        }

        // store launcher so we can return focus to it, e.g. if Esc pressed.  Ivar is non-null iff menu is a popup and is currently shown.
        this._launcher = launcher;

        //Add current menu to openPopupMenus so that it will be closed on focus lost/click away.
        _openPopupMenus.push(this);
    },

    _startOpening: function( submenu ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        clearTimeout( this.timer );

        // Don't open if already open fixes a Firefox bug that caused a .5 pixel
        // shift in the submenu position when mousing over the submenu icon
        if ( submenu.attr( "aria-hidden" ) !== "true" ) {
            return;
        }
        if (this.timer)
          clearTimeout(this.timer);
        this.timer = this._delay(function() {
            delete this.timer;
            this._close();
            this._open( submenu );
        }, this.delay );
    },

    // opens a *sub*menu
    _open: function( submenu ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        var position = $.extend( {"of": this.active}, this._submenuPosition); // normalizeHorizontalAlignment() was already called on the ivar

        clearTimeout( this.timer );
        this.element.find( ".oj-menu" ).not( submenu.parents( ".oj-menu" ) )
            .hide()
            .attr( "aria-hidden", "true" )
            .removeData(_POSITION_DATA);

        submenu
            .show()
            .removeAttr( "aria-hidden" )
            .position( position )
            .data(_POSITION_DATA, position);

        this._getSubmenuAnchor(submenu).attr( "aria-expanded", "true" );

        if (!this._launcher && _openPopupMenus.indexOf(this) < 0) {
            _openPopupMenus.push(this);
        }
    },

    /*
     * Same as calling _collapse(event, "eventSubtree") or _collapse(event, "all"), except that, if delay param is not passed, it collapses the menu immediately.
     */
    __collapseAll: function(event, all, delay) {
        clearTimeout(this.timer);
        var self = this;
        var collapseMenu = function() {
            delete self.timer;
            // If we were passed an event, look for the submenu that contains the event
            var currentMenu = all ? self.element :
                $(event && event.target).closest(self.element.find(".oj-menu"));

            // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
            if (!currentMenu.length) {
                currentMenu = self.element;
            }

            self._close(currentMenu);

            self._blur(event);
            self.activeMenu = currentMenu;
        };
        if (delay) {
            this.timer = this._delay(collapseMenu, delay);
        } else {
            collapseMenu();
        }
    },

    // With no arguments, closes the currently active menu - if nothing is active
    // it closes all menus.  If passed an argument, it will search for menus BELOW
    _close: function( startMenu ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.

        //TODO: Consider refatoring _close moving into the __dismiss logic.  The _close logic
        //      will hide levels of nested menus.  The __dismiss knocks down the root
        //      menu.  Both _close and _dismiss are called from _closeAll which closes
        //      all submenus and the main menu.

        if ( !startMenu ) {
            startMenu = this.active ? this.active.parent() : this.element;
        }

        var menus = startMenu.find( ".oj-menu" );
        menus.hide()
             .attr( "aria-hidden", "true" )
             .removeData(_POSITION_DATA);
        this._getSubmenuAnchor( menus ).attr( "aria-expanded", "false" );
        startMenu.find( "a.oj-focus-ancestor" ).removeClass( "oj-focus-ancestor" );

        if (!this._launcher) {
            // If the current menu is not a popup menu and it's submenu is already open then remove the menu from _openPopupMenus
            // while closing the submenus of top level menu.
            if (_openPopupMenus.indexOf(this) >= 0) {
                if (startMenu === this.element) {
                    _openPopupMenus.splice(_openPopupMenus.indexOf(this), 1);
                }
            }
        }
    },

    /**
     * Closes one or more open submenus.
     *
     * @memberof oj.ojMenu
     * @instance
     * @private
     * @param {Event=} event - What triggered the menu to collapse.  May be <code class="prettyprint">null</code>.
     *                         May be omitted if the <code class="prettyprint">which</code> parameter is omitted.
     * @param {string=} which - Optional; defaults to <code class="prettyprint">"active"</code>.  Values are the following <code class="prettyprint">string</code>s:
     *     <ul>
     *       <li><code class="prettyprint">"active"</code>: Closes the currently active submenu.</li>
     *       <li><code class="prettyprint">"all"</code>: Closes all submenus.</li>
     *       <li><code class="prettyprint">"eventSubtree"</code>: Closes submenus below but not including the menu that is or contains the target of the triggering event.</li>
     *     </ul>
     */
    _collapse: function( event, which ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        if (which == null || which === "active") {
            var newItem = this.activeMenu &&
                this.activeMenu.closest( ".oj-menu-item", this.element );
            if ( newItem && newItem.length ) {
                this._close();
                this._focus( event, newItem );
            }
        } else if ( which === "all" || which === "eventSubtree") {
            this.__collapseAll(event, which === "all", this.delay);
        } else {
            oj.Logger.warn("Invalid param " + which + " passed to Menu._collapse().  Ignoring the call.");
        }
    },

    /**
     * Opens the submenu below the currently focused item, if one exists.
     *
     * @memberof oj.ojMenu
     * @instance
     * @private
     * @param {Event=} event - What triggered the menu to expand.  May be <code class="prettyprint">null</code> or omitted.
     */
    _expand: function( event ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        var newItem = this.active &&
            this.active
                .children( ".oj-menu " )
                .children( ".oj-menu-item" )
                .first();

        if ( newItem && newItem.length ) {
            this._open( newItem.parent() );

            if (this.timer)
              clearTimeout(this.timer);

            // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
            this.timer = this._delay(function() {
                delete this.timer;
                this._focus( event, newItem );
            });
        }
    },

    /**
     * Focuses the next menu item, wrapping at the bottom, as if <kbd>DownArrow</kbd> had been pressed.
     *
     * @memberof oj.ojMenu
     * @instance
     * @private
     * @param {Event=} event - What triggered the focus to move.  May be <code class="prettyprint">null</code> or omitted.
     */
    _next: function( event ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        this._move( "next", "first", event );
    },

    /**
     * Focuses the previous menu item, wrapping at the top, as if <kbd>UpArrow</kbd> had been pressed.
     *
     * @memberof oj.ojMenu
     * @instance
     * @private
     * @param {Event=} event - What triggered the focus to move.  May be <code class="prettyprint">null</code> or omitted.
     */
    _previous: function( event ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        this._move( "prev", "last", event );
    },

    _isFirstItem: function() { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        return this.active && !this.active.prevAll( ".oj-menu-item" ).length;
    },

    _isLastItem: function() { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        return this.active && !this.active.nextAll( ".oj-menu-item" ).length;
    },

    _move: function( direction, filter, event ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        var next;
        if ( this.active ) {
            if ( direction === "first" || direction === "last" ) {
                next = this.active
                    [ direction === "first" ? "prevAll" : "nextAll" ]( ".oj-menu-item" )
                    .eq( -1 );
            } else {
                next = this.active
                    [ direction + "All" ]( ".oj-menu-item" )
                    .eq( 0 );
            }
        }
        if ( !next || !next.length || !this.active ) {
            next = this.activeMenu.children( ".oj-menu-item" )[ filter ]();
        }

        this._focus( event, next );
    },

    /* TODO: update JSdoc to be something like this revised version, once todo's in code are resolved.
     * Let selectItem be the currently focused menu item if any, else the menu item containing the target of the supplied event if any, else null.
     *
     * If selectItem is non-null, this method selects that item, collapses all submenus, and triggers the menu's
     * <code class="prettyprint">select</code> event.
     *
     * Internally, this method should not be invoked for parent menu items or disabled menu items. But still there is a chance of
     * invoking _select() externally. (Not anymore now that it's private.) In that case, if focused menu item is a disabled or parent menu item then a warning message will be logged.
     */
    /**
     * Selects the currently focused menu item, collapses all submenus and triggers the menu's <code class="prettyprint">select</code> event.
     *
     * @memberof oj.ojMenu
     * @instance
     * @private
     * @param {Event=} event - What triggered the selection.  May be <code class="prettyprint">null</code> or omitted.
     */
    _select: function( event ) { // Private, not an override (not in base class).  Method name unquoted so will be safely optimized (renamed) by GCC as desired.
        // If no menu item is focused, then infer one from the event if possible.  TBD: still need this now that not public?  Or is this.active always set?
        if (!this.active && event && event.target ) {
            var menuItem = $( event.target ).closest( ".oj-menu-item" );
            if (menuItem.closest( this.element ).length)
                this._makeActive(menuItem, event);
        }

        if (!this.active) {
            // If we reach here, this must be an external call to the method.
            oj.Logger.warn("Menu._select() called when no menu item is focused and no menu item can be inferred from event param.");
            return;
        }

        // now we know this.active is non-null
        if (this.active.has( ".oj-menu" ).length || this.active.is( ".oj-disabled" )) {
            // If we reach here, this must be an external call to the method.
            oj.Logger.warn("Selecting a disabled menu item or parent menu item is not allowed.");
            return;
        }

        var ui = { "item": this.active }; // must grab this.active before calling __collapseAll, which clears this.active

        // The menu item has been selected, so we can collapse all menus immediately with no timeout via __collapseAll.
        // If we call the version with a timeout, _collapse(event, "all"), then mouseleave event handler will invoke _collapse(event, "eventSubtree") on event.target
        // which will clear our scheduled _collapse(event, "all") on this.element, so that submenu will not be collapsed,
        // which means that when the menu is later re-launched, the submenu is already open.
        this.__collapseAll( event, true );

        // if this is a popup menu that's currently shown
        if (this._launcher) {
            this._focusLauncherAndDismiss(event);
        }

        // TODO: should this fire before or after calling __collapseAll (clears this.active and fires
        // _activeItem event) and/or _focusLauncherAndDismiss() (browser-blurs and hides poupup menu)?
        this._trigger( "select", event, ui );
    },

   /**
    * @instance
    * @private
    */
    _surrogateRemoveHandler: function()
    {
      var element = this.element;
      element.remove();
    },

   /**
    * @instance
    * @private
    * @return {!Object.<oj.PopupService.EVENT, function(...)>}
    */
    _getPopupServiceEvents: function()
    {
      if (!this._popupServiceEvents)
      {
        /** @type {!Object.<oj.PopupService.EVENT, function(...)>} **/
        var events = this._popupServiceEvents = {};
        events[oj.PopupService.EVENT.POPUP_CLOSE] = $.proxy(this._closeAll, this);
        events[oj.PopupService.EVENT.POPUP_REMOVE] = $.proxy(this._surrogateRemoveHandler, this);
        events[oj.PopupService.EVENT.POPUP_REFRESH] = $.proxy(this.refresh, this);
        events[oj.PopupService.EVENT.POPUP_AUTODISMISS] = $.proxy(this._clickAwayHandler, this);
      }
      return this._popupServiceEvents;
    },

   /**
    * @instance
    * @private
    */
    _closeAll: function()
    {
      this._close(this.element);
      this.__dismiss(null);
    },

   /**
    * @private
    * @param {Object} pos "my" element associated with the position object
    * @param {Object} props directions as to where the element should be moved
    * @return {void}
    */
    _usingHandler: function(pos, props)
    {
      var rootMenu = props["element"]["element"];
      rootMenu.css(pos);

      // call on the original using
      var position = rootMenu.data(_POSITION_DATA);
      if (position)
      {
        var origUsing = position["origUsing"];
        if (origUsing)
          origUsing(pos, props);
      }

      // implicitly dismiss the menu when the position.of is clipped in an overflow container.
      if (oj.PositionUtils.isAligningPositionClipped(props))
        this._closeDelayTimer = this._delay($.proxy(this._closeAll, this), 1);
    }
    
    // API doc for inherited methods with no JS in this file:

    /**
     * Returns a <code class="prettyprint">jQuery</code> object containing the root element of the Menu component.
     *
     * @method
     * @name oj.ojMenu#widget
     * @memberof oj.ojMenu
     * @instance
     * @return {jQuery} the root element of the component
     *
     * @example <caption>Invoke the <code class="prettyprint">widget</code> method:</caption>
     * var widget = $( ".selector" ).ojMenu( "widget" );
     */

    /**
     * Removes the menu functionality completely. This will return the element back to its pre-init state.
     *
     * <p>This method does not accept any arguments.
     *
     * @method
     * @name oj.ojMenu#destroy
     * @memberof oj.ojMenu
     * @instance
     *
     * @example <caption>Invoke the <code class="prettyprint">destroy</code> method:</caption>
     * $( ".selector" ).ojMenu( "destroy" );
     */
    
    // Fragments:
    
    /**
     * <table class="keyboard-table">
     *   <thead>
     *     <tr>
     *       <th>Target</th>
     *       <th>Gesture</th>
     *       <th>Action</th>
     *     </tr>
     *   </thead>
     *   <tbody>
     *     <tr>
     *       <td>Menu Item</td>
     *       <td><kbd>Tap</kbd></td>
     *       <td>Invoke the menu item's action, which may be opening a submenu.</td>
     *     </tr>
     *     <tr>
     *       <td>JET Component or HTML Element having a JET Context Menu</td>
     *       <td><kbd>Press & Hold</kbd></td>
     *       <td>Open the context menu.</td>
     *     </tr>
     *     <tr>
     *       <td>Elsewhere on Page</td>
     *       <td><kbd>Touch</kbd></td>
     *       <td>Close the menu.</td>
     *     </tr>
     *   </tbody>
     * </table>
     * 
     * <p>Disabled items do not allow any touch interaction.
     *
     * @ojfragment touchDoc - Used in touch gesture section of classdesc, and standalone gesture doc
     * @memberof oj.ojMenu
     */
    
    /**
     * <table class="keyboard-table">
     *   <thead>
     *     <tr>
     *       <th>Target</th>
     *       <th>Key</th>
     *       <th>Action</th>
     *     </tr>
     *   </thead>
     *   <tbody>
     *     <tr>
     *       <td rowspan = "6">Menu Item</td>
     *       <td><kbd>Enter</kbd> or <kbd>Space</kbd></td>
     *       <td>Invoke the focused menu item's action, which may be opening a submenu.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>UpArrow</kbd></td>
     *       <td>Move focus to the previous menu item, wrapping around at the top.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>DownArrow</kbd></td>
     *       <td>Move focus to the next menu item, wrapping around at the bottom.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>Home</kbd></td>
     *       <td>Move focus to the first menu item.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>End</kbd></td>
     *       <td>Move focus to the last menu item.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>RightArrow</kbd> (<kbd>LeftArrow</kbd> in RTL*)</td>
     *       <td>Open the submenu, if any.</td>
     *     </tr>
     *     <tr>
     *       <td>Menu Item in Top-level Menu</td>
     *       <td><kbd>Esc</kbd></td>
     *       <td>Close the menu and move focus to the launcher.</td>
     *     </tr>
     *     <tr>
     *       <td>Menu Item in Submenu</td>
     *       <td><kbd>Esc</kbd> or <kbd>LeftArrow</kbd> (<kbd>RightArrow</kbd> in RTL*)</td>
     *       <td>Close the submenu and move focus to the parent menu item.</td>
     *     </tr>
     *     <tr>
     *       <td>JET Component or HTML Element having a JET Context Menu</td>
     *       <td><kbd>Shift + F10</kbd></td>
     *       <td>Open the context menu.</td>
     *     </tr>
     *   </tbody>
     * </table>
     *
     * <p>* RTL refers to pages written in a right-to-left language such as Arabic.
     *
     * <p>Typing a letter moves focus to the first item whose title starts with that character. Repeating the same character cycles through matching items.
     * Typing more characters within the one second timer matches those characters.
     *
     * <p>Note that the "Search for text when I start typing" feature in Firefox can interfere with web content that accepts keystrokes, such as this "type a letter" feature of JET Menu.
     *
     * <p>Disabled items can receive keyboard focus, but do not allow any other interaction.
     *
     * @ojfragment keyboardDoc - Used in keyboard section of classdesc, and standalone gesture doc
     * @memberof oj.ojMenu
     */
});

// "private static members" shared by all menus

// Array to track all opened menu popups. All the menus opened by Menu Buttons/ Context Menu/using menu.open() and standalone menus having open submenus, will be added to list
// and later will be removed on __dismiss()/_close() on menu popup/standalone menu.
var _openPopupMenus = new Array();

// See usage for explanation.  Can be boolean (doesn't need to be re-entrant int), since 
// baseComponent.touchendMousedownThreshold is much less than baseComponent.pressHoldThreshold.
var _contextMenuPressHoldJustEnded = false

/**
 * Key used to store the menu's position object as a jQuery data property.
 * @const
 * @private
 * @type {string}
 */
var _POSITION_DATA = "oj-menu-position";

}());