X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=resources%2Fsrc%2Fmediawiki.rcfilters%2Fui%2Fmw.rcfilters.ui.ChangesListWrapperWidget.js;h=ea32e3643e1bebfa5cc6517858ba6bc047430168;hb=3df3b575c6617df64ec98533cc7141bd2314e274;hp=ec12783b0f781ed31b328488996812a2dd0eb6b8;hpb=be80e2614cfd0dd56eda32edb93d368aee58a729;p=lhc%2Fweb%2Fwiklou.git diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js index ec12783b0f..ea32e3643e 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js @@ -28,11 +28,14 @@ this.filtersViewModel = filtersViewModel; this.changesListViewModel = changesListViewModel; this.controller = controller; + this.highlightClasses = null; + this.filtersModelInitialized = false; // Events this.filtersViewModel.connect( this, { itemUpdate: 'onItemUpdate', - highlightChange: 'onHighlightChange' + highlightChange: 'onHighlightChange', + initialize: 'onFiltersModelInitialize' } ); this.changesListViewModel.connect( this, { invalidate: 'onModelInvalidate', @@ -45,16 +48,40 @@ // We handle our own display/hide of the empty results message .removeClass( 'mw-changeslist-empty' ); - // Set up highlight containers - this.setupHighlightContainers( this.$element ); - - this.setupNewChangesButtonContainer( this.$element ); + this.setupNewChangesButtonContainer(); }; /* 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 * @@ -72,7 +99,7 @@ * Respond to a filter item model update */ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onItemUpdate = function () { - if ( this.filtersViewModel.isHighlightEnabled() ) { + if ( this.filtersModelInitialized && this.filtersViewModel.isHighlightEnabled() ) { this.clearHighlight(); this.applyHighlight(); } @@ -82,8 +109,7 @@ * 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' ); }; /** @@ -157,8 +183,7 @@ 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' ); } ); }; @@ -221,10 +246,8 @@ /** * 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(), @@ -233,7 +256,10 @@ 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( $( '
' ) .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-newChanges' ) .append( this.showNewChangesLink.$element ) @@ -246,7 +272,9 @@ * @param {jQuery|string} $content The content of the updated changes list */ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupHighlightContainers = function ( $content ) { - var highlightClass = 'mw-rcfilters-ui-changesListWrapperWidget-highlights', + var $enhancedTopPageCell, $enhancedNestedPagesCell, + widget = this, + highlightClass = 'mw-rcfilters-ui-changesListWrapperWidget-highlights', $highlights = $( '
' ) .addClass( highlightClass ) .append( @@ -271,13 +299,59 @@ } ); if ( this.inEnhancedMode() ) { - // Enhanced RC - $content.find( 'td.mw-enhanced-rc' ) - .parent() + $enhancedTopPageCell = $content.find( 'table.mw-enhanced-rc.mw-collapsible' ); + $enhancedNestedPagesCell = $content.find( 'td.mw-enhanced-rc-nested' ); + + // Enhanced RC highlight containers + $content.find( 'table.mw-enhanced-rc tr:first-child' ) + .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhanced-toplevel' ) .prepend( $( '' ) .append( $highlights.clone() ) ); + + // We are adding and changing cells in a table that, despite having nested rows, + // 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 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 to nested rows to compensate + $enhancedNestedPagesCell.parent().prepend( $( '' ) ); + // Add highlights cell to nested rows + $enhancedNestedPagesCell + .before( + $( '' ) + .append( $highlights.clone().addClass( 'mw-enhanced-rc-nested' ) ) + ); + + // 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 4 cells td:not( :nth-child( -n+4 ) + $enhancedNestedPagesCell + .closest( 'tr' ) + .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhanced-nested' ); + + // Go over pages that have sub results + // HACK: We really only can collect those by targetting the collapsible class + $enhancedTopPageCell.each( function () { + var collectedClasses, + $table = $( this ); + + // Go over s and pick up all recognized classes + collectedClasses = widget.getHighlightClasses().filter( function ( className ) { + return $table.find( 'tr' ).hasClass( className ); + } ); + + $table.find( 'tr:first-child' ) + .addClass( collectedClasses.join( ' ' ) ); + } ); + + $content.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhancedView' ); } else { // Regular RC $content.find( 'ul.special li' ) @@ -285,6 +359,52 @@ } }; + /** + * In enhanced mode, we need to check whether the grouped results all have the + * same active highlights in order to see whether the "parent" of the group should + * be grey or highlighted normally. + * + * This is called every time highlights are applied. + */ + mw.rcfilters.ui.ChangesListWrapperWidget.prototype.updateEnhancedParentHighlight = function () { + var activeHighlightClasses, + $enhancedTopPageCell = this.$element.find( 'table.mw-enhanced-rc.mw-collapsible' ); + + activeHighlightClasses = this.filtersViewModel.getCurrentlyUsedHighlightColors().map( function ( color ) { + return 'mw-rcfilters-highlight-color-' + color; + } ); + + // Go over top pages and their children, and figure out if all sub-pages have the + // same highlights between themselves. If they do, the parent should be highlighted + // with all colors. If classes are different, the parent should receive a grey + // background + $enhancedTopPageCell.each( function () { + var firstChildClasses, $rowsWithDifferentHighlights, + $table = $( this ); + + // Collect the relevant classes from the first nested child + firstChildClasses = activeHighlightClasses.filter( function ( className ) { + return $table.find( 'tr:nth-child(2)' ).hasClass( className ); + } ); + // Filter the non-head rows and see if they all have the same classes + // to the first row + $rowsWithDifferentHighlights = $table.find( 'tr:not(:first-child)' ).filter( function () { + var classesInThisRow, + $this = $( this ); + + classesInThisRow = activeHighlightClasses.filter( function ( className ) { + return $this.hasClass( className ); + } ); + + return !OO.compare( firstChildClasses, classesInThisRow ); + } ); + + // If classes are different, tag the row for using grey color + $table.find( 'tr:first-child' ) + .toggleClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey', $rowsWithDifferentHighlights.length > 0 ); + } ); + }; + /** * @return {boolean} Whether the changes are grouped by page */ @@ -331,6 +451,10 @@ } } ); + if ( this.inEnhancedMode() ) { + this.updateEnhancedParentHighlight(); + } + // Turn on highlights this.$element.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlighted' ); }; @@ -347,6 +471,11 @@ this.$element.find( '[data-highlightedFilters]' ) .removeAttr( 'title' ) .removeAttr( 'data-highlightedFilters' ); + + // Remove grey from enhanced rows + this.$element.find( '.mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey' ) + .removeClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey' ); + // Turn off highlights this.$element.removeClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlighted' ); };