Extension:SectionHide
![]() |
This extension stores its source code on a wiki page. Please be aware that this code may be unreviewed or maliciously altered. They may contain security holes, outdated interfaces that are no longer compatible etc. Note: No localisation updates are provided for this extension by translatewiki.net. |
SectionHide Release status: beta |
|||
---|---|---|---|
![]() |
|||
Implementation | User interface, Skin | ||
Description | Adds a link alongside edit links to collapse and expand sections of the article | ||
Author(s) | Simon Oliver (Hoggle42talk) | ||
Latest version | 1.7 (2014-08-26) | ||
MediaWiki | 1.19+ | ||
PHP | 5.5+ | ||
Database changes | No | ||
License | GNU General Public Licence 2.0 or later | ||
Download | See the code section | ||
|
|||
|
|||
Translate the SectionHide extension if it is available at translatewiki.net |
|||
Check usage and version matrix; code metrics |
The SectionHide extension adds a [hide] link wherever there is a section heading [edit] link. This link will hide all content between that section header and the next section header of the same level, changing itself to read [show] in the process. Clicking [show] will restore the section to view.
Contents
Example[edit | edit source]
Illustration showing how each hide link conceals the related block in a nested fashion while keeping the title visible.
Installation[edit | edit source]
- Copy the code and extract the tarball in your
extensions/
folder. It should generate a new folder calledSectionHide
directly inside yourextensions/
folder. - Add the following code at the bottom of your LocalSettings.php:
require_once "$IP/extensions/SectionHide/SectionHide.php";
- Done! Navigate to "Special:Version" on your wiki to verify that the extension is successfully installed.
Code[edit | edit source]
SectionHide.php[edit | edit source]
/**
* SectionHide extension - implements a hide/show link on sections on any ordinary page.
* @version 1.7 - 2014/08/26
* version 1.1 added a hide all/show all link for the entire article
* version 1.2 added an option on the hide all/show all link to show the initial text
* version 1.3 added opt out error if installed alongside header tabs
* version 1.4 added options for images as well as/instead of text
* version 1.5 tweaks to improve appearance under vector skin, class change
* version 1.6 options to show the link before the title and change the brackets
* version 1.7 changed the closing tags to adhere to strict html
*
* @link https://www.mediawiki.org/wiki/Extension:SectionHide Documentation
*
* @file
* @ingroup Extensions
* @package MediaWiki
* @author Simon Oliver
* @copyright © 2013 Simon Oliver (Hoggle42)
* @licence http://www.gnu.org/copyleft/gpl.html GNU General Public Licence 2.0 or later
*
* add the following line to localsettinge.php to use
* require_once("$IP/extensions/SectionHide/SectionHide.php");
* // Set this option to 1 to show the text before the first section when hiding all
* // Set to X to show the top x-1 sections (use with caution - some browsers may complain)
* // Set to -1 to disable
* $wgSectionHideShowtop = 0; //default
* // Set the first option to 1 to use images and add a relative path from the wiki root to the two images
* // Set the second option to 1 to not include the text as well as the image
* $wgSectionHideUseImages = 0; //default
* $wgSectionHideUseImagesOnly = 0; //default
* $wgSectionHideHideImage = ""; //default - set to e.g. "images/minus.gif" NB direction of slash
* $wgSectionHideShowImage = ""; //default - e.g. "images/plus.gif"
* // Use this option to show the link before the title (set to 1)
* $wgSectionHideb4title = 0; //default
* // These options allow you to change or hide the brackets
* $wgSectionHideopenbracket = "["; //default
* $wgSectionHideclosebracket = "]"; //default
*/
if( !defined( 'MEDIAWIKI' ) ) {
echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" );
die( 1 );
}
if( isset( $htUseHistory ) ) {
echo( "This extension should not be used in conjunction with the Header Tabs extension.\n" );
die( 1 );
}
$wgExtensionCredits['other'][] = array(
'name' => 'SectionHide',
'author' => 'Simon Oliver',
'version' => '1.7',
'url' => 'https://www.mediawiki.org/wiki/Extension:SectionHide',
'descriptionmsg' => 'sectionhide-desc',
);
$wgHooks['ParserAfterParse'][] = 'SectionHideHooks::onParserAfterParse';
$wgHooks['ParserSectionCreate'][] = 'SectionHideHooks::onParserSectionCreate';
$wgAutoloadClasses[ 'SectionHideHooks' ] = __DIR__ . '/SectionHideHooks.php';
$wgExtensionMessagesFiles[ 'SectionHide' ] = __DIR__ . '/SectionHide.i18n.php';
$wgExtensionMessagesFiles[ 'SectionHideAlias' ] = __DIR__ . '/SectionHide.alias.php';
SectionHideHooks.php[edit | edit source]
/**
* Body file for extension SectionHide.
*
* @file
* @ingroup Extensions
*/
# hooks class
class SectionHideHooks
{
public static function onParserSectionCreate( $parser, $section, &$sectionContent, $showEditLinks )
{
global $wgSectionHideUseImages, $wgSectionHideUseImagesOnly, $wgSectionHideHideImage, $wgSectionHideShowImage;
global $wgSectionHideopenbracket, $wgSectionHideclosebracket, $wgSectionHideb4title;
if ($showEditLinks && $section > 0)
{
$hidetext = wfMsg( 'sectionhide-hide' );
$showtext = wfMsg( 'sectionhide-show' );
$initialtext = $hidetext;
if ($wgSectionHideUseImages != 0)
{
if ($wgSectionHideUseImagesOnly == 0)
{
$initialtext = '<img src="'.$wgSectionHideHideImage.'">'.$hidetext;
$hidetext = $wgSectionHideHideImage.':'.$hidetext;
$showtext = $wgSectionHideShowImage.':'.$showtext;
}
else
{
$initialtext = '<img src="'.$wgSectionHideHideImage.'">';
$hidetext = $wgSectionHideHideImage.':';
$showtext = $wgSectionHideShowImage.':';
}
}
$divstart = '<div class="sectionblocks" id="sectionblock'.$section.'">';
$divend = '</div><!-- id="sectionblock'.$section.'" -->';
if($wgSectionHideb4title == 1)
{
$hidelink = '<span class="visibilitytoggle">'.$wgSectionHideopenbracket.'<a href="#" onclick="toggleSectionVisibility(this, '.$section.", '".$showtext."','".$hidetext."'".');">'.$initialtext.'</a>'.$wgSectionHideclosebracket.'</span>';
$sectionContent = preg_replace( '/<h[2-6]>/', "$0$hidelink", $sectionContent);
$sectionContent = preg_replace( '/<\/h[2-6]>/', "$0\n$divstart\n", $sectionContent);
}
else
{
$hidelink = '<span class="mw-editsection visibilitytoggle">'.$wgSectionHideopenbracket.'<a href="#" onclick="toggleSectionVisibility(this, '.$section.", '".$showtext."','".$hidetext."'".');">'.$initialtext.'</a>'.$wgSectionHideclosebracket.'</span>';
$sectionContent = preg_replace( '/<\/h[2-6]>/', "$hidelink$0\n$divstart\n", $sectionContent);
}
$sectionContent = $sectionContent."\n$divend\n";
}
return true;
}
public static function onParserAfterParse( &$parser, &$text, &$sstate )
{
global $wgSectionHideShowtop;
// need to nest sections by levels by moving around the closing tags
$numberofmatches = preg_match_all('#<h[2-6].*<\/h[2-6]>\n<div class="sectionblocks"#', $text, $matches, PREG_OFFSET_CAPTURE);
$closingdivmatches = preg_match_all('#<\/div><!-- id=#', $text, $divmatches, PREG_OFFSET_CAPTURE);
if($numberofmatches == $closingdivmatches && $numberofmatches > 1)
{
if( $wgSectionHideShowtop > $numberofmatches) $wgSectionHideShowtop = $numberofmatches; // cannot exceed the number of matches
$headlevel = array();
$i = 0;
foreach($matches[0] as $match)
{
$headlevel[$i] = substr($match[0],2,1); // heading level always third character
$i++;
}
$headlevel[$i] = 1; // make sure it terminates correctly
for($i = 0 ; $i < $numberofmatches - 1 ; $i++)
{
// the rule is:
// for each heading if the next level is lower, move the closing div to after the closing div of that level and re-test
// length of closing divs is </div><!-- id="sectionblock2" --> = 32 + number of digits of id (which is $i+1)
$divlength = 33 + ($i>98 ? 2 : ($i>8 ? 1 : 0)); //NB this should cope with up to 999 heading sections. Articles with more than that deserve to be broken
$j = 1;
while(($i+$j) < $numberofmatches && $headlevel[$i+$j] > $headlevel[$i])
{
// insert a closing div before the next heading, or at the end if no more headings
$text = insertAtLoc($text
, '</div><!-- id="sectionblock'.($i+1).'" -->'
, $divmatches[0][$i+$j][1] + $divlength + (($i+$j>98 && $i <= 8) ? 2 : ((($i+$j>98 && $i <= 98) || ($i+$j > 8 && $i <= 8)) ? 1 : 0))); // deal with situations where sublevel div is longer than parent level
$text = removeAtLoc($text, $divlength, $divmatches[0][$i][1]); // remove the closing div from its previous location
// update the current positions
$divmatches[0][$i][1] = $divmatches[0][$i+$j][1]; // is now where the sublevel div was
$divmatches[0][$i+$j][1] = $divmatches[0][$i+$j][1]-$divlength; // moves by divlength towards the start
$matches[0][$i+$j][1] = $matches[0][$i+$j][1]-$divlength; // moves by sublevel heading towards the start
$j++;
}
}
// new hide all link
if ( $wgSectionHideShowtop > 0 )
{
// insert a section zero opening div before the first section heading
$text = insertAtLoc($text, '<div class="sectionblocks" id="sectionblock0">', $matches[0][($wgSectionHideShowtop-1)][1]);
$text = '<p><span class="visibilitytoggle">[<a href="#" onclick="toggleSectionVisibility(this, 0,'."'"
.wfMsg( 'sectionhide-showall' )."','".wfMsg( 'sectionhide-hideall' )."'".')">'.wfMsg( 'sectionhide-hideall' )
.'</a>]</span></p>'
.$text
.'</div><!-- id="sectionblock0" -->';
}
elseif ( $wgSectionHideShowtop == 0 )
{
$text = '<p><span class="visibilitytoggle">[<a href="#" onclick="toggleSectionVisibility(this, 0,'."'"
.wfMsg( 'sectionhide-showall' )."','".wfMsg( 'sectionhide-hideall' )."'".')">'.wfMsg( 'sectionhide-hideall' )
.'</a>]</span></p><div class="sectionblocks" id="sectionblock0">'
.$text
.'</div><!-- id="sectionblock0" -->';
}
}
return true;
}
} # end of SectionHideHooks class
function insertAtLoc($subject, $toinsert, $atloc)
{
return substr($subject,0,$atloc).$toinsert.substr($subject,$atloc);
}
function removeAtLoc($subject, $remlength, $atloc)
{
return substr($subject,0,$atloc).substr($subject,$atloc+$remlength);
}
SectionHide.i18n.php[edit | edit source]
<?php /** * Internationalisation file for extension SectionHide (system messages). * * @file * @ingroup Extensions */ $messages = array(); /** English * @author Hoggle42 */ $messages['en'] = array( 'sectionhide' => 'Section Hide', 'sectionhide-desc' => 'Provides a hide/show link on section headings', 'sectionhide-hide' => 'hide', 'sectionhide-show' => 'show', 'sectionhide-hideall' => 'hide all', 'sectionhide-showall' => 'show all', ); /** German (Deutsch) * @author Kghbln */ $messages['de'] = array( 'sectionhide' => 'Section Hide', 'sectionhide-desc' => 'Stellt einen Link zum Ein- und Ausblenden von Abschnittsüberschriften bereit', 'sectionhide-hide' => 'ausblenden', 'sectionhide-show' => 'einblenden', 'sectionhide-hideall' => 'alle ausblenden', 'sectionhide-showall' => 'alle einblenden', ); /** French * @author Arcane21 */ $messages['fr'] = array( 'sectionhide' => 'Section Cacher', 'sectionhide-desc' => 'Fournit un lien de cacher/montrer sur les en-têtes de section', 'sectionhide-hide' => 'Cacher', 'sectionhide-show' => 'Montrer', 'sectionhide-hideall' => 'toute cacher', 'sectionhide-showall' => 'toute montrer', ); /** Spanish * @author Arcane21 */ $messages['es'] = array( 'sectionhide' => 'Sección Ocultar', 'sectionhide-desc' => 'Proporciona un enlace mostrar/ocultar en las partidas de la sección', 'sectionhide-hide' => 'Ocultar', 'sectionhide-show' => 'Mostrar', 'sectionhide-hideall' => 'todos ocultar', 'sectionhide-showall' => 'todos mostrar', );
SectionHide.alias.php[edit | edit source]
<?php /** * Internationalisation file for extension SectionHide (aliases). * * @file * @ingroup Extensions */ $aliases = array(); /** English * @author Simon Oliver (Hoggle42) */ $aliases['en'] = array( 'SectionHide' => array( 'SectionHide' ), );
Mediawiki:Common.js[edit | edit source]
Add this here, or in individual skins
function toggleSectionVisibility(fieldObj, id, txt1, txt2) { var e = document.getElementById('sectionblock'+id); if(txt1.search(/gif:/i) >= 0) txt1 = '<img src="'+txt1.replace(':', '">'); if(txt2.search(/gif:/i) >= 0) txt2 = '<img src="'+txt2.replace(':', '">'); if(fieldObj.innerHTML == txt1) { fieldObj.innerHTML = txt2; e.style.display = 'block'; } else { fieldObj.innerHTML = txt1; e.style.display = 'none'; } }
Versions[edit | edit source]
- Version 1.1
Added a hide/show all link at the top
- Version 1.2
Added an option to keep the content before the first X-1 headings visible when using the hide all link. NB set to 1 to hide everything from the first heading to the end.
Note: Using anything other than 1 means that divs are overlapping instead of nested, which is a standards violation in xhtml [1]. Mediawiki is still using HTML, however, so overlapping is tolerated and most browsers deal with it. Some may have issues. By the same token, any divs in the actual text that cross over headings will potentially cause a problem, which is why every closing tag added has an id attribute to match it with the opening tag.
- Version 1.3
added an opt-out error if installed alongside header tabs
- Version 1.4
Added an option to use images (NB gifs only but change the javascript if you want to use pngs or jpegs) instead of/alongside words - as per requested feature
Allow hideall to be disabled with setting less than zero - as requested
- Version 1.5
Resolved issues with display under Vector skin, resulting from renaming editsection class to mw-editsection in 1.22. Validated in 1.23.2
- Version 1.6
Added an option on request to show the link before the title (on purpose this time) and two more to change or leave out the brackets
- Version 1.7
Tweaked the closing div tag handling to avoid parser issues
Author Notes[edit | edit source]
Several similar extensions were created in the past, but they are not maintained and didn't do quite what I needed.