DokuWiki

It's better when it's simple

User Tools

Site Tools


devel:section_editor

This is an old revision of the document!


Custom Section Editors in plugins

DokuWiki allows plugins to provide custom edit forms for their syntax elements. First, you need to mark a DIV element in the XHTML output as editable. Optional you can also change sectiontype name when you like. Next you have to provide an editor for your content.

Marking the DIV

The XHTML renderer provides two methods for the DIV section edit marking:

These are used to create markers in the xhtml output of the renderer and after the render is done, a replacement or remove of the markers by html_secedit($text,$show=true) is executed.

Note that finishSectionEdit() assumes correctly nested edit sections. To use this methods, you will need to save your byte positions in your handle() method of your syntax plugin.

A step-by-step example for a syntax plugin:

syntax.php
    function render($format, &$renderer, $data) {
        $class = '';
        // Add section edit infos only in XHTML renderers which are
        // sufficiently new
        if ($format === 'xhtml' && method_exists($renderer, 'startSectionEdit')) {
            // FIXME: Insert plugin name here as section type
            // If this section has a distinguishable name, you may add it to
            // the method call as well
            $class = $renderer->startSectionEdit($data['bytepos_start'],
                                                 'plugin_exampleplugin');
        }
        $renderer->doc .= '<div class="' . $class . '">';
 
        // FIXME: Put your content here
 
        $renderer->doc .= '</div>';
        // Add section edit infos only in XHTML renderers which are
        // sufficiently new
        if ($format === 'xhtml' &&
            method_exists($renderer, 'finishSectionEdit')) {
            $renderer->finishSectionEdit($data['bytepos_end']);
        }
    }

You may have noticed that I used $data['bytepos_start'] and $data['bytepos_end'] which your handler has to provide:

syntax.php
    function handle($match, $state, $pos, &$handler) {
        $data = array();
 
        // FIXME: Do your handling
 
        return $data + array('bytepos_start' => $pos,
                             'bytepos_end'   => $pos + strlen($match));
    }

If you did not provide a special section name as third argument in the startSectionEdit() call, you must hook the HTML_SECEDIT_BUTTON event providing a general-purpose name used for all section with target/sectiontype plugin_exampleplugin.

action.php
    function register(Doku_Event_Handler $controller) {
        $controller->register_hook('HTML_SECEDIT_BUTTON', 'BEFORE', $this, '_editbutton');
    }
 
    function _editbutton(&$event, $param) {
        // FIXME: Insert plugin name
        if ($event->data['target'] !== 'plugin_exampleplugin') {
            return;
        }
 
        // FIXME: Add your lang field to your lang files
        $event->data['name'] = $this->getLang('sectioneditname');
    }

Now your users will get a special edit button for your syntax elements. You will probably want to style it:

style.css
/* FIXME: Insert plugin name here */
div.dokuwiki div.editbutton_plugin_exampleplugin {
 
}
 
/* FIXME: Insert plugin name here */
div.dokuwiki div.editbutton_plugin_exampleplugin form input.button {
 
}

Now there is a nice button, but still no form – the users have to use the plain wikitext editor!

Providing the form

For this step, we need to hook HTML_EDIT_FORMSELECTION in an action plugin.

action.php
    function register(Doku_Event_Handler $controller) {
        $controller->register_hook('HTML_SECEDIT_BUTTON', 'BEFORE', $this, '_editbutton');
        $controller->register_hook('HTML_EDIT_FORMSELECTION', 'BEFORE', $this, '_editform');
    }
 
    function _editform(&$event, $param) {
        global $TEXT;
        // FIXME: Insert plugin name
        if ($event->data['target'] !== 'plugin_exampleplugin') {
            // Not an edit for exampleplugin
            return;
        }
        $event->preventDefault();
 
        // FIXME: Remove this if you want the default edit intro
        unset($event->data['intro_locale']);
 
        // FIXME: Remove this if you want a media manager fallback link
        // You will probably want a media link if you want a normal toolbar
        $event->data['media_manager'] = false;
 
        // FIXME: Create the lang files edit_intro.txt
        echo $this->locale_xhtml('edit_intro');
 
        // FIXME: Add real edit form
        $attr = array();
        if (!$event->data['wr']) $attr['readonly'] = 'readonly';
        $event->data['form']->addElement(form_makeWikiText($TEXT, $attr));
    }

The form you provided here has to be rendered into wiki text again on POST.

action.php
    function register(Doku_Event_Handler $controller) {
        $controller->register_hook('HTML_SECEDIT_BUTTON', 'BEFORE', $this, '_editbutton');
        $controller->register_hook('HTML_EDIT_FORMSELECTION', 'BEFORE', $this, '_editform');
        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, '_editpost');
    }
 
    function _handle_edit_post($event) {
        // FIXME: Insert the name of a form field you use
        if (!isset($_POST['some_of_the_form_fields_you_use'])) {
            return;
        }
        global $TEXT;
 
        // FIXME: Create wikitext from post
        $TEXT = magic_form_to_wiki_function();
    }

Example implementations

The Data Plugin and the EditTable Plugin uses this mechanisms. Have a look on their source.

devel/section_editor.1383354993.txt.gz · Last modified: 2013-11-02 02:16 by Klap-in

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki