* @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' ]
} ),
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, {
}
}, 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' ]
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 = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-row' )
+ .append(
+ this.$content
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-filters' )
+ );
+
+ if ( areSavedQueriesEnabled ) {
+ rcFiltersRow.append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-save' )
+ .append( this.saveQueryButton.$element )
+ );
+ }
+
+ rcFiltersRow.append(
+ $( '<div>' )
+ .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,
$( '<div>' )
.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
- $( '<div>' )
- .addClass( 'mw-rcfilters-ui-row' )
- .append(
- this.$content
- .addClass( 'mw-rcfilters-ui-cell' )
- .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-filters' ),
- $( '<div>' )
- .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();
};
/* 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
*
} 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( '' );
+ }
}
};
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
*/
* 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
+ );
+ }
};
/**
this.removeTagByData( item.getName() );
}
+ this.setSavedQueryVisibility();
+
// Re-evaluate reset state
this.reevaluateResetRestoreState();
};
*/
mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.isAllowedData = function ( data ) {
return (
- this.menu.getItemFromData( data ) &&
+ this.model.getItemByName( data ) &&
!this.isDuplicateData( data )
);
};
*/
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 );
* @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( {
);
};
- /**
- * 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
*/