Table of Contents

The Toolbar

The toolbar makes DokuWiki easy to use even for novice users. Sometimes you may want to extend the toolbar with another button. This page will tell you a bit how the toolbar works and how to extend it.

How the toolbar is built (and cached)

The toolbar is completely built through JavaScript. Which buttons the toolbar contains, is read from an array called toolbar. This array is initialized in /lib/exe/js.php. This is simply done by converting the PHP array structure defined in inc/toolbar.php to JavaScript using JSON.

This means, the toolbar gets cached like any other JavaScript in DokuWiki. When ever you do changes affecting the toolbar you should invalidate DokuWiki's cache (eg. touch conf/local.php) and refresh your browser cache while editing a page (Hit Shift/Ctrl-Reload and ignore the post warning).

The toolbar array

The mentioned toolbar array contains one entry per button. The order of the entries defines the position of the button, with the first entry defining the most left button.

Each entry is an associative array itself, defining the behavior of the button. The following table explains the available fields for the entries.

Name Description
type button action type:
format ⇒ wiki markup
mediapopup ⇒ popup window
picker ⇒ picker menu
signature ⇒ signature generation and insertion
title title of the button, displayed on mouseover
icon icon to use for the button
key Hotkey for the button, a value of n here would result in the button being pressed when the user presses ALT + n in his browser
format type specific parameters
open opening tag of wiki markup to insert, cursor will be placed between opening and closing tag
sample example input to be placed between opening and closing tag, will be automatically selected to be overwritten on first input
close closing tag of the wiki markup to insert, cursor will be placed between opening and closing tag
insert wiki markup to insert (for full substitutions)
mediapopup type specific parameters
url URL of the popup to open
name internal name of the popup to open
options additional options for the popup window (comma-separated name-value-pairs valid as parameters for the JS function window.open
picker type specific parameters
list list of insertable items. can either be an associative array (with the item to insert as the key and an image to use as the value) or just a simple array (with the text-items to insert directly displayed)
icobase basedirectory for item images

A look at inc/toolbar.php should give you enough examples of what can be defined. Because the array is simply translated from PHP to JavaScript, the above description applies to the PHP array as well as to the resulting JavaScript array from which the toolbar is finally built.

Extending the Toolbar...

The toolbar can be customized in two ways - via JavaScript or PHP. Which method you choose basically depends on your skills and familiarity with the language at hand. For the PHP approach you will always need to write a plugin, the JavaScript method can be used from a userscript as well.

...using PHP

To extend the toolbar from your plugin you need to write a Action Plugin which registers as handler for the TOOLBAR_DEFINE event with an AFTER advise. Your handler function will receive the toolbar array as described earlier.

Create your button structure according to the above information and add it to the received event data.-function in inc/toolbar.php.

Example:

function register(&$controller) {
    $controller->register_hook('TOOLBAR_DEFINE', 'AFTER', $this, 'insert_button', array ());
}
 
// ...
 
/**
 * Inserts a toolbar button
 */
function insert_button(& $event, $param) {
    $event->data[] = array (
        'type' => 'format',
        'title' => $this->getLang('abutton'),
        'icon' => '../../plugins/example/abutton.png',
        'open' => '<abutton>',
        'close' => '</abutton>',
    );
}

...using JavaScript

Adding a button using JavaScript is similar to doing it in PHP. You just extend the toolbar array.

Because user and plugin scripts will be loaded on all requests, but the toolbar is initialized on editing only, you need to make sure the toolbar array does exist first. Do this by checking if window.toolbar is defined. If it is, you can add your button at the end of the array.

if(window.toolbar!=undefined){
  toolbar[toolbar.length] = {"type":"format",
                             "title":"A Button",
                             "icon":"abutton.png",
                             "key":"",
                             "open":"<abutton>",
                             "sample":"Text between the tags",
                             "close":"</abutton>"};
}

Here is another example defining a picker dropdown:

if(window.toolbar!=undefined){
  var notes_arr = new Array(); /* array[key]= insertion string , value = icon filename. */
  notes_arr['<note></note>\\n']          ='note.png';
  notes_arr['<note tip></note>\\n']      ='tip.png';
  notes_arr['<note important></note>\\n']='important.png';
  notes_arr['<note warning></note>\\n']  ='warning.png';
 
  toolbar[toolbar.length] = {"type":"picker",
                             "title":"Notes",
                             "icon":"note.png",
                             "key":"",
                             "list": notes_arr,
                             "icobase":"notes"}; /* subdir of lib/images/ where images found.*/
}

Dynamic Data

The above methods work well for adding static buttons that add static data. When you need to do something more dynamic like adding the current date, you can not simply extend the toolbar array. Instead you need to dynamically add your button into the DOM using JavaScript.

lib/scripts/edit.js and lib/scripts/linkwiz.js contains some useful functions to help you with this.

Here's an example partly from the link wizard:

/**
 * With the first function we create a new button type called Click
 * 
 * the function name must be addBtnAction<Your type name>
 * in our case it is addBtnActionClick
 *
 * in the other function we simply use the simple toolbar method with the new type
 * 
 * you can easily extend it to complex scripts like the link wizard etc
 */
 
/**
 * Add button action for the link wizard button
 *
 * @param  DOMElement btn   Button element to add the action to
 * @param  array      props Associative array of button properties
 * @param  string     edid  ID of the editor textarea
 * @return boolean    If button should be appended
 */
function addBtnActionClick(btn, props, edid)
{
    addEvent(btn,'click',function(){
        alert('hey you clicked me');
        return false;
    });
    return true;
}
 
// add a new toolbar button just like the simple way
addInitEvent(function()
{
    // but first check if there is a toolbar
    if (window.toolbar != undefined)
    {
        window.toolbar[window.toolbar.length] = {
            "type":"Click", // we have a new type that links to the function
            "title":"Hey Click me!",
            "icon":"/lib/plugins/klick/klickme.png"
        }
    }
});

Tips