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

Oracle® JavaScript Extension Toolkit (JET)
1.1.2

E65298-01

/**
 * Copyright (c) 2014, Oracle and/or its affiliates.
 * All rights reserved.
 */
(function () {
    /**
     * @ojcomponent oj.ojNavigationList
     * @augments oj.baseComponent
     * @since 1.1.0
     * 
     * @classdesc
     * <h3 id="navlistOverview-section">
     *   JET Navigation List Component
     *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#navlistOverview-section"></a>
     * </h3>
     * 
     * <p>Description:  The JET Navigation List enhances a HTML list element into a themable, WAI-ARIA compliant, mobile friendly component with advance interactive features.
     * 
     * <p>The JET Navigation List gets its data in following ways. </p>
     * <ul>
     * <li><b>Using table datasource</b>. This is typically used in case of flat list.There are several types of TableDataSource that 
     * are available out of the box like oj.ArrayTableDataSource,oj.CollectionTableDataSource.NOTE: oj.PagingTableDataSource is not supported by navigation list.
     * For large amount of data, It is recommended to use hierarhcial navigation list with tree data source.</li>
     * <li><b>Using TreeDataSource</b>.  This is typically used to display hierarchical navigation list.  There are several types 
     * of TreeDataSource that are available out of the box like oj.JsonTreeDataSource, oj.CollectionTreeDataSource </li>
     * <li><b>Using static content </b>. The structure of the content can be either flat or hierarhical.</li>
     * </ul>
     * <p>Example of flat static content</p>
     * <pre class="prettyprint">
     * <code>
     * <div id="navigationlist">
     *  <ul>
     *   <li><a href="#">Item 1</a></li>
     *   <li><a href="#">Item 2</a></li>
     *   <li><a href="#">Item 3</a></li>
     *  </ul>
     * </div> 
     * </code></pre>
     *
     * <p>Example of hierarchical static content</p>
     * <pre class="prettyprint">
     * <code>
     * <div id="navigationlist">
     *  <ul >
     *   <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>
     * </div>
     * </code></pre>
     * <p>NOTE: Currently, the only supported way to react to the selection of a list item is to listen for <a href="#event:optionChange">optionChange</a> event. Click listeners and href navigation should not be used. </p>
     * <h4 id="treeJSON-section"> JSON Tree Node Format</h4>
     * </br>
     * Each node object typically have an
     * <code class="prettyprint">attr</code> property. This attr value will be provided as <code class="prettyprint">itemContext.data</code> to renderer function. See <a href="#itemContext">itemContext</a> section. Any node can be defined as a parent by supplying
     * a <code class="prettyprint">children</code> property, which is an array of one or more node definitions.
     * (Note: lazy-loading is not supported in navigation list so <code class="prettyprint">children</code> property should be a non empty array)
     * <p>Example: Basic JSON Tree definition
     * <pre class="prettyprint">
     * <code>
     *[
     *   {                                    
     *     "attr": {
     *               "id": "home", 
     *               "title": "Home"
     *             },
     *   },
     *   { 
     *     "attr": {
     *               "id": "news", 
     *               "title": "News"
     *             }
     *   },
     *   { 
     *      "attr": {
     *                "id": "blogs",
     *                "title": "Blogs"
     *              },
     *      "children": [ {
     *                       
     *                       "attr": {
     *                                   "id": "today",
     *                                   "title": "Today"
     *                               }
     *                    },
     *                    {
     *                       "attr": {   
     *                                   "id": "yesterday",
     *                                   "title": "Yesterday"
     *                               }
     *                    }
     *                  ]
     *   }
     *] 
     *</code></pre>
     *</p></br>
     * <p>Any list 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.  
     * 
     * 
     * <h3 id="icons-section">
     *   Icons
     *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#icons-section"></a>
     * </h3>
     * 
     * <p>Sublist icons are inserted automatically.  To add other icons to list items, include them in the markup and include the <code class="prettyprint">oj-navigationlist-item-icon</code> class, as follows:
     * 
     * <pre class="prettyprint">
     * <code><ul id="navigationlist">
     *   <li id="foo"><a href="#"><span class="oj-navigationlist-item-icon demo-icon-font-24 demo-palette-icon-24"></span>Foo</a></li>
     * </ul>
     * </code></pre>
     * 
     * <h3 id="styling-section">
     *   Styling
     *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#styling-section"></a>
     * </h3>
     * 
     * <table class="generic-table styling-table">
     *   <thead>
     *     <tr>
     *       <th>Class(es)</th>
     *       <th>Description</th>
     *     </tr>
     *   </thead>
     *   <tbody>
     *     <tr>
     *       <td>oj-navigationlist-stack-icon-label</td>
     *       <td>Add this class to display Navigation List with Stacked icon and label. Applicable only when edge is top.</td>
     *     </tr>
     *     <tr>
     *       <td>oj-navigationlist-category-divider</td>
     *       <td>Use this class to add horizontal divider line between two categories of items.</td>
     *     </tr>
     *     <tr>
     *       <td>oj-navigationlist-item-icon</td>
     *       <td>Use this class to add icon to list item.</td>
     *     </tr>
     *     <tr>
     *       <td>oj-navigationlist-item-title</td>
     *       <td>When arbitrary content is placed in side item, mark item title using this marker class.
     *       <p>Example of item markup with arbitrary content. 
     *        <pre class="prettyprint">
     *        <code>
     *<li>
     *  <div>
     *      <span class="oj-navigationlist-item-title">Play</span>
     *      <button>Button</button>
     *  </div>
     *</li>
     *        </code>
     *        </pre>
     *        </p> 
     *       </td>
     *     </tr>
     *   </tbody>
     * </table>
     * <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"}
     * 
     * <p>Disabled items will not receive keyboard focus and do not allow any interaction.
     *
     *<h3 id="context-section">
     *   Item Context
     *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#context-section"></a>
     * </h3>
     *
     * <p>For all item options, developers can specify a function as the return value.  The function takes a single argument, which is an object that contains contextual information about the particular item.  This gives developers the flexibility to return different value depending on the context.</p>
     *
     * <p>The context paramter contains the following keys:</p>
     * <table class="keyboard-table">
     *   <thead>
     *     <tr>
     *       <th>Key</th>
     *       <th>Description</th>
     *     </tr>
     *   </thead>
     *   <tbody>
     *     <tr>
     *       <td><kbd>component</kbd></td>
     *       <td>A reference to the NavigationList widget constructor.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>datasource</kbd></td>
     *       <td>A reference to the data source object. (Not available for static content)</td>
     *     </tr>     
     *     <tr>
     *       <td><kbd>index</kbd></td>
     *       <td>The index of the item, where 0 is the index of the first item.  In the hierarchical case the index is relative to its parent.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>key</kbd></td>
     *       <td>The key of the item.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>data</kbd></td>
     *       <td>The data object for the item.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>parentElement</kbd></td>
     *       <td>The list item element.  The renderer can use this to directly append content.</td>
     *     </tr>
     *   </tbody>
     * </table>
     *
     * <p></p>
     * <p>If the data is hierarchical, the following additional contextual information are available:</p>
     * <table class="keyboard-table">
     *   <thead>
     *     <tr>
     *       <th>Key</th>
     *       <th>Description</th>
     *     </tr>
     *   </thead>
     *   <tbody>
     *     <tr>
     *       <td><kbd>depth</kbd></td>
     *       <td>The depth of the item.  The depth of the first level children under the invisible root is 1.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>parentKey</kbd></td>
     *       <td>The key of the parent item.  The parent key is null for root node.</td>
     *     </tr>
     *     <tr>
     *       <td><kbd>leaf</kbd></td>
     *       <td>Whether the item is a leaf or a group item.</td>
     *     </tr>
     *   </tbody>
     * </table>
     * <h3 id="perf-section">
     *   Performance
     *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#perf-section"></a>
     * </h3>
     *
     * <h4>Data Set Size</h4>
     * <p>As a rule of thumb, it's recommended that applications limit the amount of data to display.  Displaying large
     * number of items in Navigation List makes it hard for user to find what they are looking for, but affects the load time.
     * If displaying large number of items is neccessary, it is recommended to group the items in to hierarchial navigation list. 
     *
     * <h4>Item Content</h4>
     * <p>Navigation List allows developers to specify arbitrary content inside its item. In order to minimize any negative effect on 
     * performance, you should avoid putting a large number of heavy-weight components inside because as you add more complexity 
     * to the structure, the effect will be multiplied because there can be many items in the Navigation List.</p>
     *
     * <h4>Expand All</h4>
     * <p>While Navigation List provides a convenient way to initially expand all group items, it might have an impact
     * on the initial rendering performance since expanding each group item might cause a fetch from the server depending on 
     * the TreeDataSource.  Other factors that could impact performance includes the depth of the tree, and the number of children 
     * in each level.</p>
     * 
     * <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="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 navigation list 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-navigationlist</code> pseudo-selector can be used in jQuery expressions to select JET Navigation Lists.  For example:
     * 
     * <pre class="prettyprint">
     * <code>$( ":oj-navigationlist" ) // selects all JET Navigation lists on the page
     * $myEventTarget.closest( ":oj-navigationlist" ) // selects the closest ancestor that is a JET Navigation lists
     * </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 Navigation List.
     * 
     * @param {Object=} options a map of option-value pairs to set on the component
     * 
     * @example <caption>Initialize the Navigation list with no options specified:</caption>
     * $( ".selector" ).ojNavigationList();
     * 
     * @example <caption>Initialize the Navigation list with some options and callbacks specified:</caption>
     * $( ".selector" ).ojNavigationList( { "drillMode": "none", "beforeSelect": function( event, ui ) {} } );
     * 
     * @example <caption>Initialize the Navigation list via the JET <code class="prettyprint">ojComponent</code> binding:</caption>
     * <div id="navigationlist" data-bind="ojComponent: { component: 'ojNavigationList', 
     *                                         drillMode: 'none', 
     *                                         beforeSelect: beforeSelectItem }">
     */
    oj.__registerWidget("oj.ojNavigationList", $['oj']['baseComponent'], {
        widgetEventPrefix: 'oj',
        options: {
            /** 
             * Key of the current item.  Current item is the list item which is having active focus.  Note that if currentItem 
             * is set to an item that is currently not available (not fetched or
             * inside a collapsed parent node), then the value is ignored.
             *
             * @expose 
             * @public 
             * @instance
             * @memberof! oj.ojNavigationList
             * @type {Object}
             * @default <code class="prettyprint">null</code>
             * 
             * @example <caption>Get the current item:</caption>
             * $( ".selector" ).ojNavigationList("option", "currentItem");
             * 
             * @example <caption>Set the current item on the NavigationList during initialization:</caption>
             * $(".selector").ojNavigationList({"currentItem", "item2"});
             */
            currentItem: null,
            /**
             * Defines style of navigation used to drill down hierarchical list items.
             * <ul>
             * <li>none</li>
             * <li>collapsible</li>
             * <li>sliding</li>
             * </ul>
             * 
             * @expose 
             * @memberof oj.ojNavigationList
             * @instance
             * @type {string}
             * @default <code class="prettyprint">"none"</code>
             * @ojvalue {string} "none" All group items are expanded by default and user not allowed to collapse them.
             * @ojvalue {string} "collapsible" Allows user to expand and collapse group items. If there are more than two levels in hierarchy, <code class="prettyprint">sliding</code> is preferered drill mode.
             * @ojvalue {string} "sliding" This is typically used for hierarchical lists. This allows user to view one level at a time.
             * 
             * @example <caption>Initialize the menu with the <code class="prettyprint">drillMode</code> option specified:</caption>
             * $( ".selector" ).ojNavigationList({ drillMode: "collapsible" });
             * 
             * @example <caption>Get the <code class="prettyprint">drillMode</code> option, after initialization:</caption>
             * // getter
             * var drillMode = $( ".selector" ).ojNavigationList( "option", "drillMode" );
             */
            drillMode: "none",
            /**
             * The position of the Navigation List. Valid Values: top and start.
             * <p> NOTE: when value is <code class="prettyprint">top</code>,<code class="prettyprint">"none"</code> is the only supported drillMode and it also does't support hierarchical items.
             * @expose
             * @name edge
             * @memberof oj.ojNavigationList
             * @instance
             * @type {string|null}
             * @ojvalue {string} "top" This renders list items horizontally. 
             * @ojvalue {string} "start" This renders list items vertically.
             * @default <code class="prettyprint">"start"</code>
             */
            edge: "start",
            /** 
             * Label for top level list items.
             * <p>NOTE: This is needed only for sliding navigation list where
             * this will be used as title for the top level list elements. 
             * @type {?string}
             * @default <code class="prettyprint">Navigation List</code>
             * @expose 
             * @instance
             * @memberof oj.ojNavigationList 
             */
            rootLabel: null,
            /** 
             * Item key of currently selected list item. If the value is modified
             * by an application, navigation list UI is modified to match the new value.
             * @type {string|null}
             * @default <code class="prettyprint">null</code>
             * @expose 
             * @instance
             * @memberof oj.ojNavigationList 
             */
            selection: null,
            /** 
             * Specifies which items in NavigationList should be expanded. Specifies "all" value to expand all items.  Specifies
             * an array of keys to expand specific items.
             *
             * The default value is "auto", which means that NavigationList will determine which items are expanded by default.  
             * Specifically, if drillMode is set to "none", then all items are expanded, any other values for 
             * drillMode will not cause any items to expand by default.
             *
             * Note that expanded does not return the currently expanded items.  This only returns what is specified
             * by default.  To retrieve the keys of currently expanded items, use the <code class="prettyprint">getExpanded</code>
             * method. 
             * @type {Array|string}
             * @default <code class="prettyprint">[]</code>
             * @expose 
             * @instance
             * @memberof oj.ojNavigationList 
             */
            expanded: "auto",
            /**
             * The data source for the NavigationList accepts either a oj.TableDataSource or oj.TreeDataSource. 
             * See the data source section in the introduction for out of the box data source types.
             * If the data attribute is not specified, the child elements are used as content.  If there's no
             * content specified, then an empty list is rendered.
             * 
             * @expose 
             * @memberof! oj.ojNavigationList
             * @instance
             * @type {oj.TableDataSource|oj.TreeDataSource}
             * @default <code class="prettyprint">null</code>
             * 
             * @example <caption>Initialize the NavigationList with a one-dimensional array:</caption>
             * $( ".selector" ).ojNavigationList({ "data": new oj.ArrayTableDataSource([1,2,3])});
             * 
             * @example <caption>Initialize the NavigationList with an oj.Collection:</caption>
             * $( ".selector" ).ojNavigationList({ "data": new oj.CollectionTableDataSource(collection)});
             */
            data: null,
            /**
             * Whether to display both the label and icons (<code class="prettyprint">"all"</code>) or just the icons (<code class="prettyprint">"icons"</code>).
             * In the latter case, the label is displayed in a tooltip instead, unless a tooltip was already supplied at create time.
             * Note: <code class="prettyprint">display="icons"</code> is valid only when <code class="prettyprint">drillMode=none</code> and navigation list is a flat list.
             * It is also mandatory to provide icons for each item as stated in <a href="#icons-section">icons section</a>.  
             *
             * @expose
             * @memberof oj.ojNavigationList
             * @instance
             * @type {string}
             * @ojvalue {string} "all" Display both the label and icons.
             * @ojvalue {string} "icons" Display only the icons.This option 
             * @default <code class="prettyprint">"all"</code>
             *
             * @example <caption>Initialize the NavigationList with the <code class="prettyprint">display</code> option specified:</caption>
             * $( ".selector" ).ojNavigationList( { "display": "icons" } );
             *
             * @example <caption>Get or set the <code class="prettyprint">display</code> option, after initialization:</caption>
             * // getter
             * var display = $( ".selector" ).ojNavigationList( "option", "display" );
             *
             * // setter
             * $( ".selector" ).ojNavigationList( "option", "display", "icons" );
             */
            display: "all",
            /**
             * The item option contains a subset of options for items.
             * 
             * @expose 
             * @memberof! oj.ojNavigationList
             * @instance
             */
            item: {
                /**
                 * The renderer function that renders the content of the item. See <a href="#context-section">itemContext</a>
                 * in the introduction to see the object passed into the renderer function.
                 * The function returns either a String or a DOM element of the content inside the item.
                 * If the developer chooses to manipulate the list element directly, the function should return 
                 * nothing. If no renderer is specified, Navigation List will treat the data as a String.
                 * 
                 * @expose 
                 * @alias item.renderer
                 * @memberof! oj.ojNavigationList
                 * @instance
                 * @type {function(Object)|null}
                 * @default <code class="prettyprint">null</code>
                 * 
                 * @example <caption>Initialize the NavigationList with a renderer:</caption>
                 * $( ".selector" ).ojNavigationList({ "data":data, "item": { "renderer": function(itemContext) {
                 *                                            return itemContext['data'].get('FIRST_NAME');}}});
                 *
                 * @example <caption>Get or set the <code class="prettyprint">renderer</code> option, after initialization:</caption>
                 * // set the renderer function
                 * $( ".selector" ).ojNavigationList( "option", "item.renderer", myFunction});
                 */
                renderer: null,
                /**
                 * Whether the item is selectable.
                 * See <a href="#context-section">itemContext</a> in the introduction to see the object passed into the selectable function.
                 * 
                 * @expose 
                 * @alias item.selectable
                 * @memberof! oj.ojNavigationList
                 * @instance
                 * @type {function(Object)|boolean}
                 * @default <code class="prettyprint">true</code>
                 * 
                 * @example <caption>Initialize the NavigationList such that the first 3 items are not selectable:</caption>
                 * $( ".selector" ).ojNavigationList({ "data":data, "item": { "selectable": function(itemContext) {
                 *                                            return itemContext['index'] > 3;}}});
                 */
                selectable: true
                        /**
                         * The knockout template used to render the content of the item.
                         *
                         * This attribute is only exposed via the <code class="prettyprint">ojComponent</code> binding, and is not a 
                         * component option.
                         *
                         * @ojbindingonly
                         * @name item.template
                         * @memberof! oj.ojNavigationList
                         * @instance
                         * @type {string|null}
                         * @default <code class="prettyprint">null</code>
                         * 
                         * @example <caption>Specify the <code class="prettyprint">template</code> when initializing NavigationList:</caption>
                         * // set the template
                         * <div id="navlist" data-bind="ojComponent: {component: 'ojNavigationList', data: dataSource, template: 'my_template'}"></div>
                         */
            },
            //Events
            /**
             * <p>Triggered before this list item is selected. 
             * To prevent the item selection, return <code class="prettyprint">false</code> from event handler or invoke <code class="prettyprint">event.preventDefault()</code>.
             * <p>The <code class="prettyprint">ui.key</code> contains item key which uniquely identifies the item. 
             * <code class="prettyprint">ui.item</code> payload field contains item element being selected. 
             *
             * @expose 
             * @event 
             * @memberof! oj.ojNavigationList
             * @instance
             * @property {Event} event <code class="prettyprint">jQuery</code> event object
             * @property {Object} ui Parameters
             * @property {Object} ui.key Selected list item key.
             * @property {jQuery} ui.item Selected list item.
             * 
             * @example <caption>Initialize the Navigation List with the <code class="prettyprint">beforeSelect</code> callback specified:</caption>
             * $( ".selector" ).ojNavigationList({
             *     "beforeSelect": function( event, ui ) {}
             * });
             *
             * @example <caption>Bind an event listener to the <code class="prettyprint">ojbeforeselect</code> event:</caption>
             * $( ".selector" ).on( "ojbeforeselect", function( event, ui ) {} );
             */
            beforeSelect: null,
            /**
             * Triggered before an item is collapse via the <code class="prettyprint">expanded</code> option, 
             * the <code class="prettyprint">collapse</code> method, or via the UI.
             * To prevent the item being collapsed, return <code class="prettyprint">false</code> from event handler or invoke <code class="prettyprint">event.preventDefault()</code>.
             *
             * @expose 
             * @event 
             * @memberof! oj.ojNavigationList
             * @instance
             * @property {Event} event <code class="prettyprint">jQuery</code> event object
             * @property {Object} ui Parameters
             * @property {Object} ui.key the key of the item to be collapse
             * @property {jQuery} ui.item the item to be collapse
             * 
             * @example <caption>Initialize the NavigationList with the <code class="prettyprint">beforeCollapse</code> callback specified:</caption>
             * $( ".selector" ).ojNavigationList({
             *     "beforeCollapse": function( event, ui ) {
             *         // return false to veto the event, which prevents the item to collapse
             *     }
             * });
             *
             * @example <caption>Bind an event listener to the <code class="prettyprint">ojbeforecollapse</code> event:</caption>
             * $( ".selector" ).on( "ojbeforecollapse", function( event, ui ) {} );
             */
            beforeCollapse: null,
            /**
             * Triggered before the current item is changed via the <code class="prettyprint">currentItem</code> option or via the UI.
             * To prevent the item being focused, return <code class="prettyprint">false</code> from event handler or invoke <code class="prettyprint">event.preventDefault()</code>.
             * @expose 
             * @event 
             * @memberof! oj.ojNavigationList
             * @instance
             * @property {Event} event <code class="prettyprint">jQuery</code> event object
             * @property {Object} ui Parameters
             * @property {Object} ui.previousKey the key of the previous item
             * @property {jQuery} ui.previousItem the previous item
             * @property {Object} ui.key the key of the new current item
             * @property {jQuery} ui.item the new current item
             * 
             * @example <caption>Initialize the NavigationList with the <code class="prettyprint">beforeCurrentItem</code> callback specified:</caption>
             * $( ".selector" ).ojNavigationList({
             *     "beforeCurrentItem": function( event, ui ) {
             *         // return false to veto the event, which prevents the item to become focus
             *     }
             * });
             *
             * @example <caption>Bind an event listener to the <code class="prettyprint">ojbeforecurrentitem</code> event:</caption>
             * $( ".selector" ).on( "ojbeforecurrentitem", function( event, ui ) {} );
             */
            beforeCurrentItem: null,
            /**
             * Triggered after an item has been collapsed via the <code class="prettyprint">expanded</code> option, 
             * the <code class="prettyprint">collapse</code> method, or via the UI.
             *
             * @expose 
             * @event 
             * @memberof! oj.ojNavigationList
             * @instance
             * @property {Event} event <code class="prettyprint">jQuery</code> event object
             * @property {Object} ui Parameters
             * @property {Object} ui.key The key of the item that was just collapsed.
             * @property {jQuery} ui.item The list item that was just collapsed.
             * 
             * @example <caption>Initialize the NavigationList with the <code class="prettyprint">expand</code> callback specified:</caption>
             * $( ".selector" ).ojNavigationList({
             *     "collapse": function( event, ui ) {}
             * });
             *
             * @example <caption>Bind an event listener to the <code class="prettyprint">ojcollapse</code> event:</caption>
             * $( ".selector" ).on( "ojcollapse", function( event, ui ) {} );
             */
            collapse: null,
            /**
             * Triggered before an item is expand via the <code class="prettyprint">expanded</code> option, 
             * the <code class="prettyprint">expand</code> method, or via the UI.
             * To prevent the item being expanded, return <code class="prettyprint">false</code> from event handler or invoke <code class="prettyprint">event.preventDefault()</code>.
             * @expose 
             * @event 
             * @memberof! oj.ojNavigationList
             * @instance
             * @property {Event} event <code class="prettyprint">jQuery</code> event object
             * @property {Object} ui Parameters
             * @property {Object} ui.key the key of the item to be expand
             * @property {jQuery} ui.item the item to be expand
             * 
             * @example <caption>Initialize the NavigationList with the <code class="prettyprint">beforeExpand</code> callback specified:</caption>
             * $( ".selector" ).ojNavigationList({
             *     "beforeExpand": function( event, ui ) {
             *         // return false to veto the event, which prevents the item to expand
             *     }
             * });
             *
             * @example <caption>Bind an event listener to the <code class="prettyprint">ojbeforeexpand</code> event:</caption>
             * $( ".selector" ).on( "ojbeforeexpand", function( event, ui ) {} );
             */
            beforeExpand: null,
            /**
             * Triggered after an item has been expanded via the <code class="prettyprint">expanded</code> option, 
             * the <code class="prettyprint">expand</code> method, or via the UI.
             *
             * @expose 
             * @event 
             * @memberof! oj.ojNavigationList
             * @instance
             * @property {Event} event <code class="prettyprint">jQuery</code> event object
             * @property {Object} ui Parameters
             * @property {Object} ui.key The key of the item that was just expanded.
             * @property {jQuery} ui.item The list item that was just expanded.
             * 
             * @example <caption>Initialize the NavigationList with the <code class="prettyprint">expand</code> callback specified:</caption>
             * $( ".selector" ).ojNavigationList({
             *     "expand": function( event, ui ) {}
             * });
             *
             * @example <caption>Bind an event listener to the <code class="prettyprint">ojexpand</code> event:</caption>
             * $( ".selector" ).on( "ojexpand", function( event, ui ) {} );
             */
            expand: null,
            /**
             * Fired whenever a supported component option changes, whether due to user interaction or programmatic
             * intervention.  If the new value is the same as the previous value, no event will be fired.
             * 
             * <p>NOTE: Currently, the only supported way to react to the selection of a list item is 
             * to listen for this event. Click listeners and href navigation should not be used. </p>
             * @expose
             * @event
             * @memberof! oj.ojNavigationList
             * @instance
             * @property {Event} event <code class="prettyprint">jQuery</code> event object
             * @property {Object} ui Parameters
             * @property {string} ui.option the name of the option that is changing
             * @property {boolean} ui.previousValue the previous value of the option
             * @property {boolean} ui.value the current value of the option
             * @property {Object} ui.optionMetadata information about the option that is changing
             * @property {string} ui.optionMetadata.writeback <code class="prettyprint">"shouldWrite"</code> or
             *           <code class="prettyprint">"shouldNotWrite"</code>.  For use by the JET writeback mechanism.
             *
             * @example <caption>Initialize component with the <code class="prettyprint">optionChange</code> callback</caption>
             * $(".selector").ojNavigationList({
             *   'optionChange': function (event, data) {
             *        if (data['option'] === 'selection') { // handle selection change }
             *    }
             * });
             * @example <caption>Bind an event listener to the ojoptionchange event</caption>
             * $(".selector").on({
             *   'ojoptionchange': function (event, data) {
             *       window.console.log("option that changed is: " + data['option']);
             *   };
             * });
             */
            optionChange: null
        },
        /**
         * Create the Navigation List
         * @override
         * @memberof! oj.ojNavigationList
         * @protected
         */
        _ComponentCreate: function () {
            this._super();
            this._setup();
        },
        /**
         * Initialize the NavigationList after creation
         * @protected
         * @override
         * @memberof! oj.ojNavigationList
         */
        _AfterCreate: function ()
        {
            this._super();
            this.navlist.afterCreate();
        },
        /**
         * When the <a href="#contextMenu">contextMenu</a> option is set, this method is called when the user invokes the context menu via
         * the default gestures: right-click, pressHold, and <kbd>Shift-F10</kbd>.  Components should not call this method directly.
         * 
         * @param {!Object} menu The JET Menu to open as a context menu.  Always non-<code class="prettyprint">null</code>.
         * @param {!Event} event What triggered the menu launch.  Always non-<code class="prettyprint">null</code>.
         * @param {string} eventType "mouse", "touch", or "keyboard".  Never <code class="prettyprint">null</code>.
         * @private
         */
        _NotifyContextMenuGesture: function (menu, event, eventType)
        {
            this.navlist.notifyContextMenuGesture(menu, event, eventType);
        },
        /**
         * Initialize DOM structure for navigation list.
         * @private
         * @memberof! oj.ojNavigationList
         */
        _setup: function () {
            for (var key in this.options) {
                this._validateOptionValues(key, this.options[key]);
            }
            this._validateOptionsForIconsOnlyAndHorizontalList(this.options['drillMode'], this.options['display'], this.options['edge']);

            this.navlist = new _ojNavigationListView();
            
            var opts = {};
            opts.ojContext = this;
            opts = $.extend(this.options, opts);
            this.navlist.init(opts);
        },
        /**
         * Return the subcomponent node represented by the documented locator attribute values.
         * <p>
         * To lookup the list items the locator object should have the following:
         * <ul>
         * <li><b>subId</b>: 'oj-navigationlist-item'</li>
         * <li><b>key</b>: the key of the item</li>                
         * </ul>
         * 
         * For sliding navigation list, To lookup the previous link the locator object should have the following:
         * <ul>
         * <li><b>subId</b>: 'oj-navigationlist-previous-link'</li>
         * </ul>
         * 
         * For sliding navigation list, To lookup the hierarchical menu button the locator object should have the following:
         * <ul>
         * <li><b>subId</b>: 'oj-navigationlist-hierarchical-button'</li>
         * </ul>
         * 
         * For sliding navigation list, To lookup the hierarchical menu the locator object should have the following:
         * <ul>
         * <li><b>subId</b>: 'oj-navigationlist-hierarchical-menu'</li>
         * </ul>
         * 
         *                   
         * @expose
         * @memberof! oj.ojNavigationList
         * @instance
         * @override
         * @param {Object} locator An Object containing at minimum a subId property 
         *        whose value is a string, documented by the component, that allows 
         *         the component to look up the subcomponent associated with that 
         *        string.  It contains:<p>
         *        component: optional - in the future there may be more than one 
         *        component contained within a page element<p>
         *        subId: the string, documented by the component, that the component 
         *        expects in getNodeBySubId to locate a particular subcomponent
         * @returns {Array.<(Element|null)>|Element|null} the subcomponent located by the subId string passed
         *          in locator, if found.<p>
         */
        getNodeBySubId: function (locator)
        {
            return this.navlist.getNodeBySubId(locator);
        },
        /**
         * Expand an item.<p>
         * Note when vetoable is set to false, beforeExpand event will still be fired but the event cannot be veto.<p>
         * 
         * @expose 
         * @memberof oj.ojNavigationList
         * @instance
         * @param {Object} key the key of the item to expand
         * @param {boolean} vetoable if event is vetoable
         */
        expand: function (key, vetoable)
        {
            this.navlist.expandKey(key, vetoable, true);
        },
        /**
         * Collapse an item.<p>
         * Note when vetoable is set to false, beforeCollapse event will still be fired but the event cannot be veto.<p>
         * 
         * @expose 
         * @memberof oj.ojNavigationList
         * @instance
         * @param {Object} key the key of the item to collapse
         * @param {boolean} vetoable if event is vetoable
         */
        collapse: function (key, vetoable)
        {
            this.navlist.collapseKey(key, vetoable, true);
        },
        /**
         * Gets the key of currently expanded items.
         * 
         * @expose
         * @memberof oj.ojNavigationList
         * @instance
         * @return {Array} array of keys of currently expanded items
         */
        getExpanded: function ()
        {
            return this.navlist.getExpanded();
        },
        _validateOptionsForIconsOnlyAndHorizontalList: function (drillMode, display, edge) {
            if (drillMode !== 'none') {
                if (display === 'icons') {
                    throw "Icon only navigation list should have drillMode set to 'none'.";
                }
                if (edge === 'top') {
                    throw "Horizontal navigation list should have drillMode set to 'none'.";
                }
            }
        },
        _validateOptionValues: function (key, value) {
            var valid = true;
            if (key === "drillMode") {
                valid = (value === 'none' || value === 'collapsible' || value === 'sliding');
            } else if (key === "display") {
                valid = (value === 'all' || value === 'icons');
            } else if (key === "edge") {
                valid = (value === 'top' || value === 'start');
            }

            if (!valid) {
                throw "Invalid value: " + value + " for key: " + key;
            }

        },
        /**
         * Set single option
         * @param {string} key the option key
         * @param {Object} value value for option
         * @override
         * @memberof oj.ojNavigationList
         * @instance
         * @private
         */
        _setOption: function (key, value) {
            this._validateOptionValues(key, value);
            switch (key) {
                case "drillMode":
                    this._validateOptionsForIconsOnlyAndHorizontalList(value, this.options['display'], this.options['edge']);
                    break;
                case "display":
                    this._validateOptionsForIconsOnlyAndHorizontalList(this.options['drillMode'], value, this.options['edge']);
                    break;
                case "edge":
                    this._validateOptionsForIconsOnlyAndHorizontalList(this.options['drillMode'], this.options['display'], value);
                    break;
            }
            this._super(key, value);
        },
        /**
         * Sets multiple options 
         * @param {Object} options the options object
         * @param {Object} flags additional flags for option
         * @override
         * @private
         */
        _setOptions: function (options, flags)
        {
            var needRefresh = this.navlist.setOptions(options, flags);

            // updates the options last
            this._super(options, flags);

            if (needRefresh)
            {
                this.navlist.refresh();
            }
        },
        /**
         * In browsers [Chrome v35, Firefox v24.5, IE9, Safari v6.1.4], blur and mouseleave events are generated for hidden content but not detached content,
         * so for detached content only, we must use this hook to remove the focus and hover classes.
         * @override
         * @private
         */
        _NotifyDetached: function ()
        {
            this.navlist.notifyDetached();
        },
        /**
         * Invoked when application calls oj.Components.subtreeShown.
         * @override
         * @private
         */
        _NotifyShown: function()
        {
             this.navlist.notifyShown();
        },
        /**
         * Refreshes the visual state of the Navigation List. JET components require a <code class="prettyprint">refresh()</code> after the DOM is 
         * programmatically changed underneath the component.  
         * <p>This method does not accept any arguments.
         * 
         * @expose 
         * @memberof oj.ojNavigationList
         * @instance
         * 
         * @example <caption>Invoke the <code class="prettyprint">refresh</code> method:</caption>
         * $( ".selector" ).ojNavigationList( "refresh" );
         */
        refresh: function () {
            this._super();
            this.navlist.refresh();

        },
        /**
         * Destroy the Navigation List
         * @memberof! oj.ojNavigationList
         * @private
         */
        _destroy: function ()
        {
            this.navlist.destroy();
            this._super();
            delete this.navlist;
        }

        // Fragments:

        /**
         * <table class="keyboard-table">
         *   <thead>
         *     <tr>
         *       <th>Target</th>
         *       <th>Gesture</th>
         *       <th>Action</th>
         *     </tr>
         *   </thead>
         *   <tbody>
         *     <tr>
         *       <td rowspan="2">List Item</td>
         *       <td><kbd>Tap</kbd></td>
         *       <td>Selects the item.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>Press & Hold</kbd></td>
         *       <td>Display context menu</td>
         *     </tr>
         *     <tr>
         *       <td rowspan="2">Group Item</td>
         *       <td><kbd>Tap</kbd></td>
         *       <td>Expand or collapse the group item if <code class="prettyprint">drillMode</code> is set to collapsible.
         *       When <code class="prettyprint">drillMode</code> is set to sliding, sublist will silde in.
         *       When <code class="prettyprint">drillMode</code> is set to none, group item will be selecetd.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>Press & Hold</kbd></td>
         *       <td>Display context menu</td>
         *     </tr>
         *     <tr>
         *       <td>Hierarchical Menu button</td>
         *       <td><kbd>Tap</kbd></td>
         *       <td>Open menu. Refer <a href="oj.ojButton.html#touch-section">menu button</a> touch documentation. Note: This is applicable only for Sliding Navigation List. </td>
         *     </tr>
         *     <tr>
         *       <td>Previous Icon or List Header</td>
         *       <td><kbd>Tap</kbd></td>
         *       <td>Collapses the sublist and slides to parent list. Note: This is applicable only for Sliding Navigation List. </td>
         *     </tr>
         *   </tbody>
         * </table>
         *
         * @ojfragment touchDoc - Used in touch gesture section of classdesc, and standalone gesture doc
         * @memberof oj.ojNavigationList
         */

        /**
         * <table class="keyboard-table">
         *   <thead>
         *     <tr>
         *       <th>Target</th>
         *       <th>Key</th>
         *       <th>Action</th>
         *     </tr>
         *   </thead>
         *   <tbody>
         *     <tr>
         *       <td rowspan="10">List Item</td>
         *       <td><kbd>Enter</kbd> or <kbd>Space</kbd></td>
         *       <td>Selects list item.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>UpArrow</kbd></td>
         *       <td>Moves focus to the previous visible list item.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>DownArrow</kbd></td>
         *       <td>Moves focus to the next  visible list item</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>RightArrow</kbd> (<kbd>LeftArrow</kbd> in RTL)</td>
         *       <td>For horizontal navigation list,focus will be moved to next visible item.
         *       </td>
         *     </tr>
         *     <tr>
         *       <td><kbd>LeftArrow</kbd> (<kbd>RightArrow</kbd> in RTL)</td>
         *       <td>For horizontal navigation list,focus will be moved to previous visible item.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>Home</kbd></td>
         *       <td>Moves focus to the first visible list item.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>End</kbd></td>
         *       <td>Moves focus to the last visible list item.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>F2</kbd></td>
         *       <td>If focus is on a list item, pressing F2 will make its contents accessible using TAB.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>Esc</kbd></td>
         *       <td>When F2 mode is enabled, press Esc to exit F2 mode.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>Shift+Tab</kbd></td>
         *       <td>Move fous to hierarchical menu button.Only applicable for sliding navigation list and when hierarchial menu button is enabled.</td>
         *     </tr>
         *     <tr>
         *       <td rowspan="2">Group Item</td>
         *       <td><kbd>RightArrow</kbd> (<kbd>LeftArrow</kbd> in RTL)</td>
         *       <td>If focus is on collapsed node, expands the sub list.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>LeftArrow</kbd> (<kbd>RightArrow</kbd> in RTL)</td>
         *       <td>If focus is on expanded node, collapses the sub list.</td>
         *     </tr>
         *     <tr>
         *       <td>List Item in sublist</td>  
         *       <td><kbd>Esc</kbd></td>
         *       <td>Applicable only for sliding navigation list. If focus is in a sub list, closes the sublist and moves focus to the parent list item.</td>
         *     </tr>
         *     <tr>
         *       <td rowspan="3">Hierarchical Menu button</td>
         *       <td><kbd>Enter</kbd></td>
         *       <td>Open menu. Refer <a href="oj.ojButton.html#keyboard-section">menu button</a> keyboard documentation. Note: This target is visible only for Sliding Navigation List.</td>
         *     </tr>
         *     <tr>
         *       <td><kbd>Tab</kbd></td>
         *       <td>Moves focus to current list item. Note: This target is visible only for Sliding Navigation List. </td>
         *     </tr>
         *     <tr>
         *       <td><kbd>Shift + Tab</kbd></td>
         *       <td>Moves focus to Previous Icon. Note: This target is visible only for Sliding Navigation List.</td>
         *     </tr>
         *     <tr>
         *       <td rowspan="2">Previous Icon or List Header</td>
         *       <td><kbd>Enter</kbd></td>
         *       <td>Collapses the sublist and slides to parent list.Note: This target is visible only for Sliding Navigation List. </td>
         *     </tr>
         *     <tr>
         *       <td><kbd>Tab</kbd></td>
         *       <td>Moves focus to Hierarchical Menu button. Note: This target is visible only for Sliding Navigation List. </td>
         *     </tr>
         *     
         *   </tbody>
         * </table>
         *
         *
         * @ojfragment keyboardDoc - Used in keyboard section of classdesc, and standalone gesture doc
         * @memberof oj.ojNavigationList
         */

    });

}());