1<?php
2/**
3 * <spoiler> tag for dokuwiki. Allows sections that are initially hidden, and
4 * are shown when a "Show" button is clicked. The spoiler can be hidden again
5 * by pressing the button.
6 *
7 * <spoiler>Content with default title</spoiler>
8 * <spoiler |Plot details>The butler did it!</spoiler>
9 *
10 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
11 * @author     Heikki Hokkanen <hoxu@users.sf.net>
12 */
13
14if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
15if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
16require_once(DOKU_PLUGIN.'syntax.php');
17
18class syntax_plugin_spoiler extends DokuWiki_Syntax_Plugin {
19
20	function getInfo(){
21		return array(
22			'author' => 'Heikki Hokkanen',
23			'email'  => 'hoxu@users.sf.net',
24			'date'   => '2007-07-19',
25			'name'   => 'spoiler plugin',
26			'desc'   => 'Add <spoiler> tag, allowing sections that are initially hidden and can be made visible by clicking on a button. Another click will hide the spoiler again',
27			'url'    => 'http://wiki.splitbrain.org/wiki:plugins',
28		);
29	}
30
31	function getType(){
32		return 'container';
33	}
34
35	function getPType() {
36		return 'block';
37	}
38
39	function getAllowedTypes() {
40		return array('container', 'substition', 'protected', 'disabled', 'formatting', 'paragraphs');
41	}
42
43	function getSort(){
44		return 195;
45	}
46
47    // override default accepts() method to allow nesting
48    // - ie, to get the plugin accepts its own entry syntax
49	function accepts($mode) {
50		// ($mode == 'plugin_spoiler')
51		if ($mode == substr(get_class($this), 7)) return true;
52
53		return parent::accepts($mode);
54	}
55
56	function connectTo($mode) {
57		// Lookahead assertion: check that there is an end tag.
58		$this->Lexer->addEntryPattern('<spoiler[^>\r\n]*?>(?=.*?</spoiler>)', $mode, 'plugin_spoiler');
59	}
60
61	function postConnect() {
62		$this->Lexer->addExitPattern('</spoiler>', 'plugin_spoiler');
63	}
64
65	function handle($match, $state, $pos, &$handler){
66		switch ($state) {
67			case DOKU_LEXER_ENTER :
68				// "<spoiler" options ">"
69				$options = substr($match, 7, -1);
70
71				$title = 'Spoiler';
72				if (strpos($options, '|') !== False) {
73					$title = substr($options, strpos($options, '|') + 1);
74				}
75
76				return array($state, $title);
77				break;
78			case DOKU_LEXER_MATCHED :
79				break;
80			case DOKU_LEXER_UNMATCHED :
81				return array($state, $match);
82				break;
83			case DOKU_LEXER_EXIT :
84				break;
85			case DOKU_LEXER_SPECIAL :
86				break;
87		}
88		return array($state);
89	}
90
91	function render($mode, &$renderer, $data) {
92		if($mode == 'xhtml'){
93			list($state, $payload) = $data;
94
95			switch ($state) {
96				case DOKU_LEXER_ENTER :
97					$script = "c = this.parentNode.getElementsByTagName('div')[1]; if (this.value == 'Show') { c.style.display = ''; this.value = 'Hide' } else { c.style.display = 'none'; this.value = 'Show' }";
98					$renderer->doc .= '<div class="spoiler"><div class="title">'. $payload .'</div><input type="button" value="Show" onClick="'. $script .'" /><div class="content" style="display: none">';
99					// two open div tags
100					break;
101				case DOKU_LEXER_MATCHED :
102					break;
103				case DOKU_LEXER_UNMATCHED :
104					$renderer->doc .= $renderer->_xmlEntities($payload);
105					break;
106				case DOKU_LEXER_EXIT :
107					$renderer->doc .= '</div></div>';
108					break;
109			}
110
111			return true;
112		}
113		return false;
114	}
115}
116
117// VIM: ex: noet ts=4 sw=4 enc=utf-8 :
118