DokuWiki

It's better when it's simple

User Tools

Site Tools


plugin:boxes_mod

Modified Boxes Plugin

Compatible with DokuWiki

No compatibility info given!

plugin Just an example to prove the point

Last updated on
2005-10-25
Provides
Syntax
Conflicts with
box, boxwh

This extension has not been updated in over 2 years. It may no longer be maintained or supported and may have compatibility issues.

Extension name contains underscore, will not generate popularity points.

Similar to box, note

Tagged with boxes

This page is a child of box, and outlines a modified version of it. Please consult the original version for more detailed documentation

Changes

  1. Syntax changed: <<< width classes | title ::: content ::: caption >>>
  2. Markup allows in captions
  3. Title and Caption may be multiple lines now (i.e. multiple paragraphs)
  4. Width may be specified in %, px, em or ex

Why might you want this? If you can specify the width in px, you can use boxes to caption images seamlessly (by making the box the same width as the image) regardless of the browser width. Being able to place markup in the caption is nice for when you want to draw attention to a note about, say, an alternative version of some software — it looks really nice having the download link in the caption.

syntax.php

syntax.php
<?php
/**
 * Box Plugin: Draw highlighting boxes around wiki markup
 *
 * Syntax:     <<< width style1..styleN | title ::: ... ::: caption >>>
 *   width     width of the box, must include unit (one of "%", "px", "em" or "ex")
 *   styles    one or more classes used to style the box, several predefined styles included in style.css
 *   title     (optional) all text between '|' and ':::' will be rendered above the main code text with a
 *             different style.
 *   caption   (optional) all text between ':::' and '>>>' will be rendered above the main code text with a
 *             different style.
 *
 *       NB: To omit the title, drop it and it's preceding '|'
 *           To omit the caption, drop it and it's preceding ':::'
 *           To omit styles, drop the first ':::' and all preceding it
 *           You can have an empty style section and title: <<< | title ::: content >>>
 *       EG1: <<< contents >>>
 *       EG2: <<< round red ::: contents >>>
 *       EG3: <<< {media_link} ::: From left to right: Person 1, Person 2, Person 3 >>>
 *
 * Acknowledgments:
 *  Rounded corners based on snazzy borders by Stu Nicholls (http://www.cssplay.co.uk/boxes/snazzy) 
 *  which is in turn based on nifty corners by Alessandro Fulciniti (http://pro.html.it/esempio/nifty/)
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Christopher Smith <chris@jalakai.co.uk>  
 * @modified   Robert Meerman <robert.meerman@gmail.com>
 */
 
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
 
/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class syntax_plugin_box extends DokuWiki_Syntax_Plugin {
 
    var $title_mode = false;
    var $caption_mode = false;
 
    /**
     * return some info
     */
    function getInfo(){
      return array(
        'author' => 'Christopher Smith',
        'email'  => 'chris@jalakai.co.uk',
        'date'   => '2005-10-25',
        'name'   => 'Box Plugin',
        'desc'   => 'Boxes with titles, colour and rounded corners. 
                     Syntax: 
                        <<< ... >>>
                     or <<< style1..styleN ::: ... >>>
                     or <<< style1..styleN | title ::: ... >>>
                     or <<<  ... ::: caption >>>
                     or combination of above.
                     Styles to try: round, square, orange, green, blue and red.',
        'url'    => 'http://www.dokuwiki.org/plugin:boxes_mod',
      );
    }
 
    function getType(){ return 'container';}
    function getAllowedTypes() { return array('container','substition','protected','disabled','formatting','paragraphs'); }
    function getPType(){ return 'normal';}
 
    // must return a number lower than returned by native 'code' mode (200)
    function getSort(){ return 195; }
 
    /**
     * Connect pattern to lexer
     *
     * Avoid matching the title (if present) so its markup can be parsed normally
     */
    function connectTo($mode) {       
      $this->Lexer->addEntryPattern('<<<[^:\|\r\n]*?\|(?=.*?>>>)',$mode,'plugin_box');  // Styled & Titled
      $this->Lexer->addEntryPattern('<<<[^:\|\r\n]*?:::(?=.*?>>>)',$mode,'plugin_box'); // Styled only
      $this->Lexer->addEntryPattern('<<<(?=.*?>>>)',$mode,'plugin_box');                // Plain (default)
    }
 
    function postConnect() {
      $this->Lexer->addPattern(':::', 'plugin_box');                    // Begin caption (a title/style ":::" is consumed by addEntryPattern)
      $this->Lexer->addExitPattern(':::[^\r\n]*?>>>', 'plugin_box');    // Captioned
      $this->Lexer->addExitPattern('>>>', 'plugin_box');                // Plain
    }
 
    /**
     * Handle the match
     */
    function handle($match, $state, $pos, &$handler){
 
        switch ($state) {
            // addEntryPattern matched
            case DOKU_LEXER_ENTER:
                // Expect either plain "<<<" or "<<< style1 ... styleN |"
                $data = $this->_boxstyle(trim(substr($match, 3, -1)));
                if (substr($match, -1) == '|') {
                    $this->title_mode = true;
                    return array('title_open',$data);
                } else {
                    return array('box_open',$data);
                }
 
            // addPattern matched
            case DOKU_LEXER_MATCHED:
                if ($this->title_mode) {
                    // End title mode and open content box
                    $this->title_mode = false;
                    return array('box_open','');
                } else {
                    // begin caption mode and open caption
                    $this->caption_mode = true;
                    return array('caption_open', '');
                }
 
            case DOKU_LEXER_UNMATCHED:                
                return array('data', $match);
 
            // addExitPattern matched
            case DOKU_LEXER_EXIT:               
                return array('box_close', $match);
 
        }       
        return false;
    }
 
    /**
     * Create output
     */
    function render($mode, &$renderer, $indata) {
 
      list($instr, $data) = $indata;
 
      if($mode == 'xhtml'){
          switch ($instr) {
          case 'title_open' : 
              $this->title_mode = true;
            $renderer->doc .= "</p>\n".$this->_xhtml_boxopen($data)."<div class='box_title'><p>";
            break;
 
          case 'box_open' :   
            if ($this->title_mode) {
                $this->title_mode = false;
                $renderer->doc .= "</p></div>\n<div class='box_content'><p>";
            } else {
                $renderer->doc .= "</p>\n".$this->_xhtml_boxopen($data)."<div class='box_content'><p>";
            }
            break;
 
          case 'data' :      
            $renderer->doc .= $renderer->_xmlEntities($data); 
            break;
 
          case 'caption_open' :
            $this->caption_mode = true;
 
            $renderer->doc .= "</p></div>\n";                   // First close content div
            $renderer->doc .= "<div class='box_caption'><p>";   // Then open caption
            break;
 
          case 'box_close' : 
            if($this->caption_mode){
                // Close caption div
                $renderer->doc .= "</p></div>\n";
            } else {
                // Close content div
                $renderer->doc .= "</p></div>\n";
            }
 
            $renderer->doc .= $this->_xhtml_boxclose()."<p>"; 
            break;
        }
 
        return true;
      }
      return false;
    }
 
    function _boxstyle($str) {
      if (!strlen($str)) return array();
 
      $styles = array();
 
      $tokens = preg_split('/\s+/', $str, 9);                      // limit is defensive
      foreach ($tokens as $token) {
          if (preg_match('/^\d+(%|px|em|ex)$/', $token)) {
            $styles['width'] = $token;
            continue;
          }
 
          $styles['class'] = (isset($styles['class']) ? $styles['class'].' ' : '').$token;
      }
 
      return $styles;
    }
 
    function _xhtml_boxopen($style) {
      $class = "class='box" . (isset($style['class']) ? ' '.$style['class'] : '') . "'";
      $style = isset($style['width']) ? " style='width: {$style['width']};'" : '';
 
      $html = "<div $class$style>\n";
      $html .="  <b class='xtop'><b class='xb1'></b><b class='xb2'></b><b class='xb3'></b><b class='xb4'></b></b>\n";
      $html .="  <div class='xbox'>\n";
 
      return $html;
    }
 
    function _xhtml_boxclose() {
 
      $html = "  </div>\n";
      $html .= "  <b class='xbottom'><b class='xb4'></b><b class='xb3'></b><b class='xb2'></b><b class='xb1'></b></b>\n";
      $html .= "</div>\n";
 
      return $html;
    }
 
}
 
//Setup VIM: ex: et ts=4 enc=utf-8 :

style.css

Not much was changed: Two conversion took place and an additional rule was added:

Title / Caption

This was done to allow multi-line markup within both, giving you greater flexibility.

  • p.box_titlediv.box_title
  • p.box_captiondiv.box_caption

Additional Rule

The following rule was added to ensure all immediate child paragraphs of the title and caption did not gaps caused by margin-bottoms, which are defined in the default DokuWiki CSS.

div.box div.box_title > p, div.box div.box_caption > p{
  margin: 0;
  padding: 0;
}

Complete stylesheet

Should you wish to download the complete stylesheet, here it is.

style.css
/* plugin:box */
div.box {
  width: 50%;
  margin: 1em auto;
  border: 1px solid;
  padding: 4px;
}
 
/* rounded corners styles from Stu Nicholls snazzy borders, http://www.cssplay.co.uk/boxes/snazzy.html */
.xtop, .xbottom {background:transparent; font-size:0; line-height: 1px;}
.xb1, .xb2, .xb3, .xb4 {display:block; overflow:hidden; border-style: solid;}
.xb2, .xb3 {height:1px;}
.xb2, .xb3, .xb4 {border-width:0 1px;}
.xb1 {height: 0; margin:0 5px; border-width:1px 0 0 0;}
.xb2 {margin:0 3px; border-width:0 2px;}
.xb3 {margin:0 2px;}
.xb4 {height:2px; margin:0 1px;}
 
div.box .xtop, div.box .xbottom {display: none;}
div.box.round .xtop, div.box.round .xbottom {display: block;}
 
div.box.round { border: none; padding: 0;}
div.box.round .xbox {display:block; border-width:0 1px; border-style: solid; padding: 0 4px; }
 
div.box div.box_title, div.box div.box_caption {
  font-size: 90%;
  margin: 0;
  padding: 2px 6px;
  line-height: 1.2em;
}
div.box div.box_title > p, div.box div.box_caption > p{
  margin: 0;
  padding: 0;
}
 
 
div.box div.box_title { margin-bottom: 4px;}
div.box div.box_caption { margin-top: 4px;}
 
div.box .box_content {
  margin: 0;
  padding: 0 6px;
  border-width: 1px;
  border-style: dashed;
  line-height: 1.2em;
}
 
/* floating alignment */
 
div.box.left {
  float: left;
  margin-right: 1em;
}
 
div.box.right {
  float: right;
  margin-left: 1em;
}
 
/* colours */
/* default */
div.box, div.box .box_content, div.box .xbox, div.box .xb1, div.box .xb2, div.box .xb3, div.box .xb4 {
  border-color:  #8cacbb;
}
 
div.box, div.box .xbox, div.box .xb1, div.box .xb2, div.box .xb3, div.box .xb4 {
  background: #ecf1f4;
}
 
div.box div.box_title, div.box div.box_caption { background: #dee7ec;}
div.box .box_content { background: #f7fafb;}
 
/* blue */
div.box.blue, div.box.blue .box_content, div.box.blue .xbox, 
div.box.blue .xb1, div.box.blue .xb2, div.box.blue .xb3, div.box.blue .xb4 {
  border-color:  #bbbbdd;
}
 
div.box.blue, div.box.blue .xbox, 
div.box.blue .xb1, div.box.blue .xb2, div.box.blue .xb3, div.box.blue .xb4 {
  background: #e4ecf8;
}
 
div.box.blue div.box_title, div.box.blue div.box_caption {background: #cad0ee;}
div.box.blue .box_content {background: #f4f8fd;}
 
/* red */
div.box.red, div.box.red .box_content, div.box.red .xbox, 
div.box.red .xb1, div.box.red .xb2, div.box.red .xb3, div.box.red .xb4 {
  border-color:  #ddbbbb;
}
 
div.box.red, div.box.red .xbox, 
div.box.red .xb1, div.box.red .xb2, div.box.red .xb3, div.box.red .xb4 {
  background: #f8ece4;
}
 
div.box.red div.box_title, div.box.red div.box_caption {background: #eed0ca;}
div.box.red .box_content {background: #fdf4ec;}
 
/* green */
div.box.green, div.box.green .box_content, div.box.green .xbox, 
div.box.green .xb1, div.box.green .xb2, div.box.green .xb3, div.box.green .xb4 {
  border-color:  #bbddbb;
}
 
div.box.green, div.box.green .xbox, 
div.box.green .xb1, div.box.green .xb2, div.box.green .xb3, div.box.green .xb4 {
  background: #e4f8f2;
}
 
div.box.green div.box_title, div.box.green div.box_caption {background: #c4e4d4;}
div.box.green .box_content {background: #ecfaf6;}
 
/* orange */
div.box.orange, div.box.orange .box_content, div.box.orange .xbox, 
div.box.orange .xb1, div.box.orange .xb2, div.box.orange .xb3, div.box.orange .xb4 {
  border-color:  #da3;
}
 
div.box.orange, div.box.orange .xbox, 
div.box.orange .xb1, div.box.orange .xb2, div.box.orange .xb3, div.box.orange .xb4 {
  background: #f4e8ca;
}
 
div.box.orange div.box_title, div.box.orange div.box_caption {background: #f0d499;}
div.box.orange .box_content {background: #f8f0da;}
 
/* must come last to override coloured background when using rounded corners */
 
div.box.round {
  background: transparent !important;
}
 
/* end plugin:box */

Tips

To resolve the conflicts with 'box' plugin:

  • In /lib/plugins/ create plugin folder and name it boxes.
  • Download/copy and save the syntax.php and the style.css to your computer.
  • In the syntax.php file search and replace all occurrences of the word 'box' with the word 'boxes'.
  • In the style.css file, search and replace all occurrences of the word 'box' with the word 'boxes'.
  • In both files there may be a few occurrences of the word 'boxeses', replace with the word 'boxes'.
  • Upload both files to the lib/plugins/boxes/ folder you created earlier.

That's it! You're done, and ready to nest boxes from both plugins.

Note: DO NOT MIX the SYNTAX of the two plugins in a single box.

email : Keith Shepherd

rhabdo[dot]sidera[at]gmail[dot]com

plugin/boxes_mod.txt · Last modified: 2011-12-04 17:17 by Aleksandr