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.
Here is an example of the script in action:
<spoiler> The quick brown fox jumps over the lazy dog. How razorback-jumping frogs can level six piqued gymnasts! Back in June we delivered oxygen equipment of the same size. A quick movement of the enemy will jeopardize six gunboats. All questions asked by five watch experts amazed the judge. Crazy Fredericka bought many very exquisite opal jewels. Sixty zippers were quickly picked from the woven jute bag. John Prady, give me a black walnut box of quite small size. Big July earthquakes confound zany experimental vow. Six big devils from Japan quickly forgot how to waltz. My girl wove six dozen plaid jackets before she quit. Foxy parsons quiz & cajole the lovably dim wiki-girl. Cozy lummox gives smart squid who asks for job pen. Adjusting quiver and bow, Zompyc killed the fox. My faxed joke won a pager in the cable TV quiz show. Woven silk pyjamas exchanged for blue quartz. Brawny gods just flocked up to quiz and vex him. A wizard’s job is to vex chumps quietly in fog. </spoiler>
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; return true; } 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; } ?>