( function ( mw ) { /** * List of changes * * @extends OO.ui.Widget * * @constructor * @param {mw.rcfilters.dm.FiltersViewModel} filtersViewModel View model * @param {mw.rcfilters.dm.ChangesListViewModel} changesListViewModel View model * @param {mw.rcfilters.Controller} controller * @param {jQuery} $changesListRoot Root element of the changes list to attach to * @param {Object} [config] Configuration object */ mw.rcfilters.ui.ChangesListWrapperWidget = function MwRcfiltersUiChangesListWrapperWidget( filtersViewModel, changesListViewModel, controller, $changesListRoot, config ) { config = $.extend( {}, config, { $element: $changesListRoot } ); // Parent mw.rcfilters.ui.ChangesListWrapperWidget.parent.call( this, config ); this.filtersViewModel = filtersViewModel; this.changesListViewModel = changesListViewModel; this.controller = controller; this.highlightClasses = null; this.filtersModelInitialized = false; // Events this.filtersViewModel.connect( this, { itemUpdate: 'onItemUpdate', highlightChange: 'onHighlightChange', initialize: 'onFiltersModelInitialize' } ); this.changesListViewModel.connect( this, { invalidate: 'onModelInvalidate', update: 'onModelUpdate' } ); this.$element .addClass( 'mw-rcfilters-ui-changesListWrapperWidget' ) // We handle our own display/hide of the empty results message // We keep the timeout class here and remove it later, since at this // stage it is still needed to identify that the timeout occurred. .removeClass( 'mw-changeslist-empty' ); }; /* Initialization */ OO.inheritClass( mw.rcfilters.ui.ChangesListWrapperWidget, OO.ui.Widget ); /** * Respond to filters model initialize event */ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onFiltersModelInitialize = function () { this.filtersModelInitialized = true; // Set up highlight containers. We need to wait for the filters model // to be initialized, so we can make sure we have all the css class definitions // we get from the server with our filters this.setupHighlightContainers( this.$element ); }; /** * Get all available highlight classes * * @return {string[]} An array of available highlight class names */ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.getHighlightClasses = function () { if ( !this.highlightClasses || !this.highlightClasses.length ) { this.highlightClasses = this.filtersViewModel.getItemsSupportingHighlights() .map( function ( filterItem ) { return filterItem.getCssClass(); } ); } return this.highlightClasses; }; /** * Respond to the highlight feature being toggled on and off * * @param {boolean} highlightEnabled */ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onHighlightChange = function ( highlightEnabled ) { if ( highlightEnabled ) { this.applyHighlight(); } else { this.clearHighlight(); } }; /** * Respond to a filter item model update */ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onItemUpdate = function () { if ( this.filtersModelInitialized && this.filtersViewModel.isHighlightEnabled() ) { this.clearHighlight(); this.applyHighlight(); } }; /** * Respond to changes list model invalidate */ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelInvalidate = function () { $( 'body' ).addClass( 'mw-rcfilters-ui-loading' ); }; /** * Respond to changes list model update * * @param {jQuery|string} $changesListContent The content of the updated changes list * @param {jQuery} $fieldset The content of the updated fieldset * @param {string} noResultsDetails Type of no result error * @param {boolean} isInitialDOM Whether $changesListContent is the existing (already attached) DOM * @param {boolean} from Timestamp of the new changes */ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelUpdate = function ( $changesListContent, $fieldset, noResultsDetails, isInitialDOM, from ) { var conflictItem, $message = $( '