/**
* SearchWidgets combine a {@link OO.ui.TextInputWidget text input field}, where users can type a search query,
* and a {@link OO.ui.TextInputMenuSelectWidget menu} of search results, which is displayed beneath the query
* field. Unlike {@link OO.ui.LookupElement lookup menus}, search result menus are always visible to the user.
* Users can choose an item from the menu or type a query into the text field to search for a matching result item.
* In general, search widgets are used inside a separate {@link OO.ui.Dialog dialog} window.
*
* Each time the query is changed, the search result menu is cleared and repopulated. Please see
* the [OOjs UI demos][1] for an example.
*
* [1]: https://tools.wmflabs.org/oojs-ui/oojs-ui/demos/#dialogs-mediawiki-vector-ltr
*
* @class
* @extends OO.ui.Widget
*
* @constructor
* @param {Object} [config] Configuration options
* @cfg {string|jQuery} [placeholder] Placeholder text for query input
* @cfg {string} [value] Initial query value
*/
OO.ui.SearchWidget = function OoUiSearchWidget( config ) {
// Configuration initialization
config = config || {};
// Parent constructor
OO.ui.SearchWidget.super.call( this, config );
// Properties
this.query = new OO.ui.TextInputWidget( {
icon: 'search',
placeholder: config.placeholder,
value: config.value
} );
this.results = new OO.ui.SelectWidget();
this.$query = $( '
' );
this.$results = $( '
' );
// Events
this.query.connect( this, {
change: 'onQueryChange',
enter: 'onQueryEnter'
} );
this.results.connect( this, {
highlight: 'onResultsHighlight',
select: 'onResultsSelect'
} );
this.query.$input.on( 'keydown', this.onQueryKeydown.bind( this ) );
// Initialization
this.$query
.addClass( 'oo-ui-searchWidget-query' )
.append( this.query.$element );
this.$results
.addClass( 'oo-ui-searchWidget-results' )
.append( this.results.$element );
this.$element
.addClass( 'oo-ui-searchWidget' )
.append( this.$results, this.$query );
};
/* Setup */
OO.inheritClass( OO.ui.SearchWidget, OO.ui.Widget );
/* Events */
/**
* A 'highlight' event is emitted when an item is highlighted. The highlight indicates which
* item will be selected. When a user mouses over a menu item, it is highlighted. If a search
* string is typed into the query field instead, the first menu item that matches the query
* will be highlighted.
* @event highlight
* @deprecated Connect straight to getResults() events instead
* @param {Object|null} item Item data or null if no item is highlighted
*/
/**
* A 'select' event is emitted when an item is selected. A menu item is selected when it is clicked,
* or when a user types a search query, a menu result is highlighted, and the user presses enter.
*
* @event select
* @deprecated Connect straight to getResults() events instead
* @param {Object|null} item Item data or null if no item is selected
*/
/* Methods */
/**
* Handle query key down events.
*
* @private
* @param {jQuery.Event} e Key down event
*/
OO.ui.SearchWidget.prototype.onQueryKeydown = function ( e ) {
var highlightedItem, nextItem,
dir = e.which === OO.ui.Keys.DOWN ? 1 : ( e.which === OO.ui.Keys.UP ? -1 : 0 );
if ( dir ) {
highlightedItem = this.results.getHighlightedItem();
if ( !highlightedItem ) {
highlightedItem = this.results.getSelectedItem();
}
nextItem = this.results.getRelativeSelectableItem( highlightedItem, dir );
this.results.highlightItem( nextItem );
nextItem.scrollElementIntoView();
}
};
/**
* Handle select widget select events.
*
* Clears existing results. Subclasses should repopulate items according to new query.
*
* @private
* @param {string} value New value
*/
OO.ui.SearchWidget.prototype.onQueryChange = function () {
// Reset
this.results.clearItems();
};
/**
* Handle select widget enter key events.
*
* Selects highlighted item.
*
* @private
* @param {string} value New value
*/
OO.ui.SearchWidget.prototype.onQueryEnter = function () {
// Reset
this.results.selectItem( this.results.getHighlightedItem() );
};
/**
* Handle select widget highlight events.
*
* @private
* @deprecated Connect straight to getResults() events instead
* @param {OO.ui.OptionWidget} item Highlighted item
* @fires highlight
*/
OO.ui.SearchWidget.prototype.onResultsHighlight = function ( item ) {
this.emit( 'highlight', item ? item.getData() : null );
};
/**
* Handle select widget select events.
*
* @private
* @deprecated Connect straight to getResults() events instead
* @param {OO.ui.OptionWidget} item Selected item
* @fires select
*/
OO.ui.SearchWidget.prototype.onResultsSelect = function ( item ) {
this.emit( 'select', item ? item.getData() : null );
};
/**
* Get the query input.
*
* @return {OO.ui.TextInputWidget} Query input
*/
OO.ui.SearchWidget.prototype.getQuery = function () {
return this.query;
};
/**
* Get the search results menu.
*
* @return {OO.ui.SelectWidget} Menu of search results
*/
OO.ui.SearchWidget.prototype.getResults = function () {
return this.results;
};