class ChangesList {
public $skin;
protected $watchlist = false;
-
+
/**
* Changeslist contructor
* @param $skin Skin
}
}
+
/**
* Returns the appropriate flags for new page, minor change and patrolling
- * @param $flags Associative array of 'flag' => Bool
+ * @param $new Boolean
+ * @param $minor Boolean
+ * @param $patrolled Boolean
* @param $nothing String to use for empty space
+ * @param $bot Boolean
* @return String
*/
- protected function recentChangesFlags( $flags, $nothing = ' ' ) {
- $f = '';
- foreach( array( 'newpage', 'minor', 'bot', 'unpatrolled' ) as $flag ){
- $f .= isset( $flags[$flag] ) && $flags[$flag]
- ? self::flag( $flag )
- : $nothing;
- }
+ protected function recentChangesFlags( $new, $minor, $patrolled, $nothing = ' ', $bot = false ) {
+ $f = $new ? self::flag( 'newpage' ) : $nothing;
+ $f .= $minor ? self::flag( 'minor' ) : $nothing;
+ $f .= $bot ? self::flag( 'bot' ) : $nothing;
+ $f .= $patrolled ? self::flag( 'unpatrolled' ) : $nothing;
return $f;
}
public static function flag( $key ) {
static $messages = null;
if ( is_null( $messages ) ) {
- $messages = array(
- 'newpage' => array( 'newpageletter', 'recentchanges-label-newpage' ),
- 'minor' => array( 'minoreditletter', 'recentchanges-label-minor' ),
- 'bot' => array( 'boteditletter', 'recentchanges-label-bot' ),
- 'unpatrolled' => array( 'unpatrolledletter', 'recentchanges-label-unpatrolled' ),
- );
- foreach( $messages as $key => &$value ) {
- $value[0] = wfMsgExt( $value[0], 'escapenoentities' );
- $value[1] = wfMsgExt( $value[1], 'escapenoentities' );
+ foreach ( explode( ' ', 'minoreditletter boteditletter newpageletter ' .
+ 'unpatrolledletter recentchanges-label-minor recentchanges-label-bot ' .
+ 'recentchanges-label-newpage recentchanges-label-unpatrolled' ) as $msg ) {
+ $messages[$msg] = wfMsgExt( $msg, 'escapenoentities' );
}
}
- return "<abbr class='$key' title='" . $messages[$key][1] . "'>" . $messages[$key][0] . '</abbr>';
+ # Inconsistent naming, bleh
+ if ( $key == 'newpage' || $key == 'unpatrolled' ) {
+ $key2 = $key;
+ } else {
+ $key2 = $key . 'edit';
+ }
+ return "<abbr class=\"$key\" title=\""
+ . $messages["recentchanges-label-$key"] . "\">"
+ . $messages["${key2}letter"]
+ . '</abbr>';
}
/**
} else {
$this->insertDiffHist( $s, $rc, $unpatrolled );
# M, N, b and ! (minor, new, bot and unpatrolled)
- $s .= $this->recentChangesFlags(
- array(
- 'new' => $rc->mAttribs['rc_new'],
- 'minor' => $rc->mAttribs['rc_minor'],
- 'unpatrolled' => $unpatrolled,
- 'bot' => $rc->mAttribs['rc_bot']
- ),
- ''
- );
+ $s .= $this->recentChangesFlags( $rc->mAttribs['rc_new'], $rc->mAttribs['rc_minor'],
+ $unpatrolled, '', $rc->mAttribs['rc_bot'] );
$this->insertArticleLink( $s, $rc, $unpatrolled, $watched );
}
# Edit/log timestamp
$this->rcCacheIndex = 0;
$this->lastdate = '';
$this->rclistOpen = false;
- $wgOut->addModuleStyles( 'mediawiki.special.changeslist' );
+ $wgOut->addModules( 'mediawiki.legacy.enhancedchanges' );
return '';
}
/**
# Add the namespace and title of the block as part of the class
if ( $block[0]->mAttribs['rc_log_type'] ) {
# Log entry
- $classes = 'collapsible collapsed mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-log-' . $block[0]->mAttribs['rc_log_type'] . '-' . $block[0]->mAttribs['rc_title'] );
+ $classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-log-' . $block[0]->mAttribs['rc_log_type'] . '-' . $block[0]->mAttribs['rc_title'] );
} else {
- $classes = 'collapsible collapsed mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-ns' . $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
+ $classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-ns' . $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
}
$r = Html::openElement( 'table', array( 'class' => $classes ) ) .
Html::openElement( 'tr' );
$users = ' <span class="changedby">[' .
implode( $this->message['semicolon-separator'], $users ) . ']</span>';
+ # ID for JS visibility toggle
+ $jsid = $this->rcCacheIndex;
+ # onclick handler to toggle hidden/expanded
+ $toggleLink = "onclick='toggleVisibility($jsid); return false'";
# Title for <a> tags
$expandTitle = htmlspecialchars( wfMsg( 'rc-enhanced-expand' ) );
$closeTitle = htmlspecialchars( wfMsg( 'rc-enhanced-hide' ) );
- $tl = "<span class='collapsible-expander'>"
- . "<span class='mw-rc-openarrow'>"
- . "<a href='#' title='$expandTitle'>{$this->sideArrow()}</a>"
- . "</span><span class='mw-rc-closearrow'>"
- . "<a href='#' title='$closeTitle'>{$this->downArrow()}</a>"
- . "</span></span>";
- $r .= "<td>$tl</td>";
+ $tl = "<span id='mw-rc-openarrow-$jsid' class='mw-changeslist-expanded' style='visibility:hidden'><a href='#' $toggleLink title='$expandTitle'>" . $this->sideArrow() . "</a></span>";
+ $tl .= "<span id='mw-rc-closearrow-$jsid' class='mw-changeslist-hidden' style='display:none'><a href='#' $toggleLink title='$closeTitle'>" . $this->downArrow() . "</a></span>";
+ $r .= '<td class="mw-enhanced-rc">'.$tl.' ';
# Main line
- $r .= '<td class="mw-enhanced-rc">' . $this->recentChangesFlags( array(
- 'new' => $isnew,
- 'minor' => false,
- 'unpatrolled' => $unpatrolled,
- 'bot' => $bot ,
- ) );
+ $r .= $this->recentChangesFlags( $isnew, false, $unpatrolled, ' ', $bot );
# Timestamp
- $r .= ' '.$block[0]->timestamp.' </td><td>';
+ $r .= ' '.$block[0]->timestamp.' </td><td style="padding:0px;">';
# Article link
if( $namehidden ) {
$r .= $users;
$r .= $this->numberofWatchingusers($block[0]->numberofWatchingusers);
+ $r .= "</td></tr></table>\n";
+
# Sub-entries
+ $r .= '<div id="mw-rc-subentries-'.$jsid.'" class="mw-changeslist-hidden">';
+ $r .= '<table class="mw-enhanced-rc">';
foreach( $block as $rcObj ) {
# Extract fields from DB into the function scope (rc_xxxx variables)
// FIXME: Would be good to replace this extract() call with something
extract( $rcObj->mAttribs );
#$r .= '<tr><td valign="top">'.$this->spacerArrow();
- $r .= '<tr><td></td><td class="mw-enhanced-rc">';
- $r .= $this->recentChangesFlags( array(
- 'new' => $rc_new,
- 'minor' => $rc_minor,
- 'unpatrolled' => $rcObj->unpatrolled,
- 'bot' => $rc_bot,
- ) );
- $r .= ' </td><td class="mw-enhanced-rc-nested"><span class="mw-enhanced-rc-time">';
+ $r .= '<tr><td style="vertical-align:top;font-family:monospace; padding:0px;">';
+ $r .= $this->spacerIndent() . $this->spacerIndent();
+ $r .= $this->recentChangesFlags( $rc_new, $rc_minor, $rcObj->unpatrolled, ' ', $rc_bot );
+ $r .= ' </td><td style="vertical-align:top; padding:0px;"><span style="font-family:monospace">';
$params = $queryParams;
$r .= "</td></tr>\n";
}
- $r .= "</table>\n";
+ $r .= "</table></div>\n";
$this->rcCacheIndex++;
return $this->arrow( '', codepointToUtf8( 0xa0 ) ); // non-breaking space
}
+ /**
+ * Add a set of spaces
+ * @return String: HTML <td> tag
+ */
+ protected function spacerIndent() {
+ return '     ';
+ }
+
/**
* Enhanced RC ungrouped line.
* @return String: a HTML formated line (generated using $r)
$r = Html::openElement( 'table', array( 'class' => $classes ) ) .
Html::openElement( 'tr' );
- $r .= '<td class="mw-enhanced-rc">' . $this->spacerArrow();
+ $r .= '<td class="mw-enhanced-rc">' . $this->spacerArrow() . ' ';
# Flag and Timestamp
if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
$r .= '    '; // 4 flags -> 4 spaces
} else {
- $r .= $this->recentChangesFlags( array(
- 'new' => $rc_type == RC_NEW,
- 'minor' => $rc_minor,
- 'unpatrolled' => $rcObj->unpatrolled,
- 'bot' => $rc_bot
- ) );
+ $r .= $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $rcObj->unpatrolled, ' ', $rc_bot );
}
- $r .= ' '.$rcObj->timestamp.' </td><td>';
+ $r .= ' '.$rcObj->timestamp.' </td><td style="padding:0px;">';
# Article or log link
if( $rc_log_type ) {
$logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL );
$sk = $wgUser->getSkin();
// Add base resources
- $this->addModules( array( 'mediawiki.legacy.wikibits', 'mediawiki.util', 'skins.common' ) );
+ $this->addModules( array( 'mediawiki.legacy.wikibits', 'mediawiki.util' ) );
// Add various resources if required
if ( $wgUseAjax ) {
'user.options' => array( 'class' => 'ResourceLoaderUserOptionsModule' ),
/* Skins */
-
- 'skins.common' => array(
- 'scripts' => 'resources/skins.common/skins.common.js',
- 'styles' => array(
- 'resources/skins.common/skins.common.css',
- 'resources/skins.common/skins.common.print.css' => array( 'media' => 'print' )
- ),
- 'messages' => array( 'hide', 'show' ),
- 'dependencies' => array( 'jquery.effects.fade' ),
- ),
'skins.vector' => array(
'styles' => array( 'skins/vector/screen.css' => array( 'media' => 'screen' ) )
'scripts' => 'resources/jquery.effects/jquery.effects.explode.js',
'dependencies' => 'jquery.effects.core',
),
- 'jquery.effects.fade' => array(
- 'scripts' => 'resources/jquery.effects/jquery.effects.fade.js',
- 'dependencies' => 'jquery.effects.core',
- ),
'jquery.effects.fold' => array(
'scripts' => 'resources/jquery.effects/jquery.effects.fold.js',
'dependencies' => 'jquery.effects.core',
'scripts' => 'resources/mediawiki.special/mediawiki.special.preferences.js',
'styles' => 'resources/mediawiki.special/mediawiki.special.preferences.css',
),
- 'mediawiki.special.changeslist' => array(
- 'styles' => 'resources/mediawiki.special/mediawiki.special.changeslist.css',
- ),
'mediawiki.special.search' => array(
'scripts' => 'resources/mediawiki.special/mediawiki.special.search.js',
),
'scripts' => 'skins/common/edit.js',
'dependencies' => 'mediawiki.legacy.wikibits',
),
+ 'mediawiki.legacy.enhancedchanges' => array(
+ 'scripts' => 'skins/common/enhancedchanges.js',
+ 'dependencies' => 'mediawiki.legacy.wikibits',
+ ),
'mediawiki.legacy.history' => array(
'scripts' => 'skins/common/history.js',
'dependencies' => 'mediawiki.legacy.wikibits',
+++ /dev/null
-/*
-* jQuery UI Effects Fade @VERSION
-*
-* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*
-* http://docs.jquery.com/UI/Effects/Fade
-*
-* Depends:
-* jquery.effects.core.js
-*/
-(function( $, undefined ) {
-
- $.effects.fade = function(o) {
- return this.queue(function() {
- var elem = $(this),
- mode = $.effects.setMode(elem, o.options.mode || 'hide');
-
- elem.animate({ opacity: mode }, {
- queue: false,
- duration: o.duration,
- easing: o.options.easing,
- complete: function() {
- (o.callback && o.callback.apply(this, arguments));
- elem.dequeue();
- }
- });
- });
- };
-
-})(jQuery);
\ No newline at end of file
+++ /dev/null
-/**
- * Styling for Special:Watchlist and Special:RecentChanges
- */
-
-table.mw-enhanced-rc {
- background: none;
- border:0;
- border-spacing:0;
-}
-
-table.mw-enhanced-rc th, table.mw-enhanced-rc td {
- padding:0;
- vertical-align:top;
-}
-
-td.mw-enhanced-rc {
- white-space:nowrap;
- font-family:monospace;
-}
-
-.mw-enhanced-rc-time {
- font-family: monospace;
-}
-
-table.mw-enhanced-rc td.mw-enhanced-rc-nested {
- padding-left: 1em;
-}
-
-/* Show/hide arrows in enhanced changeslist */
-.mw-enhanced-rc .collapsible-expander {
- float: none;
-}
-
-.mw-rc-openarrow,
-.show .mw-rc-closearrow {
- display: none;
-}
-.show .mw-rc-openarrow {
- display: inline;
-}
+++ /dev/null
-/**
- * 'show'/'hide' buttons created dynamically
- * by the CollapsibleTables javascript
- */
-.collapsible-expander {
- float: right;
- font-weight: normal;
- text-align: right;
- width: auto;
-}
-
-/**
- * Note that IE<7 sees the second selector here as
- * just ".collapsible-expander", and doesn't accept
- * the multiple classes. Fortunately these two cursors
- * are generally the same, a pair of up-and-down arrows.
- */
- .collapsible-expander {
- cursor: n-resize;
-}
-.show.collapsible-expander {
- cursor: s-resize;
-}
-
+++ /dev/null
-/*
- * Scripts common to all skins
- */
-
-/**
- * Collapsible tables and divs.
- *
- * Users can create tables and nested divs which collapse either on-click or on-load,
- * to save space on a page, or to conceal information at first sight. Eg:
- *
- * <table class="wikitable collapsible collapsed"><tr>
- * <th>A table header which will always be visible</th>
- * </tr><tr>
- * <td>A table cell which will be hidden on page-load</td>
- * </tr></table>
- *
- * <div class="collapsible collapsed">
- * Content which will always be visible
- * <span class="collapsible-expander">Click me!</span>
- * <div>
- * This content will be hidden until the span above is clicked
- * </div>
- * </div>
- *
- * If the user does not create a toggle-button manually, one will be created,
- * in the top-right header cell for tables, and at the beginning of the outer
- * div's content for a collapsible div.
- * @author Happy-melon
- */
-$('.collapsible').each( function(){
- var $x = $j(this);
- if( $('.collapsible-expander', $x).size() ){
- $('.collapsible-expander', $x)
- .click(function(e, rmClass){
- e.preventDefault();
- rmClass = !(rmClass == false);
- $(this)
- .toggleClass('show')
- .trigger('mw-toggle-collapse', [rmClass]);
- return false;
- });
- } else {
- var $expander = $j('<div class="collapsible-expander">')
- .text( '[' + mediaWiki.msg( 'hide' ) + ']' )
- .click(function(e, rmClass){
- rmClass = !(rmClass == false);
- e.preventDefault();
- $(this)
- .toggleClass('show')
- .trigger('mw-toggle-collapse', [rmClass])
- .text(
- '[' +
- ($(this).is('.collapsible.collapsed .collapsible-expander')
- ? mediaWiki.msg( 'show' )
- : mediaWiki.msg( 'hide' )) +
- ']'
- );
- return false;
- });
- if( $x.is('div.collapsible')){
- $x.prepend($expander);
- } else {
- $('tr:first th:last',$x).append($expander);
- }
- }
-
-});
-
-/**
- * This is a bit nasty because it also toggles any nested
- * collapsible objects. But it would be a nightmare to only
- * select the outer collapser without adding ids everywhere.
- */
-$('table.collapsible').live( 'mw-toggle-collapse', function(e, rmClass){
- e.stopPropagation();
- var time = rmClass ? 500 : 0;
- $('tr:gt(0)',$(this))
- // We'd like to use slideToggle() like for divs, but the jQuery
- // slide animation for table rows is just *pig ugly*...
- .toggle("fade", { direction: "vertical" }, time);
- if( rmClass ){
- $('table.collapsible',$(this)).andSelf().toggleClass('collapsed');
- }
- return false;
-});
-
-$('div.collapsible').live( 'mw-toggle-collapse', function(e, rmClass){
- e.stopPropagation();
- var time = rmClass ? 500 : 0;
- $(this).children(':not(.collapsible-expander)')
- .slideToggle(time);
- if( rmClass ){
- $('div.collapsible',$(this)).andSelf().toggleClass('collapsed');
- }
- return false;
-});
-
-/**
- * Here we want to collapse .collapsible-expander buttons whose closest
- * div.collapsible parent wants to be collapsed on first view
- */
-$('.collapsible-expander').filter(function(){
- return $(this).closest('.collapsible').is('.collapsible.collapsed')
-}).trigger( 'click', [false] );
-
-
-
+++ /dev/null
-/**
- * Uncollapse collapsible tables/divs. The proper way to do this
- * for tables is to use display:table-row, but this is not supported
- * by all browsers, so use display:block as fallback. Equally, the >
- * selector is not supported by IE<7, so the fourth rule is recognised
- * only by IE6 and below.
- */
-table.collapsible tr {
- display: block !important;
-}
-table.collapsible tr {
- display: table-row !important;
-}
-div.collapsible > * {
- display: auto !important;
-}
-* html div.collapsible * {
- display: auto !important;
-}
\ No newline at end of file
--- /dev/null
+/*
+ JavaScript file for enhanced recentchanges
+ */
+
+/*
+ * Add the CSS to hide parts that should be collapsed
+ *
+ * We do this with JS so everything will be expanded by default
+ * if JS is disabled
+ */
+appendCSS('.mw-changeslist-hidden {'+
+ ' display:none;'+
+ '}'+
+ 'div.mw-changeslist-expanded {'+
+ ' display:block;'+
+ '}'+
+ 'span.mw-changeslist-expanded {'+
+ ' display:inline !important;'+
+ ' visibility:visible !important;'+
+ '}'
+);
+
+/*
+ * Switch an RC line between hidden/shown
+ * @param int idNumber : the id number of the RC group
+*/
+window.toggleVisibility = function(idNumber) {
+ var openarrow = document.getElementById("mw-rc-openarrow-"+idNumber);
+ var closearrow = document.getElementById("mw-rc-closearrow-"+idNumber);
+ var subentries = document.getElementById("mw-rc-subentries-"+idNumber);
+ if (openarrow.className == 'mw-changeslist-expanded') {
+ openarrow.className = 'mw-changeslist-hidden';
+ closearrow.className = 'mw-changeslist-expanded';
+ subentries.className = 'mw-changeslist-expanded';
+ } else {
+ openarrow.className = 'mw-changeslist-expanded';
+ closearrow.className = 'mw-changeslist-hidden';
+ subentries.className = 'mw-changeslist-hidden';
+ }
+};
word-wrap: break-word;
}
+table.mw-enhanced-rc {
+ background: none;
+ border:0;
+ border-spacing:0;
+}
+td.mw-enhanced-rc {
+ white-space:nowrap;
+ padding:0;
+ vertical-align:top;
+ font-family:monospace
+}
+
#mw-addcategory-prompt {
display: inline;
margin-left: 1em;