From 18c6615d01ecf6aab61197998c511ec5edc1abfe Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 25 Nov 2015 21:01:58 +0100 Subject: [PATCH] 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 --- autoload.php | 1 + includes/widget/SearchInputWidget.php | 52 ++++++++ resources/Resources.php | 19 +++ .../mw.widgets.SearchInputWidget.css | 3 + .../mw.widgets.SearchInputWidget.js | 111 ++++++++++++++++++ .../mw.widgets.TitleWidget.js | 3 +- 6 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 includes/widget/SearchInputWidget.php create mode 100644 resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css create mode 100644 resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js diff --git a/autoload.php b/autoload.php index e882547a78..e74df0aa1f 100644 --- a/autoload.php +++ b/autoload.php @@ -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', diff --git a/includes/widget/SearchInputWidget.php b/includes/widget/SearchInputWidget.php new file mode 100644 index 0000000000..7b3de4a557 --- /dev/null +++ b/includes/widget/SearchInputWidget.php @@ -0,0 +1,52 @@ + 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 ); + } +} diff --git a/resources/Resources.php b/resources/Resources.php index dcc02b7e19..16f6c94603 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -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' => [ diff --git a/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css b/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css new file mode 100644 index 0000000000..3da5d31888 --- /dev/null +++ b/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css @@ -0,0 +1,3 @@ +.mw-widget-searchInputWidget { + display: inline-block; +} diff --git a/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js b/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js new file mode 100644 index 0000000000..1f526e254c --- /dev/null +++ b/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js @@ -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 ) ); diff --git a/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js b/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js index abe1228cf4..b805e65516 100644 --- a/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js +++ b/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js @@ -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 ) { -- 2.20.1