/**
* Copyright (c) 2014, Oracle and/or its affiliates.
* All rights reserved.
*/
/**
* @ojcomponent oj.ojCombobox
* @augments oj.editableValue
* @since 0.6
*
* @classdesc
* <h3 id="comboboxOverview-section">
* JET Combobox Component
* <a class="bookmarkable-link" title="Bookmarkable Link" href="#comboboxOverview-section"></a>
* </h3>
*
* <p>Description: JET Combobox enhances a html input and datalist element into a Combobox that supports
* single-select, multi-select, free text input, and search filtering.</p>
*
* <p>A JET Combobox can be created with the following markup. By default, it creates a single-select
* Combobox. The 'multiple' option can be specified to change it to a multi-select Combobox.</p>
*
* <pre class="prettyprint">
* <code>
* <input list="items" data-bind="ojComponent: {component: 'ojCombobox', multiple: true}"/>
* <datalist id="items">
* <option value="option 1">option 1</option>
* <option value="option 2">option 2</option>
* <option value="option 3">option 3</option>
* <option value="option 4">option 4</option>
* </datalist>
* </code></pre>
*
* <p>Please note that datalist is not supported in IE 9. To create a JET Combobox that works across browsers
* including IE 9, please use the <code class="prettyprint">options</code> array to provide the option items.</p>
*
* <pre class="prettyprint">
* <code>
* <input data-bind="ojComponent: {component: 'ojCombobox', options:
* [{value: 'option1', label: 'option1'}, {value: 'option2', label: 'option2'}]}"/>
* </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="rtl-section">
* Reading direction
* <a class="bookmarkable-link" title="Bookmarkable Link" href="#rtl-section"></a>
* </h3>
*
* <p>As with any JET component, in the unusual case that the directionality (LTR or RTL) changes post-init, the Combobox must be <code class="prettyprint">refresh()</code>ed.</p>
*
*
* <h3 id="pseudos-section">
* Pseudo-selectors
* <a class="bookmarkable-link" title="Bookmarkable Link" href="#pseudos-section"></a>
* </h3>
*
* <p>The <code class="prettyprint">:oj-combobox</code> pseudo-selector can be used in jQuery expressions to select JET Combobox. For example:</p>
*
* <pre class="prettyprint">
* <code>$( ":oj-combobox" ) // selects all JET Combobox on the page
* $myEventTarget.closest( ":oj-combobox" ) // selects the closest ancestor that is a JET Combobox
* </code></pre>
*
* <h3 id="a11y-section">
* Accessibility
* <a class="bookmarkable-link" title="Bookmarkable Link" href="#a11y-section"></a>
* </h3>
* <p>
* It is up to the application developer to associate the label to the input component.
* For combobox, you should put an <code>id</code> on the input, and then set
* the <code>for</code> attribute on the label to be the input's id.
* </p>
* <h3 id="label-section">
* Label and Combobox
* <a class="bookmarkable-link" title="Bookmarkable Link" href="#label-section"></a>
* </h3>
* <p>
* For accessibility, you should associate a label element with the input
* by putting an <code>id</code> on the input, and then setting the
* <code>for</code> attribute on the label to be the input's id.
* </p>
* <p>
* The component will decorate its associated label with required and help
* information, if the <code>required</code> and <code>help</code> options are set.
* </p>
* <h3 id="jqui2jet-section">
* JET for jQuery UI developers
* <a class="bookmarkable-link" title="Bookmarkable Link" href="#jqui2jet-section"></a>
* </h3>
*
* <p>Event names for all JET components are prefixed with "oj", instead of component-specific prefixes like "Combobox".</p>
*
* @desc Creates a JET Combobox.
* @example <caption>Initialize the Combobox with no options specified:</caption>
* $( ".selector" ).ojCombobox();
*
* @example <caption>Initialize the Combobox with some options:</caption>
* $( ".selector" ).ojCombobox( { "multiple": true, "placeholder": "Select multiple values." } );
*
* @example <caption>Initialize the Combobox via the JET <code class="prettyprint">ojComponent</code> binding:</caption>
* <div id="combobox" data-bind="ojComponent: { component: 'ojCombobox',
* multiple: true}">
*/
oj.__registerWidget("oj.ojCombobox", $['oj']['editableValue'],
{
defaultElement : "<input>",
widgetEventPrefix : "oj",
options :
{
/**
* A converter instance that duck types {@link oj.Converter}. Or an object literal containing
* the following properties.
* <p>
* When <code class="prettyprint">converter</code> option changes due to programmatic
* intervention, the component performs various tasks based on the current state it is in. </br>
*
* <h4>Steps Performed Always</h4>
* <ul>
* <li>Any cached converter instance is cleared and new converter created. The converter hint is
* pushed to messaging. E.g., notewindow displays the new hint(s).
* </li>
* </ul>
*
* <h4>Running Validation</h4>
* <ul>
* <li>if component is valid when <code class="prettyprint">converter</code> option changes, the
* display value is refreshed.</li>
* <li>if component is invalid and is showing messages -
* <code class="prettyprint">messagesShown</code> option is non-empty, when
* <code class="prettyprint">converter</code> option changes, then all messages generated by the
* component are cleared and full validation run using its current display value.
* <ul>
* <li>if there are validation errors, then <code class="prettyprint">value</code>
* option is not updated, and the errors pushed to <code class="prettyprint">messagesShown</code>
* option. The display value is not refreshed in this case. </li>
* <li>if no errors result from the validation, <code class="prettyprint">value</code>
* option is updated; page author can listen to the <code class="prettyprint">optionChange</code>
* event on the <code class="prettyprint">value</code> option to clear custom errors. The
* display value is refreshed with the formatted value provided by converter.</li>
* </ul>
* </li>
* <li>if component is invalid and has deferred messages -
* <code class="prettyprint">messagesHidden</code> option is non-empty, when
* <code class="prettyprint">converter</code> option changes, then the display value is
* refreshed with the formatted value provided by converter.</li>
* </ul>
* </p>
*
* <h4>Clearing Messages</h4>
* <ul>
* <li>When component messages are cleared in the cases described above, messages created by
* the component that are present in both <code class="prettyprint">messagesHidden</code> and
* <code class="prettyprint">messagesShown</code> options are cleared.</li>
* <li><code class="prettyprint">messagesCustom</code> option is not cleared. Page authors can
* choose to clear it explicitly when setting the converter option.</li>
* </ul>
* </p>
*
* @property {string} type - the conveter type registered with the oj.ConverterFactory.
* Supported type is 'number'. See {@link oj.ConverterFactory} for details. <br/>
* E.g., <code class="prettyprint">{converter: {type: 'number'}</code>
* @property {Object=} options - optional Object literal of options that the converter expects.
* See {@link oj.IntlNumberConverter} for options supported by the number converter.
* E.g., <code class="prettyprint">{converter: {type: 'number', options: {style: 'decimal'}}</code>
*
* @expose
* @access public
* @instance
* @memberof! oj.ojCombobox
* @type {Object|undefined}
*/
converter: undefined,
/**
* The placeholder text to set on the element. Though it is possible to set placeholder
* attribute on the element itself, the component will only read the value when the component
* is created. Subsequent changes to the element's placeholder attribute will not be picked up
* and page authors should update the option directly.
*
*
* @example <caption>Initialize the combobox with the <code class="prettyprint">placeholder</code> option specified:</caption>
* $( ".selector" ).ojCombobox( { "placeholder": "Please select ..." } );
*
* @default when the option is not set, the element's placeholder attribute is used if it exists.
*
* @expose
* @access public
* @instance
* @memberof! oj.ojCombobox
* @type {string|null|undefined}
*/
placeholder: undefined,
/**
* The id of the html list for the Combobox.
*
* @example <caption>Initialize the combobox with the <code class="prettyprint">list</code> option specified:</caption>
* $( ".selector" ).ojCombobox( { "list": "list" } );
*
* @example <caption>The <code class="prettyprint">list</code> points to a html <code class="prettyprint">ul</code> element.
* The value for the list item should be specified with <code class="prettyprint">oj-data-value</code> field. By default, we use the first text node for search filtering. An optional <code class="prettyprint">oj-data-label</code> field can be added to the list item, in which case it will take precedence over the text node.</caption>
* <ul id="list">
* <li oj-data-value="li1">Item 1</li>
* <li oj-data-value="li2">Item 2</li>
* </ul>
*
* @expose
* @memberof! oj.ojCombobox
* @instance
* @type {string|null|undefined}
*/
list: undefined,
/**
* If multi-select is enabled for the combobox.
*
* @expose
* @memberof! oj.ojCombobox
* @instance
* @type {boolean}
* @default <code class="prettyprint">false</code>
*
* @example <caption>Initialize the Combobox with the <code class="prettyprint">multiple</code> option specified:</caption>
* $( ".selector" ).ojCombobox( { "multiple": true } );
*/
multiple : false,
/**
* The option items for the Combobox. Instead of providing the option items in a datalist, they can be specified as an array of objects containing value and label.
* The value is used as the value of the option item and label as the label. Both should be of string type. Group data can be provided with label and a children
* array containing the option items. Option item can be set as disabled.
*
* @expose
* @memberof! oj.ojCombobox
* @instance
* @type {Array}
*
* @example <caption>Initialize the Combobox with the <code class="prettyprint">options</code> specified:</caption>
* $( ".selector" ).ojCombobox( { "options": [{value: 'option1', label: 'option1'}, {value: 'option2', label: 'option2', disabled: true}, {value: 'option3', label: 'option3'}] } );
* @example <caption>Initialize the Combobox with group data:</caption>
* $( ".selector" ).ojCombobox( { "options": [{label : 'group1', children: [{value: 'option1', label: 'option1'}, {value: 'option2', label: 'option2'}]}, {label: 'group2', children: [{value: 'option3', label: 'option3'}]} ] } );
*/
options : null,
/**
* Specify the key names to use in the options array.
*
* @expose
* @memberof! oj.ojCombobox
* @instance
* @type {Object}
*
* @example <caption>Initialize the Combobox with <code class="prettyprint">optionsKeys</code> specified. This allows the key names to be redefined in the options array.</caption>
* $( ".selector" ).ojCombobox( { "optionsKeys": {value : "state_abbr", label : "state_name"} } );
* @example <caption>Redefine keys for data with subgroups.</caption>
* $( ".selector" ).ojCombobox( { "optionsKeys": {label : "regions", children : "states", childKeys : {value : "state_abbr", label : "state_name"}} } );
*/
optionsKeys : null,
/**
* Triggered immediately before the combobox drop down is expanded.
*
* @expose
* @event
* @memberof! oj.ojCombobox
* @instance
* @property {Event} event <code class="prettyprint">jQuery</code> event object
* @property {Object} ui Parameters
*
* @example <caption>Initialize the Combobox with the <code class="prettyprint">beforeExpand</code> callback specified:</caption>
* $( ".selector" ).ojCombobox({
* "beforeExpand": function( event, ui ) {}
* });
*
* @example <caption>Bind an event listener to the <code class="prettyprint">ojbeforeexpand</code> event:</caption>
* $( ".selector" ).on( "ojbeforeexpand", function( event, ui ) {} );
*/
beforeExpand : null
/**
* The type of value is an array, and an array will always be returned from the component.
* For single-select the first element of the array will be used as the value.
* As a convenience we allow a string to be passed into the setter,
* but note that the value option can only be bound to a knockout observableArray.
*
* @example <caption>Initialize the combobox with the <code class="prettyprint">value</code> option specified:</caption>
* $(".selector").ojCombobox({'value': "option1,option2"});<br/>
*
* @example <caption>Initialize the combobox with the <code class="prettyprint">value</code> option specified as Array for selecting multiple items:</caption>
* $(".selector").ojCombobox({'value': ["option1", "option2"]});<br/>
* @example <caption>Get or set the <code class="prettyprint">value</code> option, after initialization:</caption>
* // Getter: returns value
* $(".selector").ojCombobox("option", "value");
* // Setter: sets value with array containing "option1"
* $(".selector").ojCombobox("option", "value", ["option1"]);
* // Setter: sets value with array containing "option1" and "option2"
* $(".selector").ojCombobox("option", "value", ["option1", "option2"]);
* // Setter: sets value with string "option1"
* $(".selector").ojCombobox("option", "value", "option1");
*
* @member
* @name value
* @access public
* @instance
* @default When the option is not set, the element's value property is used as its initial value
* if it exists.
* @memberof! oj.ojCombobox
* @type {string|Array}
*/
},
/**
* Returns a jQuery object containing the element visually representing the combobox.
*
* <p>This method does not accept any arguments.
*
* @expose
* @memberof! oj.ojCombobox
* @instance
* @return {jQuery} the combobox
*/
widget : function ()
{
return this.combobox.container;
},
/**
* @override
* @private
*/
_ComponentCreate : function ()
{
this._super();
this._setup();
},
_InitOptions : function (originalDefaults, constructorOptions)
{
var props = [{attribute: "disabled", defaultOptionValue: null, validateOption: true},
{attribute: "placeholder", defaultOptionValue: ""},
{attribute: "required", defaultOptionValue: false,
coerceDomValue: true, validateOption: true},
{attribute: "title", defaultOptionValue: ""}
// {attribute: "value", defaultOptionValue: null}
];
this._super(originalDefaults, constructorOptions);
oj.EditableValueUtils.initializeOptionsFromDom(props, constructorOptions, this);
// TODO: PAVI - Let's discuss
if (this.options['value'] === undefined) {
this.options['value'] = (this.element.attr('value') !== undefined) ? _ComboUtils.splitVal(this.element.val(), ",") : null;
} else {
//clone the value, otherwise _setDisplayValue will not be invoked on binding value to ko observableArray.
//TODO: Need to revisit this once 18724975 is fixed.
var value = this.options['value'];
if (Array.isArray(value)) {
value = value.slice(0);
} else if(typeof value === "string") {
if (this.options['multiple'] === true)
value = _ComboUtils.splitVal(value, ",");
else
value = [value];
}
this.options['value'] = value;
}
},
_setup : function ()
{
var opts = {},
multiple = this.options.multiple;
opts.element = this.element;
opts.ojContext = this;
opts = $.extend(this.options, opts);
this.combobox = multiple ? new _OjMultiCombobox() : new _OjSingleCombobox();
this.combobox._init(opts);
},
/**
* @override
* @private
*/
_destroy : function ()
{
this.combobox._destroy();
this._super();
},
/**
* Refreshes the combobox.
*
* <p>This method does not accept any arguments.
*
* @expose
* @memberof! oj.ojCombobox
* @instance
*/
refresh : function ()
{
this._super();
this.combobox._destroy();
this._setup();
this._SetRootAttributes();
// re-apply oj-required on container
this._Refresh("required", this.options['required']);
},
/**
* Handles options specific to combobox.
* @override
* @protected
* @memberof! oj.ojCombobox
*/
_setOption : function (key, value, flags)
{
if (key === "value") {
//clone the value, otherwise _setDisplayValue will not be invoked on binding value to ko observableArray.
//TODO: Need to revisit this once 18724975 is fixed.
if (Array.isArray(value)) {
value = value.slice(0);
}
else if(typeof value === "string") {
if (this.options['multiple'] === true)
value = _ComboUtils.splitVal(value, ",");
else
value = [value];
}
}
this._super(key, value, flags);
if (key === "options")
{
this.combobox.opts.options = value;
this.combobox.opts = this.combobox._prepareOpts(this.combobox.opts);
}
if (key === "disabled")
{
if (value)
this.combobox._disable();
else
this.combobox._enable();
}
},
//19670748, dropdown popup should be closed on subtreeDetached notification.
_NotifyDetached : function() {
this.combobox.close();
},
//19670748, dropdown popup should be closed on subtreeHidden notification.
_NotifyHidden : function() {
this.combobox.close();
},
/**
* Updates display value of combobox.
* @override
* @protected
* @memberof! oj.ojCombobox
*/
_SetDisplayValue: function(displayValue)
{
this.combobox._initSelection();
},
/**
* Set the placeholder.
* @override
* @protected
* @memberof! oj.ojCombobox
*/
_SetPlaceholder : function(value)
{
if (this.combobox)
{
this.combobox.opts.placeholder = value;
// TODO: pavitra - noticed that some combobox tests fail because the _setPlaceholder is
// undefined, when this method is called from _AfterCreate().
if (this.combobox._setPlaceholder)
{
this.combobox._setPlaceholder();
}
}
},
/**
* Validates the component's value using the converter and all validators registered on
* the component.
*
* @example <caption>Validate component using its current value.</caption>
* // validate display value.
* $(.selector).ojCombobox('validate');
*
* @expose
* @override
* @memberof! oj.ojCombobox
* @instance
*/
validate : function ()
{
var displayValue = this.combobox.search.val();
var newValue = null;
if (this.options['multiple'] !== true) {
if (displayValue === undefined || displayValue === null || displayValue === "")
newValue = [];
else
newValue = [displayValue];
} else {
var existingValue = this.combobox.getVal();
if (displayValue === undefined || displayValue === null || displayValue === "")
newValue = existingValue;
else
newValue = existingValue.push(displayValue);
}
return this._SetValue(newValue, null, this._VALIDATE_METHOD_OPTIONS);
},
/**
* Parses the value using the converter set and returns the parsed value. If parsing fails the
* error is written into the element
*
* @override
* @protected
* @memberof! oj.ojCombobox
* @instance
*/
_parseValue: function(submittedValue)
{
var parsedVal = [];
if (typeof submittedValue === "string") {
if (this.options['multiple'] === true)
submittedValue = _ComboUtils.splitVal(submittedValue, ",");
else
submittedValue = [submittedValue];
}
if (Array.isArray(submittedValue)) {
for (var i = 0; i<submittedValue.length; i++) {
var parsed = this._super(submittedValue[i]);
parsedVal.push(parsed.toString());
}
}
return parsedVal;
},
/**
* Returns the messaging launcher element i.e., where user sets focus that triggers the popup.
* Usually this is the element input or select that will receive focus and on which the popup
* for messaging is initialized.
*
* @override
* @protected
* @memberof! oj.ojCombobox
* @return {Object} jquery element which represents the messaging launcher component
*/
_GetMessagingLauncherElement : function ()
{
return this.combobox.search;
},
/**
* Returns the jquery element that represents the content part of the component.
* This is usually the component that user sets focus on (tabindex is set 0) and
* where aria attributes like aria-required, aria-labeledby etc. are set. This is
* also the element where the new value is updated. Usually this is the same as
* the _GetMessagingLauncherElement.
*
* @override
* @protected
* @memberof! oj.ojCombobox
* @return {Object} jquery element which represents the content.
*/
_GetContentElement : function ()
{
return this.combobox.search;
},
/**
* Returns the default styleclass for the component.
*
* @return {string}
* @expose
* @memberof! oj.ojCombobox
* @override
* @protected
*/
_GetDefaultStyleClass : function ()
{
return "oj-combobox";
},
_getDropdown : function ()
{
if (this.combobox && this.combobox._opened())
{
var dropdown = $(".oj-listbox-drop");
for (var i=0; i<dropdown.length; i++)
{
if ($(dropdown[i]).attr("id") == "oj-listbox-drop" &&
$(dropdown[i]).attr("data-oj-containerid") == this.combobox.containerId)
return $(dropdown[i]);
}
}
return null;
},
////////////////// SUB-IDS //////////////////
/**
* <p>Sub-ID for the input field
*
* <p>See the <a href="#getNodeBySubId">getNodeBySubId</a> and
* <a href="#getSubIdByNode">getSubIdByNode</a> methods for details.
*
* @ojsubid
* @member
* @name oj-combobox-input
* @memberof oj.ojCombobox
* @instance
*
* @example <caption>Get the input field element</caption>
* var node = $( ".selector" ).ojCombobox( "getNodeBySubId", {'subId': 'oj-combobox-input'} );
*/
/**
* <p>Sub-ID for the drop down arrow of single-select combobox.
*
* <p>See the <a href="#getNodeBySubId">getNodeBySubId</a> and
* <a href="#getSubIdByNode">getSubIdByNode</a> methods for details.
*
* @ojsubid
* @member
* @name oj-combobox-arrow
* @memberof oj.ojCombobox
* @instance
*
* @example <caption>Get the drop down arrow of the single-select combobox</caption>
* var node = $( ".selector" ).ojCombobox( "getNodeBySubId", {'subId': 'oj-combobox-arrow'} );
*/
/**
* <p>Sub-ID for the dropdown box.
*
* <p>See the <a href="#getNodeBySubId">getNodeBySubId</a> and
* <a href="#getSubIdByNode">getSubIdByNode</a> methods for details.
*
* @ojsubid
* @member
* @name oj-combobox-drop
* @memberof oj.ojCombobox
* @instance
*
* @example <caption>Get the dropdown box</caption>
* var node = $( ".selector" ).ojCombobox( "getNodeBySubId", {'subId': 'oj-combobox-drop'} );
*/
/**
* <p>Sub-ID for the filtered result list.
*
* <p>See the <a href="#getNodeBySubId">getNodeBySubId</a> and
* <a href="#getSubIdByNode">getSubIdByNode</a> methods for details.
*
* @ojsubid
* @member
* @name oj-combobox-results
* @memberof oj.ojCombobox
* @instance
*
* @example <caption>Get the filtered result list</caption>
* var node = $( ".selector" ).ojCombobox( "getNodeBySubId", {'subId': 'oj-combobox-results'} );
*/
/**
* <p>Sub-ID for the selected items of multi-select combobox.
* <p>This returns a list of the selected items.
* <p>See the <a href="#getNodeBySubId">getNodeBySubId</a> and
* <a href="#getSubIdByNode">getSubIdByNode</a> methods for details.
*
* @ojsubid
* @member
* @name oj-combobox-selection
* @memberof oj.ojCombobox
* @instance
*
* @example <caption>Get the list of selected items</caption>
* var node = $( ".selector" ).ojCombobox( "getNodeBySubId", {'subId': 'oj-combobox-selection'} );
*/
getNodeBySubId: function(locator)
{
var node = null, subId;
if (locator == null)
{
return this.combobox.container ? this.combobox.container[0] : null;
}
else
{
node = this._super(locator);
}
if (!node)
{
subId = locator['subId'];
if (subId === "oj-combobox-drop")
subId = "oj-listbox-drop";
if (subId === "oj-combobox-results")
subId = "oj-listbox-results";
if (subId === "oj-combobox-selection")
subId = "oj-combobox-selected-choice";
var dropdown = this._getDropdown();
switch (subId)
{
case "oj-combobox-input":
case "oj-combobox-arrow":
node = this.widget().find("." + subId)[0];
break;
case "oj-listbox-drop":
if (dropdown) {
node = dropdown[0];
}
break;
case "oj-listbox-results":
if (dropdown) {
node = dropdown.find("." + subId)[0];
}
break;
case "oj-combobox-selected-choice":
node = this.widget().find("." + subId).toArray();
break;
}
}
// Non-null locators have to be handled by the component subclasses
return node || null;
}
// Fragments:
/**
* <table class="keyboard-table">
* <thead>
* <tr>
* <th>Target</th>
* <th>Gesture</th>
* <th>Action</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td>Input Field</td>
* <td><kbd>Tap</kbd></td>
* <td> If the drop down is not open, expand the drop down list. Otherwise, close the drop down list.</td>
* </tr>
* <tr>
* <td>Arrow Button</td>
* <td><kbd>Tap</kbd></td>
* <td> If the drop down is not open, expand the drop down list. Otherwise, close the drop down list.</td>
* </tr>
* <tr>
* <td>Option Item</td>
* <td><kbd>Tap</kbd></td>
* <td>Tap on a option item in the drop down list to select/add a new item.</td>
* </tr>
* <tr>
* <td>Selected Item with Clear Entry Button</td>
* <td><kbd>Tap</kbd></td>
* <td>Remove item from the selected items list by taping on the clear button next to the data item.</td>
* </tr>
*
* </tbody>
* </table>
*
* <p>Disabled option items receive no highlight and are not selectable.</p>
*
*
* @ojfragment touchDoc - Used in touch gesture section of classdesc, and standalone gesture doc
* @memberof oj.ojCombobox
*/
/**
* <table class="keyboard-table">
* <thead>
* <tr>
* <th>Key</th>
* <th>Use</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td><kbd>Enter</kbd></td>
* <td> Select the highlighted choice from the drop down.
* If it's a new entry, add to existing selections.</td>
* </tr>
* <tr>
* <td><kbd>UpArrow or DownArrow</kbd></td>
* <td> Highlight the option item on the drop down list in the direction of the arrow.
* If the drop down is not open, expand the drop down list.</td>
* </tr>
* <tr>
* <td><kbd>LeftArrow or RightArrow</kbd></td>
* <td> Move focus to the previous or next selected item in Multi-select Combobox.</td>
* </tr>
* <tr>
* <td><kbd>Esc</kbd></td>
* <td> Collapse the drop down list. If the drop down is already closed, do nothing.</td>
* </tr>
*
* </tbody>
* </table>
*
* <p>Disabled option items receive no highlight and are not selectable.</p>
*
* @ojfragment keyboardDoc - Used in keyboard section of classdesc, and standalone gesture doc
* @memberof oj.ojCombobox
*/
});
Source: src/main/javascript/oracle/oj/ojselectcombobox/ojcombobox.js
Oracle® JavaScript Extension Toolkit (JET)
1.1.2
E65298-01