X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=resources%2Fsrc%2Fmediawiki.rcfilters%2Fui%2Fmw.rcfilters.ui.FilterTagMultiselectWidget.js;h=268138fbda1f8895ec475815710a7a2a95c4df11;hb=f7e1770fb832aa77bf4e16ce8cc815f2b24dd10d;hp=c52ca1fc2277dac394509efc833b5a3c3c1ffac3;hpb=212f96ec2a4f06becb4a51efe411664bd0abf856;p=lhc%2Fweb%2Fwiklou.git 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 c52ca1fc22..268138fbda 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js @@ -8,11 +8,14 @@ * @constructor * @param {mw.rcfilters.Controller} controller Controller * @param {mw.rcfilters.dm.FiltersViewModel} model View model + * @param {mw.rcfilters.dm.SavedQueriesModel} savedQueriesModel Saved queries model * @param {Object} config Configuration object * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups */ - mw.rcfilters.ui.FilterTagMultiselectWidget = function MwRcfiltersUiFilterTagMultiselectWidget( controller, model, config ) { - var title = new OO.ui.LabelWidget( { + mw.rcfilters.ui.FilterTagMultiselectWidget = function MwRcfiltersUiFilterTagMultiselectWidget( controller, model, savedQueriesModel, config ) { + var rcFiltersRow, + areSavedQueriesEnabled = mw.config.get( 'wgStructuredChangeFiltersEnableSaving' ), + title = new OO.ui.LabelWidget( { label: mw.msg( 'rcfilters-activefilters' ), classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-wrapper-content-title' ] } ), @@ -23,7 +26,10 @@ this.controller = controller; this.model = model; + this.queriesModel = savedQueriesModel; this.$overlay = config.$overlay || this.$element; + this.matchingQuery = null; + this.areSavedQueriesEnabled = areSavedQueriesEnabled; // Parent mw.rcfilters.ui.FilterTagMultiselectWidget.parent.call( this, $.extend( true, { @@ -55,11 +61,30 @@ } }, config ) ); + this.savedQueryTitle = new OO.ui.LabelWidget( { + label: '', + classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-wrapper-content-savedQueryTitle' ] + } ); + this.resetButton = new OO.ui.ButtonWidget( { framed: false, classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-resetButton' ] } ); + if ( areSavedQueriesEnabled ) { + this.saveQueryButton = new mw.rcfilters.ui.SaveFiltersPopupButtonWidget( + this.controller, + this.queriesModel + ); + + this.saveQueryButton.$element.on( 'mousedown', function ( e ) { e.stopPropagation(); } ); + + this.saveQueryButton.connect( this, { + click: 'onSaveQueryButtonClick', + saveCurrent: 'setSavedQueryVisibility' + } ); + } + this.emptyFilterMessage = new OO.ui.LabelWidget( { label: mw.msg( 'rcfilters-empty-filter' ), classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-emptyFilters' ] @@ -73,42 +98,60 @@ this.resetButton.$element.on( 'mousedown', function ( e ) { e.stopPropagation(); } ); this.model.connect( this, { initialize: 'onModelInitialize', + update: 'onModelUpdate', itemUpdate: 'onModelItemUpdate', highlightChange: 'onModelHighlightChange' } ); + this.input.connect( this, { change: 'onInputChange' } ); + this.queriesModel.connect( this, { itemUpdate: 'onSavedQueriesItemUpdate' } ); + + // The filter list and button should appear side by side regardless of how + // wide the button is; the button also changes its width depending + // on language and its state, so the safest way to present both side + // by side is with a table layout + rcFiltersRow = $( '
' ) + .addClass( 'mw-rcfilters-ui-row' ) + .append( + this.$content + .addClass( 'mw-rcfilters-ui-cell' ) + .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-filters' ) + ); + + if ( areSavedQueriesEnabled ) { + rcFiltersRow.append( + $( '
' ) + .addClass( 'mw-rcfilters-ui-cell' ) + .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-save' ) + .append( this.saveQueryButton.$element ) + ); + } + + rcFiltersRow.append( + $( '
' ) + .addClass( 'mw-rcfilters-ui-cell' ) + .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-reset' ) + .append( this.resetButton.$element ) + ); // Build the content $contentWrapper.append( title.$element, + this.savedQueryTitle.$element, $( '
' ) .addClass( 'mw-rcfilters-ui-table' ) .append( - // The filter list and button should appear side by side regardless of how - // wide the button is; the button also changes its width depending - // on language and its state, so the safest way to present both side - // by side is with a table layout - $( '
' ) - .addClass( 'mw-rcfilters-ui-row' ) - .append( - this.$content - .addClass( 'mw-rcfilters-ui-cell' ) - .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-filters' ), - $( '
' ) - .addClass( 'mw-rcfilters-ui-cell' ) - .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-reset' ) - .append( this.resetButton.$element ) - ) + rcFiltersRow ) ); // Initialize this.$handle.append( $contentWrapper ); this.emptyFilterMessage.toggle( this.isEmpty() ); + this.savedQueryTitle.toggle( false ); this.$element .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget' ); - this.populateFromModel(); this.reevaluateResetRestoreState(); }; @@ -118,6 +161,36 @@ /* Methods */ + /** + * Respond to input change event + * + * @param {string} value Value of the input + */ + mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onInputChange = function ( value ) { + var view = this.model.getViewByTrigger( value.substr( 0, 1 ) ); + + this.controller.switchView( view ); + }; + /** + * Respond to query button click + */ + mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onSaveQueryButtonClick = function () { + this.getMenu().toggle( false ); + }; + + /** + * Respond to save query item change. Mainly this is done to update the label in case + * a query item has been edited + * + * @param {mw.rcfilters.dm.SavedQueryItemModel} item Saved query item + */ + mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onSavedQueriesItemUpdate = function ( item ) { + if ( this.matchingQuery === item ) { + // This means we just edited the item that is currently matched + this.savedQueryTitle.setLabel( item.getLabel() ); + } + }; + /** * Respond to menu toggle * @@ -139,6 +212,14 @@ } else { // Clear selection this.selectTag( null ); + + // Clear input if the only thing in the input is the prefix + if ( + this.input.getValue() === this.model.getViewTrigger( this.model.getCurrentView() ) + ) { + // Clear the input + this.input.setValue( '' ); + } } }; @@ -153,6 +234,17 @@ this.scrollToTop( this.$element ); }; + /** + * @inheritdoc + */ + mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.doInputEscape = function () { + // Parent + mw.rcfilters.ui.FilterTagMultiselectWidget.parent.prototype.doInputEscape.call( this ); + + // Blur the input + this.input.$input.blur(); + }; + /** * @inheridoc */ @@ -167,7 +259,54 @@ * Respond to model initialize event */ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onModelInitialize = function () { - this.populateFromModel(); + this.setSavedQueryVisibility(); + }; + + /** + * Respond to model update event + */ + mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onModelUpdate = function () { + this.updateElementsForView(); + }; + + /** + * Update the elements in the widget to the current view + */ + mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.updateElementsForView = function () { + var view = this.model.getCurrentView(), + inputValue = this.input.getValue(), + inputView = this.model.getViewByTrigger( inputValue.substr( 0, 1 ) ); + + if ( inputView !== 'default' ) { + // We have a prefix already, remove it + inputValue = inputValue.substr( 1 ); + } + + if ( inputView !== view ) { + // Add the correct prefix + inputValue = this.model.getViewTrigger( view ) + inputValue; + } + + // Update input + this.input.setValue( inputValue ); + }; + + /** + * Set the visibility of the saved query button + */ + mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.setSavedQueryVisibility = function () { + if ( this.areSavedQueriesEnabled ) { + this.matchingQuery = this.controller.findQueryMatchingCurrentState(); + + this.savedQueryTitle.setLabel( + this.matchingQuery ? this.matchingQuery.getLabel() : '' + ); + this.savedQueryTitle.toggle( !!this.matchingQuery ); + this.saveQueryButton.toggle( + !this.isEmpty() && + !this.matchingQuery + ); + } }; /** @@ -189,6 +328,8 @@ this.removeTagByData( item.getName() ); } + this.setSavedQueryVisibility(); + // Re-evaluate reset state this.reevaluateResetRestoreState(); }; @@ -198,7 +339,7 @@ */ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.isAllowedData = function ( data ) { return ( - this.menu.getItemFromData( data ) && + this.model.getItemByName( data ) && !this.isDuplicateData( data ) ); }; @@ -243,12 +384,15 @@ */ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onTagSelect = function ( tagItem ) { var widget = this, - menuOption = this.menu.getItemFromData( tagItem.getData() ), + menuOption = this.menu.getItemFromModel( tagItem.getModel() ), oldInputValue = this.input.getValue(); // Reset input this.input.setValue( '' ); + // Switch view + this.controller.switchView( tagItem.getView() ); + // Parent method mw.rcfilters.ui.FilterTagMultiselectWidget.parent.prototype.onTagSelect.call( this, tagItem ); @@ -339,7 +483,7 @@ * @inheritdoc */ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.createMenuWidget = function ( menuConfig ) { - return new mw.rcfilters.ui.FloatingMenuSelectWidget( + return new mw.rcfilters.ui.MenuSelectWidget( this.controller, this.model, $.extend( { @@ -348,46 +492,6 @@ ); }; - /** - * Populate the menu from the model - */ - mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.populateFromModel = function () { - var widget = this, - items = []; - - // Reset - this.getMenu().clearItems(); - - $.each( this.model.getFilterGroups(), function ( groupName, groupModel ) { - items.push( - // Group section - new mw.rcfilters.ui.FilterMenuSectionOptionWidget( - widget.controller, - groupModel, - { - $overlay: widget.$overlay - } - ) - ); - - // Add items - widget.model.getGroupFilters( groupName ).forEach( function ( filterItem ) { - items.push( - new mw.rcfilters.ui.FilterMenuOptionWidget( - widget.controller, - filterItem, - { - $overlay: widget.$overlay - } - ) - ); - } ); - } ); - - // Add all items to the menu - this.getMenu().addItems( items ); - }; - /** * @inheritdoc */