Move construction of highlight divs to backend
authorMoriel Schottlender <moriel@gmail.com>
Mon, 25 Jun 2018 21:25:19 +0000 (14:25 -0700)
committerMoriel Schottlender <moriel@gmail.com>
Wed, 27 Jun 2018 00:19:47 +0000 (17:19 -0700)
Create the highlight container div in the backend for
both regular and enhanced result view, so we spare
the load in the frontend.

Bug: T197168
Change-Id: I36bd7b7c4c124d305ac7b07e824dc2a58e152be4

includes/changes/ChangesList.php
includes/changes/EnhancedChangesList.php
includes/changes/OldChangesList.php
includes/templates/EnhancedChangesListGroup.mustache
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js

index 703acd6..0bf3eb4 100644 (file)
@@ -115,6 +115,31 @@ class ChangesList extends ContextSource {
                throw new RuntimeException( 'recentChangesLine should be implemented' );
        }
 
+       /**
+        * Get the container for highlights that are used in the new StructuredFilters
+        * system
+        *
+        * @return string HTML structure of the highlight container div
+        */
+       protected function getHighlightsContainerDiv() {
+               $highlightColorDivs = '';
+               foreach ( [ 'none', 'c1', 'c2', 'c3', 'c4', 'c5' ] as $color ) {
+                       $highlightColorDivs .= Html::rawElement(
+                               'div',
+                               [
+                                       'class' => 'mw-rcfilters-ui-highlights-color-' . $color,
+                                       'data-color' => $color
+                               ]
+                       );
+               }
+
+               return Html::rawElement(
+                       'div',
+                       [ 'class' => 'mw-rcfilters-ui-highlights' ],
+                       $highlightColorDivs
+               );
+       }
+
        /**
         * Sets the list to use a "<li class='watchlist-(namespace)-(page)'>" tag
         * @param bool $value
index 81eccbc..0c56fdd 100644 (file)
@@ -705,9 +705,14 @@ class EnhancedChangesList extends ChangesList {
                }
 
                $line = Html::openElement( 'table', $attribs ) . Html::openElement( 'tr' );
+               // Highlight block
+               $line .= Html::rawElement( 'td', [],
+                       $this->getHighlightsContainerDiv()
+               );
+
                $line .= Html::rawElement( 'td', [], '<span class="mw-enhancedchanges-arrow-space"></span>' );
                $line .= Html::rawElement( 'td', [ 'class' => 'mw-changeslist-line-prefix' ], $prefix );
-               $line .= '<td class="mw-enhanced-rc">';
+               $line .= '<td class="mw-enhanced-rc" colspan="2">';
 
                if ( isset( $data['recentChangesFlags'] ) ) {
                        $line .= $this->recentChangesFlags( $data['recentChangesFlags'] );
index 88c3c22..51ee481 100644 (file)
@@ -63,6 +63,7 @@ class OldChangesList extends ChangesList {
                $dateheader = ''; // $html now contains only <li>...</li>, for hooks' convenience.
                $this->insertDateHeader( $dateheader, $rc->mAttribs['rc_timestamp'] );
 
+               $html = $this->getHighlightsContainerDiv() . $html;
                $attribs['class'] = implode( ' ', $classes );
 
                return $dateheader . Html::rawElement( 'li', $attribs,  $html ) . "\n";
index 6493df8..24f0613 100644 (file)
@@ -1,10 +1,20 @@
 <table class="{{# tableClasses }}{{ . }} {{/ tableClasses }}" data-mw-ts="{{{ fullTimestamp }}}">
-       <tr>
+       <tr class="mw-rcfilters-ui-highlights-enhanced-toplevel">
+               <td>
+                       <div class="mw-rcfilters-ui-highlights">
+                               <div class="mw-rcfilters-ui-highlights-color-none" data-color="none"></div>
+                               <div class="mw-rcfilters-ui-highlights-color-c1" data-color="c1"></div>
+                               <div class="mw-rcfilters-ui-highlights-color-c2" data-color="c2"></div>
+                               <div class="mw-rcfilters-ui-highlights-color-c3" data-color="c3"></div>
+                               <div class="mw-rcfilters-ui-highlights-color-c4" data-color="c4"></div>
+                               <div class="mw-rcfilters-ui-highlights-color-c5" data-color="c5"></div>
+                       </div>
+               </td>
                <td>
                        <span class="mw-collapsible-toggle mw-collapsible-arrow mw-enhancedchanges-arrow mw-enhancedchanges-arrow-space"></span>
                </td>
                <td class="mw-changeslist-line-prefix">{{{ prefix }}}</td>
-               <td class="mw-enhanced-rc">{{{ collectedRcFlags }}}&#160;{{ timestamp }}&#160;</td>
+               <td class="mw-enhanced-rc" colspan="2">{{{ collectedRcFlags }}}&#160;{{ timestamp }}&#160;</td>
                <td class="mw-changeslist-line-inner">
                        {{# rev-deleted-event }}<span class="history-deleted">{{{ . }}}</span>{{/ rev-deleted-event }}
                        {{{ articleLink }}}{{{ languageDirMark }}}{{{ logText }}}
                </td>
        </tr>
        {{# lines }}
-       <tr class="{{# classes }}{{ . }} {{/ classes }}"{{{ attribs }}}>
+       <tr class="mw-rcfilters-ui-highlights-enhanced-nested {{# classes }}{{ . }} {{/ classes }}"{{{ attribs }}}>
+               <td></td>
                <td></td>
                <td></td>
                <td class="mw-enhanced-rc">{{{ recentChangesFlags }}}&#160;</td>
+               <td>
+                       <div class="mw-rcfilters-ui-highlights mw-enhanced-rc-nested">
+                               <div class="mw-rcfilters-ui-highlights-color-none" data-color="none"></div>
+                               <div class="mw-rcfilters-ui-highlights-color-c1" data-color="c1"></div>
+                               <div class="mw-rcfilters-ui-highlights-color-c2" data-color="c2"></div>
+                               <div class="mw-rcfilters-ui-highlights-color-c3" data-color="c3"></div>
+                               <div class="mw-rcfilters-ui-highlights-color-c4" data-color="c4"></div>
+                               <div class="mw-rcfilters-ui-highlights-color-c5" data-color="c5"></div>
+                       </div>
+               </td>
                <td class="mw-enhanced-rc-nested" data-target-page="{{ targetTitle }}">
                        {{# timestampLink }}
                        <span class="mw-enhanced-rc-time">{{{ . }}}</span>
index 790e015..daa7a91 100644 (file)
 // so it is before the rest of the rule; we need the li& to be in
 // between the wrapper scope and the color-cX class, which doesn't
 // work if the rules are inside the above widget LESS scope
-.highlight-changesListWrapperWidget( @bgcolor ) {
+.highlight-results( @bgcolor ) {
        .mw-rcfilters-ui-changesListWrapperWidget li&,
        .mw-rcfilters-ui-changesListWrapperWidget & tr:first-child,
-       .mw-rcfilters-ui-changesListWrapperWidget tr&.mw-rcfilters-ui-changesListWrapperWidget-enhanced-toplevel:not( .mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey ) td:not( :nth-child( -n+2 ) ),
-       .mw-rcfilters-ui-changesListWrapperWidget tr&.mw-rcfilters-ui-changesListWrapperWidget-enhanced-nested:not( .mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey ) td:not( :nth-child( -n+4 ) ) {
+       .mw-rcfilters-ui-changesListWrapperWidget tr&.mw-rcfilters-ui-highlights-enhanced-toplevel:not( .mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey ) td:not( :nth-child( -n+2 ) ),
+       .mw-rcfilters-ui-changesListWrapperWidget tr&.mw-rcfilters-ui-highlights-enhanced-nested:not( .mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey ) td:not( :nth-child( -n+4 ) ) {
                background-color: @bgcolor;
        }
 }
 
        // Two colors
        @{highlight-color-class-var} when ( @color3 = false ) and ( @color4 = false ) and not ( @color1 = false ), ( @color2 = false ) {
-               .highlight-changesListWrapperWidget( tint( average( @@c1var, @@c2var ), 50% ) );
+               .highlight-results( tint( average( @@c1var, @@c2var ), 50% ) );
        }
        // Three colors
        @{highlight-color-class-var}.mw-rcfilters-highlight-color-@{color3} when ( @color4 = false ) and not ( @color3 = false ) {
                @c3var: ~'highlight-@{color3}';
-               .highlight-changesListWrapperWidget( tint( mix( @@c1var, average( @@c2var, @@c3var ), 33% ), 30% ) );
+               .highlight-results( tint( mix( @@c1var, average( @@c2var, @@c3var ), 33% ), 30% ) );
        }
 
        // Four colors
        @{highlight-color-class-var}.mw-rcfilters-highlight-color-@{color3}.mw-rcfilters-highlight-color-@{color4} when not ( @color4 = false ) {
                @c3var: ~'highlight-@{color3}';
                @c4var: ~'highlight-@{color4}';
-               .highlight-changesListWrapperWidget( tint( mix( @@c1var, mix( @@c2var, average( @@c3var, @@c4var ), 25% ), 25% ), 25% ) );
+               .highlight-results( tint( mix( @@c1var, mix( @@c2var, average( @@c3var, @@c4var ), 25% ), 25% ), 25% ) );
        }
 }
index e9e331b..e0c3c8b 100644 (file)
                        width: 100%;
                }
        }
+}
 
-       &-highlights {
-               display: none;
-               padding: 0 @result-circle-general-margin 0 0;
-               text-align: right;
-               // The width is 5 circles times their diameter + individual margin
-               // and then plus the general margin
-               width: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 )';
-               // And we want to shift the entire block to the left of the li
-               position: relative;
-               // Negative left margin of width + padding
-               margin-left: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * -5 - @{result-circle-general-margin} )';
-
-               .mw-rcfilters-ui-changesListWrapperWidget-highlighted & {
-                       display: inline-block;
-               }
+.mw-rcfilters-ui-highlights {
+       display: none;
+       padding: 0 @result-circle-general-margin 0 0;
+       // The width is 5 circles times their diameter + individual margin
+       // and then plus the general margin
+       width: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 )';
+       // And we want to shift the entire block to the left of the li
+       position: relative;
+       // Negative left margin of width + padding
+       margin-left: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * -5 - @{result-circle-general-margin} )';
 
-               // This needs to be very specific, since these are
-               // position rules that should apply to all overrides
-               .mw-rcfilters-ui-changesListWrapperWidget .mw-rcfilters-ui-changesListWrapperWidget-highlights > div&-circle {
-                       .box-sizing( border-box );
-                       margin-right: @result-circle-margin;
-                       vertical-align: middle;
-                       // This is to make the dots appear at the center of the
-                       // text itself; it's a horrendous hack and blame JamesF for it.
-                       margin-top: -2px;
-               }
+       .mw-rcfilters-ui-changesListWrapperWidget-highlighted & {
+               display: inline-block;
+       }
 
-               &-color {
+       > div {
+               .box-sizing( border-box );
+               margin-right: @result-circle-margin;
+               vertical-align: middle;
+               // This is to make the dots appear at the center of the
+               // text itself; it's a horrendous hack and blame JamesF for it.
+               margin-top: -2px;
+               float: right;
+       }
 
-                       &-none {
-                               .mw-rcfilters-mixin-circle( @highlight-none, @result-circle-diameter, 0, true );
-                               display: inline-block;
+       &-color {
+               &-none {
+                       .mw-rcfilters-mixin-circle( @highlight-none, @result-circle-diameter, 0, true );
+                       display: inline-block;
 
-                               .mw-rcfilters-highlight-color-c1 &,
-                               .mw-rcfilters-highlight-color-c2 &,
-                               .mw-rcfilters-highlight-color-c3 &,
-                               .mw-rcfilters-highlight-color-c4 &,
-                               .mw-rcfilters-highlight-color-c5 & {
-                                       display: none;
-                               }
+                       .mw-rcfilters-highlight-color-c1 &,
+                       .mw-rcfilters-highlight-color-c2 &,
+                       .mw-rcfilters-highlight-color-c3 &,
+                       .mw-rcfilters-highlight-color-c4 &,
+                       .mw-rcfilters-highlight-color-c5 & {
+                               display: none;
                        }
-                       .result-circle( c1 );
-                       .result-circle( c2 );
-                       .result-circle( c3 );
-                       .result-circle( c4 );
-                       .result-circle( c5 );
                }
+               .result-circle( c1 );
+               .result-circle( c2 );
+               .result-circle( c3 );
+               .result-circle( c4 );
+               .result-circle( c5 );
        }
 }
 
 // One color
 .mw-rcfilters-highlight-color-c1 {
-       .highlight-changesListWrapperWidget( tint( @highlight-c1, 70% ); );
+       .highlight-results( tint( @highlight-c1, 70% ); );
 }
 
 .mw-rcfilters-highlight-color-c2 {
-       .highlight-changesListWrapperWidget( tint( @highlight-c2, 70% ); );
+       .highlight-results( tint( @highlight-c2, 70% ); );
 }
 
 .mw-rcfilters-highlight-color-c3 {
-       .highlight-changesListWrapperWidget( tint( @highlight-c3, 70% ); );
+       .highlight-results( tint( @highlight-c3, 70% ); );
 }
 
 .mw-rcfilters-highlight-color-c4 {
-       .highlight-changesListWrapperWidget( tint( @highlight-c4, 70% ); );
+       .highlight-results( tint( @highlight-c4, 70% ); );
 }
 
 .mw-rcfilters-highlight-color-c5 {
-       .highlight-changesListWrapperWidget( tint( @highlight-c5, 70% ); );
+       .highlight-results( tint( @highlight-c5, 70% ); );
 }
 
 // Two colors
 // a custom color rather than the computed tint
 // see https://phabricator.wikimedia.org/T161267
 .mw-rcfilters-highlight-color-c1.mw-rcfilters-highlight-color-c3 {
-       .highlight-changesListWrapperWidget( @light-green );
+       .highlight-results( @light-green );
 }
 .highlight-color-mix( c1, c4 );
 .highlight-color-mix( c1, c5 );
 
 // Five colors:
 .mw-rcfilters-highlight-color-c1.mw-rcfilters-highlight-color-c2.mw-rcfilters-highlight-color-c3.mw-rcfilters-highlight-color-c4.mw-rcfilters-highlight-color-c5 {
-       .highlight-changesListWrapperWidget( tint( mix( @highlight-c1, mix( @highlight-c2, mix( @highlight-c3, average( @highlight-c4, @highlight-c5 ), 20% ), 20% ), 20% ), 15% ) );
+       .highlight-results( tint( mix( @highlight-c1, mix( @highlight-c2, mix( @highlight-c3, average( @highlight-c4, @highlight-c5 ), 20% ), 20% ), 20% ), 15% ) );
 }
index b49a1cb..ec3fe31 100644 (file)
         * @param {jQuery|string} $content The content of the updated changes list
         */
        mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupHighlightContainers = function ( $content ) {
-               var $enhancedTopPageCell, $enhancedNestedPagesCell,
-                       widget = this,
-                       highlightClass = 'mw-rcfilters-ui-changesListWrapperWidget-highlights',
-                       $highlights = $( '<div>' )
-                               .addClass( highlightClass )
-                               .append(
-                                       $( '<div>' )
-                                               .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-circle' )
-                                               .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-color-none' )
-                                               .prop( 'data-color', 'none' )
-                               );
-
-               if ( $( '.mw-rcfilters-ui-changesListWrapperWidget-highlights' ).length ) {
-                       // Already set up
-                       return;
-               }
-
-               mw.rcfilters.HighlightColors.forEach( function ( color ) {
-                       $highlights.append(
-                               $( '<div>' )
-                                       .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-color-' + color )
-                                       .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-circle' )
-                                       .prop( 'data-color', color )
-                       );
-               } );
+               var $enhancedTopPageCell,
+                       widget = this;
 
                if ( this.inEnhancedMode() ) {
                        $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(
-                                       $( '<td>' )
-                                               .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 <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>' )
-                                               .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 () {
                                $table.find( 'tr:first-child' )
                                        .addClass( collectedClasses.join( ' ' ) );
                        } );
-
-                       $content.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhancedView' );
-               } else {
-                       // Regular RC
-                       $content.find( 'ul.special li' )
-                               .prepend( $highlights.clone() );
-
-                       $content.removeClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhancedView' );
                }
        };