3 * Filter-specific CapsuleMultiselectWidget
6 * @extends OO.ui.CapsuleMultiselectWidget
9 * @param {mw.rcfilters.Controller} controller RCFilters controller
10 * @param {mw.rcfilters.dm.FiltersViewModel} model RCFilters view model
11 * @param {OO.ui.InputWidget} filterInput A filter input that focuses the capsule widget
12 * @param {Object} config Configuration object
13 * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
15 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
= function MwRcfiltersUiFilterCapsuleMultiselectWidget( controller
, model
, filterInput
, config
) {
16 var title
= new OO
.ui
.LabelWidget( {
17 label
: mw
.msg( 'rcfilters-activefilters' ),
18 classes
: [ 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-wrapper-content-title' ]
20 $contentWrapper
= $( '<div>' )
21 .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-wrapper' );
23 this.$overlay
= config
.$overlay
|| this.$element
;
26 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.parent
.call( this, $.extend( true, {
28 $autoCloseIgnore
: filterInput
.$element
.add( this.$overlay
),
29 $floatableContainer
: filterInput
.$element
33 this.controller
= controller
;
35 this.filterInput
= filterInput
;
36 this.isSelecting
= false;
39 this.resetButton
= new OO
.ui
.ButtonWidget( {
41 classes
: [ 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-resetButton' ]
44 this.emptyFilterMessage
= new OO
.ui
.LabelWidget( {
45 label
: mw
.msg( 'rcfilters-empty-filter' ),
46 classes
: [ 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-emptyFilters' ]
48 this.$content
.append( this.emptyFilterMessage
.$element
);
51 this.resetButton
.connect( this, { click
: 'onResetButtonClick' } );
52 this.model
.connect( this, {
53 itemUpdate
: 'onModelItemUpdate',
54 highlightChange
: 'onModelHighlightChange'
56 this.aggregate( { click
: 'capsuleItemClick' } );
58 // Add the filterInput as trigger
59 this.filterInput
.$input
60 .on( 'focus', this.focus
.bind( this ) );
63 $contentWrapper
.append(
66 .addClass( 'mw-rcfilters-ui-table' )
68 // The filter list and button should appear side by side regardless of how
69 // wide the button is; the button also changes its width depending
70 // on language and its state, so the safest way to present both side
71 // by side is with a table layout
73 .addClass( 'mw-rcfilters-ui-row' )
76 .addClass( 'mw-rcfilters-ui-cell' )
77 .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell-filters' ),
79 .addClass( 'mw-rcfilters-ui-cell' )
80 .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell-reset' )
81 .append( this.resetButton
.$element
)
87 this.$handle
.append( $contentWrapper
);
90 .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget' );
92 this.reevaluateResetRestoreState();
97 OO
.inheritClass( mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
, OO
.ui
.CapsuleMultiselectWidget
);
103 * @param {string[]} filters Array of names of removed filters
105 * Filters were removed
111 * Respond to model itemUpdate event
113 * @param {mw.rcfilters.dm.FilterItem} item Filter item model
115 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onModelItemUpdate = function ( item
) {
119 this.model
.isHighlightEnabled() &&
120 item
.isHighlightSupported() &&
121 item
.getHighlightColor()
124 this.addItemByName( item
.getName() );
126 this.removeItemByName( item
.getName() );
129 // Re-evaluate reset state
130 this.reevaluateResetRestoreState();
134 * Respond to highlightChange event
136 * @param {boolean} isHighlightEnabled Highlight is enabled
138 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onModelHighlightChange = function ( isHighlightEnabled
) {
139 var highlightedItems
= this.model
.getHighlightedItems();
141 if ( isHighlightEnabled
) {
142 // Add capsule widgets
143 highlightedItems
.forEach( function ( filterItem
) {
144 this.addItemByName( filterItem
.getName() );
147 // Remove capsule widgets if they're not selected
148 highlightedItems
.forEach( function ( filterItem
) {
149 if ( !filterItem
.isSelected() ) {
150 this.removeItemByName( filterItem
.getName() );
157 * Respond to click event on the reset button
159 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onResetButtonClick = function () {
160 if ( this.model
.areCurrentFiltersEmpty() ) {
161 // Reset to default filters
162 this.controller
.resetToDefaults();
164 // Reset to have no filters
165 this.controller
.emptyFilters();
170 * Reevaluate the restore state for the widget between setting to defaults and clearing all filters
172 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.reevaluateResetRestoreState = function () {
173 var defaultsAreEmpty
= this.model
.areDefaultFiltersEmpty(),
174 currFiltersAreEmpty
= this.model
.areCurrentFiltersEmpty(),
175 hideResetButton
= currFiltersAreEmpty
&& defaultsAreEmpty
;
177 this.resetButton
.setIcon(
178 currFiltersAreEmpty
? 'history' : 'trash'
181 this.resetButton
.setLabel(
182 currFiltersAreEmpty
? mw
.msg( 'rcfilters-restore-default-filters' ) : ''
184 this.resetButton
.setTitle(
185 currFiltersAreEmpty
? null : mw
.msg( 'rcfilters-clear-all-filters' )
188 this.resetButton
.toggle( !hideResetButton
);
189 this.emptyFilterMessage
.toggle( currFiltersAreEmpty
);
193 * Mark an item widget as selected
195 * @param {mw.rcfilters.ui.CapsuleItemWidget} item Capsule widget
197 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.select = function ( item
) {
198 if ( this.selected
!== item
) {
200 if ( this.selected
) {
201 this.selected
.toggleSelected( false );
205 this.selected
= item
;
206 if ( this.selected
) {
207 item
.toggleSelected( true );
213 * Reset selection and remove selected states from all items
215 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.resetSelection = function () {
216 if ( this.selected
!== null ) {
217 this.selected
= null;
218 this.getItems().forEach( function ( capsuleWidget
) {
219 capsuleWidget
.toggleSelected( false );
227 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.createItemWidget = function ( data
) {
228 var item
= this.model
.getItemByName( data
);
234 return new mw
.rcfilters
.ui
.CapsuleItemWidget(
237 { $overlay
: this.$overlay
}
242 * Add items by their filter name
244 * @param {string} name Filter name
246 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.addItemByName = function ( name
) {
247 var item
= this.model
.getItemByName( name
);
253 // Check that the item isn't already added
254 if ( !this.getItemFromData( name
) ) {
255 this.addItems( [ this.createItemWidget( name
) ] );
260 * Remove items by their filter name
262 * @param {string} name Filter name
264 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.removeItemByName = function ( name
) {
265 this.removeItemsFromData( [ name
] );
271 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.focus = function () {
272 // Override this method; we don't want to focus on the popup, and we
273 // don't want to bind the size to the handle.
274 if ( !this.isDisabled() ) {
275 this.popup
.toggle( true );
276 this.filterInput
.$input
.get( 0 ).focus();
284 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onFocusForPopup = function () {
285 // HACK can be removed once I21b8cff4048 is merged in oojs-ui
292 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onKeyDown = function () {};
297 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onPopupFocusOut = function () {};
302 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.clearInput = function () {
303 if ( this.filterInput
) {
304 this.filterInput
.setValue( '' );
306 this.menu
.toggle( false );
307 this.menu
.selectItem();
308 this.menu
.highlightItem();
314 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.removeItems = function ( items
) {
316 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.parent
.prototype.removeItems
.call( this, items
);
318 // Destroy the item widget when it is removed
319 // This is done because we re-add items by recreating them, rather than hiding them
320 // and items include popups, that will just continue to be created and appended
322 items
.forEach( function ( widget
) {
328 * Override 'editItem' since it tries to use $input which does
329 * not exist when a popup is available.
331 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.editItem = function () {};
332 }( mediaWiki
, jQuery
) );