comments
[ikiwiki] / doc / todo / progressbar_plugin.mdwn
1 I would like to add next plugin to Ikiwiki. It's `progressbar` or simply `progress`.
2 I'm not sure what plugin name better is, probably that shorter ;) I know that
3 [DokuWiki](http://wiki.splitbrain.org/plugin:progressbar) has similar plugin,
4 so I think it can be useful also for Ikiwiki users.
5
6 Here is proposition of the plugin syntax:
7
8     \[[!progress done=50]]
9
10 Of course, `done` argument is integer from 0 to 100. 
11
12 A here is its HTML result:
13
14     <div class="progress">
15       <div class="progress-done" style="width: 50%">50%</div>
16     </div>
17
18 Note: I was trying with `<span>` tags too, but that tag is inline, so I can't
19 set `width` property for it.
20
21 > In the poll plugin, I ended up using a `<hr>` for the progress-like
22 > thing. One reason I did so is because it actually works in text-mode
23 > browsers (w3m, lynx), that do not support css or colorized
24 > divs. Since the hr is an element they display, just setting its width can
25 > make a basic progress-type display. The style then makes it display
26 > better in more capable browsers.
27
28 > The other advantage to that approach is that the htmlscrubber lets
29 > through the `class` and `width` fields, that are all that are needed for
30 > it to work. No need to work around htmlscrubber.
31
32 > So I suggest adapting this to use similar html. --[[Joey]]
33
34 Default CSS styles for the plugin can be like below:
35
36     div.progress {
37             border: 1px solid #ddd;
38             /* border: 2px solid #ddd; */
39             width: 200px;
40             background: #fff;
41             padding: 2px;
42             /* padding: 0px; */
43             border: 2px solid #aaa;
44             background: #eee;
45     }
46     div.progress-done {
47             height: 14px;
48             background: #ff6600;
49             font-size: 12px;
50             text-align: center;
51             vertical-align: middle;
52     }
53
54 > Please make sure to always set a foreground color if a background color is
55 > set, and use '!important' so the foreground color can be overridden. (CSS
56 > best practices) --[[Joey]]
57
58 You can use alternative, commented CSS code for `div.progress` if you dislike
59 padding around done strip.
60
61 Any comments? --[[Paweł|ptecza]]
62
63 > This looks like a nice idea.  If I could add one further suggestion: Allow your
64 > ratio to be a pair of pagespecs.  Then you could have something like:
65
66     \[[!progress totalpages="bugs/* and backlink(milestoneB)" donepages="bugs/* and backlink(milestoneB) and !link(bugs/done)"]]
67
68 > to have a progress bar marking how many bugs were compete for a
69 > particular milestone.  -- [[Will]]
70
71 >> Thanks a lot for your comment, Will! It seems very interesting for me.
72 >> I need to think more about improving that plugin. --[[Paweł|ptecza]]
73
74 >> Attached is a [[patch]] (well, source) for this.  You also need to add the proposed CSS above to `style.css`.
75 >> At the moment this plugin interacts poorly with the [[plugins/htmlscrubber]] plugin.
76 >> HTMLScrubber plugin removes the `style` attribute from the `progress-done` `div` tag, and so it defaults
77 >> to a width of 100%. -- [[Will]]
78
79 >>> Thank you for the code! I know how to fix that problem, because I had
80 >>> the same issue while writing [[todo/color_plugin]] :) --[[Paweł|ptecza]]
81
82 >>>> Ahh - good idea.  Patch updated to work with HTMLScrubber. --[[Will]]
83
84 >>>>> I like it, but I think that Joey should take a look at that patch too :)
85 >>>>> --[[Paweł|ptecza]]
86
87     #!/usr/bin/perl
88     package IkiWiki::Plugin::progress;
89     
90     use warnings;
91     use strict;
92     use IkiWiki 2.00;
93     
94     my $percentage_pattern = qr/[0-9]+\%/; # pattern to validate percentages
95     
96     sub import { #{{{
97         hook(type => "getsetup", id => "progress", call => \&getsetup);
98         hook(type => "preprocess", id => "progress", call => \&preprocess);
99         hook(type => "format",     id => "progress", call => \&format);
100     } # }}}
101     
102     sub getsetup () { #{{{
103         return 
104                 plugin => {
105                         safe => 1,
106                         rebuild => undef,
107                 },
108     } #}}}
109     
110     sub preprocess (@) { #{{{
111         my %params=@_;
112         
113         my $fill;
114         
115         if (defined $params{percent}) {
116                 $fill = $params{percent};
117                 ($fill) = $fill =~ m/($percentage_pattern)/; # fill is untainted now
118         }
119         elsif (defined $params{totalpages} and defined $params{donepages}) {
120                 add_depends($params{page}, $params{totalpages});
121                 add_depends($params{page}, $params{donepages});
122     
123                 my @pages=keys %pagesources;
124                 my $totalcount=0;
125                 my $donecount=0;
126                 foreach my $page (@pages) {
127                         $totalcount++ if pagespec_match($page, $params{totalpages}, location => $params{page});
128                         $donecount++ if pagespec_match($page, $params{donepages}, location => $params{page});
129                 }
130                 
131                 if ($totalcount == 0) {
132                         $fill = "100%";
133                 } else {
134                         my $number = $donecount/$totalcount*100;
135                         $fill = sprintf("%u%%", $number);
136                 }
137         }
138         else {
139                 error("Missing parameters to progress plugin.  Need either `percent` or `totalpages` and `donepages` parameters.");
140         }
141     
142         return <<EODIV
143     <div class="progress">
144       <div class="progress-done" style="width: $fill">$fill</div>
145     </div>
146     EODIV
147     
148     } # }}}
149     
150     sub format(@) { #{{{
151         my %params = @_;
152     
153         # If HTMLScrubber has removed the style attribute, then bring it back
154     
155         $params{content} =~ s!<div class="progress-done">($percentage_pattern)</div>!<div class="progress-done" style="width: $1">$1</div>!g;
156     
157         return $params{content};    
158     } #}}}
159     
160     1
161
162 Here is a potential documentation page:
163
164 -----
165
166 [[!template id=plugin name=progress author="[[Will]]"]]
167 [[!tag type/meta]]
168
169 Provides a \\[[!progress ]] [[ikiwiki/PreProcessorDirective]] that is
170 replaced with a progress bar.
171
172 There are two possible parameter sets.  The first is a single parameter
173 `percent` which holds a percentage figure for how complete the progress bar is.
174
175 The second possible set of parameters is a pair of [[ikiwiki/PageSpec]]s,
176 `totalpages` and `donepages`.  The progress plugin counts the number of
177 pages in each pagespec and shows the percentage of the total pages that are
178 done.
179
180 This plugin is included in ikiwiki, but is not enabled by default.
181
182 If it is turned on it can show what percentage of pages have discussion pages:
183
184         \[[!progress totalpages="* and !*/Discussion" donepages="*/Discussion"]]