Table of Contents

Spoiler Plugin

Compatible with DokuWiki

  • 2024-02-06 "Kaos" unknown
  • 2023-04-04 "Jack Jackrum" unknown
  • 2022-07-31 "Igor" unknown
  • 2020-07-29 "Hogfather" no

plugin Adds initially hidden sections

Last updated on
2007-07-19
Provides
Syntax

Similar to folded, stepbystep, togglewrap, wrap

Tagged with hide

Spoiler tag for DokuWiki. Allows sections that are initially hidden, and are shown when a “Show” button is clicked. The spoiler can be hidden again by pressing the button. An optional title can be given, otherwise a “Spoiler:” text is shown before the button.

Syntax

<spoiler>Content with default title</spoiler>
<spoiler |Plot details>The butler did it!</spoiler>
<spoiler>
This spoiler contains another spoiler
<spoiler>8-o</spoiler>
</spoiler>

You can make a button for this code with plugin:custombuttons.

See https://wiki.hokkanen.org/projects/dokuwiki/spoiler FIXME for images, playground, and download.

Discussion

Patch to work with 2020-07-29 “Hogfather”
in lib/plugins/spoiler/syntax.php change the following lines (65+91)

function handle($match, $state, $pos, &$handler){
function render($mode, &$renderer, $data) {

to

function handle($match, $state, $pos, Doku_Handler $handler){
function render($mode, Doku_Renderer $renderer, $data) {

– halbbit 2021-01-23


I'd like to see it work within a list

  * <spoiler>
    * Foo
    * Bar
    </spoiler>

This would be a very helpful bonus to this already very helpful plugin.

Yes, it doesn't work with latest Dokuwiki version. Perhaps author would never come with solution as plugin released in 2007…


Patch to provide control over all 'spoiler' items in a page

Usage:

%%~~SPOILER:open|Label Text~~%%
%%~~SPOILER:close|Label Text~~%%
%%~~SPOILER:hide|Label Text~~%%
%%~~SPOILER~~%%

Default behaviour is open, which is to un-hide all spoiler items, this is opposite of using <spoiler> without ~~SPOILER~~.

Permitted modes are:

The Label Text works similar to <spoiler>.

Here are the code changes to style.css and syntax.php:

*** ./style.css Wed Jul 18 14:14:43 2007
--- ./new_style.css     Tue Nov 17 15:43:41 2009
***************
*** 24,26 ****
--- 24,47 ----
        margin-top: 0.5em;
  }
 
+ .spoilerctrl {
+       margin-top: 0.5em;
+       margin-bottom: 1em;
+ }
+
+ .spoilerctrl .title {
+       /* font-size: 110%; */
+       font-size: 90%;
+       font-weight: bold;
+       display: block;
+       float: left;
+ }
+
+ .spoilerctrl .title:after {
+       content: ': ';
+ }
+
+
+ .spoilerctrl input {
+       font-size: 70%;
+ }
*** ./syntax.php        Thu Jul 19 15:32:57 2007
--- ./new_syntax.php    Tue Nov 17 15:43:41 2009
***************
*** 56,61 ****
--- 56,62 ----
        function connectTo($mode) {
                // Lookahead assertion: check that there is an end tag.
                $this->Lexer->addEntryPattern('<spoiler[^>\r\n]*?>(?=.*?</spoiler>)', $mode, 'plugin_spoiler');
+               $this->Lexer->addSpecialPattern('~~SPOILER[^~\r\n]*?~~', $mode, 'plugin_spoiler');
        }
 
        function postConnect() {
***************
*** 73,88 ****
                                        $title = substr($options, strpos($options, '|') + 1);
                                }
 
!                               return array($state, $title);
                                break;
                        case DOKU_LEXER_MATCHED :
                                break;
                        case DOKU_LEXER_UNMATCHED :
!                               return array($state, $match);
                                break;
                        case DOKU_LEXER_EXIT :
                                break;
                        case DOKU_LEXER_SPECIAL :
                                break;
                }
                return array($state);
--- 74,108 ----
                                        $title = substr($options, strpos($options, '|') + 1);
                                }
 
!                               return array($state, $title, '');
                                break;
                        case DOKU_LEXER_MATCHED :
                                break;
                        case DOKU_LEXER_UNMATCHED :
!                               return array($state, $match, '');
                                break;
                        case DOKU_LEXER_EXIT :
                                break;
                        case DOKU_LEXER_SPECIAL :
+                               // "~~SPOILER" options "~~"
+                               $options = substr($match, 8, -2);
+
+                                 $endPos = strlen($options) + 1;
+                               if (strpos($options, '|') !== False) {
+                                         $endPos = strpos($options,'|');
+                                       $title = substr($options, $endPos + 1);
+                               }
+
+                                 $switch = 'show';
+                                 $options = substr($options,1,$endPos - 1);
+                               if (strpos($options, ':') !== False) {
+                                         $startPos = strpos($options,':');
+                                       $switch = substr($options, $startPos + 1, $endPos - ($startPos + 1));
+                               }
+
+                                 if ($title == '') $title = 'Spoiler Control';
+
+                               return array($state, $title, $switch);
                                break;
                }
                return array($state);
***************
*** 90,96 ****
 
        function render($mode, &$renderer, $data) {
                if($mode == 'xhtml'){
!                       list($state, $payload) = $data;
 
                        switch ($state) {
                                case DOKU_LEXER_ENTER :
--- 110,116 ----
 
        function render($mode, &$renderer, $data) {
                if($mode == 'xhtml'){
!                       list($state, $payload, $switch) = $data;
 
                        switch ($state) {
                                case DOKU_LEXER_ENTER :
***************
*** 100,105 ****
--- 120,139 ----
                                        break;
                                case DOKU_LEXER_MATCHED :
                                        break;
+                               case DOKU_LEXER_SPECIAL :
+                                       $script = "if (this.value == 'Show All') { spoilerControl(1); this.value = 'Hide All' } else { spoilerControl(0); this.value = 'Show All' }";
+                                         switch($switch){
+                                             case 'close':
+                                               $renderer->doc .= '<div class="spoilerctrl"><div class="title">'. $payload .'</div><input type="button" value="Show All" onClick="'. $script .'" /></div><script type="text/javascript">spoilerControl(0);</script>';
+                                                 break;
+                                             case 'hide':
+                                               $renderer->doc .= '<script type="text/javascript">spoilerControl(0);</script>';
+                                                 break;
+                                             default:
+                                               $renderer->doc .= '<div class="spoilerctrl"><div class="title">'. $payload .'</div><input type="button" value="Hide All" onClick="'. $script .'" /></div>';
+                                                 break;
+                                         }
+                                       break;
                                case DOKU_LEXER_UNMATCHED :
                                        $renderer->doc .= $renderer->_xmlEntities($payload);
                                        break;

Also, add the file script.js:

function spoilerControl(state) {
    var el = document.getElementsByTagName('DIV');
    for(var j=0; j < el.length; j++) {
    var className = el[j].className;
    if (className == "spoiler") {
        if (state == 1) {
            el[j].style.display = '';
        }else {
            el[j].style.display = 'none';
        }
    }
    }
}

This extra file hides away any 'spoiler' items when printing (call it print.css):

div.dokuwiki .spoiler {
    visibility: hidden;
    display: none;
}
div.dokuwiki .spoilerctrl {
    visibility: hidden;
    display: none;
}

– Chris Usher 2009-11-17


Problems