[30098] | 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 |
|
---|
| 16 | if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
|
---|
| 17 | if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
|
---|
| 18 | require_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 | */
|
---|
| 24 | class syntax_plugin_simpletabs
|
---|
| 25 | extends 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 | ?> |
---|