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

Oracle® JavaScript Extension Toolkit (JET)
1.1.2

E65298-01

/**
 * Copyright (c) 2015, Oracle and/or its affiliates.
 * All rights reserved.
 */
/**
 * @ojcomponent oj.ojListView
 * @augments oj.baseComponent
 * @since 1.1.0
 *
 * @classdesc
 * <h3 id="listViewOverview-section">
 *   JET ListView Component
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#listViewOverview-section"></a>
 * </h3>
 *
 * <p>Description: The JET ListView enhances a HTML list element into a themable, WAI-ARIA compliant, mobile friendly component with advance interactive features.</p>
 * 
 * <h3 id="data-section">
 *   Data
 *   <a class="bookmarkable-link" title="Bookmarkable Link" href="#data-section"></a>
 * </h3>
 * <p>The JET ListView gets its data in three different ways.  The first way is from a TableDataSource.  There are several types of TableDataSource that 
 * are available out of the box:</p>
 * <ul>
 * <li>oj.ArrayTableDataSource</li>
 * <li>oj.CollectionTableDataSource</li>
 * <li>oj.PagingTableDataSource</li>
 * </ul>
 *
 * <p><b>oj.ArrayTableDataSource</b> - Use this when the underlying data is an array object or an observableArray.  In the observableArray case, ListView will automatically react 
 * when items are added or removed from the array.  See the documentation for oj.ArrayTableDataSource for more details on the available options.</p>
 *
 * <p><b>oj.CollectionTableDataSource</b> - Use this when oj.Collection is the model for the underlying data.  Note that the ListView will automatically react to model event from 
 * the underlying oj.Collection.  See the documentation for oj.CollectionTableDataSource for more details on the available options.</p>
 *
 * <p><b>oj.PagingTableDataSource</b> - Use this when the ListView is driven by an associating ojPagingControl.  See the documentation for oj.PagingTableDataSource for more 
 * details on the available options.</p>
 *
 * <p>The second way is from a TreeDataSource.  This is typically used to display data that are logically categorized in groups.  There are several types 
 * of TreeDataSource that are available out of the box:</p>
 * <ul>
 * <li>oj.JsonTreeDataSource</li>
 * <li>oj.CollectionTreeDataSource</li>
 * </ul>
 *
 * <p><b>oj.JsonTreeDataSource</b> - Use this when the underlying data is a JSON object.  See the documentation for oj.JsonTreeDataSource for more details on the available options.</p>
 *
 * <p><b>oj.CollectionTreeDataSource</b> - Use this when oj.Collection is the model for each group of data.  See the documentation for oj.CollectionTableDataSource 
 * for more details on the available options.</p>
 *
 * <p>Finally, ListView also supports static HTML content as data.  The structure of the content can be either flat or hierarhical.</p>
 *
 * <p>Example of flat static content</p>
 * <pre class="prettyprint">
 * <code><ul id="listView" data-bind="ojComponent: {component: 'ojListView'}">
 *   <li><a id="item1" href="#">Item 1</a></li>
 *   <li><a id="item2" href="#">Item 2</a></li>
 *   <li><a id="item3" href="#">Item 3</a></li>
 * </ul>
 * </code></pre>
 *
 * <p>Example of hierarchical static content</p>
 * <pre class="prettyprint">
 * <code><ul id="listView" data-bind="ojComponent: {component: 'ojListView'}">
 *   <li><a id="group1" href="#">Group 1</a>
 *     <ul>
 *       <li><a id="item1-1" href="#">Item 1-1</a></li>
 *       <li><a id="item1-2" href="#">Item 1-2</a></li>
 *     </ul>
 *   </li>
 *   <li><a id="group2" href="#">Group 2</a>
 *     <ul>
 *       <li><a id="item2-1" href="#">Item 2-1</a></li>
 *       <li><a id="item2-2" href="#">Item 2-2</a></li>
 *     </ul>
 *   </li>
 * </ul>
 * </code></pre>
 * 
 * <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="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 ListView 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 ListView makes it hard for user to find what they are looking for, but affects the load time and 
 * scrolling performance as well.  If displaying large number of items is neccessary, use a paging control with ListView
 * to limit the number of items to display at a time.  Setting <code class="prettyprint">scrollPolicy</code> to 
 * 'loadMoreOnScroll' will also reduce the number of items to display initially.</p>
 *
 * <h4>Item Content</h4>
 * <p>ListView 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 ListView.</p>
 *
 * <h4>Expand All</h4>
 * <p>While ListView provides a convenient way to initially expand all group items in the ListView, 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>
 */
oj.__registerWidget('oj.ojListView', $['oj']['baseComponent'],
{
    widgetEventPrefix: 'oj',
    options:
            {
               /** 
                * The current item.  This is typically the item the user navigated to.  Note that if current 
                * is set to an item that is currently not available (not fetched in highwater mark scrolling case or
                * inside a collapsed parent node), then the value is ignored.
                *
                * @expose 
                * @public 
                * @instance
                * @memberof! oj.ojListView
                * @type {Object}
                * @default <code class="prettyprint">null</code>
                * 
                * @example <caption>Get the current item:</caption>
                * $( ".selector" ).ojListView("option", "currentItem");
                * 
                * @example <caption>Set the current item on the ListView during initialization:</caption>
                * $(".selector").ojListView({"currentItem", "item2"});
                */
                currentItem: null,
                /**
                 * The data source for the ListView 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.ojListView
                 * @instance
                 * @type {oj.TableDataSource|oj.TreeDataSource}
                 * @default <code class="prettyprint">null</code>
                 * 
                 * @example <caption>Initialize the ListView with a one-dimensional array:</caption>
                 * $( ".selector" ).ojListView({ "data": new oj.ArrayTableDataSource([1,2,3])});
                 * 
                 * @example <caption>Initialize the ListView with an oj.Collection:</caption>
                 * $( ".selector" ).ojListView({ "data": new oj.CollectionTableDataSource(collection)});
                 */
                data: null,
                /**
                 * Changes the expand and collapse operations on ListView.  If "none" is specified, then
                 * the current expanded state is fixed and user cannot expand or collapse an item.
                 * 
                 * @expose 
                 * @memberof! oj.ojListView
                 * @instance
                 * @type {string}
                 * @default <code class="prettyprint">collapsible</code>
                 * @ojvalue {string} "collapsible" group item can be expanded or collapsed by user.
                 * @ojvalue {string} "none" the expand state of a group item cannot be changed by user.
                 * 
                 * @example <caption>Initialize the list view with a fixed expanded state:</caption>
                 * $( ".selector" ).ojListView({ "drillMode": "none" });
                 */ 
                drillMode: "collapsible",
                /**
                 * Specifies which items in ListView 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 ListView 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. 
                 *
                 * @expose 
                 * @memberof! oj.ojListView
                 * @instance
                 * @type {Array.<Object>|string}
                 * @default <code class="prettyprint">[]</code>
                 * 
                 * @example <caption>Initialize the list view with a fixed expanded state:</caption>
                 * $( ".selector" ).ojListView({ "expanded": ["group1", "group2"] });
                 */
                expanded: "auto",
                /**
                 * The item option contains a subset of options for items.
                 * 
                 * @expose 
                 * @memberof! oj.ojListView
                 * @instance
                 */                
                item: {
                    /**
                     * Whether the item is focusable.  An item that is not focusable cannot be clicked on or navigated to.
                     * See <a href="#context-section">itemContext</a> in the introduction to see the object passed into the focusable function.
                     * 
                     * @expose 
                     * @alias item.focusable
                     * @memberof! oj.ojListView
                     * @instance
                     * @type {function(Object)|boolean}
                     * @default <code class="prettyprint">true</code>
                     * 
                     * @example <caption>Initialize the ListView such that only leaf items are focusable:</caption>
                     * $( ".selector" ).ojListView({ "data":data, "item": { "focusable": function(itemContext) {
                     *                                            return itemContext['leaf'];}}});
                     */
                    focusable: true,
                    /**
                     * 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, ListView will treat the data as a String.
                     * 
                     * @expose 
                     * @alias item.renderer
                     * @memberof! oj.ojListView
                     * @instance
                     * @type {function(Object)|null}
                     * @default <code class="prettyprint">null</code>
                     * 
                     * @example <caption>Initialize the ListView with a renderer:</caption>
                     * $( ".selector" ).ojListView({ "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" ).ojListView( "option", "item.renderer", myFunction});
                     */
                    renderer: null,
                    /**
                     * Whether the item is selectable.  Note that if selectionMode is set to "none" this option is ignored.  In addition,
                     * if selectable is set to true, then the focusable option is automatically overridden and set to true.
                     * 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.ojListView
                     * @instance
                     * @type {function(Object)|boolean}
                     * @default <code class="prettyprint">true</code>
                     * 
                     * @example <caption>Initialize the ListView such that the first 3 items are not selectable:</caption>
                     * $( ".selector" ).ojListView({ "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.ojListView
                     * @instance
                     * @type {string|null}
                     * @default <code class="prettyprint">null</code>
                     * 
                     * @example <caption>Specify the <code class="prettyprint">template</code> when initializing ListView:</caption>
                     * // set the template
                     * <ul id="listview" data-bind="ojComponent: {component: 'ojListView', data: dataSource, item: {template: 'my_template'}}"></ul>
                     */
                },
                /**
                 * Specifies the mechanism used to scroll the data inside the list view. Possible values are: auto and loadMoreOnScroll.
                 * When loadMoreOnScroll is specified, additional data is fetched when the user scrolls to the bottom of the ListView.
                 * Note that currently this option is only available when TableDataSource is used.
                 * 
                 * @expose 
                 * @memberof! oj.ojListView
                 * @instance
                 * @type {string|null}
                 * @default <code class="prettyprint">auto</code>
                 * @ojvalue {string} "auto" the behavior is determined by the component.
                 * @ojvalue {string} "loadMoreOnScroll" additional data is fetched when the user scrolls to the bottom of the ListView.
                 * 
                 * @example <caption>Initialize the list view with a fixed expanded state:</caption>
                 * $( ".selector" ).ojListView({ "scrollPolicy": "loadMoreOnScroll" });
                 */
                scrollPolicy: "auto",
                /** 
                 * scrollPolicy options. 
                 * <p>
                 * The following options are supported:
                 * <ul>
                 *   <li>fetchSize: Fetch size for scroll.</li>
                 *   <li>maxCount: Maximum rows which will be displayed before fetching more rows will be stopped.</li>
                 * </ul>
                 * When scrollPolicy is loadMoreOnScroll, the next block of rows is fetched
                 * when the user scrolls to the end of the list. The fetchSize option
                 * determines how many rows are fetched in each block.
                 * Note that currently this option is only available when TableDataSource is used.
                 * 
                 * @expose 
                 * @instance
                 * @memberof! oj.ojListView
                 * @type {Object.<string, number>|null}
                 * @property {number} fetchSize the number of rows to fetch in each block of rows
                 * @default <code class="prettyprint">25</code>
                 * @property {number} maxCount the maximum total number of rows to fetch
                 * @default <code class="prettyprint">500</code>
                 */
                scrollPolicyOptions: {'fetchSize': 25, 'maxCount': 500},
                /**
                 * The current selections in the ListView. An empty array indicates nothing is selected.
                 * 
                 * @expose 
                 * @memberof! oj.ojListView
                 * @instance
                 * @type {Array.<Object>}
                 * @default <code class="prettyprint">[]</code>
                 * 
                 * @example <caption>Initialize the list view with specific selection:</caption>
                 * $( ".selector" ).ojListView({ "data":data, "selection": ["item1", "item2"] });
                 */
                selection: [],                
                /**
                 * Specifies whether selection can be made and the cardinality of selection in the ListView.  
                 * Selection is initially disabled, but setting the value to null will disable selection.
                 * 
                 * @expose 
                 * @memberof! oj.ojListView
                 * @instance
                 * @type {string}
                 * @default <code class="prettyprint">none</code>
                 * @ojvalue {string} "none" selection is disabled.
                 * @ojvalue {string} "single" only one item can be selected at a time.
                 * @ojvalue {string} "multiple": multiple items can be selected at the same time.     
                 * 
                 * @example <caption>Initialize the list view to enable multiple selection:</caption>
                 * $( ".selector" ).ojListView({ "data":data, "selectionMode": "multiple" });
                 */
                selectionMode: "none",
                /**
                 * Triggered before the current item is changed via the <code class="prettyprint">current</code> option or via the UI.
                 *
                 * @expose 
                 * @event 
                 * @memberof! oj.ojListView
                 * @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 ListView with the <code class="prettyprint">beforeCurrentItem</code> callback specified:</caption>
                 * $( ".selector" ).ojListView({
                 *     "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 before an item is expanded via the <code class="prettyprint">expanded</code> option, 
                 * the <code class="prettyprint">expand</code> method, or via the UI.
                 *
                 * @expose 
                 * @event 
                 * @memberof! oj.ojListView
                 * @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 expanded
                 * @property {jQuery} ui.item the item to be expanded
                 * 
                 * @example <caption>Initialize the ListView with the <code class="prettyprint">beforeExpand</code> callback specified:</caption>
                 * $( ".selector" ).ojListView({
                 *     "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 before an item is collapsed via the <code class="prettyprint">expanded</code> option, 
                 * the <code class="prettyprint">collapse</code> method, or via the UI.
                 *
                 * @expose 
                 * @event 
                 * @memberof! oj.ojListView
                 * @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 collapsed
                 * @property {jQuery} ui.item the item to be collapsed
                 * 
                 * @example <caption>Initialize the ListView with the <code class="prettyprint">beforeCollapse</code> callback specified:</caption>
                 * $( ".selector" ).ojListView({
                 *     "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 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.ojListView
                 * @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 ListView with the <code class="prettyprint">expand</code> callback specified:</caption>
                 * $( ".selector" ).ojListView({
                 *     "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 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.ojListView
                 * @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 ListView with the <code class="prettyprint">expand</code> callback specified:</caption>
                 * $( ".selector" ).ojListView({
                 *     "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.
                 *
                 * @expose
                 * @event
                 * @memberof! oj.ojListView
                 * @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").ojListView({
                 *   '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,
                /**
                 * Triggered after all items in the ListView has been rendered.  Note that in the highwatermark scrolling case, 
                 * all items means the items that are fetched so far.
                 *
                 * @expose 
                 * @event 
                 * @memberof! oj.ojListView
                 * @instance
                 * @property {Event} event <code class="prettyprint">jQuery</code> event object
                 * @property {Object} ui Parameters
                 * 
                 * @example <caption>Initialize the ListView with the <code class="prettyprint">ready</code> callback specified:</caption>
                 * $( ".selector" ).ojListView({
                 *     "ready": function( event, ui ) {}
                 * });
                 *
                 * @example <caption>Bind an event listener to the <code class="prettyprint">ojready</code> event:</caption>
                 * $( ".selector" ).on( "ojready", function( event, ui ) {} );
                 */
                ready: null
            },

    /**
     * Create the listview
     * @override
     * @memberof! oj.ojListView
     * @protected
     */
    _ComponentCreate: function()
    {
        this._super();
        this._setup();
    },

    /**
     * Initialize the listview
     * @private
     */
    _setup: function()
    {
        var opts = {};
        opts.element = this.element;
        opts.ojContext = this;
        opts = $.extend(this.options, opts);

        this.listview = new oj._ojListView();
        this.listview.init(opts);        
    },

    /**
     * Initialize the listview after creation
     * @protected
     * @override
     * @memberof! oj.ojListView
     */        
    _AfterCreate: function () 
    {     
        this._super();          
        this.listview.afterCreate();
    },

    /**
     * Destroy the list view
     * @memberof! oj.ojListView
     * @private
     */
    _destroy: function()
    {
        this.listview.destroy();
        this._super();
    },

    /**
     * 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.listview.notifyContextMenuGesture(menu, event, eventType);
    },

    /**
     * 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.listview.setOptions(options, flags);

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

        if (needRefresh)
        {
            this.listview.refresh();
        }
    },

   /**
    * Sets a single option
    * @param {Object} key the key for the option
    * @param {Object} value the value for the option
    * @override
    * @private
    */
    _setOption: function(key, value)
    {
        // checks whether value is valid for the key
        var valid = true;
        if (key == "selectionMode")
        {
            valid = (value == "none" || value == "single" || value == "multiple");
        }
        else if (key == "drillMode")
        {
            valid = (value == "collapsible" || value == "none");
        }
        else if (key == "scrollPolicy")
        {
            valid = (value == "auto" || value == "loadMoreOnScroll");
        }

        // update option if it's valid otherwise throw an error
        if (valid)
        {
            this._super(key, value);
        }
        else
        {
            throw "Invalid value: "+value+" for key: "+key;
        }
    },

   /**
    * 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.listview.notifyDetached();
    },

   /**
    * Invoked when application calls oj.Components.subtreeShown.
    * @override
    * @private
    */
    _NotifyShown: function()
    {
        this.listview.notifyShown();
    },

    /********************************* public methods **************************************/
    /**
     * Returns a jQuery object containing the root dom element of the table
     * 
     * <p>This method does not accept any arguments.
     * 
     * @expose
     * @override
     * @memberof oj.ojListView
     * @instance
     * @return {jQuery} the root DOM element of list
     */
    'widget' : function ()
    {
        return this.listview.getRootElement();
    },

    /**
     * Redraw the entire list view after having made some external modifications.
     *      
     * <p>This method does not accept any arguments.
     * 
     * @expose 
     * @memberof! oj.ojListView
     * @instance
     * 
     * @example <caption>Invoke the <code class="prettyprint">refresh</code> method:</caption>
     * $( ".selector" ).ojListView( "refresh" );
     */
    refresh: function()
    {
        this._super();	
        this.listview.refresh();
    },

    /**
     * Return the subcomponent node represented by the documented locator attribute values.
     * <p>
     * To lookup the expand/collapse icon the locator object should have the following:
     * <ul>
     * <li><b>subId</b>: 'oj-listview-icon'</li>
     * <li><b>key</b>: the key of the item</li>                
     * </ul>
     *          
     * @expose
     * @memberof! oj.ojListView
     * @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.listview.getNodeBySubId(locator);
    },

    /**
     * <p>Returns the subId string for the given child DOM node.  For more details, see
     * <a href="#getNodeBySubId">getNodeBySubId</a>.
     *
     * @expose
     * @memberof! oj.ojListView
     * @instance
     * @override
     * @param {!Element} node - child DOM node
     * @return {string|null} The subId for the DOM node, or <code class="prettyprint">null</code> when none is found.
     */
    getSubIdByNode: function(node)
    {
        return this.listview.getSubIdByNode(node);
    },

    /**
     * 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.ojListView
     * @instance
     * @param {Object} key the key of the item to expand
     * @param {boolean} vetoable whether the event should be vetoable
     */
    expand: function (key, vetoable)
    {
        this.listview.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.ojListView
     * @instance
     * @param {Object} key the key of the item to collapse
     * @param {boolean} vetoable whether the event should be vetoable
     */
    collapse: function (key, vetoable)
    {
        this.listview.collapseKey(key, vetoable, true);
    },
  
    /**
     * Gets the key of currently expanded items.
     * 
     * @expose
     * @memberof oj.ojListView
     * @instance
     * @return {Array} array of keys of currently expanded items
     */
    getExpanded: function ()
    {
        return this.listview.getExpanded();
    }

    // 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>Focus on the item.  If <code class="prettyprint">selectionMode</code> is enabled, selects the item as well.</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.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Press & Hold</kbd></td>
 *       <td>Display context menu</td>
 *     </tr>
 *   </tbody>
 * </table>
 *
 * @ojfragment touchDoc - Used in touch gesture section of classdesc, and standalone gesture doc
 * @memberof oj.ojListView
 */

/**
 * <table class="keyboard-table">
 *   <thead>
 *     <tr>
 *       <th>Target</th>
 *       <th>Key</th>
 *       <th>Action</th>
 *     </tr>
 *   </thead>
 *   <tbody>
 *     <tr>
 *       <td rowspan = "13" nowrap>List Item</td>
 *       <td><kbd>F2</kbd></td>
 *       <td>Enters Actionable mode.  This enables keyboard action on elements inside the item, including navigate between focusable elements inside the item.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Esc</kbd></td>
 *       <td>Exits Actionable mode.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Tab</kbd></td>
 *       <td>When in Actionable Mode, navigates to next focusable element within the item.  If the last focusable element is reached, shift focus back to the first focusable element.
 *           When not in Actionable Mode, navigates to next focusable element on page (outside ListView).</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Shift+Tab</kbd></td>
 *       <td>When in Actionable Mode, navigates to previous focusable element within the item.  If the first focusable element is reached, shift focus back to the last focusable element.
 *           When not in Actionable Mode, navigates to previous focusable element on page (outside ListView).</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>DownArrow</kbd></td>
 *       <td>Move focus to the item below.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>UpArrow</kbd></td>
 *       <td>Move focus to the item above.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Shift+DownArrow</kbd></td>
 *       <td>Extend the selection to the item below.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Shift+UpArrow</kbd></td>
 *       <td>Extend the selection to the item above.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Shift+F10</kbd></td>
 *       <td>Launch the context menu if there is one associated with the current item.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Enter</kbd></td>
 *       <td>Selects the current item.  No op if the item is already selected.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Space</kbd></td>
 *       <td>Toggles to select and deselect the current item.  If previous items have been selected, deselects them and selects the current item.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Shift+Space</kbd></td>
 *       <td>Selects contiguous items from the last selected item to the current item.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>Ctrl+Space</kbd></td>
 *       <td>Toggles to select and deselect the current item while maintaining previous selected items.</td>
 *     </tr>
 *     <tr>
 *       <td rowspan = "2" nowrap>Group Item</td>
 *       <td><kbd>LeftArrow</kbd></td>
 *       <td>Collapse the current item if it is expanded and is collapsible.  For non-hierarchical data, do nothing.</td>
 *     </tr>
 *     <tr>
 *       <td><kbd>RightArrow</kbd></td>
 *       <td>Expand the current item if it has children and is expandable.  For non-hierarchical data, do nothing.</td>
 *     </tr>
 *   </tbody>
 * </table>
 *
 * @ojfragment keyboardDoc - Used in keyboard section of classdesc, and standalone gesture doc
 * @memberof oj.ojListView
 */
});

//////////////////     SUB-IDS     //////////////////

/**
 * <p>Sub-ID for the ojListView component's disclosure icon in group items.  See the <a href="#getNodeBySubId">getNodeBySubId</a> 
 * method for details.</p>
 * 
 * @ojsubid
 * @member
 * @name oj-listview-icon
 * @memberof oj.ojListView
 * @instance
 * 
 * @example <caption>Get the disclosure icon for the group item with key 'foo':</caption>
 * var node = $( ".selector" ).ojListView( "getNodeBySubId", {'subId': 'oj-listview-icon', 'key': 'foo'} );
 */