MediaWiki:Spoiler
Overview
Several people have asked me about the spoiler extension, so I figured I might as well release it to the public. The JavaScript and CSS are based around the Perplex City Card Catalog invisiclues I did earlier in the year. The MediaWiki plugin code is based on the Extending Wiki Markup article at MediaWiki.
Bugs
Keep in mind that only limited testing has been done on this extension. There is certainly an issue in the rare case that a browser supports CSS but not JavaScript: the spoilerized block starts out with the CSS "visibility:hidden" attribute with no way to switch it to visible.
If you find any bugs (or if you have fixes for bugs you've found--which is what I would much prefer), drop me a line at brian@{this domain name}.
TODO
- Spoilerized text should probably start out as being visible, with on-load JavaScript to hide it immediately. This would help in the case where a browser supports CSS but not JavaScript (e.g. the NoScript Firefox extension)
- There should probably be "media=print" CSS styles defined so that spoilerized text will be visible on printouts.
Installation
To install, simply copy spoiler.php (the code is below) to your mediawiki /extensions/ folder and add the following line to your LocalSettings.php:
require_once("$IP/extensions/spoiler.php");
This is the content of the spoiler.php file:
<?php # WikiMedia spoiler extension # <spoiler> some text </spoiler> # the function registered by the extension hides the text between the # tags behind a JavaScript spoiler block. # # (C) Copyright 2006, Brian Enigma <brian@netninja.com> # This work is licensed under a Creative Commons Attribution-Noncommercial-Share # Alike 2.5 License. Some rights reserved. # http://creativecommons.org/licenses/by-nc-sa/2.5/ $wgExtensionFunctions[] = "wfSpoilerExtension"; # $wgHooks['ParserBeforeTidy'][] = 'spoilerParserHook' ; $wgHooks['OutputPageBeforeHTML'][] = 'spoilerParserHook' ; function wfSpoilerExtension() { global $wgParser; # register the extension with the WikiText parser # the first parameter is the name of the new tag. # In this case it defines the tag <example> ... </example> # the second parameter is the callback function for # processing the text between the tags $wgParser->setHook( "spoiler", "renderSpoiler" ); } function wfSpoilerJavaScript() { return "<script language=\"JavaScript\">\n" . "\n" . "function getStyleObject(objectId) {\n" . " // checkW3C DOM, then MSIE 4, then NN 4.\n" . " //\n" . " if(document.getElementById) {\n" . " if (document.getElementById(objectId)) {\n" . " return document.getElementById(objectId).style;\n" . " }\n" . " } else if (document.all) {\n" . " if (document.all(objectId)) {\n" . " return document.all(objectId).style;\n" . " }\n" . " } else if (document.layers) { \n" . " if (document.layers[objectId]) { \n" . " return document.layers[objectId];\n" . " }\n" . " } else {\n" . " return false;\n" . " }\n" . "}\n" . "\n" . "function toggleObjectVisibility(objectId) {\n" . " // first get the object's stylesheet\n" . " var styleObject = getStyleObject(objectId);\n" . "\n" . " // then if we find a stylesheet, set its visibility\n" . " // as requested\n" . " //\n" . " if (styleObject) {\n" . " if (styleObject.visibility == 'hidden') {\n" . " styleObject.visibility = 'visible';\n" . " styleObject.position = 'relative';\n" . " } else {\n" . " styleObject.visibility = 'hidden';\n" . " styleObject.position = 'absolute';\n" . " }\n" . " return true;\n" . " } else {\n" . " return false;\n" . " }\n" . "}\n" . "</script>\n" . "<style type=\"text/css\"><!--\n" . "div.spoiler {border: dashed red 3px; background-color: #ffdddd; padding:3px;}\n" . "span.spoilerHeader {font-size:135%; color:#ff0000;}\n" . "a.spoilerLink {background-color:#ff0000; color:#ffff00; font-weight:bold; padding:4px 4px 2px 4px; border:solid black 1px;}\n" . "--></style>\n"; } function spoilerParserHook( &$parser , &$text ) { $text = wfSpoilerJavaScript() . $text; } function wfMakeSpoilerId() { $result = ""; for ($i=0; $i<20; $i++) $result .= chr(rand(ord('A'), ord('Z'))); return $result; } # The callback function for converting the input text to HTML output function renderSpoiler( $input, $argv, &$parser ) { # $argv is an array containing any arguments passed to the # extension like <example argument="foo" bar>.. # Put this on the sandbox page: (works in MediaWiki 1.5.5) # <example argument="foo" argument2="bar">Testing text **example** in between the new tags</example> $localParser = new Parser(); $outputObj = $localParser->parse($input, $parser->mTitle, $parser->mOptions); $spoilerId = wfMakeSpoilerId(); $output = "<a href=\"#\"onclick=\"toggleObjectVisibility('" . $spoilerId . "'); return false;\" class=\"spoilerLink\">"; $output .= "Click to reveal Spoiler</a>\n"; $output .= "<div id=\"" . $spoilerId . "\" class=\"spoiler\" style=\"visibility: hidden; position:absolute;\">\n"; $output .= "<span class=\"spoilerHeader\">SPOILER</span><br />\n"; $output .= $outputObj->getText() . "\n"; #$output .= $input . "\n"; $output .= "</div>\n"; # $output .= "Text passed into example extension: <br/>$input"; # $output .= " <br/> and the value for the arg 'argument' is " . $argv["argument"]; # $output .= " <br/> and the value for the arg 'argument2' is: " . $argv["argument2"]; return $output; } ?>