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
}
$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'] );
$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";
<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 }}} {{ timestamp }} </td>
+ <td class="mw-enhanced-rc" colspan="2">{{{ collectedRcFlags }}} {{ timestamp }} </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 }}} </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>
// 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% ) );
}
}
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% ) );
}
* @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' );
}
};