Revert "Make mw.widgets.SearchInputWidget extend OO.ui.SearchInputWidget"
authorEBernhardson <ebernhardson@wikimedia.org>
Wed, 19 Jul 2017 21:36:17 +0000 (21:36 +0000)
committerEBernhardson <ebernhardson@wikimedia.org>
Wed, 19 Jul 2017 21:39:36 +0000 (21:39 +0000)
Typing a search query into the main box on Special:Search
causes the search to be performed for the first autocomplete
result, rather than the typed query. The first autocomplet
result should only be searched for if explicitly selected with
the mouse or arrow key.

This reverts commit 7882e3b66060f7bbd37e15688baf4dd30954b1b7.

Bug: T171112
Change-Id: I1af6ba90542fafe3ed1aeca420e9d6df6612f7d0

includes/widget/SearchInputWidget.php
resources/Resources.php
resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js

index 47d3717..90792fc 100644 (file)
@@ -10,10 +10,12 @@ namespace MediaWiki\Widget;
 /**
  * Search input widget.
  */
-class SearchInputWidget extends \OOUI\TextInputWidget {
+class SearchInputWidget extends TitleInputWidget {
 
        protected $pushPending = false;
        protected $performSearchOnClick = true;
+       protected $validateTitle = false;
+       protected $highlightFirst = false;
        protected $dataLocation = 'header';
 
        /**
@@ -28,6 +30,7 @@ class SearchInputWidget extends \OOUI\TextInputWidget {
         */
        public function __construct( array $config = [] ) {
                $config = array_merge( [
+                       'maxLength' => null,
                        'icon' => 'search',
                ], $config );
 
index 4176fe6..ccfe970 100644 (file)
@@ -2538,9 +2538,9 @@ return [
                ],
                'dependencies' => [
                        'mediawiki.searchSuggest',
-                       // FIXME: Needs TitleWidget only
+                       'oojs-ui.styles.icons-interactions',
+                       // FIXME: Needs TitleInputWidget only
                        'mediawiki.widgets',
-                       'oojs-ui-widgets',
                ],
        ],
        'mediawiki.widgets.SearchInputWidget.styles' => [
index 22e5874..08997aa 100644 (file)
@@ -10,9 +10,7 @@
         * Creates a mw.widgets.SearchInputWidget object.
         *
         * @class
-        * @extends OO.ui.SearchInputWidget
-        * @mixins mw.widgets.TitleWidget
-        * @mixins OO.ui.mixin.LookupElement
+        * @extends mw.widgets.TitleInputWidget
         *
         * @constructor
         * @param {Object} [config] Configuration options
                var $form = config.$input ? config.$input.closest( 'form' ) : $();
 
                config = $.extend( {
+                       icon: 'search',
+                       maxLength: undefined,
                        performSearchOnClick: true,
-                       dataLocation: 'header'
+                       dataLocation: 'header',
+                       namespace: 0
                }, config );
 
                // Parent constructor
-               mw.widgets.SearchInputWidget.parent.call( this, $.extend( {}, config, {
-                       autocomplete: false
-               } ) );
-
-               // Mixin constructors
-               mw.widgets.TitleWidget.call( this, config );
-               OO.ui.mixin.LookupElement.call( this, config );
+               mw.widgets.SearchInputWidget.parent.call( this, config );
 
                // Initialization
                this.$element.addClass( 'mw-widget-searchInputWidget' );
                this.lookupMenu.$element.addClass( 'mw-widget-searchWidget-menu' );
                this.lastLookupItems = [];
                if ( !config.pushPending ) {
-                       // TODO This actually overrides a method, that's pretty crazy. Surely there's a better way?
                        this.pushPending = false;
                }
                if ( config.dataLocation ) {
                                )
                        } );
                }.bind( this ) );
+
+               this.$element.addClass( 'oo-ui-textInputWidget-type-search' );
+               this.updateSearchIndicator();
+               this.connect( this, {
+                       disable: 'onDisable'
+               } );
        };
 
        /* Setup */
 
-       OO.inheritClass( mw.widgets.SearchInputWidget, OO.ui.SearchInputWidget );
-       OO.mixinClass( mw.widgets.SearchInputWidget, mw.widgets.TitleWidget );
-       OO.mixinClass( mw.widgets.SearchInputWidget, OO.ui.mixin.LookupElement );
+       OO.inheritClass( mw.widgets.SearchInputWidget, mw.widgets.TitleInputWidget );
 
        /* Methods */
 
        /**
-        * @inheritdoc mw.widgets.TitleWidget
+        * @inheritdoc
+        * @protected
+        */
+       mw.widgets.SearchInputWidget.prototype.getInputElement = function () {
+               return $( '<input>' ).attr( 'type', 'search' );
+       };
+
+       /**
+        * @inheritdoc
         */
-       mw.widgets.SearchInputWidget.prototype.getQueryValue = function () {
-               return this.getValue();
+       mw.widgets.SearchInputWidget.prototype.onIndicatorMouseDown = function ( e ) {
+               if ( e.which === OO.ui.MouseButtons.LEFT ) {
+                       // Clear the text field
+                       this.setValue( '' );
+                       this.$input[ 0 ].focus();
+                       return false;
+               }
+       };
+
+       /**
+        * Update the 'clear' indicator displayed on type: 'search' text
+        * fields, hiding it when the field is already empty or when it's not
+        * editable.
+        */
+       mw.widgets.SearchInputWidget.prototype.updateSearchIndicator = function () {
+               if ( this.getValue() === '' || this.isDisabled() || this.isReadOnly() ) {
+                       this.setIndicator( null );
+               } else {
+                       this.setIndicator( 'clear' );
+               }
        };
 
        /**
-        * @inheritdoc OO.ui.mixin.LookupElement
+        * @see OO.ui.SearchInputWidget#onChange
         */
-       mw.widgets.SearchInputWidget.prototype.getLookupRequest = function () {
-               return this.getSuggestionsPromise();
+       mw.widgets.SearchInputWidget.prototype.onChange = function () {
+               mw.widgets.SearchInputWidget.parent.prototype.onChange.call( this );
+               this.updateSearchIndicator();
+       };
+
+       /**
+        * Handle disable events.
+        *
+        * @param {boolean} disabled Element is disabled
+        * @private
+        */
+       mw.widgets.SearchInputWidget.prototype.onDisable = function () {
+               this.updateSearchIndicator();
+       };
+
+       /**
+        * @inheritdoc
+        */
+       mw.widgets.SearchInputWidget.prototype.setReadOnly = function ( state ) {
+               mw.widgets.SearchInputWidget.parent.prototype.setReadOnly.call( this, state );
+               this.updateSearchIndicator();
+               return this;
        };
 
        /**
        };
 
        /**
-        * @inheritdoc OO.ui.mixin.LookupElement
+        * @inheritdoc mw.widgets.TitleInputWidget
         */
        mw.widgets.SearchInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
                var resp;
 
+               // mw.widgets.TitleInputWidget uses response.query, which doesn't exist for opensearch,
+               // so return the whole response (titles only, and links)
                resp = {
                        data: response || {},
                        metadata: {
        };
 
        /**
-        * @inheritdoc OO.ui.mixin.LookupElement
+        * @inheritdoc
         */
-       mw.widgets.SearchInputWidget.prototype.onLookupMenuItemChoose = function ( item ) {
-               this.closeLookupMenu();
-               this.setLookupsDisabled( true );
-               this.setValue( item.getData() );
-               this.setLookupsDisabled( !this.suggestions );
+       mw.widgets.SearchInputWidget.prototype.onLookupMenuItemChoose = function () {
+               mw.widgets.SearchInputWidget.parent.prototype.onLookupMenuItemChoose.apply( this, arguments );
 
                if ( this.performSearchOnClick ) {
                        this.$element.closest( 'form' ).submit();
        };
 
        /**
-        * @inheritdoc OO.ui.mixin.LookupElement
+        * @inheritdoc
         */
-       mw.widgets.SearchInputWidget.prototype.getLookupMenuOptionsFromData = function ( response ) {
-               var items = this.getOptionsFromData( response );
+       mw.widgets.SearchInputWidget.prototype.getLookupMenuOptionsFromData = function () {
+               var items = mw.widgets.SearchInputWidget.parent.prototype.getLookupMenuOptionsFromData.apply(
+                       this, arguments
+               );
 
                this.lastLookupItems = items.map( function ( item ) {
                        return item.data;
                return items;
        };
 
-       /**
-        * @inheritdoc
-        */
-       mw.widgets.SearchInputWidget.prototype.focus = function () {
-               var retval;
-
-               // Prevent programmatic focus from opening the menu
-               this.setLookupsDisabled( true );
-
-               // Parent method
-               retval = mw.widgets.SearchInputWidget.parent.prototype.focus.apply( this, arguments );
-
-               this.setLookupsDisabled( !this.suggestions );
-
-               return retval;
-       };
-
 }( jQuery, mediaWiki ) );