Table of Contents
Doodle Plugin
Compatible with DokuWiki
- 2024-02-06 "Kaos" unknown
- 2023-04-04 "Jack Jackrum" unknown
- 2022-07-31 "Igor" unknown
- 2020-07-29 "Hogfather" yes
The idea is stolen from Doodle by Michael Näf.
Syntax
This plugin can help your team to schedule meetings or making other decisions in a team. The syntax looks like this:
<doodle [id]> ^ [choice] ^ [choice] ^ ... ^ </doodle>
That means, you can simply put <doodle>
tags around regular table header to get a check box table with different choices.
[id] | the ID of the doodle; must be unique1); appears as title | required |
---|---|---|
[choice] | an option for which users can tick a checkbox whether it's okay for them or not | required |
You may also add more optional parameters…
<doodle [disable] [single] [login]| [id]> ^ [choice] ^ [choice] ^ ... ^ </doodle>
[disable] | view the result(cannot vote) |
---|---|
[single] | only can check one choice |
[login] | voter must login first & use fullname to be voter name |
You can see this plugin in action here.
Release Notes
- 2009-02-05 :
- Fix options can support special character Exp. & (Jonas noticed the bug)
- Add submit datetime function over the Okay Icon
- 2009-08-10 :
- Fix the bug when using HTML tag as a part of fullname string, table will be broken.
Installation Notes
When the blog plugin is also installed, you need to turn $conf['plugin']['blog']['useifmodifiedsince']
off. I will make sure this incompatibility is still exist or not.
Languages
The “Submit” Button needs to be translated to other languages. Currently only Catalan (ca), German (de), English (en), Spanish (es), French (fr), Hungarian (hu), Italian (it), Dutch (nl), Swedish (sv), Simplified Chinese (zh-cn), Traditional Chinese (zh-tw), Euskera (eu), Luxembourgish (lb) and Valencian (val) are available. Send us your translation or put below!
English
<?php $lang['btn_submit'] = 'Submit'; //Setup VIM: ex: et ts=4 enc=utf-8 : ?>
Esperanto
<?php $lang['btn_submit'] = 'Konservi'; //Setup VIM: ex: et ts=4 enc=utf-8 : ?>
Catalan
<?php /** * translation by Raimon <gwindor@auna.com> */ $lang['btn_submit'] = 'Envia'; //Setup VIM: ex: et ts=4 enc=utf-8 : ?>
German
<?php $lang['btn_submit'] = 'Abschicken'; //Setup VIM: ex: et ts=4 enc=utf-8 : ?>
Simplified Chinese
<?php $lang['btn_submit'] = '提交'; //Setup VIM: ex: et ts=4 enc=utf-8 : ?>
Traditional Chinese
<?php $lang['btn_submit'] = '送出'; //Setup VIM: ex: et ts=4 enc=utf-8 : ?>
Swedish
<?php $lang['btn_submit'] = 'Skicka'; //Setup VIM: ex: et ts=4 enc=utf-8 : ?>
Danish
<?php $lang['btn_submit'] = 'Send'; //Setup VIM: ex: et ts=4 enc=utf-8 : ?>
Dutch
<?php $lang['btn_submit'] = 'Gezien'; //Setup VIM: ex: et ts=4 enc=utf-8 : ?>
French
<?php $lang['btn_submit'] = 'Envoyer'; ?>
Italian
<?php $lang['btn_submit'] = 'Invia'; ?>
Japanese
<?php $lang['btn_submit'] = '提出'; ?>
Luxembourgish
<?php $lang['btn_submit'] = 'Aschécken'; ?>
Spanish
<?php $lang['btn_submit'] = 'Enviar'; ?>
Hungarian
<?php $lang['btn_submit'] = 'Szavazok'; ?>
Euskera
<?php $lang['btn_submit'] = 'Bidali'; ?>
Valencian
<?php $lang['btn_submit'] = 'Enviar'; ?>
Icelandic
<?php $lang['btn_submit'] = 'Senda'; ?>
Czech
<?php $lang['btn_submit'] = 'Odeslat'; ?>
Further Resources
- Click here to download the syntax.php file
Discussion
export to csv
Sometimes voting results have to be further processed in other software. An option similar to disable like “export” would be helpful to export the voting. — 2010/06/26 11:23
Delete Lines
Hi, great job! But I have a problem.
How I can delete lines in an existing doodle? E.g. if somebody did a joke by writing nonsense in the name.
Thanks, Christian
You can uncheck all choices of the line, it will not show on doodle. (It's not Really delete lines, but can meet your requirement) — Jonathan Tsai 2008-03-03 21:55
Retain scroll position
I just set up a questionnaire with a dozen doodles on one page. It is very unfortunate that you have to scroll up after each vote submission - a true showstopper for a questionnaire.
(The wiki I'm using has an older version of the plugin installed, and a have no access to that. I apologize if this has been fixed in the meantime.)
Configuration
How hard would it be to configure doodle plugin to have this functionality:
- Show VoteCount if Configuration Parameter (such as conf['doodle_show_vote_count']) is TRUE.
- Show VoteDate beneath the Yes GreenIcon if Configuration Parameter (such as conf['doodle_show_vote_date']) is TRUE.
This plugin would become very useful to my team if each person would be tagged with the date of the vote and if the count wouldn't show up (since we're aiming at using it as a Go-No-Go tool). — José Carlos Monteiro 2006-04-21 21:03
Options
Is there any chance of incorporating Jonathan Tsai's changes into the plugin (rather than forking it) to ensure future changes are included and details are recorded on this page, particularly as his site is not written in English. The single/disable/login options are really useful.
Also, the ability to delete (erroneous) rows would be useful (ref Christian's request) in a similar way to btable. This could be limited to an administrator or logged in user.
Thanks, Bob (28 Nov 2007)
Bob,
Last month I got a mail from Chi, … and now I am being the doodle plugin maintainer..
— Jonathan Tsai 2008-03-03 21:55
Yes / No / Ifneedbe -polls
Great plugin! It would be nice to have a “maybe” or “if nothing else works”-option, like in the "powerdoodle" of doodle.ch. Oh, and I added Swedish translation to the submit-button. - Erik H 2008-03-12 13:45
I'd like to see this option too - Id2ndR 2008-03-12 13:45
Sure this could be a good idea, but keep your design which is way nicer than powerdoodle :) - fr32c 2008-09-10 10:49
Added by Martasdx
I edit my doodle code and add this option. To use it, download it here: http://files.use-it.cz/free/doodle.zip. Added ifneed option to other 3 options.
Questions to polivma2 [at] fit [dot] cvut [dot] cz
Included:
* Syntax.php
* style.css
* EN and CS lang files
Edit 14.3.2012 - Added support for editing more doodles one same page
If title string with dot, it cannot work
The issue is fixed on 2008-05-20 — Jonathan Tsai 2008/05/20 05:55
Siegfried Schnapka report that :
I get no answerline; results…
Working with DokuWiki current release 2008-05-05.
After “submit” the choice is lost, and it happens nothing more \\
>I will try to fix it soon. — Jonathan Tsai 2008/05/14 04:19
After tracing the source code, I found the issue is from title string with dot. In your case, the title string is
“Testanfrage: Palmenfest in der Karibik am 16.06 bis 29.08”. It will be transformed to
“Testanfrage:_Palmenfest_in_der_Karibik_am_16_06_bis_29_08”; however,
“Testanfrage:_Palmenfest_in_der_Karibik_am_16.06_bis_29.08” should be right.
The issue is fixed on doodle-2008-05-20 version(Use md5 encoding to solve it). Old meta_doodle files are also renamed automatically to meet the new version.
— Jonathan Tsai 2008/05/20 05:55
Where is the ''$conf['plugin']['blog']['useifmodifiedsince']''
I have searched in the blog plugin and in the doodle plugin, but I don't found the $conf['plugin']['blog']['useifmodifiedsince']
anywhere.
Multi-line text in headers
What about to enable more lines in headers? Doodle results with more words in header ( especially time&date ) would be more readable.
Example:
Name | 08-01-01 9:00 | 08-01-01 12:00 | 08-01-02 9:00 | 08-01-02 12:00 |
---|---|---|---|---|
Name1 | y | n | n | n |
Name2 | n | n | y | y |
Quick patch:
Replace line 124 in syntax.php
:
$renderer->doc .= $renderer->_xmlEntities($options[$i]);
by:
$renderer->doc .= str_replace('\\\\','<br/>'.DOKU_LF,$renderer->_xmlEntities($options[$i]));
I'm not familiar with PHP at all, this is only dirty code “that works”. Also centering multiline text in header would be nice.
— Martin 2008/09/25 13:40
Muti Vote Please
Hi I need a Multivote like this, can this be done?? Voting 2times is not intuitive enough for users. Thanks
Name | Mo | Tu | Wed 08-01-02 | Thu |
---|---|---|---|---|
Name1 | y | y | n | n |
Name2 | n | n | y | y |
Name | 08-01-01 9:00 | 08-01-01 12:00 | 08-01-02 9:00 | 08-01-02 12:00 |
Name1 | y | n | n | n |
Name2 | n | n | y | y |
Alternate Syntax Suggestion
To be more consistent with a another plugin I have installed on my wiki(userpoll), it'd be nice if this doodle plugin supported the following alternate syntax:
<doodle [id]> * [option] * [option] * ... </doodle>
This also seems to be more consistent with a list of choices.
Require Login by Default
Perhaps as an option on the config page, it'd be nice if the [login] option was able to be set as always on. My wiki is on an intranet so everybody who would be responding has an account.
Loginname instead of realname
It would be nice to have the loginname instead of the realname when the [login] option is used. How can I achieve that? Could this be made an option? –Rolf 2009/01/03 14:46
I made some big changes to the doodle plugin, like using loginname(pseudo) instead of realname. I will post my diff as soon as I have a bit of time –JRD 2009/03/26 14:35
Email address
It would be nice to have a option for a second input field for emailadress, which should be hidden after send for non registered users. –Björn 2009/02/05 15:26
Multi-Vote, sorting, implicit group member fill and admin edit
I needed the following features:
- allow to sign up more than one person for the scheduled date
- sort signed-up list of users by last name
- auto-fill the vote list with members of a certain group
- for normal users limit signup capability to self
- for advanced users (group member…) allow signing up other users or overriding their entries
Disclaimer: I hacked doodle to do what I need. It works for me, but may not be right for you. Please note that this is the first time I ever touched PHP code, so this might be not the best nor most efficient solution. I found no built-in way to determine if a user is a member of a certain DokuWiki group, so this code was handcrafted as well. Only use this code in restricted environments, I am pretty sure there are security issues (even when limiting the doodle via 'login' it is possible to override the user by changing the hidden param; cross site scripting is very likely possible as well).
New options:
autogroup=GROUP
If this is set, the doodle is pre-filled with all members of Dokuwik group GROUP.
admingroup=GROUP
Only makes sense if option 'login' is also set. Normal users may only change their own values, members of group GROUP can change entries for any doodle entry as if 'login' option was not given.
multi=NUMBER
Display drop-down box instead of checkbox allowing to select at most NUMBER participants for the doodle entry. Summary on the bottom of the doodle will reflect correct total number. Option 'single' must not be set when using multi.
Example:
<doodle login group=normalusers admin=powerusers multi=9 | My cool activity > ^ 08:00-12:00 ^ 13:30-17:30 ^ 20:00-23:00 ^ </doodle>
Deficiencies:
- currently there is no way to delete a single doodle user entry
Diff against version 2009-08-10:
--- a/syntax.php +++ b/syntax.php @@ -53,12 +53,28 @@ class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin { $disable = ""; $single = ""; $login = ""; + $autogroup = ""; + $admingroup = ""; + $multi= false; } else { $title = $rightstr; $disable = strpos($leftstr, "disable"); $single = strpos($leftstr, "single"); $login = strpos($leftstr, "login"); + $autogroup = false; + $admingroup = false; + $multi = false; + + if (preg_match('/group=(\w+)/', $leftstr, $arg)) { + $autogroup = $arg[1]; + } + if (preg_match('/admin=(\w+)/', $leftstr, $arg)) { + $admingroup = $arg[1]; + } + if (preg_match('/multi=(\d+)/', $leftstr, $arg)) { + $multi = $arg[1]; + } } if (!$options){ $options = $title; @@ -71,15 +87,27 @@ class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin { $options[$i] = trim($options[$i]); } - return array(trim($title), $options, $disable, $single, $login); + return array(trim($title), $options, $disable, $single, $login, $autogroup, $admingroup, $multi); } /** * Create output */ function render($mode, &$renderer, $data) { + if (! function_exists("sortByLastName")) { + function sortByLastName($a, $b) { + $a = preg_match('/\w+$/', $a, $a_n); + $b = preg_match('/\w+$/', $b, $b_n); + if (($a != 0) && ($b != 0)) { + return strcasecmp($a_n[0], $b_n[0]); + } else { + return strcasecmp($a, $b); + } + } + } if ($mode == 'xhtml'){ global $lang; + global $auth; $options = $data[1]; $c = count($options)-1; @@ -87,6 +115,9 @@ class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin { $disable = $renderer->_xmlEntities($data[2]); $single = $renderer->_xmlEntities($data[3]); $login = $renderer->_xmlEntities($data[4]); + $autogroup = $renderer->_xmlEntities($data[5]); + $admingroup = $renderer->_xmlEntities($data[6]); + $multi = $renderer->_xmlEntities($data[7]); $dID = md5($title); // prevent caching to ensure the poll results are fresh @@ -100,12 +131,36 @@ class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin { rename($old_dfile, $dfile); } $doodle = unserialize(@file_get_contents($dfile)); - if ($c == 0){ // no options given: reset the doodle $doodle = NULL; } - + #$renderer->doc .= var_dump($doodle); + if ($autogroup) { + # TAG ADDGROUP + if (! is_array ($doodle)) { + $doodle = array(); + } + /* add users not yet contained in the array */ + # TAG GROUP + $filter['grps'] = $autogroup; + $getuser = $auth->retrieveUsers(0, -1, $filter); + foreach ($getuser as $entry) { + $fullname = $entry["name"]; + for ($i = 1; $i < $c; $i++){ + $opt = md5($options[$i]); + if (! isset($doodle[$fullname][$opt])) { + $doodle[$fullname][$opt] = false; + } + } + $doodle[$fullname]['show'] = true; + } + } + + if (is_array($doodle)) { + uksort($doodle, "sortByLastName"); + } + // output the doodle $renderer->table_open(); if ($title){ @@ -138,24 +193,29 @@ class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin { if (isset($doodle[$user][$opt_old])) { $doodle[$user][$opt_old] = false; } - if ($_REQUEST[$dID.'-option'.$i]){ - $doodle[$user][$opt] = true; + if (! $multi) { + if ($_REQUEST[$dID.'-option'.$i]){ + $doodle[$user][$opt] = true; + } else { + $doodle[$user][$opt] = false; + } } else { - $doodle[$user][$opt] = false; + $doodle[$user][$opt] = $_REQUEST[$dID.'-option'.$i]; } } $doodle[$user]['time']=time(); } + uksort($doodle, "sortByLastName"); $fh = fopen($dfile, 'w'); fwrite($fh, serialize($doodle)); fclose($fh); } // display results - if (is_array($doodle)) $renderer->doc .= $this->_doodleResults($doodle, $options); + if (is_array($doodle)) $renderer->doc .= $this->_doodleResults($doodle, $options, $multi); // display entry form if ($disable=="") { - $renderer->doc .= $this->_doodleForm($c, $dID, $doodle, $options, $login, $single); + $renderer->doc .= $this->_doodleForm($c, $dID, $doodle, $options, $login, $single, $autogroup, $admingroup, $multi); } $renderer->table_close(); return true; @@ -164,36 +224,63 @@ class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin { return false; } - function _doodleResults($doodle, $options){ + function _doodleResults($doodle, $options, $multi){ + global $INFO; $cuser = count($doodle); if ($cuser < 1) return ''; $copt = count($options)-1; $users = array_keys($doodle); $ret = ''; $count = array(); - + $logged_in_user = ($_SERVER['REMOTE_USER'] ? $INFO['userinfo']['name'] : ''); + // table okay / not okay for ($i = 0; $i < $cuser; $i++){ $isChecked = 0; + if ($doodle[$user]['show']) { + $isChecked = 1; + } $user = $users[$i]; + $highlighted_user=$user; + if (strpos($user, $logged_in_user) !== false) { + $highlighted_user="<strong>$user</strong>"; + } $updTime = isset($doodle[$user]['time'])?date('Y-m-d H:i:s', $doodle[$user]['time']):'Okey'; - $retTmp = '<tr><td class="rightalign">'.$user.'</td>'; + $retTmp = '<tr><td class="rightalign">'.$highlighted_user.'</td>'; for ($j = 1; $j < $copt; $j++){ $option = md5($options[$j]); $option_old = $options[$j]; - if ($doodle[$user][$option] || $doodle[$user][$option_old]){ - $class = 'okay'; - $title = '<img src="'.DOKU_BASE.'lib/images/success.png" title="'. - $updTime.'" alt="'.$updTime.'" '. - 'width="16" height="16" />'; - $count[$option] += 1; - $isChecked = 1; - } elseif (!isset($doodle[$user][$option]) && !isset($doodle[$user][$option_old])){ - $class = 'centeralign'; - $title = ' '; + $value = $doodle[$user][$option]; + if (! isset($value)) { + $value = $doodle[$user][$option_old]; + } + if (! $multi) { + if ($value){ + $class = 'okay'; + $title = '<img src="'.DOKU_BASE.'lib/images/success.png" title="'. + $updTime.'" alt="'.$updTime.'" '. + 'width="16" height="16" />'; + $count[$option] += 1; + $isChecked = 1; + } elseif (!isset($doodle[$user][$option]) && !isset($doodle[$user][$option_old])){ + $class = 'centeralign'; + $title = ' '; + } else { + $class = 'notokay'; + $title = ' '; + } } else { - $class = 'notokay'; - $title = ' '; + $class = 'centeralign'; + if (strpos($user, $logged_in_user) !== false) { + if ($value > 0) { + $class = 'okay'; + } else { + $class = 'notokay'; + } + } + $title = $value; + $count[$option] += $value; + $isChecked = 1; } $retTmp .= '<td class="'.$class.'">'.$title.'</td>'; } @@ -212,10 +299,11 @@ class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin { return $ret; } - function _doodleForm($n, $dID, $doodle, $options, $login, $single){ + function _doodleForm($n, $dID, $doodle, $options, $login, $single, $autogroup, $admingroup, $multi){ global $lang; global $ID; global $INFO; + global $auth; $user = ($_SERVER['REMOTE_USER'] ? $INFO['userinfo']['name'] : ''); $count = array(); @@ -224,6 +312,21 @@ class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin { '" accept-charset="'.$lang['encoding'].'"><tr>'. '<input type="hidden" name="do" value="show" />'. '<input type="hidden" name="id" value="'.$ID.'" />'; + + if ($admingroup) { + $filter = array(); + $filter['name'] = $user; + $getuser = $auth->retrieveUsers(0, -1, $filter); + #$ret .= var_dump($getuser); + foreach ($getuser as $key => $value) { + if ($getuser[$key]['name'] == $user) { + $usergroups = $getuser[$key]['grps']; + if (count(preg_grep("/^$admingroup$/", $usergroups)) > 0) { + $login = ""; + } + } + } + } if ($login=="") { $ret .= '<td class="rightalign"><input type="text" name="fullname" '.'value="'.$user.'" /></td>'; } @@ -235,13 +338,19 @@ class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin { } $i = 1; while ($i < $n){ + $selected = ""; if (is_array($doodle)){ $option = md5($options[$i]); $option_old = $options[$j]; - if ($doodle[$user][$option] || $doodle[$user][$option_old]){ + + $checked = ' '; + if ($doodle[$user][$option_old]) { + $selected = $doodle[$user][$option_old]; + $checked = 'checked="checked" '; + } + if ($doodle[$user][$option]) { + $selected = $doodle[$user][$option]; $checked = 'checked="checked" '; - } else { - $checked = ' '; } } else { $checked = ' '; @@ -256,8 +365,21 @@ class syntax_plugin_doodle extends DokuWiki_Syntax_Plugin { } $onclickstr .= '"'; } - $ret.= '<td class="centeralign"><input type="checkbox" '. + if (! $multi) { + $ret.= '<td class="centeralign"><input type="checkbox" '. 'name="'.$dID.'-option'.$i.'" value="1" '.$checked.' '.$onclickstr.'/></td>'; + } else { + $ret.= '<td class="centeralign"><select size="1" '. + 'name="' . $dID . '-option' . $i . '"' . $onclickstr.'>'; + for ($k = 0; $k <= $multi; $k++) { + $selected_string = ""; + if ($selected == $k) { + $selected_string = " selected"; + } + $ret .= "<option" . $selected_string . ">$k</option>"; + } + $ret .= '</select></td>'; + } $i++; } $ret .= '</tr><tr><td class="centeralign" colspan="'.($n).'">'.
–Martin 2009-09-01 15:00 CEST
more confortable edit function
I just patched your plugin to allow a more comfortable way to edit existing entries. Just click the name (it's a link now) and the input fields will be initialised with the saved values.
See my demo: http://strukturpunkt.de/doodle/demo
Here is the source: http://strukturpunkt.de/doodle/start
If you like it, it will be great if you integrate my changes in your official plugin.
– Klaus Franken 2010-07-28
Doodle Poll Plugin V2.0
I merged the doodle, vote and userpoll plugins into one with all their features. Have a look at doodle2. I already asked the author of this plugin. We see the doodle2 as the new version. — Doogie - September 2010