DokuWiki

It's better when it's simple

User Tools

Site Tools


tips:template_chooser

This is an old revision of the document!


Template Chooser

:!: Even if different, you should consider namespace_templates

FIXME please update this tip to take new version in account

It did bother me, that in our DokuWiki I had to write the same stuff for certain types of documentation over and over again or copy it to my clipboard and then back into DokuWiki.

That's why I made this simple thing. If you hate JavaScript, you should certainly run away and hide now, because this will be gruesome…

The “plugin” is called “Template chooser” and doesn't confirm to the standard plugins for DokuWiki, that exist right now. Perhaps there will be something in future versions, that allows me to better include this. Until then, here's what I did.

I have two files in my template-directory. The first one includes a function to display the template-selectbox, the other one does the nasty JavaScript for it.

So put these two files into your template-path (normally 'lib/tpl/default/'):

The first one's called “template_chooser.php”:

<?php
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/');
if (is_null($conf['template_chooser']['namespace'])) {
    $conf['template_chooser']['namespace'] = 'templates';
}
if (is_null($lang['select_template'])) {
        $lang['select_template'] = 'Select template';
}
function read_files($path, $preg) {
    $templates = array();
    $dh = opendir($path);
    while (($file = readdir($dh)) !== false) {
        if ((is_dir($path.'/'.$file)) && (!in_array($file, array('.', '..')))) {
            $tmp = read_files($path.'/'.$file, $preg);
            $templates = array_merge($templates, $tmp);
        }
        if (preg_match($preg, $file)) {
            // Read in file
            $contents = file($path.'/'.$file);
            // Template name is in the first line and cutted out
            $templatename = array_shift($contents);
            if (preg_match('/\$\$TEMPLATE:(.*?)\$\$/', $templatename, $matches)) {
                $templates[$matches[1]] = $contents;
            }
        }
    }
    closedir($dh);
    return $templates;
}
function tpl_template_chooser() {
    global $conf,$lang;
    $template_dir = DOKU_INC.'data/pages/'.$conf['template_chooser']['namespace'];
    if (!file_exists($template_dir)) {
        return true;
    }
    $templates = read_files($template_dir, '/\.txt$/');
    ?>
    <script type="text/javascript">
    <!--**Bold Text**
    <?php
    foreach ($templates as $key => $value) {
        print "var newitem = new template_chooser_template('$key', ''\n";
        foreach ($value as $line) {
	  $line = addslashes(rtrim($line));
	  print "  + '$line\\n'\n";
        }
        print ");\ntemplate_chooser_templates.push(newitem);\n";
    }
    ?>
    //-->
    </script>
    <?php
    if (count($templates) > 0) {
        ksort($templates);
        print '<div id="template_chooser">';
        print $lang['select_template'].' <select onChange="template_chooser_set_template(this)" name="template_chooser">';
        print '<option value="">-</option>';
        foreach ($templates as $key => $value) {
            print '<option value="'.$key.'">'.$key.'</option>';
        }
        print '</select>';
        print '</div>';
    }
}
?>

The second one's called “template_chooser.js”. (Brilliant idea, eh?)

var template_chooser_templates = new Array();
 
function template_chooser_template(template_name, template_content)
{
    this.template_name = template_name;
    this.template_content = template_content;
}
 
function template_chooser_set_template(selector)
{
    tpl_name = selector[selector.selectedIndex].value;
 
    if (tpl_name == '') {
        return true;
    }
 
    textbox = document.getElementById('wiki__text');
 
    tpl_content = '';
    // Get Content
    for (var i=0; i<template_chooser_templates.length; i++) {
        if (template_chooser_templates[i].template_name == tpl_name) {
            tpl_content = template_chooser_templates[i].template_content;
        }
    }
 
    if (tpl_content != '') {
        textbox.value = textbox.value + tpl_content;
    }
}

Now, in your main.php, add these lines:

In the HTML-head area, add:

<script src="<?php print DOKU_TPL.'template_chooser.js'; ?>" type="text/javascript"></script>

and in the point where you'd like to have the selectbox add a:

<?php
        // Include template chooser
        if (($ACT == 'edit') || ($ACT == 'preview')) {
            include(dirname(__FILE__).'/template_chooser.php');
            tpl_template_chooser();
        }
?>

After that, nothing should happen. That's because you probably haven't created a namespace for the templates. I used the namespace “templates”, but this thing can be configured through the configuration-value “$conf['template_chooser']['namespace']” in your local.php.

If you create the namespace and put a document in it, you'll have to add a certain line before the content starts:

$$TEMPLATE:<Short description of template>$$

If you leave this line out, the document won't be show inside the selectbox. This line will be used to determine what to show inside the selectbox. This line will be dropped in the content, of course.

Now, there are two more things you'd like to do. In the lang.php-file of your chosen language, you should add “$lang['select_template']” and set it to the text, that's shown left of the selectbox.

And you should add the id “#template_chooser” to your css-setup to alter the display of the selectbox. I've used:

Append file 'layout.css' with:

/* ---------------  Template Chooser  ----------------- */
 
#template_chooser {
 margin-left: 40px;
 float: right;
}

That should be all. After you have set up all this, you should have a nice selectbox showing you templates out of your template-namespace, that you can use for new documents.

Discussion

  • I've updated the PHP script to support subnamespaces under the templates-namespace. – Dennis Ploeger 2006-05-02 14:03

I can get everything to work except the template names don't show up in the dropdown box. There are just empty lines added. When I choose a “blank” line the template does paste in. Do you know why the names of the templates don't show up? I'm using, for example,

$$TEMPLATE:<test>$$

at the start of the template. – Dan (2006-07-06)

I contacted the author and he was kind enough to help solve my problem. The template-chooser needs you to put “$$TEMPLATE: template-name$$” for the very first line in your template-document, but there should not be any < or >s in the template-name – Dan (2006-07-06)

—-

  • Where would be the best place to place the PHP code in my main.php:?:
    by now I placed right after <!– wikipage stop –> but in the class=“page”. I must admit I have no idea about PHP… :!:Sebastian 2007/08/31 16:05
  • 2007-12-19: I've updated the PHP code to simplify the embedded JavaScript code. This should hopefully make the pages significantly smaller and solve some problems with backslashes.
  • 2008-03-08: I made a small change in the tpl_template_chooser() function in order allow this “plugin” function with private data configuration. The change looks for the $conf['savedir'] variable, if this has been configured, then the path to the template dir use this variable.

:!:Diego Acosta 2008/03/08 10:47

function tpl_template_chooser() {
 
    global $conf,$lang;
//My changes
    $path="";
    if(empty($conf['savedir'])){
      $path=DOKU_INC;
      $path.="data";
    }
    else{
      $path=$conf['savedir'];
    }
 
    $template_dir = $path.'/pages/'.$conf['template_chooser']['namespace'];
//End of my changes.
 if (!file_exists($template_dir)) {
        return true;
    }
 
    $templates = read_files($template_dir, '/\.txt$/');
 ....
  • 2008-10-24: My first attempt at PHP, so bear with me. I changed the read_files function so that @ID@, @NS@, @PAGE@, @NAME@, @MAIL@, and @DATE@ get expanded in template_chooser templates. I hope this is useful to someone :-)

:!:Steve Hodges 2008/10/24 22:10

function read_files($path, $preg) {
    global $INFO, $conf, $ID;
    $data = array($ID);
    $id = $data[0];
    $templates = array();
    $dh = opendir($path);
    while (($file = readdir($dh)) !== false) {
        if ((is_dir($path.'/'.$file)) && (!in_array($file, array('.', '..')))) {
            $tmp = read_files($path.'/'.$file, $preg);
            $templates = array_merge($templates, $tmp);
        }
        if (preg_match($preg, $file)) {
            // Read in file
            $contents = file($path.'/'.$file);
            // Replace macros
            $contents = str_replace('@ID@',$id,$contents);
            $contents = str_replace('@NS@',getNS($id),$contents);
            $contents = str_replace('@PAGE@',strtr(noNS($id),'_',' '),$contents);
            $contents = str_replace('@USER@',$_SERVER['REMOTE_USER'],$contents);
            $contents = str_replace('@NAME@',$INFO['userinfo']['name'],$contents);
            $contents = str_replace('@MAIL@',$INFO['userinfo']['mail'],$contents);
            $contents = str_replace('@DATE@',strftime($conf['dformat']),$contents);
            // Template name is in the first line and cutted out
            $templatename = array_shift($contents);
            if (preg_match('/\$\$TEMPLATE:(.*?)\$\$/', $templatename, $matches)) {
                $templates[$matches[1]] = $contents;
            }
        }
    }
    closedir($dh);
    return $templates;
}




2009-06-21: I want to use the template chooser not only on new blank pages, but also on existing pages with existing code. But it doesn't matter where I put the cursor, the template chooser puts the template always on the end of the page. Any ideas how to fix that?
I remember that this worked before, but after upgrading to the new version “DokuWiki Release 2009-02-14” it doesn't work anymore. — Sam Carter 2009/06/21 15:33

tips/template_chooser.1245591586.txt.gz · Last modified: 2009-06-21 15:39 by 213.235.238.246

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