class ChangesList {
public $skin;
protected $watchlist = false;
-
+
/**
* Changeslist contructor
* @param $skin Skin
}
}
-
/**
* Returns the appropriate flags for new page, minor change and patrolling
- * @param $new Boolean
- * @param $minor Boolean
- * @param $patrolled Boolean
+ * @param $flags Associative array of 'flag' => Bool
* @param $nothing String to use for empty space
- * @param $bot Boolean
* @return String
*/
- 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;
+ protected function recentChangesFlags( $flags, $nothing = ' ' ) {
+ $f = '';
+ foreach( array( 'newpage', 'minor', 'bot', 'unpatrolled' ) as $flag ){
+ $f .= isset( $flags[$flag] ) && $flags[$flag]
+ ? self::flag( $flag )
+ : $nothing;
+ }
return $f;
}
public static function flag( $key ) {
static $messages = null;
if ( is_null( $messages ) ) {
- 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' );
+ $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' );
}
}
- # 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>';
+ return "<abbr class='$key' title='" . $messages[$key][1] . "'>" . $messages[$key][0] . '</abbr>';
}
/**
} else {
$this->insertDiffHist( $s, $rc, $unpatrolled );
# M, N, b and ! (minor, new, bot and unpatrolled)
- $s .= $this->recentChangesFlags( $rc->mAttribs['rc_new'], $rc->mAttribs['rc_minor'],
- $unpatrolled, '', $rc->mAttribs['rc_bot'] );
+ $s .= $this->recentChangesFlags(
+ array(
+ 'new' => $rc->mAttribs['rc_new'],
+ 'minor' => $rc->mAttribs['rc_minor'],
+ 'unpatrolled' => $unpatrolled,
+ 'bot' => $rc->mAttribs['rc_bot']
+ ),
+ ''
+ );
$this->insertArticleLink( $s, $rc, $unpatrolled, $watched );
}
# Edit/log timestamp
$this->rcCacheIndex = 0;
$this->lastdate = '';
$this->rclistOpen = false;
- $wgOut->addModules( 'mediawiki.legacy.enhancedchanges' );
+ $wgOut->addModuleStyles( 'mediawiki.special.changeslist' );
return '';
}
/**
# Add the namespace and title of the block as part of the class
if ( $block[0]->mAttribs['rc_log_type'] ) {
# Log entry
- $classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-log-' . $block[0]->mAttribs['rc_log_type'] . '-' . $block[0]->mAttribs['rc_title'] );
+ $classes = 'collapsible collapsed mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-log-' . $block[0]->mAttribs['rc_log_type'] . '-' . $block[0]->mAttribs['rc_title'] );
} else {
- $classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-ns' . $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
+ $classes = 'collapsible collapsed 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 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.' ';
+ $tl = "<span class='collapsible-expander'>"
+ . "<span class='mw-rc-openarrow'>"
+ . "<a href='#' title='$expandTitle'>{$this->arrow( 'd', '-', wfMsg( 'rc-enhanced-hide' ) )}</a>"
+ . "</span><span class='mw-rc-closearrow'>"
+ . "<a href='#' title='$closeTitle'>{$this->arrow( 'd', '-', wfMsg( 'rc-enhanced-hide' ) )}</a>"
+ . "</span></span>";
+ $r .= "<td>$tl</td>";
# Main line
- $r .= $this->recentChangesFlags( $isnew, false, $unpatrolled, ' ', $bot );
+ $r .= '<td class="mw-enhanced-rc">' . $this->recentChangesFlags( array(
+ 'new' => $isnew,
+ 'minor' => false,
+ 'unpatrolled' => $unpatrolled,
+ 'bot' => $bot ,
+ ) );
# Timestamp
- $r .= ' '.$block[0]->timestamp.' </td><td style="padding:0px;">';
+ $r .= ' '.$block[0]->timestamp.' </td><td>';
# 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 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">';
+ $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">';
$params = $queryParams;
$r .= "</td></tr>\n";
}
- $r .= "</table></div>\n";
+ $r .= "</table>\n";
$this->rcCacheIndex++;
return "<img src=\"$encUrl\" width=\"12\" height=\"12\" alt=\"$encAlt\" title=\"$encTitle\" />";
}
- /**
- * Generate HTML for a right- or left-facing arrow,
- * depending on language direction.
- * @return String: HTML <img> tag
- */
- protected function sideArrow() {
- global $wgContLang;
- $dir = $wgContLang->isRTL() ? 'l' : 'r';
- return $this->arrow( $dir, '+', wfMsg( 'rc-enhanced-expand' ) );
- }
-
- /**
- * Generate HTML for a down-facing arrow
- * depending on language direction.
- * @return String: HTML <img> tag
- */
- protected function downArrow() {
- return $this->arrow( 'd', '-', wfMsg( 'rc-enhanced-hide' ) );
- }
-
- /**
- * Generate HTML for a spacer image
- * @return String: HTML <img> tag
- */
- protected function spacerArrow() {
- 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->arrow( '', codepointToUtf8( 0xa0 ) );
# Flag and Timestamp
if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
$r .= '    '; // 4 flags -> 4 spaces
} else {
- $r .= $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $rcObj->unpatrolled, ' ', $rc_bot );
+ $r .= $this->recentChangesFlags( array(
+ 'new' => $rc_type == RC_NEW,
+ 'minor' => $rc_minor,
+ 'unpatrolled' => $rcObj->unpatrolled,
+ 'bot' => $rc_bot
+ ) );
}
- $r .= ' '.$rcObj->timestamp.' </td><td style="padding:0px;">';
+ $r .= ' '.$rcObj->timestamp.' </td><td>';
# Article or log link
if( $rc_log_type ) {
$logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL );
'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
+/*
+ * 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 {
+ $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 true;
+ })
+ .before('[').after(']');
+ 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 true;
+});
+
+$('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 true;
+});
+
+$('.collapsible.collapsed .collapsible-expander').trigger( 'click', [false] );
\ No newline at end of file