blib/lib/HTML/StickyForms.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 7 | 145 | 4.8 |
branch | 0 | 72 | 0.0 |
condition | 0 | 21 | 0.0 |
subroutine | 3 | 16 | 18.7 |
pod | 12 | 12 | 100.0 |
total | 22 | 266 | 8.2 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | |||||||
2 | package HTML::StickyForms; | ||||||
3 | BEGIN { | ||||||
4 | 1 | 1 | 24606 | $HTML::StickyForms::VERSION = '0.08'; | |||
5 | } | ||||||
6 | 1 | 1 | 8 | use strict; | |||
1 | 1 | ||||||
1 | 23 | ||||||
7 | 1 | 1 | 4 | use warnings; | |||
1 | 1 | ||||||
1 | 2337 | ||||||
8 | |||||||
9 | |||||||
10 | ################################################################################ | ||||||
11 | # Class method: new($request) | ||||||
12 | # Description: Return a new HTML::StickyForms object | ||||||
13 | # $request may be an instance of CGI (new or old) or Apache::Request | ||||||
14 | # Author: Peter Haworth | ||||||
15 | sub new{ | ||||||
16 | 0 | 0 | 1 | my($class,$req)=@_; | |||
17 | |||||||
18 | 0 | my $type; | |||||
19 | 0 | 0 | 0 | if(!$req){ | |||
0 | |||||||
0 | |||||||
20 | 0 | $type='empty'; | |||||
21 | }elsif(UNIVERSAL::isa($req,'Apache::Request')){ | ||||||
22 | 0 | $type='apreq'; | |||||
23 | }elsif(UNIVERSAL::isa($req,'CGI') || UNIVERSAL::isa($req,'CGI::State')){ | ||||||
24 | 0 | $type='CGI'; | |||||
25 | }else{ | ||||||
26 | # XXX Maybe this should die? | ||||||
27 | 0 | return undef; | |||||
28 | } | ||||||
29 | |||||||
30 | 0 | my $self=bless { | |||||
31 | req => $req, | ||||||
32 | type => $type, | ||||||
33 | values_as_labels => 0, | ||||||
34 | well_formed => '', | ||||||
35 | },$class; | ||||||
36 | |||||||
37 | # Count submitted fields | ||||||
38 | 0 | $self->set_sticky; | |||||
39 | |||||||
40 | 0 | $self; | |||||
41 | } | ||||||
42 | |||||||
43 | ################################################################################ | ||||||
44 | # Method: set_sticky([BOOL]) | ||||||
45 | # Description: Count the number of parameters set in the request | ||||||
46 | # Author: Peter Haworth | ||||||
47 | sub set_sticky{ | ||||||
48 | 0 | 0 | 1 | my $self=shift; | |||
49 | 0 | 0 | return $self->{params}=!!$_[0] if @_; | ||||
50 | |||||||
51 | 0 | 0 | $self->{params}=()=$self->{type} eq 'empty' ? () : $self->{req}->param; | ||||
52 | } | ||||||
53 | |||||||
54 | ################################################################################ | ||||||
55 | # Method: values_as_labels([BOOL]) | ||||||
56 | # Description: Set/Get the values_as_labels attribute | ||||||
57 | # Author: Peter Haworth. Idea from Thomas Klausner (domm@zsi.at) | ||||||
58 | sub values_as_labels{ | ||||||
59 | 0 | 0 | 1 | my $self=shift; | |||
60 | 0 | 0 | return $self->{values_as_labels}=$_[0] if @_; | ||||
61 | 0 | $self->{values_as_labels}; | |||||
62 | } | ||||||
63 | |||||||
64 | ################################################################################ | ||||||
65 | # Method: well_formed([BOOL]) | ||||||
66 | # Description: Set/Get the well_formed attribute | ||||||
67 | # Author: Peter Haworth | ||||||
68 | sub well_formed{ | ||||||
69 | 0 | 0 | 1 | my $self=shift; | |||
70 | 0 | 0 | return !!($self->{well_formed}=$_[0] ? '/' : '') if @_; | ||||
0 | |||||||
71 | 0 | !!$self->{well_formed}; | |||||
72 | } | ||||||
73 | |||||||
74 | ################################################################################ | ||||||
75 | # Method: trim_params() | ||||||
76 | # Description: Trim leading and trailing whitespace from all submitted values | ||||||
77 | # Author: Peter Haworth | ||||||
78 | sub trim_params{ | ||||||
79 | 0 | 0 | 1 | my($self)=@_; | |||
80 | 0 | my $req=$self->{req}; | |||||
81 | 0 | my $type=$self->{type}; | |||||
82 | 0 | 0 | return if $type eq 'empty'; | ||||
83 | |||||||
84 | 0 | foreach my $k($req->param){ | |||||
85 | 0 | my @v=$req->param($k); | |||||
86 | 0 | my $changed; | |||||
87 | 0 | foreach(@v){ | |||||
88 | 0 | $changed+= s/^\s+//s + s/\s+$//s; | |||||
89 | } | ||||||
90 | 0 | 0 | if($changed){ | ||||
91 | 0 | 0 | if($type eq 'apreq'){ | ||||
92 | # XXX This should work, but doesn't | ||||||
93 | # $req->param($k,\@v); | ||||||
94 | |||||||
95 | # This does work, though | ||||||
96 | 0 | 0 | if(@v==1){ | ||||
97 | 0 | $req->param($k,$v[0]); | |||||
98 | }else{ | ||||||
99 | 0 | my $tab=$req->parms; | |||||
100 | 0 | $tab->unset($k); | |||||
101 | 0 | foreach(@v){ | |||||
102 | 0 | $tab->add($k,$_); | |||||
103 | } | ||||||
104 | } | ||||||
105 | }else{ | ||||||
106 | 0 | $req->param($k,@v) | |||||
107 | } | ||||||
108 | } | ||||||
109 | } | ||||||
110 | } | ||||||
111 | |||||||
112 | ################################################################################ | ||||||
113 | # Subroutine: _escape($string) | ||||||
114 | # Description: Escape HTML-special characters in $string | ||||||
115 | # Author: Peter Haworth | ||||||
116 | sub _escape($){ | ||||||
117 | 0 | 0 | $_[0]=~s/([<>&"\177-\377])/sprintf "%d;",ord $1/ge; | ||||
0 | |||||||
118 | } | ||||||
119 | |||||||
120 | ################################################################################ | ||||||
121 | # Method: text(%args) | ||||||
122 | # Description: Return an HTML field | ||||||
123 | # Special %args elements: | ||||||
124 | # type => type attribute value, defaults to "text" | ||||||
125 | # default => value attribute value, if sticky values not present | ||||||
126 | # Author: Peter Haworth | ||||||
127 | sub text{ | ||||||
128 | 0 | 0 | 1 | my($self,%args)=@_; | |||
129 | 0 | 0 | my $type=delete $args{type} || 'text'; | ||||
130 | 0 | my $name=delete $args{name}; | |||||
131 | 0 | my $value=delete $args{default}; | |||||
132 | 0 | 0 | $value=$self->{req}->param($name) if $self->{params}; | ||||
133 | |||||||
134 | 0 | _escape($name); | |||||
135 | 0 | _escape($value); | |||||
136 | |||||||
137 | 0 | my $field=qq( | |||||
138 | 0 | while(my($key,$val)=each %args){ | |||||
139 | 0 | $field.=qq( $key="$val"); # XXX Escape? | |||||
140 | } | ||||||
141 | |||||||
142 | 0 | return "$field$self->{well_formed}>"; | |||||
143 | } | ||||||
144 | |||||||
145 | ################################################################################ | ||||||
146 | # Method: password(%args) | ||||||
147 | # Description: Return an HTML field | ||||||
148 | # As text() | ||||||
149 | # Author: Peter Haworth | ||||||
150 | sub password{ | ||||||
151 | 0 | 0 | 1 | my $self=shift; | |||
152 | 0 | $self->text(@_,type => 'password'); | |||||
153 | } | ||||||
154 | |||||||
155 | ################################################################################ | ||||||
156 | # Method: textarea(%args) | ||||||
157 | # Description: Return an HTML | ||||||
158 | # Special %args elements: | ||||||
159 | # default => field contents, if sticky values not present | ||||||
160 | # Author: Peter Haworth | ||||||
161 | sub textarea{ | ||||||
162 | 0 | 0 | 1 | my($self,%args)=@_; | |||
163 | 0 | my $name=delete $args{name}; | |||||
164 | 0 | my $value=delete $args{default}; | |||||
165 | 0 | 0 | $value=$self->{req}->param($name) if $self->{params}; | ||||
166 | |||||||
167 | 0 | _escape($name); | |||||
168 | 0 | _escape($value); | |||||
169 | |||||||
170 | 0 | my $field=qq( | |||||
171 | 0 | while(my($key,$val)=each %args){ | |||||
172 | 0 | $field.=qq( $key="$val"); # XXX Escape? | |||||
173 | } | ||||||
174 | |||||||
175 | 0 | return "$field>$value"; | |||||
176 | } | ||||||
177 | |||||||
178 | ################################################################################ | ||||||
179 | # Method: checkbox(%args) | ||||||
180 | # Description: Return a single HTML tag | ||||||
181 | # Special %args elements: | ||||||
182 | # checked => whether the box is checked, if sticky values not present | ||||||
183 | # Author: Peter Haworth | ||||||
184 | sub checkbox{ | ||||||
185 | 0 | 0 | 1 | my($self,%args)=@_; | |||
186 | 0 | my $name=delete $args{name}; | |||||
187 | 0 | my $value=delete $args{value}; | |||||
188 | 0 | my $checked=delete $args{checked}; | |||||
189 | 0 | 0 | $checked=$self->{req}->param($name) eq $value if $self->{params}; | ||||
190 | |||||||
191 | 0 | _escape($name); | |||||
192 | 0 | _escape($value); | |||||
193 | |||||||
194 | 0 | my $field=qq( | |||||
195 | 0 | 0 | $field.=' checked="checked"' if $checked; | ||||
196 | 0 | while(my($key,$val)=each %args){ | |||||
197 | 0 | $field.=qq( $key="$val"); # XXX Escape? | |||||
198 | } | ||||||
199 | |||||||
200 | 0 | return "$field$self->{well_formed}>"; | |||||
201 | } | ||||||
202 | |||||||
203 | ################################################################################ | ||||||
204 | # Method: checkbox_group(%args) | ||||||
205 | # Description: Return a group of HTML tags | ||||||
206 | # Special %args elements: | ||||||
207 | # type => defaults to "checkbox" | ||||||
208 | # value/values => arrayref of field values, defaults to label keys | ||||||
209 | # label/labels => hashref of field names, no default | ||||||
210 | # escape => whether to escape HTML characters in labels | ||||||
211 | # default/defaults => arrayref of selected values, if no sticky values | ||||||
212 | # linebreak => whether to add s after each checkbox |
||||||
213 | # values_as_labels => override the values_as_labels attribute | ||||||
214 | # Author: Peter Haworth | ||||||
215 | sub checkbox_group{ | ||||||
216 | 0 | 0 | 1 | my($self,%args)=@_; | |||
217 | 0 | 0 | my $type=delete $args{type} || 'checkbox'; | ||||
218 | 0 | my $name=delete $args{name}; | |||||
219 | 0 | 0 | my $labels=delete $args{labels} || delete $args{label} || {}; | ||||
220 | 0 | my $escape=delete $args{escape}; | |||||
221 | 0 | 0 | my $values=delete $args{values} || delete $args{value} || [keys %$labels]; | ||||
222 | 0 | 0 | my $defaults=delete $args{exists $args{defaults} ? 'defaults' : 'default'}; | ||||
223 | 0 | 0 | $defaults=[] unless defined $defaults; | ||||
224 | 0 | 0 | $defaults=[$defaults] if ref($defaults) ne 'ARRAY'; | ||||
225 | 0 | 0 | my $br=delete $args{linebreak} ? " {well_formed}>" : ''; |
||||
226 | 0 | my $v_as_l=$self->{values_as_labels}; | |||||
227 | 0 | 0 | if(exists $args{values_as_labels}){ | ||||
228 | 0 | $v_as_l=delete $args{values_as_labels}; | |||||
229 | } | ||||||
230 | 0 | 0 | my %checked=map { ; $_ => 1 } | ||||
0 | |||||||
231 | $self->{params} ? $self->{req}->param($name) : @$defaults; | ||||||
232 | |||||||
233 | 0 | _escape($name); | |||||
234 | |||||||
235 | 0 | my $field=qq( | |||||
236 | 0 | while(my($key,$val)=each %args){ | |||||
237 | 0 | $field.=qq( $key="$val"); # XXX Escape? | |||||
238 | } | ||||||
239 | |||||||
240 | 0 | my @checkboxes; | |||||
241 | 0 | for my $value(@$values){ | |||||
242 | 0 | _escape(my $evalue=$value); | |||||
243 | 0 | my $field=qq($field value="$evalue"); | |||||
244 | 0 | 0 | $field.=' checked="checked"' if $checked{$value}; | ||||
245 | 0 | $field.="$self->{well_formed}>"; | |||||
246 | 0 | 0 | 0 | if((my $label=$v_as_l && !exists $labels->{$value} | |||
0 | |||||||
247 | ? $value : $labels->{$value})=~/\S/ | ||||||
248 | ){ | ||||||
249 | 0 | 0 | _escape($label) if $escape; | ||||
250 | 0 | $field.=$label; | |||||
251 | } | ||||||
252 | 0 | $field.=$br; | |||||
253 | 0 | push @checkboxes,$field; | |||||
254 | } | ||||||
255 | |||||||
256 | 0 | 0 | return @checkboxes if wantarray; | ||||
257 | 0 | return join '',@checkboxes; | |||||
258 | } | ||||||
259 | |||||||
260 | ################################################################################ | ||||||
261 | # Method: radio_group(%args) | ||||||
262 | # Description: Return a group of HTML tags | ||||||
263 | # Special %args elements: | ||||||
264 | # value/values => arrayref of field values, defaults to label keys | ||||||
265 | # label/labels => hashref of field labels, no default | ||||||
266 | # escape => whether to escape HTML characters in labels | ||||||
267 | # defaults/default => selected value, if no sticky values | ||||||
268 | # linebreak => whether to add s after each checkbox |
||||||
269 | # Author: Peter Haworth | ||||||
270 | sub radio_group{ | ||||||
271 | 0 | 0 | 1 | my($self,%args)=@_; | |||
272 | |||||||
273 | 0 | $self->checkbox_group(%args,type => 'radio'); | |||||
274 | } | ||||||
275 | |||||||
276 | ################################################################################ | ||||||
277 | # Method: select(%args) | ||||||
278 | # Description: Return an HTML | ||||||
279 | # Special %args elements: | ||||||
280 | # value/values => arrayref of field values, defaults to label keys | ||||||
281 | # label/labels => hashref of field labels, no default | ||||||
282 | # default/defaults => selected value(s), if no sticky values | ||||||
283 | # size => if positive, sets multiple | ||||||
284 | # values_as_labels => override the values_as_labels attribute | ||||||
285 | # Of little value, since this is HTML's default, anyway | ||||||
286 | # Author: Peter Haworth | ||||||
287 | sub select{ | ||||||
288 | 0 | 0 | 1 | my($self,%args)=@_; | |||
289 | 0 | my $name=delete $args{name}; | |||||
290 | 0 | my $multiple=delete $args{multiple}; | |||||
291 | 0 | 0 | my $labels=delete $args{labels} || delete $args{label} || {}; | ||||
292 | 0 | 0 | my $values=delete $args{values} || delete $args{value} || [keys %$labels]; | ||||
293 | 0 | 0 | my $defaults=delete $args{exists $args{defaults} ? 'defaults' : 'default'}; | ||||
294 | 0 | 0 | $defaults=[] unless defined $defaults; | ||||
295 | 0 | 0 | $defaults=[$defaults] if ref($defaults) ne 'ARRAY'; | ||||
296 | 0 | my $v_as_l=$self->{values_as_labels}; | |||||
297 | 0 | 0 | if(exists $args{values_as_labels}){ | ||||
298 | 0 | $v_as_l=delete $args{values_as_labels}; | |||||
299 | } | ||||||
300 | 0 | 0 | my %selected=map { ; $_ => 1 } | ||||
0 | |||||||
301 | $self->{params} ? $self->{req}->param($name) : @$defaults; | ||||||
302 | |||||||
303 | 0 | _escape($name); | |||||
304 | 0 | my $field=qq( | |||||
305 | 0 | while(my($key,$val)=each %args){ | |||||
306 | 0 | $field.=qq( $key="$val"); # XXX Escape? | |||||
307 | } | ||||||
308 | 0 | 0 | $field.=' multiple="multiple"' if $multiple; | ||||
309 | 0 | $field.=">\n"; | |||||
310 | 0 | for my $value(@$values){ | |||||
311 | 0 | _escape(my $evalue=$value); | |||||
312 | 0 | $field.=qq( | |||||
313 | 0 | 0 | $field.=' selected="selected"' if $selected{$value}; | ||||
314 | 0 | $field.=">"; | |||||
315 | 0 | 0 | 0 | if((my $label=$v_as_l && !exists $labels->{$value} | |||
0 | |||||||
316 | ? $value : $labels->{$value})=~/\S/ | ||||||
317 | ){ | ||||||
318 | 0 | _escape($label); | |||||
319 | 0 | $field.=$label; | |||||
320 | } | ||||||
321 | 0 | $field.="\n"; | |||||
322 | } | ||||||
323 | 0 | $field.=""; | |||||
324 | |||||||
325 | 0 | $field; | |||||
326 | } | ||||||
327 | |||||||
328 | ################################################################################ | ||||||
329 | # Return true to require | ||||||
330 | 1; | ||||||
331 | |||||||
332 | |||||||
333 | __END__ |