r78865 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r78864‎ | r78865 | r78866 >
Date:00:06, 23 December 2010
Author:happy-melon
Status:reverted (Comments)
Tags:
Comment:
(bug 17456) implement CollapsibleTables in core javascript. Using ResourceLoader/jQuery, this is now able to replace not only the ubiquitous collapsible tables in articles ([[mw:Manual:Collapsible tables]]), but also most of the other places we collapse things as well, like the enhanced Watchlist/RecentChanges feed.
Modified paths:
  • /trunk/phase3/includes/ChangesList.php (modified) (history)
  • /trunk/phase3/includes/OutputPage.php (modified) (history)
  • /trunk/phase3/resources/Resources.php (modified) (history)
  • /trunk/phase3/resources/jquery.effects/jquery.effects.fade.js (added) (history)
  • /trunk/phase3/resources/mediawiki.special/mediawiki.special.changeslist.css (added) (history)
  • /trunk/phase3/resources/skins.common (added) (history)
  • /trunk/phase3/resources/skins.common/skins.common.css (added) (history)
  • /trunk/phase3/resources/skins.common/skins.common.js (added) (history)
  • /trunk/phase3/resources/skins.common/skins.common.print.css (added) (history)
  • /trunk/phase3/skins/common/enhancedchanges.js (deleted) (history)
  • /trunk/phase3/skins/common/shared.css (modified) (history)

Diff [purge]

Index: trunk/phase3/skins/common/enhancedchanges.js
@@ -1,40 +0,0 @@
2 -/*
3 - JavaScript file for enhanced recentchanges
4 - */
5 -
6 -/*
7 - * Add the CSS to hide parts that should be collapsed
8 - *
9 - * We do this with JS so everything will be expanded by default
10 - * if JS is disabled
11 - */
12 -appendCSS('.mw-changeslist-hidden {'+
13 - ' display:none;'+
14 - '}'+
15 - 'div.mw-changeslist-expanded {'+
16 - ' display:block;'+
17 - '}'+
18 - 'span.mw-changeslist-expanded {'+
19 - ' display:inline !important;'+
20 - ' visibility:visible !important;'+
21 - '}'
22 -);
23 -
24 -/*
25 - * Switch an RC line between hidden/shown
26 - * @param int idNumber : the id number of the RC group
27 -*/
28 -window.toggleVisibility = function(idNumber) {
29 - var openarrow = document.getElementById("mw-rc-openarrow-"+idNumber);
30 - var closearrow = document.getElementById("mw-rc-closearrow-"+idNumber);
31 - var subentries = document.getElementById("mw-rc-subentries-"+idNumber);
32 - if (openarrow.className == 'mw-changeslist-expanded') {
33 - openarrow.className = 'mw-changeslist-hidden';
34 - closearrow.className = 'mw-changeslist-expanded';
35 - subentries.className = 'mw-changeslist-expanded';
36 - } else {
37 - openarrow.className = 'mw-changeslist-expanded';
38 - closearrow.className = 'mw-changeslist-hidden';
39 - subentries.className = 'mw-changeslist-hidden';
40 - }
41 -};
Index: trunk/phase3/skins/common/shared.css
@@ -827,18 +827,6 @@
828828 word-wrap: break-word;
829829 }
830830
831 -table.mw-enhanced-rc {
832 - background: none;
833 - border:0;
834 - border-spacing:0;
835 -}
836 -td.mw-enhanced-rc {
837 - white-space:nowrap;
838 - padding:0;
839 - vertical-align:top;
840 - font-family:monospace
841 -}
842 -
843831 #mw-addcategory-prompt {
844832 display: inline;
845833 margin-left: 1em;
Index: trunk/phase3/includes/OutputPage.php
@@ -1617,7 +1617,7 @@
16181618 $sk = $wgUser->getSkin();
16191619
16201620 // Add base resources
1621 - $this->addModules( array( 'mediawiki.legacy.wikibits', 'mediawiki.util' ) );
 1621+ $this->addModules( array( 'mediawiki.legacy.wikibits', 'mediawiki.util', 'skins.common' ) );
16221622
16231623 // Add various resources if required
16241624 if ( $wgUseAjax ) {
Index: trunk/phase3/includes/ChangesList.php
@@ -30,7 +30,7 @@
3131 class ChangesList {
3232 public $skin;
3333 protected $watchlist = false;
34 -
 34+
3535 /**
3636 * Changeslist contructor
3737 * @param $skin Skin
@@ -81,21 +81,19 @@
8282 }
8383 }
8484
85 -
8685 /**
8786 * Returns the appropriate flags for new page, minor change and patrolling
88 - * @param $new Boolean
89 - * @param $minor Boolean
90 - * @param $patrolled Boolean
 87+ * @param $flags Associative array of 'flag' => Bool
9188 * @param $nothing String to use for empty space
92 - * @param $bot Boolean
9389 * @return String
9490 */
95 - protected function recentChangesFlags( $new, $minor, $patrolled, $nothing = ' ', $bot = false ) {
96 - $f = $new ? self::flag( 'newpage' ) : $nothing;
97 - $f .= $minor ? self::flag( 'minor' ) : $nothing;
98 - $f .= $bot ? self::flag( 'bot' ) : $nothing;
99 - $f .= $patrolled ? self::flag( 'unpatrolled' ) : $nothing;
 91+ protected function recentChangesFlags( $flags, $nothing = ' ' ) {
 92+ $f = '';
 93+ foreach( array( 'newpage', 'minor', 'bot', 'unpatrolled' ) as $flag ){
 94+ $f .= isset( $flags[$flag] ) && $flags[$flag]
 95+ ? self::flag( $flag )
 96+ : $nothing;
 97+ }
10098 return $f;
10199 }
102100
@@ -111,22 +109,18 @@
112110 public static function flag( $key ) {
113111 static $messages = null;
114112 if ( is_null( $messages ) ) {
115 - foreach ( explode( ' ', 'minoreditletter boteditletter newpageletter ' .
116 - 'unpatrolledletter recentchanges-label-minor recentchanges-label-bot ' .
117 - 'recentchanges-label-newpage recentchanges-label-unpatrolled' ) as $msg ) {
118 - $messages[$msg] = wfMsgExt( $msg, 'escapenoentities' );
 113+ $messages = array(
 114+ 'newpage' => array( 'newpageletter', 'recentchanges-label-newpage' ),
 115+ 'minor' => array( 'minoreditletter', 'recentchanges-label-minor' ),
 116+ 'bot' => array( 'boteditletter', 'recentchanges-label-bot' ),
 117+ 'unpatrolled' => array( 'unpatrolledletter', 'recentchanges-label-unpatrolled' ),
 118+ );
 119+ foreach( $messages as $key => &$value ) {
 120+ $value[0] = wfMsgExt( $value[0], 'escapenoentities' );
 121+ $value[1] = wfMsgExt( $value[1], 'escapenoentities' );
119122 }
120123 }
121 - # Inconsistent naming, bleh
122 - if ( $key == 'newpage' || $key == 'unpatrolled' ) {
123 - $key2 = $key;
124 - } else {
125 - $key2 = $key . 'edit';
126 - }
127 - return "<abbr class=\"$key\" title=\""
128 - . $messages["recentchanges-label-$key"] . "\">"
129 - . $messages["${key2}letter"]
130 - . '</abbr>';
 124+ return "<abbr class='$key' title='" . $messages[$key][1] . "'>" . $messages[$key][0] . '</abbr>';
131125 }
132126
133127 /**
@@ -507,8 +501,15 @@
508502 } else {
509503 $this->insertDiffHist( $s, $rc, $unpatrolled );
510504 # M, N, b and ! (minor, new, bot and unpatrolled)
511 - $s .= $this->recentChangesFlags( $rc->mAttribs['rc_new'], $rc->mAttribs['rc_minor'],
512 - $unpatrolled, '', $rc->mAttribs['rc_bot'] );
 505+ $s .= $this->recentChangesFlags(
 506+ array(
 507+ 'new' => $rc->mAttribs['rc_new'],
 508+ 'minor' => $rc->mAttribs['rc_minor'],
 509+ 'unpatrolled' => $unpatrolled,
 510+ 'bot' => $rc->mAttribs['rc_bot']
 511+ ),
 512+ ''
 513+ );
513514 $this->insertArticleLink( $s, $rc, $unpatrolled, $watched );
514515 }
515516 # Edit/log timestamp
@@ -566,7 +567,7 @@
567568 $this->rcCacheIndex = 0;
568569 $this->lastdate = '';
569570 $this->rclistOpen = false;
570 - $wgOut->addModules( 'mediawiki.legacy.enhancedchanges' );
 571+ $wgOut->addModuleStyles( 'mediawiki.special.changeslist' );
571572 return '';
572573 }
573574 /**
@@ -739,9 +740,9 @@
740741 # Add the namespace and title of the block as part of the class
741742 if ( $block[0]->mAttribs['rc_log_type'] ) {
742743 # Log entry
743 - $classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-log-' . $block[0]->mAttribs['rc_log_type'] . '-' . $block[0]->mAttribs['rc_title'] );
 744+ $classes = 'collapsible collapsed mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-log-' . $block[0]->mAttribs['rc_log_type'] . '-' . $block[0]->mAttribs['rc_title'] );
744745 } else {
745 - $classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-ns' . $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
 746+ $classes = 'collapsible collapsed mw-enhanced-rc ' . Sanitizer::escapeClass( 'mw-changeslist-ns' . $block[0]->mAttribs['rc_namespace'] . '-' . $block[0]->mAttribs['rc_title'] );
746747 }
747748 $r = Html::openElement( 'table', array( 'class' => $classes ) ) .
748749 Html::openElement( 'tr' );
@@ -804,23 +805,28 @@
805806 $users = ' <span class="changedby">[' .
806807 implode( $this->message['semicolon-separator'], $users ) . ']</span>';
807808
808 - # ID for JS visibility toggle
809 - $jsid = $this->rcCacheIndex;
810 - # onclick handler to toggle hidden/expanded
811 - $toggleLink = "onclick='toggleVisibility($jsid); return false'";
812809 # Title for <a> tags
813810 $expandTitle = htmlspecialchars( wfMsg( 'rc-enhanced-expand' ) );
814811 $closeTitle = htmlspecialchars( wfMsg( 'rc-enhanced-hide' ) );
815812
816 - $tl = "<span id='mw-rc-openarrow-$jsid' class='mw-changeslist-expanded' style='visibility:hidden'><a href='#' $toggleLink title='$expandTitle'>" . $this->sideArrow() . "</a></span>";
817 - $tl .= "<span id='mw-rc-closearrow-$jsid' class='mw-changeslist-hidden' style='display:none'><a href='#' $toggleLink title='$closeTitle'>" . $this->downArrow() . "</a></span>";
818 - $r .= '<td class="mw-enhanced-rc">'.$tl.'&#160;';
 813+ $tl = "<span class='collapsible-expander'>"
 814+ . "<span class='mw-rc-openarrow'>"
 815+ . "<a href='#' title='$expandTitle'>{$this->arrow( 'd', '-', wfMsg( 'rc-enhanced-hide' ) )}</a>"
 816+ . "</span><span class='mw-rc-closearrow'>"
 817+ . "<a href='#' title='$closeTitle'>{$this->arrow( 'd', '-', wfMsg( 'rc-enhanced-hide' ) )}</a>"
 818+ . "</span></span>";
 819+ $r .= "<td>$tl</td>";
819820
820821 # Main line
821 - $r .= $this->recentChangesFlags( $isnew, false, $unpatrolled, '&#160;', $bot );
 822+ $r .= '<td class="mw-enhanced-rc">' . $this->recentChangesFlags( array(
 823+ 'new' => $isnew,
 824+ 'minor' => false,
 825+ 'unpatrolled' => $unpatrolled,
 826+ 'bot' => $bot ,
 827+ ) );
822828
823829 # Timestamp
824 - $r .= '&#160;'.$block[0]->timestamp.'&#160;</td><td style="padding:0px;">';
 830+ $r .= '&#160;'.$block[0]->timestamp.'&#160;</td><td>';
825831
826832 # Article link
827833 if( $namehidden ) {
@@ -908,11 +914,7 @@
909915 $r .= $users;
910916 $r .= $this->numberofWatchingusers($block[0]->numberofWatchingusers);
911917
912 - $r .= "</td></tr></table>\n";
913 -
914918 # Sub-entries
915 - $r .= '<div id="mw-rc-subentries-'.$jsid.'" class="mw-changeslist-hidden">';
916 - $r .= '<table class="mw-enhanced-rc">';
917919 foreach( $block as $rcObj ) {
918920 # Extract fields from DB into the function scope (rc_xxxx variables)
919921 // FIXME: Would be good to replace this extract() call with something
@@ -922,10 +924,14 @@
923925 extract( $rcObj->mAttribs );
924926
925927 #$r .= '<tr><td valign="top">'.$this->spacerArrow();
926 - $r .= '<tr><td style="vertical-align:top;font-family:monospace; padding:0px;">';
927 - $r .= $this->spacerIndent() . $this->spacerIndent();
928 - $r .= $this->recentChangesFlags( $rc_new, $rc_minor, $rcObj->unpatrolled, '&#160;', $rc_bot );
929 - $r .= '&#160;</td><td style="vertical-align:top; padding:0px;"><span style="font-family:monospace">';
 928+ $r .= '<tr><td></td><td class="mw-enhanced-rc">';
 929+ $r .= $this->recentChangesFlags( array(
 930+ 'new' => $rc_new,
 931+ 'minor' => $rc_minor,
 932+ 'unpatrolled' => $rcObj->unpatrolled,
 933+ 'bot' => $rc_bot,
 934+ ) );
 935+ $r .= '&#160;</td><td class="mw-enhanced-rc-nested"><span class="mw-enhanced-rc-time">';
930936
931937 $params = $queryParams;
932938
@@ -983,7 +989,7 @@
984990
985991 $r .= "</td></tr>\n";
986992 }
987 - $r .= "</table></div>\n";
 993+ $r .= "</table>\n";
988994
989995 $this->rcCacheIndex++;
990996
@@ -1008,42 +1014,6 @@
10091015 }
10101016
10111017 /**
1012 - * Generate HTML for a right- or left-facing arrow,
1013 - * depending on language direction.
1014 - * @return String: HTML <img> tag
1015 - */
1016 - protected function sideArrow() {
1017 - global $wgContLang;
1018 - $dir = $wgContLang->isRTL() ? 'l' : 'r';
1019 - return $this->arrow( $dir, '+', wfMsg( 'rc-enhanced-expand' ) );
1020 - }
1021 -
1022 - /**
1023 - * Generate HTML for a down-facing arrow
1024 - * depending on language direction.
1025 - * @return String: HTML <img> tag
1026 - */
1027 - protected function downArrow() {
1028 - return $this->arrow( 'd', '-', wfMsg( 'rc-enhanced-hide' ) );
1029 - }
1030 -
1031 - /**
1032 - * Generate HTML for a spacer image
1033 - * @return String: HTML <img> tag
1034 - */
1035 - protected function spacerArrow() {
1036 - return $this->arrow( '', codepointToUtf8( 0xa0 ) ); // non-breaking space
1037 - }
1038 -
1039 - /**
1040 - * Add a set of spaces
1041 - * @return String: HTML <td> tag
1042 - */
1043 - protected function spacerIndent() {
1044 - return '&#160;&#160;&#160;&#160;&#160;';
1045 - }
1046 -
1047 - /**
10481018 * Enhanced RC ungrouped line.
10491019 * @return String: a HTML formated line (generated using $r)
10501020 */
@@ -1068,14 +1038,19 @@
10691039 $r = Html::openElement( 'table', array( 'class' => $classes ) ) .
10701040 Html::openElement( 'tr' );
10711041
1072 - $r .= '<td class="mw-enhanced-rc">' . $this->spacerArrow() . '&#160;';
 1042+ $r .= '<td class="mw-enhanced-rc">' . $this->arrow( '', codepointToUtf8( 0xa0 ) );
10731043 # Flag and Timestamp
10741044 if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
10751045 $r .= '&#160;&#160;&#160;&#160;'; // 4 flags -> 4 spaces
10761046 } else {
1077 - $r .= $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $rcObj->unpatrolled, '&#160;', $rc_bot );
 1047+ $r .= $this->recentChangesFlags( array(
 1048+ 'new' => $rc_type == RC_NEW,
 1049+ 'minor' => $rc_minor,
 1050+ 'unpatrolled' => $rcObj->unpatrolled,
 1051+ 'bot' => $rc_bot
 1052+ ) );
10781053 }
1079 - $r .= '&#160;'.$rcObj->timestamp.'&#160;</td><td style="padding:0px;">';
 1054+ $r .= '&#160;'.$rcObj->timestamp.'&#160;</td><td>';
10801055 # Article or log link
10811056 if( $rc_log_type ) {
10821057 $logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL );
Index: trunk/phase3/resources/Resources.php
@@ -10,6 +10,16 @@
1111 'user.options' => array( 'class' => 'ResourceLoaderUserOptionsModule' ),
1212
1313 /* Skins */
 14+
 15+ 'skins.common' => array(
 16+ 'scripts' => 'resources/skins.common/skins.common.js',
 17+ 'styles' => array(
 18+ 'resources/skins.common/skins.common.css',
 19+ 'resources/skins.common/skins.common.print.css' => array( 'media' => 'print' )
 20+ ),
 21+ 'messages' => array( 'hide', 'show' ),
 22+ 'dependencies' => array( 'jquery.effects.fade' ),
 23+ ),
1424
1525 'skins.vector' => array(
1626 'styles' => array( 'skins/vector/screen.css' => array( 'media' => 'screen' ) )
@@ -292,6 +302,10 @@
293303 'scripts' => 'resources/jquery.effects/jquery.effects.explode.js',
294304 'dependencies' => 'jquery.effects.core',
295305 ),
 306+ 'jquery.effects.fade' => array(
 307+ 'scripts' => 'resources/jquery.effects/jquery.effects.fade.js',
 308+ 'dependencies' => 'jquery.effects.core',
 309+ ),
296310 'jquery.effects.fold' => array(
297311 'scripts' => 'resources/jquery.effects/jquery.effects.fold.js',
298312 'dependencies' => 'jquery.effects.core',
@@ -348,6 +362,9 @@
349363 'scripts' => 'resources/mediawiki.special/mediawiki.special.preferences.js',
350364 'styles' => 'resources/mediawiki.special/mediawiki.special.preferences.css',
351365 ),
 366+ 'mediawiki.special.changeslist' => array(
 367+ 'styles' => 'resources/mediawiki.special/mediawiki.special.changeslist.css',
 368+ ),
352369 'mediawiki.special.search' => array(
353370 'scripts' => 'resources/mediawiki.special/mediawiki.special.search.js',
354371 ),
@@ -433,10 +450,6 @@
434451 'scripts' => 'skins/common/edit.js',
435452 'dependencies' => 'mediawiki.legacy.wikibits',
436453 ),
437 - 'mediawiki.legacy.enhancedchanges' => array(
438 - 'scripts' => 'skins/common/enhancedchanges.js',
439 - 'dependencies' => 'mediawiki.legacy.wikibits',
440 - ),
441454 'mediawiki.legacy.history' => array(
442455 'scripts' => 'skins/common/history.js',
443456 'dependencies' => 'mediawiki.legacy.wikibits',
Index: trunk/phase3/resources/mediawiki.special/mediawiki.special.changeslist.css
@@ -0,0 +1,40 @@
 2+/**
 3+ * Styling for Special:Watchlist and Special:RecentChanges
 4+ */
 5+
 6+table.mw-enhanced-rc {
 7+ background: none;
 8+ border:0;
 9+ border-spacing:0;
 10+}
 11+
 12+table.mw-enhanced-rc th, table.mw-enhanced-rc td {
 13+ padding:0;
 14+ vertical-align:top;
 15+}
 16+
 17+td.mw-enhanced-rc {
 18+ white-space:nowrap;
 19+ font-family:monospace;
 20+}
 21+
 22+.mw-enhanced-rc-time {
 23+ font-family: monospace;
 24+}
 25+
 26+table.mw-enhanced-rc td.mw-enhanced-rc-nested {
 27+ padding-left: 1em;
 28+}
 29+
 30+/* Show/hide arrows in enhanced changeslist */
 31+.mw-enhanced-rc .collapsible-expander {
 32+ float: none;
 33+}
 34+
 35+.mw-rc-openarrow,
 36+.show .mw-rc-closearrow {
 37+ display: none;
 38+}
 39+.show .mw-rc-openarrow {
 40+ display: inline;
 41+}
Property changes on: trunk/phase3/resources/mediawiki.special/mediawiki.special.changeslist.css
___________________________________________________________________
Added: svn:eol-style
142 + native
Index: trunk/phase3/resources/jquery.effects/jquery.effects.fade.js
@@ -0,0 +1,32 @@
 2+/*
 3+* jQuery UI Effects Fade @VERSION
 4+*
 5+* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 6+* Dual licensed under the MIT or GPL Version 2 licenses.
 7+* http://jquery.org/license
 8+*
 9+* http://docs.jquery.com/UI/Effects/Fade
 10+*
 11+* Depends:
 12+* jquery.effects.core.js
 13+*/
 14+(function( $, undefined ) {
 15+
 16+ $.effects.fade = function(o) {
 17+ return this.queue(function() {
 18+ var elem = $(this),
 19+ mode = $.effects.setMode(elem, o.options.mode || 'hide');
 20+
 21+ elem.animate({ opacity: mode }, {
 22+ queue: false,
 23+ duration: o.duration,
 24+ easing: o.options.easing,
 25+ complete: function() {
 26+ (o.callback && o.callback.apply(this, arguments));
 27+ elem.dequeue();
 28+ }
 29+ });
 30+ });
 31+ };
 32+
 33+})(jQuery);
\ No newline at end of file
Property changes on: trunk/phase3/resources/jquery.effects/jquery.effects.fade.js
___________________________________________________________________
Added: svn:eol-style
134 + native
Index: trunk/phase3/resources/skins.common/skins.common.print.css
@@ -0,0 +1,19 @@
 2+/**
 3+ * Uncollapse collapsible tables/divs. The proper way to do this
 4+ * for tables is to use display:table-row, but this is not supported
 5+ * by all browsers, so use display:block as fallback. Equally, the >
 6+ * selector is not supported by IE<7, so the fourth rule is recognised
 7+ * only by IE6 and below.
 8+ */
 9+table.collapsible tr {
 10+ display: block !important;
 11+}
 12+table.collapsible tr {
 13+ display: table-row !important;
 14+}
 15+div.collapsible > * {
 16+ display: auto !important;
 17+}
 18+* html div.collapsible * {
 19+ display: auto !important;
 20+}
\ No newline at end of file
Property changes on: trunk/phase3/resources/skins.common/skins.common.print.css
___________________________________________________________________
Added: svn:eol-style
121 + native
Index: trunk/phase3/resources/skins.common/skins.common.css
@@ -0,0 +1,24 @@
 2+/**
 3+ * 'show'/'hide' buttons created dynamically
 4+ * by the CollapsibleTables javascript
 5+ */
 6+.collapsible-expander {
 7+ float: right;
 8+ font-weight: normal;
 9+ text-align: right;
 10+ width: auto;
 11+}
 12+
 13+/**
 14+ * Note that IE<7 sees the second selector here as
 15+ * just ".collapsible-expander", and doesn't accept
 16+ * the multiple classes. Fortunately these two cursors
 17+ * are generally the same, a pair of up-and-down arrows.
 18+ */
 19+ .collapsible-expander {
 20+ cursor: n-resize;
 21+}
 22+.show.collapsible-expander {
 23+ cursor: s-resize;
 24+}
 25+
Property changes on: trunk/phase3/resources/skins.common/skins.common.css
___________________________________________________________________
Added: svn:eol-style
126 + native
Index: trunk/phase3/resources/skins.common/skins.common.js
@@ -0,0 +1,99 @@
 2+/*
 3+ * Scripts common to all skins
 4+ */
 5+
 6+/**
 7+ * Collapsible tables and divs.
 8+ *
 9+ * Users can create tables and nested divs which collapse either on-click or on-load,
 10+ * to save space on a page, or to conceal information at first sight. Eg:
 11+ *
 12+ * <table class="wikitable collapsible collapsed"><tr>
 13+ * <th>A table header which will always be visible</th>
 14+ * </tr><tr>
 15+ * <td>A table cell which will be hidden on page-load</td>
 16+ * </tr></table>
 17+ *
 18+ * <div class="collapsible collapsed">
 19+ * Content which will always be visible
 20+ * <span class="collapsible-expander">Click me!</span>
 21+ * <div>
 22+ * This content will be hidden until the span above is clicked
 23+ * </div>
 24+ * </div>
 25+ *
 26+ * If the user does not create a toggle-button manually, one will be created,
 27+ * in the top-right header cell for tables, and at the beginning of the outer
 28+ * div's content for a collapsible div.
 29+ * @author Happy-melon
 30+ */
 31+$('.collapsible').each( function(){
 32+ var $x = $j(this);
 33+ if( $('.collapsible-expander', $x).size() ){
 34+ $('.collapsible-expander', $x)
 35+ .click(function(e, rmClass){
 36+ e.preventDefault();
 37+ rmClass = !(rmClass == false);
 38+ $(this)
 39+ .toggleClass('show')
 40+ .trigger('mw-toggle-collapse', [rmClass]);
 41+ return false;
 42+ });
 43+ } else {
 44+ $expander = $j('<div class="collapsible-expander">')
 45+ .text( '[' + mediaWiki.msg( 'hide' ) + ']' )
 46+ .click(function(e, rmClass){
 47+ rmClass = !(rmClass == false);
 48+ e.preventDefault();
 49+ $(this)
 50+ .toggleClass('show')
 51+ .trigger('mw-toggle-collapse', [rmClass])
 52+ .text(
 53+ '[' +
 54+ ($(this).is('.collapsible.collapsed .collapsible-expander')
 55+ ? mediaWiki.msg( 'show' )
 56+ : mediaWiki.msg( 'hide' )) +
 57+ ']'
 58+ );
 59+ return true;
 60+ })
 61+ .before('[').after(']');
 62+ if( $x.is('div.collapsible')){
 63+ $x.prepend($expander);
 64+ } else {
 65+ $('tr:first th:last',$x).append($expander);
 66+ }
 67+ }
 68+
 69+});
 70+
 71+/**
 72+ * This is a bit nasty because it also toggles any nested
 73+ * collapsible objects. But it would be a nightmare to only
 74+ * select the outer collapser without adding ids everywhere.
 75+ */
 76+$('table.collapsible').live( 'mw-toggle-collapse', function(e, rmClass){
 77+ e.stopPropagation();
 78+ var time = rmClass ? 500 : 0;
 79+ $('tr:gt(0)',$(this))
 80+ // We'd like to use slideToggle() like for divs, but the jQuery
 81+ // slide animation for table rows is just *pig ugly*...
 82+ .toggle("fade", { direction: "vertical" }, time);
 83+ if( rmClass ){
 84+ $('table.collapsible',$(this)).andSelf().toggleClass('collapsed');
 85+ }
 86+ return true;
 87+});
 88+
 89+$('div.collapsible').live( 'mw-toggle-collapse', function(e, rmClass){
 90+ e.stopPropagation();
 91+ var time = rmClass ? 500 : 0;
 92+ $(this).children(':not(.collapsible-expander)')
 93+ .slideToggle(time);
 94+ if( rmClass ){
 95+ $('div.collapsible',$(this)).andSelf().toggleClass('collapsed');
 96+ }
 97+ return true;
 98+});
 99+
 100+$('.collapsible.collapsed .collapsible-expander').trigger( 'click', [false] );
\ No newline at end of file
Property changes on: trunk/phase3/resources/skins.common/skins.common.js
___________________________________________________________________
Added: svn:eol-style
1101 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r78889Follow-up r78865 CR; restore arrow helper functions, fixing fatal on TWN.happy-melon15:03, 23 December 2010
r78891Follow-up r78865 CRhappy-melon16:21, 23 December 2010
r78987Reverting r78889 and r78865. Breaks changeslist on translatewiki (unpatrolled...krinkle00:29, 25 December 2010
r81177Removing more, no longer needed, overrides for the white table background (w...krinkle23:30, 28 January 2011

Comments

#Comment by Krinkle (talk | contribs)   01:19, 23 December 2010
+table.collapsible tr {
+    display: block !important;
+}
+table.collapsible tr {
+    display: table-row !important;
+}

One is redundant.

[CSS]
div.collapsible > * {
...

[JS]
if( $x.is('div.collapsible')){
..
$('div.collapsible')

.collapsible should be usable for any element, not just for div's and tables. There's <p>, <pre>, <center>, <blockquote> etc.

I'm not sure what $.effects.fade is suposed to do what jQuery's core fadeIn() and fadeOut() don't. Please document this in the plugin file.


+				return true;
+			})
+			.before('[').after(']');

There is a [ and ] added already a few lines higher with text()

 	/* Skins */
+	
+	'skins.common' => array(

Although a common file will most likely be needed, I think something like this is best written as a jQuery plugin. Which enables adding elements like these dynamically as well (ie. javascript tools which add a table dynamically)

In the init-function could be a call to automatically enable the functionality on all .collapsible-elements that are on the page when the dom is ready.

ie.

$.fn.collapsibleElement = 
   ....


init:
$('.collapsible').collapsibleElement();
#Comment by Krinkle (talk | contribs)   01:22, 23 December 2010
+table.collapsible tr {
+    display: block !important;
+}
+table.collapsible tr {
+    display: table-row !important;
+}

Never mind the comment about one being redundant, it does work this way - but perhaps we can come up with a nicer way.

#Comment by Happy-melon (talk | contribs)   12:15, 23 December 2010

How? This isn't even particularly ugly CSS hackery :D display:table-row is unsupported in IE8; it's going to have to stay like that for quite some time yet...

#Comment by Raymond (talk | contribs)   07:39, 23 December 2010

This change effects other extensions. Seen on Translatewiki:

PHP Fatal error: Call to undefined method NCL::downArrow() in /www/w/extensions/CleanChanges/CleanChanges_body.php on line 286
#Comment by Nikerabbit (talk | contribs)   13:23, 23 December 2010

+ . "<a href='#' title='$expandTitle'>{$this->arrow( 'd', '-', wfMsg( 'rc-enhanced-hide' ) )}</a>"

+			. "<a href='#' title='$closeTitle'>{$this->arrow( 'd', '-', wfMsg( 'rc-enhanced-hide' ) )}</a>"

One of them is wrong.

I don't like that the arrow helper methods were removed. The direct arrow() calls are much less readable without context.

BC needs to be kept and/or the CleanChanges extension updated. This blocks localisation of MediaWiki core.

#Comment by Happy-melon (talk | contribs)   15:05, 23 December 2010

Restored in r78889.

#Comment by Krinkle (talk | contribs)   14:53, 23 December 2010
{| class="wikitable sortable collapsible collapsed"
! Head
! Top
|-
| Con
| Tent
|}

I saved this to a page in my local install. The [Show] link appeared in the <th>Top</th>, but clicking it did nothing. No errors either.

The link should appear as a link (blue) instead of text, for consistency.

#Comment by Happy-melon (talk | contribs)   15:23, 23 December 2010

This is an interaction with the sortabletables code; I'm not entirely sure what. The click event is never fired for the show/hide toggle, so I suspect the sortable code is intercepting and stopping its propagation.

I don't particularly see why they should be links; the whole point of the collapsible-expander class is that they can now be anything. There's an obvious usage in the collapsible divs case in particular in making the whole title the expand link, so clicking anywhere on it expands the content.

#Comment by Krinkle (talk | contribs)   15:28, 23 December 2010

Although I too can't say for sure at this point what the cause is (could be the sortable code), I recommmend first we finish porting legacy to the new stuff first and making sure it works fine with existing articles etc. – before introducing new things like this.

#Comment by Happy-melon (talk | contribs)   16:27, 23 December 2010

By the time I've committed the ToC handling, I'll have replaced over a hundred lines of legacy code; this is migration to the new system.

#Comment by Krinkle (talk | contribs)   16:32, 23 December 2010

The reason the [show]/[hide] doesn't work inside the tablecell is because a few lines in teh Wikibits use "innerHTML =+" which replaces it's content with something added to it, thus removing any binded handlers to it.

And, although I dont know for sure if you mean this one, the toggleToc function has been assigned to me (bug 26324) and I'm already working on it locally. I would appreciate it if you let me finish it.

#Comment by Krinkle (talk | contribs)   16:37, 23 December 2010

Fixed in r78893.

#Comment by Happy-melon (talk | contribs)   16:45, 23 December 2010

Cool, thanks.

The frontend of the toggleToc() is literally twenty lines:

Index: includes/Linker.php
===================================================================
--- includes/Linker.php	(revision 78891)
+++ includes/Linker.php	(working copy)
@@ -1332,11 +1332,10 @@
 	 */
 	function tocList( $toc ) {
 		$title = wfMsgHtml( 'toc' ) ;
-		return
-		   '<table id="toc" class="toc"><tr><td>'
-		 . '<div id="toctitle"><h2>' . $title . "</h2></div>\n"
-		 . $toc
-		 . "</ul>\n</td></tr></table>\n";
+		return  '<table id="toc" class="toc collapsible"><tr>'
+			. '<th id="toctitle">' . $title . "</th></tr>\n"
+			. '<tr><td>' . $toc
+			. "</ul>\n</td></tr></table>\n";
 	}
 
 	/**
Index: resources/skins.common/skins.common.js
===================================================================
--- resources/skins.common/skins.common.js	(revision 78891)
+++ resources/skins.common/skins.common.js	(working copy)
@@ -104,4 +104,19 @@
 }).trigger( 'click', [false] );
 
 
+$(function() {
+	var cookiePos = document.cookie.indexOf( "hidetoc=" );
+	if ( cookiePos > -1 && document.cookie.charAt( cookiePos + 8 ) == 1 ) {
+		$('#toc .collapsible-expander').click();
+	}
+});
 
+$('#toc .collapsible-expander').click( function() {
+	if ( $('#toc').is('.collapsed') ) {
+		document.cookie = "hidetoc=0";
+	} else {
+		document.cookie = "hidetoc=1";
+	}
+});

The cookie stuff is the only part of the javascript left; and that does indeed need some work.

#Comment by Catrope (talk | contribs)   17:15, 23 December 2010

You can use $.cookie for this, grep the resources directory for examples. Keep in mind that if you use the cookie plugin, the module you use it in has to be marked as depending on jquery.cookie in Resources.php

#Comment by Krinkle (talk | contribs)   15:11, 23 December 2010

<div class="collapsible collapsed">
Some text here.
{| class="wikitable collapsible"
! Hello
! World
|-
| Content
| Goes
|-
| In
| Here
|}
Some text here.
</div>

In the above test case the text and table should be hidden on load and appear when clicking "[Show]". But the table heading and the text around are visible by default. And the table in side is incorrectly defaulting to a collapsed-state.

All elements inside the collapsed-element are given display:none.

#Comment by Happy-melon (talk | contribs)   16:22, 23 December 2010

Fixed in r78891; seems that returning true from an event handler overrides e.stopPropagation().

#Comment by Krinkle (talk | contribs)   00:33, 25 December 2010

This commit broke changeslists on translatewiki (unpatrolled-flag exclamation mark popping up on page histories and and diff-views where they shouldn't instead of an 'm' for minor) - something with $oldminor = ChangesList::flag( 'minor' );.

Happy-melon mentioned earlier on IRC that it's okay to remove his collapsible implementation.

The skin.common module can be re-created when we need it again. Right now it would be left empty.

-- r78987

#Comment by Happy-melon (talk | contribs)   12:14, 26 December 2010

That would have been fairly simple to fix (it's clear that the grep on my IDE is totally FUBAR); but I agree that it's simplest from a CR perspective to clear this all out and start again. I'll reimplement the ChangesList changes with your makeCollapsible plugin now that it supports custom toggles.

Status & tagging log