From 95667ea4e141b6dcd5b1c943ce12e03a09717d6f Mon Sep 17 00:00:00 2001 From: Moriel Schottlender Date: Mon, 18 Dec 2017 18:25:34 -0800 Subject: [PATCH] RCFilters: Create one single source of truth for item display Synchronize the search input, filter view and all view selection into a single source of truth through the model. - Stop using OO.ui.MenuSelectWidget's internal filtering logic, and use our own filtering logic in the model instead. - Add a concept of 'search' to the model, that is synchronized with the current search term of the systme. The search dictates the view and the visible items in the filters. -- Whenever the search changes for whatever reason, the model automatically updates the visibility of all items and groups in the filter list. -- This means that after changing view or search, the widgets can always trust that they have the most updated visible item list to scroll to or select. - Make the view model's findMatches as the ultimate source of truth as to what should be visible. The items are now **always** all included in the menu, but they change their visibility according to the logic in the findMatches. If there is a search term, the function will account for that and the selected view, so we can be sure that search results also change between changing views. This allows us to simplify the operation of selecting a tag, where we know that the order of operation is bound to switching the views, that will also show us the relevant results. We can bind to the display event and properly select -- and scroll to -- the item. Bug: T182720 Bug: T178540 Change-Id: If575f348705d863b9d68d19761ded55a4d453550 --- .../dm/mw.rcfilters.dm.FilterGroup.js | 36 ++++++ .../dm/mw.rcfilters.dm.FilterItem.js | 26 +++++ .../dm/mw.rcfilters.dm.FiltersViewModel.js | 106 +++++++++++++----- .../mw.rcfilters.Controller.js | 45 ++++++-- .../mw.rcfilters.ui.MenuSelectWidget.less | 5 - .../mw.rcfilters.ui.FilterMenuHeaderWidget.js | 16 ++- ...ilters.ui.FilterMenuSectionOptionWidget.js | 6 +- ...rcfilters.ui.FilterTagMultiselectWidget.js | 69 ++++-------- .../mw.rcfilters.ui.ItemMenuOptionWidget.js | 3 + .../ui/mw.rcfilters.ui.MenuSelectWidget.js | 85 +++++--------- 10 files changed, 241 insertions(+), 156 deletions(-) diff --git a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js index f4cdae3a6c..bb29b36191 100644 --- a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js +++ b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js @@ -34,6 +34,7 @@ * @cfg {string} [whatsThis.body] The body of the whatsThis popup message * @cfg {string} [whatsThis.url] The url for the link in the whatsThis popup message * @cfg {string} [whatsThis.linkMessage] The text for the link in the whatsThis popup message + * @cfg {boolean} [visible=true] The visibility of the group */ mw.rcfilters.dm.FilterGroup = function MwRcfiltersDmFilterGroup( name, config ) { config = config || {}; @@ -52,6 +53,7 @@ this.numericRange = config.range; this.separator = config.separator || '|'; this.labelPrefixKey = config.labelPrefixKey; + this.visible = config.visible === undefined ? true : !!config.visible; this.currSelected = null; this.active = !!config.active; @@ -944,4 +946,38 @@ return value; }; + + /** + * Toggle the visibility of this group + * + * @param {boolean} [isVisible] Item is visible + */ + mw.rcfilters.dm.FilterGroup.prototype.toggleVisible = function ( isVisible ) { + isVisible = isVisible === undefined ? !this.visible : isVisible; + + if ( this.visible !== isVisible ) { + this.visible = isVisible; + this.emit( 'update' ); + } + }; + + /** + * Check whether the group is visible + * + * @return {boolean} Group is visible + */ + mw.rcfilters.dm.FilterGroup.prototype.isVisible = function () { + return this.visible; + }; + + /** + * Set the visibility of the items under this group by the given items array + * + * @param {mw.rcfilters.dm.ItemModel[]} visibleItems An array of visible items + */ + mw.rcfilters.dm.FilterGroup.prototype.setVisibleItems = function ( visibleItems ) { + this.getItems().forEach( function ( itemModel ) { + itemModel.toggleVisible( visibleItems.indexOf( itemModel ) !== -1 ); + } ); + }; }( mediaWiki ) ); diff --git a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js index 4e2079dc40..682a937679 100644 --- a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js +++ b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js @@ -12,6 +12,7 @@ * selected, makes inactive. * @cfg {string[]} [subset] Defining the names of filters that are a subset of this filter * @cfg {Object} [conflicts] Defines the conflicts for this filter + * @cfg {boolean} [visible=true] The visibility of the group */ mw.rcfilters.dm.FilterItem = function MwRcfiltersDmFilterItem( param, groupModel, config ) { config = config || {}; @@ -29,6 +30,7 @@ this.subset = config.subset || []; this.conflicts = config.conflicts || {}; this.superset = []; + this.visible = config.visible === undefined ? true : !!config.visible; // Interaction states this.included = false; @@ -369,4 +371,28 @@ this.emit( 'update' ); } }; + + /** + * Toggle the visibility of this item + * + * @param {boolean} [isVisible] Item is visible + */ + mw.rcfilters.dm.FilterItem.prototype.toggleVisible = function ( isVisible ) { + isVisible = isVisible === undefined ? !this.visible : !!isVisible; + + if ( this.visible !== isVisible ) { + this.visible = isVisible; + this.emit( 'update' ); + } + }; + + /** + * Check whether the item is visible + * + * @return {boolean} Item is visible + */ + mw.rcfilters.dm.FilterItem.prototype.isVisible = function () { + return this.visible; + }; + }( mediaWiki ) ); diff --git a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js index 8d22c23e1a..b690bbd4a0 100644 --- a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js +++ b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js @@ -20,6 +20,7 @@ this.views = {}; this.currentView = 'default'; + this.searchQuery = null; // Events this.aggregate( { update: 'filterItemUpdate' } ); @@ -401,7 +402,7 @@ } } ); - this.currentView = 'default'; + this.setSearch( '' ); this.updateHighlightedState(); @@ -1095,19 +1096,6 @@ return allSelected; }; - /** - * Switch the current view - * - * @param {string} view View name - * @fires update - */ - mw.rcfilters.dm.FiltersViewModel.prototype.switchView = function ( view ) { - if ( this.views[ view ] && this.currentView !== view ) { - this.currentView = view; - this.emit( 'update' ); - } - }; - /** * Get the current view * @@ -1147,6 +1135,82 @@ return result; }; + /** + * Return a version of the given string that is without any + * view triggers. + * + * @param {string} str Given string + * @return {string} Result + */ + mw.rcfilters.dm.FiltersViewModel.prototype.removeViewTriggers = function ( str ) { + if ( this.getViewFromString( str ) !== 'default' ) { + str = str.substr( 1 ); + } + + return str; + }; + + /** + * Get the view from the given string by a trigger, if it exists + * + * @param {string} str Given string + * @return {string} View name + */ + mw.rcfilters.dm.FiltersViewModel.prototype.getViewFromString = function ( str ) { + return this.getViewByTrigger( str.substr( 0, 1 ) ); + }; + + /** + * Set the current search for the system. + * This also dictates what items and groups are visible according + * to the search in #findMatches + * + * @param {string} searchQuery Search query, including triggers + * @fires searchChange + */ + mw.rcfilters.dm.FiltersViewModel.prototype.setSearch = function ( searchQuery ) { + var visibleGroups, visibleGroupNames; + + if ( this.searchQuery !== searchQuery ) { + // Check if the view changed + this.switchView( this.getViewFromString( searchQuery ) ); + + visibleGroups = this.findMatches( searchQuery ); + visibleGroupNames = Object.keys( visibleGroups ); + + // Update visibility of items and groups + $.each( this.getFilterGroups(), function ( groupName, groupModel ) { + // Check if the group is visible at all + groupModel.toggleVisible( visibleGroupNames.indexOf( groupName ) !== -1 ); + groupModel.setVisibleItems( visibleGroups[ groupName ] || [] ); + } ); + + this.searchQuery = searchQuery; + this.emit( 'searchChange', this.searchQuery ); + } + }; + + /** + * Get the current search + * + * @return {string} Current search query + */ + mw.rcfilters.dm.FiltersViewModel.prototype.getSearch = function () { + return this.searchQuery; + }; + + /** + * Switch the current view + * + * @private + * @param {string} view View name + */ + mw.rcfilters.dm.FiltersViewModel.prototype.switchView = function ( view ) { + if ( this.views[ view ] && this.currentView !== view ) { + this.currentView = view; + } + }; + /** * Toggle the highlight feature on and off. * Propagate the change to filter items. @@ -1209,18 +1273,4 @@ this.getItemByName( filterName ).clearHighlightColor(); }; - /** - * Return a version of the given string that is without any - * view triggers. - * - * @param {string} str Given string - * @return {string} Result - */ - mw.rcfilters.dm.FiltersViewModel.prototype.removeViewTriggers = function ( str ) { - if ( this.getViewByTrigger( str.substr( 0, 1 ) ) !== 'default' ) { - str = str.substr( 1 ); - } - - return str; - }; }( mediaWiki, jQuery ) ); diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js index 79546b46d4..cec570c627 100644 --- a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js +++ b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js @@ -405,15 +405,6 @@ } ); }; - /** - * Switch the view of the filters model - * - * @param {string} view Requested view - */ - mw.rcfilters.Controller.prototype.switchView = function ( view ) { - this.filtersModel.switchView( view ); - }; - /** * Reset to default filters */ @@ -1169,4 +1160,40 @@ this.updateChangesList( null, 'markSeen' ); }.bind( this ) ); }; + + /** + * Set the current search for the system. + * + * @param {string} searchQuery Search query, including triggers + */ + mw.rcfilters.Controller.prototype.setSearch = function ( searchQuery ) { + this.filtersModel.setSearch( searchQuery ); + }; + + /** + * Switch the view by changing the search query trigger + * without changing the search term + * + * @param {string} view View to change to + */ + mw.rcfilters.Controller.prototype.switchView = function ( view ) { + this.setSearch( + this.filtersModel.getViewTrigger( view ) + + this.filtersModel.removeViewTriggers( this.filtersModel.getSearch() ) + ); + }; + + /** + * Reset the search for a specific view. This means we null the search query + * and replace it with the relevant trigger for the requested view + * + * @param {string} [view='default'] View to change to + */ + mw.rcfilters.Controller.prototype.resetSearchForView = function ( view ) { + view = view || 'default'; + + this.setSearch( + this.filtersModel.getViewTrigger( view ) + ); + }; }( mediaWiki, jQuery ) ); diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less index 7dd78e78b9..0906d6811b 100644 --- a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less +++ b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less @@ -10,13 +10,8 @@ } &-noresults { - display: none; padding: 0.5em; color: @colorGray5; - - .oo-ui-menuSelectWidget-invisible & { - display: inline-block; - } } &-body { diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js index dceb132038..c047e83433 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js @@ -68,9 +68,10 @@ .connect( this, { click: 'onInvertNamespacesButtonClick' } ); this.model.connect( this, { highlightChange: 'onModelHighlightChange', - update: 'onModelUpdate', + searchChange: 'onModelSearchChange', initialize: 'onModelInitialize' } ); + this.view = this.model.getCurrentView(); // Initialize this.$element @@ -127,14 +128,17 @@ /** * Respond to model update event */ - mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onModelUpdate = function () { + mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onModelSearchChange = function () { var currentView = this.model.getCurrentView(); - this.setLabel( this.model.getViewTitle( currentView ) ); + if ( this.view !== currentView ) { + this.setLabel( this.model.getViewTitle( currentView ) ); - this.invertNamespacesButton.toggle( currentView === 'namespaces' ); - this.backButton.toggle( currentView !== 'default' ); - this.helpIcon.toggle( currentView === 'tags' ); + this.invertNamespacesButton.toggle( currentView === 'namespaces' ); + this.backButton.toggle( currentView !== 'default' ); + this.helpIcon.toggle( currentView === 'tags' ); + this.view = currentView; + } }; /** diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuSectionOptionWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuSectionOptionWidget.js index e053914e2a..20bf73ff16 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuSectionOptionWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuSectionOptionWidget.js @@ -86,13 +86,14 @@ } // Events - this.model.connect( this, { update: 'onModelUpdate' } ); + this.model.connect( this, { update: 'updateUiBasedOnState' } ); // Initialize this.$element .addClass( 'mw-rcfilters-ui-filterMenuSectionOptionWidget' ) .addClass( 'mw-rcfilters-ui-filterMenuSectionOptionWidget-name-' + this.model.getName() ) .append( $header ); + this.updateUiBasedOnState(); }; /* Initialize */ @@ -104,11 +105,12 @@ /** * Respond to model update event */ - mw.rcfilters.ui.FilterMenuSectionOptionWidget.prototype.onModelUpdate = function () { + mw.rcfilters.ui.FilterMenuSectionOptionWidget.prototype.updateUiBasedOnState = function () { this.$element.toggleClass( 'mw-rcfilters-ui-filterMenuSectionOptionWidget-active', this.model.isActive() ); + this.toggle( this.model.isVisible() ); }; /** diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js index 91a2d5fbbf..3f47df2ee4 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js @@ -41,6 +41,8 @@ allowReordering: false, $overlay: this.$overlay, menu: { + // Our filtering is done through the model + filterFromInput: false, hideWhenOutOfView: false, hideOnChoose: false, width: 650, @@ -121,6 +123,7 @@ this.model.connect( this, { initialize: 'onModelInitialize', update: 'onModelUpdate', + searchChange: 'onModelSearchChange', itemUpdate: 'onModelItemUpdate', highlightChange: 'onModelHighlightChange' } ); @@ -237,20 +240,24 @@ this.focus(); }; + /** + * Respond to model search change event + * + * @param {string} value Search value + */ + mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onModelSearchChange = function ( value ) { + this.input.setValue( value ); + }; + /** * Respond to input change event * * @param {string} value Value of the input */ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onInputChange = function ( value ) { - var view; - - value = value.trim(); - - view = this.model.getViewByTrigger( value.substr( 0, 1 ) ); - - this.controller.switchView( view ); + this.controller.setSearch( value ); }; + /** * Respond to query button click */ @@ -304,13 +311,8 @@ // Clear selection this.selectTag( null ); - // Clear input if the only thing in the input is the prefix - if ( - this.input.getValue().trim() === this.model.getViewTrigger( this.model.getCurrentView() ) - ) { - // Clear the input - this.input.setValue( '' ); - } + // Clear the search + this.controller.setSearch( '' ); // Log filter grouping this.controller.trackFilterGroupings( 'filtermenu' ); @@ -508,42 +510,19 @@ * @inheritdoc */ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onTagSelect = function ( tagItem ) { - var widget = this, - menuOption = this.menu.getItemFromModel( tagItem.getModel() ), - oldInputValue = this.input.getValue().trim(); + var menuOption = this.menu.getItemFromModel( tagItem.getModel() ); this.menu.setUserSelecting( true ); - - // Reset input - this.input.setValue( '' ); - - // Switch view - this.controller.switchView( tagItem.getView() ); - // Parent method mw.rcfilters.ui.FilterTagMultiselectWidget.parent.prototype.onTagSelect.call( this, tagItem ); - this.menu.selectItem( menuOption ); - this.selectTag( tagItem ); + // Switch view + this.controller.resetSearchForView( tagItem.getView() ); - // Scroll to the item - if ( this.model.removeViewTriggers( oldInputValue ) ) { - // We're binding a 'once' to the itemVisibilityChange event - // so this happens when the menu is ready after the items - // are visible again, in case this is done right after the - // user filtered the results - this.getMenu().once( - 'itemVisibilityChange', - function () { - widget.scrollToTop( menuOption.$element ); - widget.menu.setUserSelecting( false ); - } - ); - } else { - this.scrollToTop( menuOption.$element ); - this.menu.setUserSelecting( false ); - } + this.selectTag( tagItem ); + this.scrollToTop( menuOption.$element ); + this.menu.setUserSelecting( false ); }; /** @@ -618,9 +597,7 @@ return new mw.rcfilters.ui.MenuSelectWidget( this.controller, this.model, - $.extend( { - filterFromInput: true - }, menuConfig ) + menuConfig ); }; diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ItemMenuOptionWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ItemMenuOptionWidget.js index 51fc9bcaba..15085105f0 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ItemMenuOptionWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ItemMenuOptionWidget.js @@ -117,6 +117,8 @@ this.$element.addClass( classes.join( ' ' ) ); } + + this.updateUiBasedOnState(); }; /* Initialization */ @@ -142,6 +144,7 @@ this.itemModel.isSelected() && this.invertModel.isSelected() ); + this.toggle( this.itemModel.isVisible() ); }; /** diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js index 98acab050c..07d8c88430 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js @@ -33,7 +33,6 @@ this.userSelecting = false; this.menuInitialized = false; - this.inputValue = ''; this.$overlay = config.$overlay || this.$element; this.$body = $( '
' ).addClass( 'mw-rcfilters-ui-menuSelectWidget-body' ); this.footers = []; @@ -41,7 +40,9 @@ // Parent mw.rcfilters.ui.MenuSelectWidget.parent.call( this, $.extend( { $autoCloseIgnore: this.$overlay, - width: 650 + width: 650, + // Our filtering is done through the model + filterFromInput: false }, config ) ); this.setGroupElement( $( '
' ) @@ -65,8 +66,8 @@ // Events this.model.connect( this, { - update: 'onModelUpdate', - initialize: 'onModelInitialize' + initialize: 'onModelInitialize', + searchChange: 'onModelSearchChange' } ); // Initialization @@ -104,7 +105,7 @@ }.bind( this ) ); // Switch to the correct view - this.switchView( this.model.getCurrentView() ); + this.updateView(); }; /* Initialize */ @@ -113,20 +114,9 @@ /* Events */ - /** - * @event itemVisibilityChange - * - * Item visibility has changed - */ - /* Methods */ - - /** - * Respond to model update event - */ - mw.rcfilters.ui.MenuSelectWidget.prototype.onModelUpdate = function () { - // Change view - this.switchView( this.model.getCurrentView() ); + mw.rcfilters.ui.MenuSelectWidget.prototype.onModelSearchChange = function () { + this.updateView(); }; /** @@ -144,6 +134,7 @@ */ mw.rcfilters.ui.MenuSelectWidget.prototype.lazyMenuCreation = function () { var widget = this, + items = [], viewGroupCount = {}, groups = this.model.getFilterGroups(); @@ -152,8 +143,6 @@ } this.menuInitialized = true; - // Reset - this.clearItems(); // Count groups per view $.each( groups, function ( groupName, groupModel ) { @@ -202,10 +191,12 @@ // without rebuilding the widgets each time widget.views[ view ] = widget.views[ view ] || []; widget.views[ view ] = widget.views[ view ].concat( currentItems ); + items = items.concat( currentItems ); } } ); - this.switchView( this.model.getCurrentView() ); + this.addItems( items ); + this.updateView(); }; /** @@ -216,16 +207,12 @@ }; /** - * Switch view - * - * @param {string} [viewName] View name. If not given, default is used. + * Update view */ - mw.rcfilters.ui.MenuSelectWidget.prototype.switchView = function ( viewName ) { - viewName = viewName || 'default'; + mw.rcfilters.ui.MenuSelectWidget.prototype.updateView = function () { + var viewName = this.model.getCurrentView(); if ( this.views[ viewName ] && this.currentView !== viewName ) { - this.clearItems(); - this.addItems( this.views[ viewName ] ); this.updateFooterVisibility( viewName ); this.$element @@ -235,8 +222,10 @@ this.currentView = viewName; this.scrollToTop(); - this.clip(); } + + this.postProcessItems(); + this.clip(); }; /** @@ -258,24 +247,18 @@ }; /** - * @fires itemVisibilityChange - * @inheritdoc + * Post-process items after the visibility changed. Make sure + * that we always have an item selected, and that the no-results + * widget appears if the menu is empty. */ - mw.rcfilters.ui.MenuSelectWidget.prototype.updateItemVisibility = function () { + mw.rcfilters.ui.MenuSelectWidget.prototype.postProcessItems = function () { var i, itemWasSelected = false, - inputVal = this.$input.val(), items = this.getItems(); - // Since the method hides/shows items, we don't want to - // call it unless the input actually changed - if ( - !this.userSelecting && - this.inputValue !== inputVal - ) { - // Parent method - mw.rcfilters.ui.MenuSelectWidget.parent.prototype.updateItemVisibility.call( this ); - + // If we are not already selecting an item, always make sure + // that the top item is selected + if ( !this.userSelecting ) { // Select the first item in the list for ( i = 0; i < items.length; i++ ) { if ( @@ -291,11 +274,6 @@ if ( !itemWasSelected ) { this.selectItem( null ); } - - // Cache value - this.inputValue = inputVal; - - this.emit( 'itemVisibilityChange' ); } this.noResults.toggle( !this.getItems().some( function ( item ) { @@ -316,19 +294,6 @@ } )[ 0 ]; }; - /** - * Override the item matcher to use the model's match process - * - * @inheritdoc - */ - mw.rcfilters.ui.MenuSelectWidget.prototype.getItemMatcher = function ( s ) { - var results = this.model.findMatches( s, true ); - - return function ( item ) { - return results.indexOf( item.getModel() ) > -1; - }; - }; - /** * @inheritdoc */ -- 2.20.1