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' );
- this.setupNewChangesButtonContainer( this.$element );
+ this.setupNewChangesButtonContainer();
};
/* Initialization */
* Respond to changes list model invalidate
*/
mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelInvalidate = function () {
- $( '.rcfilters-spinner' ).removeClass( 'mw-rcfilters-ui-ready' );
- this.$element.removeClass( 'mw-rcfilters-ui-ready' );
+ $( 'body' ).addClass( 'mw-rcfilters-ui-loading' );
};
/**
*
* @param {jQuery|string} $changesListContent The content of the updated changes list
* @param {jQuery} $fieldset The content of the updated fieldset
+ * @param {boolean} isDatabaseTimeout Whether this is an error state due to a database query
* @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, isInitialDOM, from
+ $changesListContent, $fieldset, isDatabaseTimeout, isInitialDOM, from
) {
- var conflictItem,
+ var conflictItem, noResultsKey,
$message = $( '<div>' )
.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-results' ),
isEmpty = $changesListContent === 'NO_RESULTS',
.text( mw.message( conflictItem.getCurrentConflictResultMessage() ).text() )
);
} else {
+ noResultsKey = isDatabaseTimeout ?
+ 'recentchanges-timeout' :
+ 'recentchanges-noresult';
+
$message
.append(
$( '<div>' )
.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-results-noresult' )
- .text( mw.message( 'recentchanges-noresult' ).text() )
+ .text( mw.message( noResultsKey ).text() )
);
+
+ this.$element.removeClass( 'mw-changeslist-timeout' );
}
this.$element.append( $message );
mw.hook( 'wikipage.content' ).fire( widget.$element );
}
- $( '.rcfilters-spinner' ).addClass( 'mw-rcfilters-ui-ready' );
- widget.$element.addClass( 'mw-rcfilters-ui-ready' );
+ $( 'body' ).removeClass( 'mw-rcfilters-ui-loading' );
} );
};
/**
* Setup the container for the 'new changes' button.
- *
- * @param {jQuery} $content
*/
- mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupNewChangesButtonContainer = function ( $content ) {
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupNewChangesButtonContainer = function () {
this.showNewChangesLink = new OO.ui.ButtonWidget( {
framed: false,
label: mw.message( 'rcfilters-show-new-changes' ).text(),
this.showNewChangesLink.connect( this, { click: 'onShowNewChangesClick' } );
this.showNewChangesLink.toggle( false );
- $content.before(
+ // HACK: Add the -newChanges div inside rcfilters-head, rather than right above us
+ // Visually it's the same place, but by putting it inside rcfilters-head we are
+ // able to use the min-height rule to prevent the page from jumping when this is added.
+ this.$element.parent().find( '.rcfilters-head' ).append(
$( '<div>' )
.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-newChanges' )
.append( this.showNewChangesLink.$element )
);
// We are adding and changing cells in a table that, despite having nested rows,
- // is actually all one big table. To do that right, we want to remove the 'placeholder'
- // cell from the top row, because we're actually adding that placeholder in the children
- // with the highlights.
- $content.find( 'table.mw-enhanced-rc tr:first-child td.mw-changeslist-line-prefix' )
- .detach();
+ // is actually all one big table. To prevent the highlights cell in the "nested"
+ // rows from stretching out the cell with the flags and timestamp in the top row,
+ // we give the latter colspan=2. Then to make things line up again, we add
+ // an empty <td> to the "nested" rows.
+
+ // Set colspan=2 on cell with flags and timestamp in top row
$content.find( 'table.mw-enhanced-rc tr:first-child td.mw-enhanced-rc' )
.prop( 'colspan', '2' );
-
+ // Add empty <td> to nested rows to compensate
+ $enhancedNestedPagesCell.parent().prepend( $( '<td>' ) );
+ // Add highlights cell to nested rows
$enhancedNestedPagesCell
.before(
$( '<td>' )
// We need to target the nested rows differently than the top rows so that the
// LESS rules applies correctly. In top rows, the rule should highlight all but
// the first 2 cells td:not( :nth-child( -n+2 ) and the nested rows, the rule
- // should highlight all but the first 3 cells td:not( :nth-child( -n+3 )
+ // should highlight all but the first 4 cells td:not( :nth-child( -n+4 )
$enhancedNestedPagesCell
.closest( 'tr' )
.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhanced-nested' );
// Add highlight class to all highlighted list items
$elements
- .addClass( 'mw-rcfilters-highlight-color-' + filterItem.getHighlightColor() );
+ .addClass(
+ 'mw-rcfilters-highlighted ' +
+ 'mw-rcfilters-highlight-color-' + filterItem.getHighlightColor()
+ );
+ // Track the filters for each item in .data( 'highlightedFilters' )
$elements.each( function () {
- var filterString = $( this ).attr( 'data-highlightedFilters' ) || '',
- filters = filterString ? filterString.split( '|' ) : [];
-
+ var filters = $( this ).data( 'highlightedFilters' );
+ if ( !filters ) {
+ filters = [];
+ $( this ).data( 'highlightedFilters', filters );
+ }
if ( filters.indexOf( filterItem.getLabel() ) === -1 ) {
filters.push( filterItem.getLabel() );
}
-
- $( this )
- .attr( 'data-highlightedFilters', filters.join( '|' ) );
} );
}.bind( this ) );
- // Apply a title for relevant filters
- this.$element.find( '[data-highlightedFilters]' ).each( function () {
- var filterString = $( this ).attr( 'data-highlightedFilters' ) || '',
- filters = filterString ? filterString.split( '|' ) : [];
-
- if ( filterString ) {
- $( this ).attr( 'title', mw.msg( 'rcfilters-highlighted-filters-list', filters.join( ', ' ) ) );
+ // Apply a title to each highlighted item, with a list of filters
+ this.$element.find( '.mw-rcfilters-highlighted' ).each( function () {
+ var filters = $( this ).data( 'highlightedFilters' );
+
+ if ( filters && filters.length ) {
+ $( this ).attr( 'title', mw.msg(
+ 'rcfilters-highlighted-filters-list',
+ filters.join( mw.msg( 'comma-separator' ) )
+ ) );
}
- } );
+ } );
if ( this.inEnhancedMode() ) {
this.updateEnhancedParentHighlight();
}
mw.rcfilters.ui.ChangesListWrapperWidget.prototype.clearHighlight = function () {
// Remove highlight classes
mw.rcfilters.HighlightColors.forEach( function ( color ) {
- this.$element.find( '.mw-rcfilters-highlight-color-' + color ).removeClass( 'mw-rcfilters-highlight-color-' + color );
+ this.$element
+ .find( '.mw-rcfilters-highlight-color-' + color )
+ .removeClass( 'mw-rcfilters-highlight-color-' + color );
}.bind( this ) );
- this.$element.find( '[data-highlightedFilters]' )
+ this.$element.find( '.mw-rcfilters-highlighted' )
.removeAttr( 'title' )
- .removeAttr( 'data-highlightedFilters' );
+ .removeData( 'highlightedFilters' )
+ .removeClass( 'mw-rcfilters-highlighted' );
// Remove grey from enhanced rows
this.$element.find( '.mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey' )