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
14 * @cfg {number} [topScrollOffset=10] When scrolling the entire widget to the top, leave this
15 * much space (in pixels) above the widget.
17 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
= function MwRcfiltersUiFilterCapsuleMultiselectWidget( controller
, model
, filterInput
, config
) {
18 var title
= new OO
.ui
.LabelWidget( {
19 label
: mw
.msg( 'rcfilters-activefilters' ),
20 classes
: [ 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-wrapper-content-title' ]
22 $contentWrapper
= $( '<div>' )
23 .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-wrapper' );
25 this.$overlay
= config
.$overlay
|| this.$element
;
28 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.parent
.call( this, $.extend( true, {
29 popup
: { $autoCloseIgnore
: filterInput
.$element
.add( this.$overlay
) }
32 this.controller
= controller
;
34 this.filterInput
= filterInput
;
36 this.topScrollOffset
= config
.topScrollOffset
|| 10;
38 this.resetButton
= new OO
.ui
.ButtonWidget( {
41 title
: mw
.msg( 'rcfilters-clear-all-filters' ),
42 classes
: [ 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-resetButton' ]
45 this.emptyFilterMessage
= new OO
.ui
.LabelWidget( {
46 label
: mw
.msg( 'rcfilters-empty-filter' ),
47 classes
: [ 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-emptyFilters' ]
49 this.$content
.append( this.emptyFilterMessage
.$element
);
52 this.resetButton
.connect( this, { click
: 'onResetButtonClick' } );
53 this.model
.connect( this, {
54 itemUpdate
: 'onModelItemUpdate',
55 highlightChange
: 'onModelHighlightChange'
57 this.popup
.connect( this, { toggle
: 'onPopupToggle' } );
59 // Add the filterInput as trigger
60 this.filterInput
.$input
61 .on( 'focus', this.focus
.bind( this ) );
64 $contentWrapper
.append(
67 .addClass( 'mw-rcfilters-ui-table' )
69 // The filter list and button should appear side by side regardless of how
70 // wide the button is; the button also changes its width depending
71 // on language and its state, so the safest way to present both side
72 // by side is with a table layout
74 .addClass( 'mw-rcfilters-ui-row' )
77 .addClass( 'mw-rcfilters-ui-cell' )
78 .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell-filters' ),
80 .addClass( 'mw-rcfilters-ui-cell' )
81 .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell-reset' )
82 .append( this.resetButton
.$element
)
88 this.$handle
.append( $contentWrapper
);
91 .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget' );
93 this.reevaluateResetRestoreState();
98 OO
.inheritClass( mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
, OO
.ui
.CapsuleMultiselectWidget
);
104 * @param {string[]} filters Array of names of removed filters
106 * Filters were removed
112 * Respond to model itemUpdate event
114 * @param {mw.rcfilters.dm.FilterItem} item Filter item model
116 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onModelItemUpdate = function ( item
) {
120 this.model
.isHighlightEnabled() &&
121 item
.isHighlightSupported() &&
122 item
.getHighlightColor()
125 this.addItemByName( item
.getName() );
127 this.removeItemByName( item
.getName() );
130 // Re-evaluate reset state
131 this.reevaluateResetRestoreState();
135 * Respond to highlightChange event
137 * @param {boolean} isHighlightEnabled Highlight is enabled
139 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onModelHighlightChange = function ( isHighlightEnabled
) {
140 var highlightedItems
= this.model
.getHighlightedItems();
142 if ( isHighlightEnabled
) {
143 // Add capsule widgets
144 highlightedItems
.forEach( function ( filterItem
) {
145 this.addItemByName( filterItem
.getName() );
148 // Remove capsule widgets if they're not selected
149 highlightedItems
.forEach( function ( filterItem
) {
150 if ( !filterItem
.isSelected() ) {
151 this.removeItemByName( filterItem
.getName() );
158 * Respond to click event on the reset button
160 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onResetButtonClick = function () {
161 if ( this.model
.areCurrentFiltersEmpty() ) {
162 // Reset to default filters
163 this.controller
.resetToDefaults();
165 // Reset to have no filters
166 this.controller
.emptyFilters();
171 * Respond to popup toggle event
173 * @param {boolean} isVisible Popup is visible
175 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onPopupToggle = function ( isVisible
) {
182 * Scroll the capsule to the top of the screen
184 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.scrollToTop = function () {
185 var container
= OO
.ui
.Element
.static.getClosestScrollableContainer( this.$element
[ 0 ], 'y' );
187 $( container
).animate( {
188 scrollTop
: this.$element
.offset().top
- this.topScrollOffset
193 * Reevaluate the restore state for the widget between setting to defaults and clearing all filters
195 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.reevaluateResetRestoreState = function () {
196 var defaultsAreEmpty
= this.model
.areDefaultFiltersEmpty(),
197 currFiltersAreEmpty
= this.model
.areCurrentFiltersEmpty(),
198 hideResetButton
= currFiltersAreEmpty
&& defaultsAreEmpty
;
200 this.resetButton
.setIcon(
201 currFiltersAreEmpty
? 'history' : 'trash'
204 this.resetButton
.setLabel(
205 currFiltersAreEmpty
? mw
.msg( 'rcfilters-restore-default-filters' ) : ''
208 this.resetButton
.toggle( !hideResetButton
);
209 this.emptyFilterMessage
.toggle( currFiltersAreEmpty
);
215 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.createItemWidget = function ( data
) {
216 var item
= this.model
.getItemByName( data
);
222 return new mw
.rcfilters
.ui
.CapsuleItemWidget(
225 { $overlay
: this.$overlay
}
230 * Add items by their filter name
232 * @param {string} name Filter name
234 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.addItemByName = function ( name
) {
235 var item
= this.model
.getItemByName( name
);
241 // Check that the item isn't already added
242 if ( !this.getItemFromData( name
) ) {
243 this.addItems( [ this.createItemWidget( name
) ] );
248 * Remove items by their filter name
250 * @param {string} name Filter name
252 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.removeItemByName = function ( name
) {
253 this.removeItemsFromData( [ name
] );
259 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.focus = function () {
260 // Override this method; we don't want to focus on the popup, and we
261 // don't want to bind the size to the handle.
262 if ( !this.isDisabled() ) {
263 this.popup
.toggle( true );
264 this.filterInput
.$input
.get( 0 ).focus();
272 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onFocusForPopup = function () {
273 // HACK can be removed once I21b8cff4048 is merged in oojs-ui
280 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onKeyDown = function () {};
285 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.onPopupFocusOut = function () {};
290 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.clearInput = function () {
291 if ( this.filterInput
) {
292 this.filterInput
.setValue( '' );
294 this.menu
.toggle( false );
295 this.menu
.selectItem();
296 this.menu
.highlightItem();
302 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.removeItems = function ( items
) {
304 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.parent
.prototype.removeItems
.call( this, items
);
306 // Destroy the item widget when it is removed
307 // This is done because we re-add items by recreating them, rather than hiding them
308 // and items include popups, that will just continue to be created and appended
310 items
.forEach( function ( widget
) {
316 * Override 'editItem' since it tries to use $input which does
317 * not exist when a popup is available.
319 mw
.rcfilters
.ui
.FilterCapsuleMultiselectWidget
.prototype.editItem = function () {};
320 }( mediaWiki
, jQuery
) );