source: documentation/trunk/packages/plugins/simpletabs/syntax.php@ 30114

Last change on this file since 30114 was 30114, checked in by jmt12, 9 years ago

Updated Greenstone customizations for Detritus, but rearranged to move into separate plugin. Initial checkin of plugins, template, special wiki pages.

File size: 11.8 KB
Line 
1<?php
2/**
3 * A simple tabbed area component, developed from the tutorial given here:
4 * http://net.tutsplus.com/tutorials/html-css-techniques/how-to-create-a-slick-tabbed-content-area/
5 *
6 * Syntax:
7 * <TABAREA tabs="comma,separated,list">
8 * <TAB>Content of 'comma' including [[:syntax|wiki syntax]]</TAB>
9 * <TAB>Content of 'separated' and here **is** //some// ''formatting''</TAB>
10 * <TAB>Content of 'list'</TAB>
11 * </TABAREA>
12 *
13 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
14 */
15
16if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
17if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
18require_once(DOKU_PLUGIN.'syntax.php');
19
20/**
21 * All DokuWiki plugins to extend the parser/rendering mechanism
22 * need to inherit from this class
23 */
24class syntax_plugin_simpletabs
25extends DokuWiki_Syntax_Plugin
26{
27 // The name of currently rendering tab - useful for ensuring syntax (no
28 // close tab before open, for example)
29 var $current_tab;
30
31 var $current_tab_number;
32
33 // Print debug messages
34 var $debug;
35
36 // The count of tabbed areas encountered on this page (so we can ensure a
37 // unique identifier is assigned)
38 var $tab_area_counter;
39
40 var $tab_counter;
41
42 var $tabs;
43
44 var $divide_edit_section;
45
46 function __construct()
47 {
48 global $PARSER_MODES;
49 $this->allowedModes = array_merge($PARSER_MODES['container'],
50 $PARSER_MODES['formatting'],
51 $PARSER_MODES['substition'],
52 $PARSER_MODES['protected'],
53 $PARSER_MODES['disabled'],
54 $PARSER_MODES['paragraphs']);
55 // Init
56 $this->debug = false;
57 $this->divide_edit_section = false;
58 $this->tab_area_counter = 0;
59 $this->tab_counter = 0;
60 }
61 /** __construct() **/
62
63
64 /** @function
65 *
66 */
67 function _debugPrint($msg)
68 {
69 if ($this->debug)
70 {
71 echo "<p><b>[DEBUG]</b> " . $msg . "</p>\n";
72 }
73 }
74 /** _debugPrint() **/
75
76
77 /**
78 * Should return the type of syntax this plugin defines.
79 */
80 function getType()
81 {
82 return 'container';
83 }
84 /** getType() **/
85
86
87 /**
88 * Returns a number used to determine in which order modes are added.
89 */
90 function getSort()
91 {
92 return 45;
93 }
94
95
96 /**
97 * What kind of syntax do we allow (optional)
98 */
99 function getAllowedTypes()
100 {
101 return array('container','formatting','substition','protected','disabled','paragraphs');
102 }
103 /** getAllowedTypes() **/
104
105
106 /**
107 * Define how this plugin is handled regarding paragraphs.
108 *
109 * <p>
110 * This method is important for correct XHTML nesting. It returns
111 * one of the following values:
112 * </p>
113 * <dl>
114 * <dt>normal</dt><dd>The plugin can be used inside paragraphs.</dd>
115 * <dt>block</dt><dd>Open paragraphs need to be closed before
116 * plugin output.</dd>
117 * <dt>stack</dt><dd>Special case: Plugin wraps other paragraphs.</dd>
118 * </dl>
119 */
120 function getPType()
121 {
122 return 'normal';
123 }
124
125
126 /**
127 * Connect lookup pattern to lexer.
128 */
129 function connectTo($mode)
130 {
131 $this->Lexer->addEntryPattern('<TABAREA tabs=".*?">(?=.*?</TABAREA>)$',$mode,'plugin_simpletabs');
132 // The tabs
133 $this->Lexer->addPattern('<TAB>', 'plugin_simpletabs');
134 $this->Lexer->addPattern('</TAB>', 'plugin_simpletabs');
135 // Special things inside the content we want to manually handle.
136 $this->Lexer->addPattern( '^[ \t]*={2,6}\s?[^\n]+={2,6}[ \t]*(?=\n)', 'plugin_simpletabs');
137 }
138
139 function postConnect()
140 {
141 $this->Lexer->addExitPattern('</TABAREA>','plugin_simpletabs');
142 }
143
144
145 /**
146 * Handler to prepare matched data for the rendering process.
147 *
148 * <p>
149 * The <tt>$aState</tt> parameter gives the type of pattern
150 * which triggered the call to this method:
151 * </p>
152 * <dl>
153 * <dt>DOKU_LEXER_ENTER</dt>
154 * <dd>a pattern set by <tt>addEntryPattern()</tt></dd>
155 * <dt>DOKU_LEXER_MATCHED</dt>
156 * <dd>a pattern set by <tt>addPattern()</tt></dd>
157 * <dt>DOKU_LEXER_EXIT</dt>
158 * <dd> a pattern set by <tt>addExitPattern()</tt></dd>
159 * <dt>DOKU_LEXER_SPECIAL</dt>
160 * <dd>a pattern set by <tt>addSpecialPattern()</tt></dd>
161 * <dt>DOKU_LEXER_UNMATCHED</dt>
162 * <dd>ordinary text encountered within the plugin's syntax mode
163 * which doesn't match any pattern.</dd>
164 * </dl>
165 * @param $aMatch String The text matched by the patterns.
166 * @param $aState Integer The lexer state for the match.
167 * @param $aPos Integer The character position of the matched text.
168 * @param $aHandler Object Reference to the Doku_Handler object.
169 * @return Integer The current lexer state for the match.
170 * @public
171 * @see render()
172 * @static
173 */
174 function handle($match, $state, $pos, &$handler)
175 {
176 switch ($state)
177 {
178 case DOKU_LEXER_ENTER:
179 // Increment the counter for tabbed area identifiers
180 $this->tab_area_counter++;
181 // Reset these two variables used to track progress through tabbed area
182 $this->current_tab = '';
183 $this->tab_counter = 0;
184 // Separate the tab names - hopefully there are the same number as tabbed
185 // areas otherwise things will go strange
186 $this->tab_names = array();
187 if (preg_match('/tabs="(.+)"/', $match, $matches))
188 {
189 $this->tab_names = explode(',', $matches[1]);
190 }
191 // When rendered this command will create the unordered list that acts as
192 // the tabs themselves as well as the precursor for the tabbed content.
193 $this->_debugPrint("Handler=>enter tabbed area: " . $matches[1]);
194 return array($state, array('action' => 'open tabbed area',
195 'tab_area_id' => $this->tab_area_counter,
196 'tab_names' => $this->tab_names,
197 'default_tab' => $this->getConf('defaulttab'),
198 'bytepos' => $pos));
199 break;
200
201 case DOKU_LEXER_MATCHED:
202 // Open tab area
203 if ($match == '<TAB>' && $this->current_tab == '')
204 {
205 $this->current_tab = $this->tab_names[$this->tab_counter];
206 $this->tab_counter++;
207 $this->current_tab_number = $this->tab_counter;
208 $active = false;
209 if ($this->current_tab == $this->getConf('defaulttab'))
210 {
211 $active = true;
212 }
213 // When rendered this command will open the div serving as a tabbed
214 // area's content
215 $this->_debugPrint("Handler=>open tab: " . $this->current_tab);
216 return array($state, array('action' => 'open tab',
217 'tab_area_id' => $this->tab_area_counter,
218 'tab_number' => $this->tab_counter,
219 'active' => $active,
220 'bytepos' => $pos));
221 }
222 if ($match == '</TAB>')
223 {
224 $this->_debugPrint("Handler=>close tab: " . $this->current_tab);
225 // Housekeeping
226 $this->current_tab = '';
227 $this->current_tab_number = 0;
228 // When rendered this command closes the tabbed area content div
229 return array($state, array('action' => 'close tab',
230 'bytepos' => $pos + strlen($match)));
231 }
232 if (preg_match('/(={2,6})\s*(.+?)\s*={2,6}/', $match, $matches))
233 {
234 $params = array();
235 $params['action'] = 'heading';
236 $params['title'] = $matches[2];
237 $params['level'] = 7 - strlen($matches[1]);
238 return array($state, $params);
239 //$handler->_addCall('header',array($params['title'],$params['level'],$pos),$pos);
240 //return false;
241 }
242 break;
243
244 case DOKU_LEXER_EXIT:
245 $this->_debugPrint("Handler=>exit tabbed area");
246 return array($state, array('action' => 'close tabbed area',
247 'bytepos' => $pos + strlen($match)));
248 break;
249
250 case DOKU_LEXER_UNMATCHED:
251 $this->_debugPrint("Handler=>unmatched: " . $match);
252 return array($state, $match);
253 break;
254 }
255
256 return array();
257 }
258
259 /**
260 * Handle the actual output creation.
261 *
262 * <p>
263 * The method checks for the given <tt>$aFormat</tt> and returns
264 * <tt>FALSE</tt> when a format isn't supported. <tt>$aRenderer</tt>
265 * contains a reference to the renderer object which is currently
266 * handling the rendering. The contents of <tt>$aData</tt> is the
267 * return value of the <tt>handle()</tt> method.
268 * </p>
269 * @see handle()
270 */
271 function render($mode, &$renderer, $data)
272 {
273 if($mode == 'xhtml')
274 {
275 list($state, $params) = $data;
276
277 switch ($state)
278 {
279 case DOKU_LEXER_ENTER:
280 if ($this->divide_edit_section && method_exists($renderer, 'finishSectionEdit'))
281 {
282 $renderer->finishSectionEdit($params['bytepos']);
283 }
284 $renderer->doc .= '</p>'; // Provide match for illegal wrapping <p>
285 $renderer->doc .= '
286
287<!-- Tabbed Area - Begin -->
288<div class="tabbed_area" id="simpletabs-t' . $params['tab_area_id'] . '">
289 <ul class="tabs">
290';
291 $total_tab_count = count($params['tab_names']);
292 $tab_count = 0;
293 foreach ($params['tab_names'] as $tab_name)
294 {
295 $tab_count++;
296 $renderer->doc .= ' <li><a href="javascript:tabSwitch(' . $params['tab_area_id'] . ',' . $total_tab_count . ',' . $tab_count . ');" id="simpletabs-t' . $params['tab_area_id'] . '_' . $tab_count . '"';
297 if ($tab_name == $params['default_tab'])
298 {
299 $renderer->doc .= ' class="active"';
300 }
301 $renderer->doc .= '>' . $tab_name . '</a></li>
302';
303 }
304 $renderer->doc .= ' </ul>
305';
306 break;
307
308 case DOKU_LEXER_MATCHED:
309 switch($params['action'])
310 {
311 case 'open tab':
312 $extra_classy = '';
313 if ($this->divide_edit_section && method_exists($renderer, 'startSectionEdit'))
314 {
315 $extra_classy = $renderer->startSectionEdit($params['bytepos'], 'plugin_simpletabs');
316 }
317 $renderer->doc .= ' <div id="simpletabs-tc' . $params['tab_area_id'] . '_' . $params['tab_number'] . '" class="tab ' . $extra_classy . '" ';
318 if (!$params['active'])
319 {
320 $renderer->doc .= ' style="display:none;"';
321 }
322 $renderer->doc .= '>';
323 $renderer->doc .= '<p>'; // Open bogus </p>
324 break;
325 case 'close tab':
326 if ($this->divide_edit_section && method_exists($renderer, 'finishSectionEdit'))
327 {
328 $renderer->finishSectionEdit($params['bytepos']);
329 }
330 $renderer->doc .= '</p>'; // Close bogus <p>
331 $renderer->doc .= '<div style="clear:both;height:0px;"></div>';
332 $renderer->doc .= '</div>';
333 break;
334 case 'heading':
335 $renderer->doc .= '<h' . $params['level'] . '>' . $params['title'] . '</h' . $params['level'] . '>';
336 break;
337 default:
338 $renderer->doc .= '<p>Error! Unknown action: ' . $params['action'] . '</p>';
339 }
340 break;
341
342 case DOKU_LEXER_EXIT:
343 $renderer->doc .= '</div>
344<!-- Tabbed Area - End -->
345';
346 $renderer->doc .= '<p>'; // Provide match for illegal wrapping <p>
347 if ($this->divide_edit_section && method_exists($renderer, 'startSectionEdit'))
348 {
349 $class = $renderer->startSectionEdit($params['bytepos'], 'plugin_simpletabs');
350 $renderer->doc .= '<div class="' . $class . '">';
351 }
352 break;
353
354 case DOKU_LEXER_UNMATCHED:
355 $renderer->doc .= $params;
356 break;
357 }
358 return true;
359 }
360 return false;
361 }
362}
363
364//Setup VIM: ex: et ts=4 enc=utf-8 :
365?>
Note: See TracBrowser for help on using the repository browser.