source: documentation/trunk/packages/dokuwiki-2011-05-25a/lib/plugins/simpletabs/syntax.php@ 30098

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

Initial checkin of plugin code

File size: 9.7 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
28 var $current_tab;
29 var $tab_area_counter;
30 var $tab_counter;
31 var $tabs;
32
33
34 function __construct()
35 {
36 global $PARSER_MODES;
37 $this->allowedModes = array_merge($PARSER_MODES['container'],
38 $PARSER_MODES['formatting'],
39 $PARSER_MODES['substition'],
40 $PARSER_MODES['protected'],
41 $PARSER_MODES['disabled'],
42 $PARSER_MODES['paragraphs']);
43 $this->tab_area_counter = 0;
44 $this->tab_counter = 0;
45 $this->tabs = array();
46 }
47
48 /**
49 * Get the type of syntax this plugin defines.
50 */
51 function getType()
52 {
53 return 'container';
54 }
55
56
57 /**
58 * What kind of syntax do we allow (optional)
59 */
60 function getAllowedTypes()
61 {
62 return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs');
63 }
64 /** getAllowedTypes() **/
65
66 /**
67 * Define how this plugin is handled regarding paragraphs.
68 *
69 * <p>
70 * This method is important for correct XHTML nesting. It returns
71 * one of the following values:
72 * </p>
73 * <dl>
74 * <dt>normal</dt><dd>The plugin can be used inside paragraphs.</dd>
75 * <dt>block</dt><dd>Open paragraphs need to be closed before
76 * plugin output.</dd>
77 * <dt>stack</dt><dd>Special case: Plugin wraps other paragraphs.</dd>
78 * </dl>
79 */
80 // function getPType()
81 // {
82 // return 'normal';
83 // }
84
85
86 /**
87 * Where to sort in?
88 */
89 function getSort()
90 {
91 return 45;
92 }
93
94
95 /**
96 * Connect lookup pattern to lexer.
97 */
98 function connectTo($mode)
99 {
100 $this->Lexer->addEntryPattern('<TABAREA tabs=".*?">(?=.*?</TABAREA>)$',$mode,'plugin_simpletabs');
101 $this->Lexer->addPattern('<TAB>', 'plugin_simpletabs');
102 $this->Lexer->addPattern('</TAB>', 'plugin_simpletabs');
103 }
104
105
106 function postConnect()
107 {
108 $this->Lexer->addExitPattern('</TABAREA>','plugin_simpletabs');
109 }
110
111
112 /**
113 * Handler to prepare matched data for the rendering process.
114 *
115 * <p>
116 * The <tt>$aState</tt> parameter gives the type of pattern
117 * which triggered the call to this method:
118 * </p>
119 * <dl>
120 * <dt>DOKU_LEXER_ENTER</dt>
121 * <dd>a pattern set by <tt>addEntryPattern()</tt></dd>
122 * <dt>DOKU_LEXER_MATCHED</dt>
123 * <dd>a pattern set by <tt>addPattern()</tt></dd>
124 * <dt>DOKU_LEXER_EXIT</dt>
125 * <dd> a pattern set by <tt>addExitPattern()</tt></dd>
126 * <dt>DOKU_LEXER_SPECIAL</dt>
127 * <dd>a pattern set by <tt>addSpecialPattern()</tt></dd>
128 * <dt>DOKU_LEXER_UNMATCHED</dt>
129 * <dd>ordinary text encountered within the plugin's syntax mode
130 * which doesn't match any pattern.</dd>
131 * </dl>
132 * @param $aMatch String The text matched by the patterns.
133 * @param $aState Integer The lexer state for the match.
134 * @param $aPos Integer The character position of the matched text.
135 * @param $aHandler Object Reference to the Doku_Handler object.
136 * @return Integer The current lexer state for the match.
137 * @public
138 * @see render()
139 * @static
140 */
141 function handle($match, $state, $pos, &$handler)
142 {
143 switch ($state)
144 {
145 case DOKU_LEXER_ENTER:
146 $this->tab_area_counter++;
147 //cho "<b>[DEBUG]</b> Encountered tabbed area: " . $this->tab_area_counter . "<br />";
148 $this->current_tab = '';
149 $this->tab_count = 0;
150 $this->tab_names = array();
151 if (preg_match('/tabs="(.+)"/', $match, $matches))
152 {
153 $this->tab_names = explode(',', $matches[1]);
154 }
155 return array($state, array($this->tab_area_counter, $this->tab_names, $this->getConf('defaulttab')));
156 break;
157
158 case DOKU_LEXER_MATCHED:
159 $params = $match;
160 if ($match == '</TAB>')
161 {
162 $this->current_tab = '';
163 // close any section edit block
164 $handler->_addCall('finishSectionEdit', array($pos - 1), $pos);
165 // render end of tabbed area
166 $params = array(true, $this->tab_area_counter, '', 0, false);
167 }
168 else
169 {
170 // Do we have a tab open?
171 $close_first = false;
172 if (!empty($this->current_tab))
173 {
174 // close any section edit block
175 $handler->_addCall('finishSectionEdit', array($pos - 1), $pos);
176 $close_first = true;
177 }
178 $this->current_tab = $this->tab_names[$this->tab_count];
179 $this->tab_count++;
180 $active = false;
181 if ($this->current_tab == $this->getConf('defaulttab'))
182 {
183 $active = true;
184 }
185 // start section edit
186 // - note the +5 is to account for the section starting "<TAB>"
187 $handler->_addCall('startSectionEdit', array(($pos + 5), 'section', $this->current_tab), $pos);
188 $params = array($close_first, $this->tab_area_counter, $this->current_tab, $this->tab_count, $active);
189 }
190 return array($state, $params);
191 break;
192
193 case DOKU_LEXER_UNMATCHED:
194 if (!empty($this->current_tab))
195 {
196 // SPECIAL CASE: We have to handle headers ourselves (apparently -
197 // having looked in several other plugins similar to this)
198 $headerMatch = preg_grep('/([ \t]*={2,}[^\n]+={2,}[ \t]*(?=))/msSi', array($match));
199 // - not a header, just pass it through
200 if (empty($headerMatch))
201 {
202 //$handler->_addCall('cdata', array($match), $pos);
203 return array($state, $match);
204 }
205 else
206 {
207 // if it's a == header ==, use the core header() renderer
208 // (copied from core header() in inc/parser/handler.php)
209 $title = trim($match);
210 $level = 7 - strspn($title,'=');
211 if ($level < 1)
212 {
213 $level = 1;
214 }
215 $title = trim($title,'=');
216 $title = trim($title);
217
218 $handler->_addCall('header',array($title,$level,$pos), $pos);
219 // close the section edit the header could open
220 /*
221 if ($title && $level <= $conf['maxseclevel'])
222 {
223 $handler->addPluginCall('wrap_closesection', array(), DOKU_LEXER_SPECIAL, $pos, '');
224 }
225 */
226 }
227 return false;
228 }
229 break;
230
231 case DOKU_LEXER_EXIT:
232 $close_first = false;
233 if (!empty($this->current_tab))
234 {
235 // close any pending section edit block
236 $handler->_addCall('finishSectionEdit', array($pos - 1), $pos);
237
238 $close_first = true;
239 }
240 // generate dummy heading at top level to ensure that no following headers are nested under titles in the tabbed area
241 $handler->_addCall('header', array('#',1,$pos), $pos);
242 return array($state, $close_first);
243 break;
244
245 case DOKU_LEXER_SPECIAL:
246 break;
247 }
248 return array();
249 }
250
251 /**
252 * Handle the actual output creation.
253 *
254 * <p>
255 * The method checks for the given <tt>$aFormat</tt> and returns
256 * <tt>FALSE</tt> when a format isn't supported. <tt>$aRenderer</tt>
257 * contains a reference to the renderer object which is currently
258 * handling the rendering. The contents of <tt>$aData</tt> is the
259 * return value of the <tt>handle()</tt> method.
260 * </p>
261 * @see handle()
262 */
263 function render($mode, &$renderer, $data)
264 {
265 if($mode == 'xhtml')
266 {
267 list($state, $params) = $data;
268
269 switch ($state)
270 {
271 case DOKU_LEXER_ENTER:
272 list($tab_area_id, $tab_names, $active_tab) = $params;
273 //cho "<b>[DEBUG]</b> Generating tabbed area: " . $tab_area_id . "<br />";
274 $renderer->doc .= '
275<!-- Tabbed Area - Begin -->
276<a href="top' . $tab_area_id . '"></a>
277<div class="tabbed_area" id="t' . $tab_area_id . '">
278 <ul class="tabs">
279';
280 $total_tab_count = count($tab_names);
281 $tab_count = 0;
282 foreach ($tab_names as $tab_name)
283 {
284 $tab_count++;
285 $renderer->doc .= ' <li><a href="javascript:tabSwitch(' . $tab_area_id . ',' . $total_tab_count . ',' . $tab_count . ');" id="t' . $tab_area_id . '_' . $tab_count . '"';
286 if ($tab_name == $active_tab)
287 {
288 $renderer->doc .= ' class="active"';
289 }
290 $renderer->doc .= '>' . $tab_name . '</a></li>
291';
292 }
293 $renderer->doc .= ' </ul>
294';
295 break;
296
297 case DOKU_LEXER_MATCHED:
298 list($close_tab, $tab_area_counter, $tab_name, $tab_content_count, $active) = $params;
299 if ($close_tab)
300 {
301 $renderer->doc .= '<div style="clear:both;height:0px;"></div></div>
302';
303 }
304 if (!empty($tab_name))
305 {
306 $this->tab_content_counter++;
307 $renderer->doc .= ' <div id="tc' . $tab_area_counter . '_' . $tab_content_count . '" class="tab" ';
308 if (!$active)
309 {
310 $renderer->doc .= ' style="display:none;"';
311 }
312 $renderer->doc .= '>';
313 }
314 break;
315
316 case DOKU_LEXER_UNMATCHED:
317 $renderer->doc .= $params;
318 break;
319
320 case DOKU_LEXER_EXIT:
321 $renderer->doc .= '</div>
322<!-- Tabbed Area - End -->';
323 break;
324 }
325 return true;
326 }
327 return false;
328 }
329}
330
331//Setup VIM: ex: et ts=4 enc=utf-8 :
332?>
Note: See TracBrowser for help on using the repository browser.