MediaWiki Widgets: Add new SearchInputWidget

SearchInputWidget is similar to a TitleInputWidget, but doesn't has
a visible loading indication, doesn't highlight the first result and
uses the opensearch api endpoint for suggestions, instead of
prefixsearch.

Extra points:
 * Improve documentation of mw.widgets.TitleInputWidget's configuration
   option validateTitle

Bug: T118443
Change-Id: I8b8098041fe2971389fa908d007d2e77255829ec
This commit is contained in:
Florian 2015-11-25 21:01:58 +01:00 committed by Florianschmidtwelzow
parent 996b7350f3
commit 18c6615d01
6 changed files with 188 additions and 1 deletions

View file

@ -821,6 +821,7 @@ $wgAutoloadLocalClasses = [
'MediaWiki\\Widget\\ComplexNamespaceInputWidget' => __DIR__ . '/includes/widget/ComplexNamespaceInputWidget.php',
'MediaWiki\\Widget\\ComplexTitleInputWidget' => __DIR__ . '/includes/widget/ComplexTitleInputWidget.php',
'MediaWiki\\Widget\\NamespaceInputWidget' => __DIR__ . '/includes/widget/NamespaceInputWidget.php',
'MediaWiki\\Widget\\SearchInputWidget' => __DIR__ . '/includes/widget/SearchInputWidget.php',
'MediaWiki\\Widget\\TitleInputWidget' => __DIR__ . '/includes/widget/TitleInputWidget.php',
'MediaWiki\\Widget\\UserInputWidget' => __DIR__ . '/includes/widget/UserInputWidget.php',
'MemCachedClientforWiki' => __DIR__ . '/includes/compat/MemcachedClientCompat.php',

View file

@ -0,0 +1,52 @@
<?php
/**
* MediaWiki Widgets SearchInputWidget class.
*
* @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
namespace MediaWiki\Widget;
/**
* Search input widget.
*/
class SearchInputWidget extends TitleInputWidget {
protected $pushPending = false;
protected $validateTitle = false;
protected $highlightFirst = false;
/**
* @param array $config Configuration options
* @param int|null $config['pushPending'] Whether the input should be visually marked as
* "pending", while requesting suggestions (default: true)
*/
public function __construct( array $config = [] ) {
// Parent constructor
parent::__construct(
array_merge( [
'infusable' => true,
'maxLength' => null,
'type' => 'search',
'icon' => 'search'
], $config )
);
// Properties, which are ignored in PHP and just shipped back to JS
if ( isset( $config['pushPending'] ) ) {
$this->pushPending = $config['pushPending'];
}
// Initialization
$this->addClasses( [ 'mw-widget-searchInputWidget' ] );
}
protected function getJavaScriptClassName() {
return 'mw.widgets.SearchInputWidget';
}
public function getConfig( &$config ) {
$config['pushPending'] = $this->pushPending;
return parent::getConfig( $config );
}
}

View file

@ -2213,6 +2213,25 @@ return [
],
'targets' => [ 'desktop', 'mobile' ],
],
'mediawiki.widgets.SearchInputWidget' => [
'scripts' => [
'resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js',
],
'dependencies' => [
'mediawiki.searchSuggest',
// FIXME: Needs TitleInputWidget only
'mediawiki.widgets',
],
],
'mediawiki.widgets.SearchInputWidget.styles' => [
'skinStyles' => [
'default' => [
'resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css',
],
],
'position' => 'top',
'targets' => [ 'desktop', 'mobile' ],
],
/* es5-shim */
'es5-shim' => [

View file

@ -0,0 +1,3 @@
.mw-widget-searchInputWidget {
display: inline-block;
}

View file

@ -0,0 +1,111 @@
/*!
* MediaWiki Widgets - SearchInputWidget class.
*
* @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
( function ( $, mw ) {
/**
* Creates a mw.widgets.SearchInputWidget object.
*
* @class
* @extends mw.widgets.TitleInputWidget
*
* @constructor
* @cfg {boolean} [pushPending=true] Visually mark the input field as "pending", while
* requesting suggestions.
*/
mw.widgets.SearchInputWidget = function MwWidgetsSearchInputWidget( config ) {
config = $.extend( {
type: 'search',
icon: 'search',
maxLength: undefined
}, config );
// Parent constructor
mw.widgets.SearchInputWidget.parent.call( this, config );
// Initialization
this.$element.addClass( 'mw-widget-searchInputWidget' );
this.lookupMenu.$element.addClass( 'mw-widget-searchWidget-menu' );
if ( !config.pushPending ) {
this.pushPending = false;
}
this.setLookupsDisabled( !this.suggestions );
};
/* Setup */
OO.inheritClass( mw.widgets.SearchInputWidget, mw.widgets.TitleInputWidget );
/* Methods */
/**
* @inheritdoc mw.widgets.TitleWidget
*/
mw.widgets.SearchInputWidget.prototype.getSuggestionsPromise = function () {
var api = new mw.Api();
// reuse the searchSuggest function from mw.searchSuggest
return mw.searchSuggest.request( api, this.getQueryValue(), $.noop, this.limit );
};
/**
* @inheritdoc mw.widgets.TitleInputWidget
*/
mw.widgets.SearchInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
// mw.widgets.TitleInputWidget uses response.query, which doesn't exist for opensearch,
// so return the whole response (titles only, and links)
return response || {};
};
/**
* @inheritdoc mw.widgets.TitleWidget
*/
mw.widgets.SearchInputWidget.prototype.getOptionsFromData = function ( data ) {
var items = [],
self = this;
// mw.widgets.TitleWidget does a lot more work here, because the TitleOptionWidgets can
// differ a lot, depending on the returned data from the request. With the request used here
// we get only the search results.
$.each( data[ 1 ], function ( i, result ) {
items.push( new mw.widgets.TitleOptionWidget(
// data[ 3 ][ i ] is the link for this result
self.getOptionWidgetData( result, null, data[ 3 ][ i ] )
) );
} );
mw.track( 'mw.widgets.SearchInputWidget', {
action: 'impression-results',
numberOfResults: items.length,
resultSetType: mw.searchSuggest.type
} );
return items;
};
/**
* @inheritdoc mw.widgets.TitleWidget
*
* @param {string} title
* @param {Object} data
* @param {string} url The Url to the result
*/
mw.widgets.SearchInputWidget.prototype.getOptionWidgetData = function ( title, data, url ) {
// the values used in mw.widgets-TitleWidget doesn't exist here, that's why
// the values are hard-coded here
return {
data: title,
url: url,
imageUrl: null,
description: null,
missing: false,
redirect: false,
disambiguation: false,
query: this.getQueryValue()
};
};
}( jQuery, mediaWiki ) );

View file

@ -23,7 +23,8 @@
* @cfg {boolean} [showRedlink] Show red link to exact match if it doesn't exist
* @cfg {boolean} [showImages] Show page images
* @cfg {boolean} [showDescriptions] Show page descriptions
* @cfg {boolean} [validateTitle=true] Whether the input must be a valid title
* @cfg {boolean} [validateTitle=true] Whether the input must be a valid title (if set to true,
* the widget will marks itself red for invalid inputs, including an empty query).
* @cfg {Object} [cache] Result cache which implements a 'set' method, taking keyed values as an argument
*/
mw.widgets.TitleWidget = function MwWidgetsTitleWidget( config ) {