File Coverage

blib/lib/HTML/StickyForm.pm
Criterion Covered Total %
statement 40 239 16.7
branch 18 96 18.7
condition 2 30 6.6
subroutine 10 24 41.6
pod 18 18 100.0
total 88 407 21.6


line stmt bran cond sub pod time code
1              
2             =head1 NAME
3              
4             HTML::StickyForm - Lightweight general-purpose HTML form generation, with sticky values
5              
6             =head1 SYNOPSIS
7              
8             # mod_perl example
9              
10             use HTML::StickyForm;
11             use Apache::Request;
12              
13             sub handler{
14             my($r)=@_;
15             $r=Apache::Request->new($r);
16             my $f=HTML::StickyForm->new($r);
17              
18             $r->send_http_header;
19             print
20             '',
21             $form->form_start,
22              
23             "Text field:",
24             $f->text(name => 'field1', size => 40, default => 'default value'),
25              
26             "
Text area:",
27             $f->textarea(name => 'field2', cols => 60, rows => 5, default => 'stuff'),
28              
29             "
Single radio button:",
30             $f->radio(name => 'field3', value => 'xyz', checked => 1),
31              
32             "
Radio buttons:",
33             $f->radio_group(name => 'field4', values => [1,2,3],
34             labels => { 1=>'one', 2=>'two', 3=>'three' }, default => 2),
35              
36             "
Single checkbox:",
37             $f->checkbox(name => 'field5', value => 'xyz', checked => 1),
38              
39             "
Checkbox group:",
40             $f->checkbox_group(name => 'field6', values => [4,5,6],
41             labels => { 4=>'four', 5=>'five', 6=>'six' }, default => [5,6]),
42              
43             "
Password field:",
44             $f->password(name => 'field7', size => 20),
45              
46             '
",
47             $f->submit(value => ' Hit me! '),
48              
49             $f->form_end,
50             '',
51             ;
52             return OK;
53             }
54              
55             =head1 DESCRIPTION
56              
57             This module provides a simple interface for generating HTML form
58             elements, with default values chosen from the previous form submission. This
59             module was written with mod_perl (L) in mind, but works
60             equally well with CGI.pm, including the new 3.x version, or any other module
61             which implements a param() method, or even completely standalone.
62              
63             The module does not provide methods for generating all possible HTML elements,
64             only those which are used in form construction.
65             In addition, this module's interface is much less flexible than CGI.pm's; all
66             routines work only as methods, and there is only one way of passing parameters
67             to each method. This was done for two reasons: to keep the API simple and
68             consistent, and to keep the code size down to a minimum.
69              
70             =cut
71              
72              
73             package HTML::StickyForm;
74             BEGIN {
75 7     7   98267 $HTML::StickyForm::VERSION = '0.07_02';
76             }
77 7     7   38 use strict;
  7         17  
  7         116  
78 7     7   22 use warnings;
  7         11  
  7         13854  
79              
80             =head1 CLASS METHODS
81              
82             =over
83              
84             =item new([REQUEST])
85              
86             Creates a new form generation object. The single argument can be:
87              
88             =over
89              
90             =item *
91              
92             any object which responds to a C method in the same way that L and
93             L objects do. That is, with no arguments, the names of the
94             parameters are returned as a list. With a single argument, the value(s) of the
95             supplied parameter is/are returned; in scalar context the first value,
96             and in list context all values.
97              
98             =item *
99              
100             a plain arrayref. This will be used to construct an
101             L object, which responds as described above.
102             The array will be passed directly to the RequestHash constructor, so both
103             methods for specifying multiple values are allowed.
104              
105             =item *
106              
107             a plain hashref. This will be used to construct an
108             L object. Multiple values must be represented
109             as arrayref values.
110              
111             =item *
112              
113             a false value. This will be used to construct an
114             L object with no parameters set.
115              
116             =back
117              
118             The constructor dies if passed an unrecognised request object.
119              
120             If an appropriate object is supplied, parameters will be fetched from the
121             object on an as needed basis, which means that changes made to the request
122             object after the form object is constructed may affect the default values
123             used in generated form elements. However, once constructed, the form object's
124             sticky status does not get automatically updated, so if changes made to the
125             request object need to affect the form object's sticky status, set_sticky()
126             must be called between request object modification and form generation.
127              
128             In contrast, L objects created as part of form
129             object construction use copies of the parameters from the supplied hashref or
130             arrayref. This means that the changes made to the original data do not affect
131             the request object, so have absolutely no effect of the behaviour of the
132             form object.
133              
134             =cut
135              
136             sub new{
137 4     4 1 426 my($class,$req)=@_;
138              
139             # Identify the type of request
140 4         5 my $type;
141 4 100       54 if(!$req){
    50          
    0          
    0          
142 2         3 $type='hash';
143 2         5 $req={};
144 2         5 }elsif(eval{ local $SIG{__DIE__}; $req->can('param'); }){
  2         14  
145 2         3 $type='object';
146             }elsif(ref($req) eq 'HASH'){
147 0         0 $type='hash';
148             }elsif(ref($req) eq 'ARRAY'){
149 0         0 $type='array';
150             }else{
151 0         0 require Carp;
152 0         0 Carp::croak(
153             "Unrecognised request passed to HTML::StickyForm constructor ($req)");
154             }
155 4 100 66     20 if($type eq 'hash' || $type eq 'array'){
156 2         864 require HTML::StickyForm::RequestHash;
157 2 50       20 $req=HTML::StickyForm::RequestHash->new($type eq 'hash' ? %$req : @$req);
158             }
159              
160 4         18 my $self=bless {
161             req => $req,
162             values_as_labels => 0,
163             well_formed => ' /',
164             },$class;
165              
166             # Count submitted fields
167 4         12 $self->set_sticky;
168              
169 4         42 $self;
170             }
171              
172             =back
173              
174             =head1 METHODS
175              
176             =head2 Configuration methods
177              
178             =over
179              
180             =item set_sticky([BOOL])
181              
182             With no arguments, the request object's parameters are counted, and the form
183             object is made sticky if one or more parameters are present, non-sticky
184             otherwise. If an argument is given, its value as a boolean determines whether
185             the form object will be sticky or not. In both cases, the return value will be
186             the new value of the sticky flag.
187              
188             A non-sticky form object always uses the values supplied to methods when
189             constructing HTML elements, whereas a sticky form object will use the values
190             from the request.
191              
192             This method is called by the constructor when the form object is created, so it
193             is not usually necessary to call it explicitly. However, it may be necessary to
194             call this method if parameters are set with the C method after the
195             form object is created.
196              
197             =cut
198              
199             sub set_sticky{
200 9     9 1 175 my $self=shift;
201 9 100       25 return $self->{params}=!!$_[0] if @_;
202              
203 7         26 $self->{params}=!!(()=$self->{req}->param);
204             }
205              
206             =item get_sticky()
207              
208             Returns true if the form object is sticky.
209              
210             =cut
211              
212             sub get_sticky{
213 7     7 1 491 my($self)=@_;
214              
215 7         21 !!$self->{params};
216             }
217              
218             =item values_as_labels([BOOL])
219              
220             With no arguments, this method returns the C attribute,
221             which determines what should happen when a value has no label in the
222             checkbox_group(), radio_group() and select() methods. If this attribute
223             is false (the default), no labels will be automatically generated. If it is
224             true, labels will default to the corresponding value if they are not supplied
225             by the user.
226              
227             If an argument is passed, it is used to set the C attribute.
228              
229             =cut
230              
231             sub values_as_labels{
232 6     6 1 6 my $self=shift;
233 6 100       20 return $self->{values_as_labels}=!!$_[0] if @_;
234 4         12 $self->{values_as_labels};
235             }
236              
237             =item well_formed([BOOL])
238              
239             With no arguments, this method return the C attribute, which
240             determines whether to generate well-formed XML, by including the trailing
241             slash in non-container elements.
242             If true, all generated elements will be well-formed. If false, no slashes
243             are added - which is unfortunately required by some older browsers.
244              
245             If an argument is passed, it is used to set the C attribute.
246              
247             =cut
248              
249             sub well_formed{
250 6     6 1 6 my $self=shift;
251 6 100       20 return !!($self->{well_formed}=$_[0] ? ' /' : '') if @_;
    100          
252 4         14 !!$self->{well_formed};
253             }
254              
255             =back
256              
257             =head2 HTML generation methods
258              
259             Most of these methods are specified as taking PAIRLIST arguments. This means
260             that arguments must be passed as a list of name/value pairs. For example:
261              
262             $form->text(name => 'fred',value => 'bloggs');
263              
264             This represents two arguments; "name" with a value of "fred", and "value"
265             with a value of "bloggs".
266              
267             In cases where sticky values are useful, there are two ways of specifying the
268             values, depending on whether stickiness is required for the element being
269             generated. To set sticky value defaults, use the C argument.
270             Alternatively, to set values which are not affected by previous values entered
271             by the user, use the C argument (or C or C, depending
272             on the type of element being generated).
273              
274             =over
275              
276             =item form_start(PAIRLIST)
277              
278             Generates a CformE> start tag. All arguments are interpreted
279             as attributes for the element. All names and values are HTML escaped.
280             The following arguments are treated specially:
281              
282             C: Defaults to C
283              
284             =cut
285              
286             sub form_start{
287 0     0 1 0 my($self,$args)=&_args;
288 0 0       0 $args->{method}='GET' unless exists $args->{method};
289              
290 0         0 my $field='
291 0         0 while(my($name,$val)=each %$args){
292 0         0 _escape($name);
293 0         0 _escape($val);
294 0         0 $field.=qq( $name="$val");
295             }
296 0         0 $field.='>';
297              
298 0         0 $field;
299             }
300              
301             =item form_start_multipart(PAIRLIST)
302              
303             As form_start(), but the C argument defaults to C.
304              
305             =cut
306              
307             sub form_start_multipart{
308 0     0 1 0 my($self,$args)=&_args;
309 0   0     0 $args->{enctype}||='mutipart/form-data';
310 0         0 $self->form_start($args);
311             }
312              
313             =item form_end()
314              
315             Generates a CformE> end tag.
316              
317             =cut
318              
319             sub form_end{
320 0     0 1 0 '';
321             }
322              
323             =item text(PAIRLIST)
324              
325             Generates an CinputE> element. In general, arguments are interpreted
326             as attributes for the element. All names and values are HTML escaped. The
327             following arguments are treated specially:
328              
329             C: Defaults to C
330              
331             C: Unconditional value. If present, causes C and any sticky
332             value to be ignored.
333              
334             C: Conditional value, ignored if C is present. If the form is
335             sticky, the sticky value will be used for the C attribute's value.
336             Otherwise, the supplied C will be used.
337             A C attribute is never created.
338              
339             =cut
340              
341             sub text{
342 0     0 1 0 my($self,$args)=&_args;
343 0   0     0 my $type=delete $args->{type} || 'text';
344 0         0 my $name=delete $args->{name};
345 0         0 my $value;
346 0 0       0 if(exists $args->{value}){
347 0         0 $value=delete $args->{value};
348 0         0 delete $args->{default};
349             }else{
350 0         0 $value=delete $args->{default};
351 0 0       0 $value=$self->{req}->param($name) if $self->{params};
352             }
353              
354 0         0 _escape($type);
355 0         0 _escape($name);
356 0         0 _escape($value);
357              
358 0         0 my $field=qq(
359 0         0 while(my($key,$val)=each %$args){
360 0         0 _escape($key);
361 0         0 _escape($val);
362 0         0 $field.=qq( $key="$val");
363             }
364              
365 0         0 return "$field$self->{well_formed}>";
366             }
367              
368             =item hidden(PAIRLIST)
369              
370             As text(), but produces an input element of type C.
371              
372             =cut
373              
374             sub hidden{
375 0     0 1 0 my($self,$args)=&_args;
376 0   0     0 $args->{type}||='hidden';
377 0         0 $self->text($args);
378             }
379              
380             =item password(PAIRLIST)
381              
382             As text(), but produces an input element of type C.
383              
384             =cut
385              
386             sub password{
387 0     0 1 0 my($self,$args)=&_args;
388 0   0     0 $args->{type}||='password';
389 0         0 $self->text($args);
390             }
391              
392             =item textarea(PAIRLIST)
393              
394             Generates a EtextareaE container. All arguments are used directly
395             to generate attributes for the start tag, except for those listed below.
396             All values are HTML-escaped.
397              
398             C: Unconditional value. If present, specifies the contents of the
399             container, and causes C and any sticky value to be ignored. A
400             C attribute is never created.
401              
402             C: Conditional value, ignored if C is present. If the form is
403             stikcy, the sticky value wil be used for the container contents. Otherwise,
404             sticky, the supplied C will be used.
405             A C attribute is never created.
406              
407             =cut
408              
409             sub textarea{
410 0     0 1 0 my($self,$args)=&_args;
411 0         0 my $name=delete $args->{name};
412 0         0 my $value;
413 0 0       0 if(exists $args->{value}){
414 0         0 $value=delete $args->{value};
415 0         0 delete $args->{default};
416             }else{
417 0         0 $value=delete $args->{default};
418 0 0       0 $value=$self->{req}->param($name) if $self->{params};
419             }
420              
421 0         0 _escape($name);
422 0         0 _escape($value);
423              
424 0         0 my $field=qq(";
432             }
433              
434             =item checkbox(PAIRLIST)
435              
436             Generates a single C type CinputE> element. All arguments
437             are used directly to generate attributes for the tag, except for those listed
438             below. All values are HTML-escaped.
439              
440             C: Unconditional status. If present, used to decide whether to include
441             a checked attribute, and causes C and any sticky value to be ignored.
442              
443             C: Conditional status, ignored if C is present. If the form
444             is sticky, the sticky value will be used to determine whether to include a
445             checked attribute. Otherwise, the supplied C will be used.
446              
447             If the decision to include the C attribute is based on the sticky
448             value, the sticky parameter must include at least one value which is the same
449             as the supplied C argument. If the decision is based on the value of
450             the C or C arguments, the supplied argument need only be
451             true for the C attribute to be created.
452              
453             =cut
454              
455             sub checkbox{
456 0     0 1 0 my($self,$args)=&_args;
457 0   0     0 my $type=delete $args->{type} || 'checkbox';
458 0         0 my $name=delete $args->{name};
459 0         0 my $value=delete $args->{value};
460 0         0 my $checked;
461 0 0       0 if(exists $args->{checked}){
462 0         0 $checked=delete $args->{checked};
463 0         0 delete $args->{default};
464             }else{
465 0         0 $checked=delete $args->{default};
466 0 0       0 $value='' unless defined($value);
467 0 0       0 $checked=grep $_ eq $value,$self->{req}->param($name) if $self->{params};
468             }
469              
470 0         0 _escape($name);
471 0         0 _escape($value);
472              
473 0         0 my $field=qq(
474 0 0       0 $field.=' checked="checked"' if $checked;
475 0         0 while(my($key,$val)=each %$args){
476 0         0 _escape($key);
477 0         0 _escape($val);
478 0         0 $field.=qq( $key="$val");
479             }
480              
481 0         0 return "$field$self->{well_formed}>";
482             }
483              
484             =item checkbox_group(PAIRLIST)
485              
486             Generates a group of C type CinputE> elements. If called in
487             list context, returns a list of elements, otherwise a single string containing
488             all tags. All arguments are used directly to generate attributes in each tag,
489             except for those listed below. Arguments with scalar values result in that
490             value being used for each element, whereas hashref values result in the value
491             keyed by the element's C attribute being used.
492             Unless otherwise stated, all names and values are HTML-escaped.
493              
494             C: An arrayref of values.
495             One element will be generated for each element, in the order supplied.
496             If not supplied, the label keys will be used instead.
497              
498             C: A hashref of labels.
499             Each element generated will be followed by the label keyed
500             by the value. Values will be HTML-escaped unless a false C argument
501             is supplied. If no label is present for a given value and C
502             is true, the value will also be used for the label.
503              
504             C: If present and false, labels will not be HTML-escaped.
505              
506             C: Unconditional status. If present, used to decide whether each
507             checkbox is marked as checked, and causes C, C and any
508             sticky values to be ignored. May be a single value or arrayref of values.
509              
510             C: Conditional status, ignored if C is present.
511             If the form is sticky, individual checkboxes are marked as checked if the
512             sticky parameter includes at least one value which is the same as the individual
513             checkbox's value. Otherwise, the supplied C values are
514             used in the same way. May be a single value or arrayref of values.
515              
516             C: If true, each element/label will be followed by a CbrE>
517             element.
518              
519             C: If supplied, overrides the form object's
520             C attribute.
521              
522             =cut
523              
524             sub checkbox_group{
525 0     0 1 0 my($self,$args)=&_args;
526 0   0     0 my $type=delete $args->{type} || 'checkbox';
527 0         0 my $name=delete $args->{name};
528 0   0     0 my $labels=delete $args->{labels} || {};
529 0         0 my $escape_labels=1;
530 0 0       0 $escape_labels=delete $args->{escape_labels} if exists $args->{escape_labels};
531 0         0 my $values=delete $args->{values};
532 0   0     0 $values||=[keys %$labels];
533 0         0 my $checked=[];
534 0 0       0 if(exists $args->{checked}){
535 0         0 $checked=delete $args->{checked};
536 0 0       0 $checked=[$checked] if ref($checked) ne 'ARRAY';
537 0         0 delete $args->{default};
538             }else{
539 0 0       0 if(exists $args->{default}){
540 0         0 $checked=delete $args->{default};
541 0 0       0 $checked=[$checked] if ref($checked) ne 'ARRAY';
542             }
543 0 0       0 $checked=[$self->{req}->param($name)] if $self->{params};
544             }
545 0         0 my %checked=map +($_,'checked'),@$checked;
546 0 0       0 my $br=delete $args->{linebreak} ? "{well_formed}>" : '';
547 0         0 my $v_as_l=$self->{values_as_labels};
548 0 0       0 if(exists $args->{values_as_labels}){
549 0         0 $v_as_l=delete $args->{values_as_labels};
550             }
551              
552 0         0 _escape($type);
553 0         0 _escape($name);
554              
555 0         0 my $field=qq(
556 0         0 my %per_value=(
557             checked => \%checked,
558             value => {map +($_,$_),@$values},
559             );
560 0         0 while(my($key,$val)=each %$args){
561 0 0 0     0 if($val && ref($val) eq 'HASH'){
562 0         0 $per_value{$key}=$val;
563 0         0 next;
564             }
565 0         0 _escape($key);
566 0         0 _escape($val);
567 0         0 $field.=qq( $key="$val");
568             }
569              
570 0         0 my @checkboxes;
571 0         0 for my $value(@$values){
572 0         0 my $field=$field;
573 0         0 while(my($key,$hash)=each %per_value){
574 0 0       0 exists $hash->{$value}
575             or next;
576 0         0 _escape($key);
577 0         0 _escape(my $val=$hash->{$value});
578 0         0 $field.=qq( $key="$val");
579             }
580 0         0 $field.="$self->{well_formed}>";
581              
582 0 0       0 if(exists $labels->{$value}){
    0          
583 0         0 my $label=$labels->{$value};
584 0 0       0 _escape($label) if $escape_labels;
585 0         0 $field.=$label;
586             }elsif($v_as_l){
587 0         0 _escape(my $evalue=$value);
588 0         0 $field.=$evalue;
589             }
590 0         0 $field.=$br;
591 0         0 push @checkboxes,$field;
592             }
593              
594 0 0       0 return @checkboxes if wantarray;
595 0         0 return join '',@checkboxes;
596             }
597              
598             =item radio(PAIRLIST)
599              
600             As radio_group(), but setting C to C.
601              
602             =cut
603              
604             sub radio{
605 0     0 1 0 my($self,$args)=&_args;
606 0   0     0 $args->{type}||='radio';
607 0         0 $self->checkbox($args);
608             }
609              
610             =item radio_group(PAIRLIST)
611              
612             As checkbox_group(), but setting C to C.
613              
614             =cut
615              
616             sub radio_group{
617 0     0 1 0 my($self,$args)=&_args;
618 0   0     0 $args->{type}||='radio';
619 0         0 $self->checkbox_group($args);
620             }
621              
622             =item select(PAIRLIST)
623              
624             Generates a CselectE> element. All arguments are used directly to
625             generate attributes in the CselectE> element, except for those listed below. Unless otherwise stated, all names and values are HTML-escaped.
626              
627             C: An arrayref of values and/or option groups.
628             Scalar values are used directly to create CoptionE> elements,
629             whereas arrayrefs represent option groups. The first element in an option
630             group is either the group's label or a hashref holding all of the group's
631             attributes, of which C is special cased to produce the attribute
632             value C if true, and no attribute if false.
633             Defaults to label keys.
634              
635             C: A hashref of labels.
636             Each CoptionE> tag generated will contain the
637             label keyed by its value. If no label is present for a given value, no label
638             will be generated. Defaults to an empty hashref.
639              
640             C: Unconditional status. If present, the supplied values will be
641             used to decide which options to mark as selected, and C and any
642             sticky values will be ignored. May be a single value or arrayref.
643              
644             C: Conditional status, ignored if C is
645             supplied. If the form is sticky, the sticky values will be used to decide which
646             options are selected. Otherwise, the supplied values will be used.
647             May be a single value or arrayref.
648              
649             C: If true, the C attribute is set to C.
650              
651             C: Overrides the form object's C attribute.
652             This is of little value, since it's the default behaviour of HTML in any case.
653              
654             =cut
655              
656             sub select{
657 0     0 1 0 my($self,$args)=_args(@_);
658 0         0 my $name=delete $args->{name};
659 0         0 my $multiple=delete $args->{multiple};
660 0   0     0 my $labels=delete $args->{labels} || {};
661 0   0     0 my $values=delete $args->{values} || [keys %$labels];
662 0         0 my $selected;
663 0 0       0 if(exists $args->{selected}){
664 0         0 $selected=delete $args->{selected};
665 0         0 delete $args->{default};
666             }else{
667 0         0 $selected=delete $args->{default};
668 0 0       0 $selected=[$self->{req}->param($name)] if $self->{params};
669             }
670 0 0       0 if(!defined $selected){ $selected=[]; }
  0 0       0  
671 0         0 elsif(ref($selected) ne 'ARRAY'){ $selected=[$selected]; }
672 0         0 my %selected=map +($_,1),@$selected;
673 0         0 my $v_as_l=$self->{values_as_labels};
674 0 0       0 if(exists $args->{values_as_labels}){
675 0         0 $v_as_l=delete $args->{values_as_labels};
676             }
677              
678 0         0 _escape($name);
679 0         0 my $field=qq(
680 0         0 while(my($key,$val)=each %$args){
681 0         0 _escape($key);
682 0         0 _escape($val);
683 0         0 $field.=qq( $key="$val");
684             }
685 0 0       0 $field.=' multiple="multiple"' if $multiple;
686 0         0 $field.=">";
687              
688 0         0 $field.=_select_options($values,\%selected,$labels,$v_as_l);
689 0         0 $field.="";
690              
691 0         0 $field;
692             }
693              
694              
695              
696             =item submit(PAIRLIST)
697              
698             Generates an CinputE> of type C. All of the supplied
699             arguments are HTML-escaped, and used directly as attributes. C
700             fields are not sticky.
701              
702             =cut
703              
704             sub submit{
705 0     0 1 0 my($self,$args)=_args(@_);
706 0 0       0 $args->{type}='submit' unless exists $args->{type};
707              
708 0         0 my $field='
709 0         0 while(my($key,$val)=each %$args){
710 0         0 _escape($key);
711 0         0 _escape($val);
712 0         0 $field.=qq( $key="$val");
713             }
714 0         0 $field.="$self->{well_formed}>";
715              
716 0         0 $field;
717             }
718              
719              
720             =back
721              
722              
723              
724              
725             =begin private
726              
727             =head1 PRIVATE SUBROUTINES
728              
729             These subs are only intended for internal use.
730              
731             =over
732              
733             =item _escape($string)
734              
735             Escape HTML-special characters in $string, in place. If $string is not defined,
736             it will be updated to an empty string.
737              
738             =cut
739              
740             sub _escape($){
741 7 100   7   1901 if(defined $_[0]){
742 6         24 $_[0]=~s/([<>&"]|[^\0-\177])/sprintf "&#%d;",ord $1/ge;
  9         34  
743             }else{
744 1         3 $_[0]='';
745             }
746             }
747              
748             =item _args(@_)
749              
750             Work out which of the two argument passing conventions is being used, and
751             return ($self,\%args). This essentially converts the public unrolled
752             PAIRLIST arguments into a single hashref, as used by the internal
753             interfaces.
754              
755             =cut
756              
757             sub _args{
758 4     4   2199 my $self=shift;
759 4 100       12 my $args=ref($_[0]) ? {%{$_[0]}} : {@_};
  2         6  
760 4         8 ($self,$args);
761             }
762              
763             =item _select_options(\@values,\%selected,\%labels,$values_as_labels)
764              
765             Returns an HTML fragment containing C
766             list of option values. Values which are arrayrefs are used to represent
767             option groups, wherein the zeroth element is either the group name, or
768             a hashref holding the group's attributes.
769              
770             =cut
771              
772             sub _select_options{
773 0     0     my($values,$selected,$labels,$v_as_l)=@_;
774 0           my $field='';
775 0           for my $value(@$values){
776 0 0         if(ref $value){
777             # Handle option group
778 0           my($_group,@subvalues)=@$value;
779 0 0         my %group=ref($_group) ? %$_group : (label => $_group);
780 0 0         if(delete $group{disabled}){
781 0           $group{disabled}='disabled';
782             }
783 0           $field.=qq(
784 0           while(my($name,$value)=each %group){
785 0           _escape($value);
786 0           $field.=qq( $name="$value");
787             }
788 0           $field.='>';
789 0           $field.=_select_options(\@subvalues,$selected,$labels);
790 0           $field.='';
791             }else{
792             # Handle single option
793 0           _escape(my $evalue=$value);
794 0           $field.=qq(
795 0 0         $field.=' selected="selected"' if $selected->{$value};
796 0           $field.=">";
797 0 0         if(exists $labels->{$value}){
    0          
798 0           my $label=$labels->{$value};
799 0           _escape($label);
800 0           $field.=$label;
801             }elsif($v_as_l){
802 0           $field.=$evalue;
803             }
804 0           $field.="";
805             }
806             }
807              
808 0           $field;
809             }
810              
811             =back
812              
813             =end private
814              
815             =cut
816              
817             # Return true to require
818             1;
819              
820              
821              
822             =head1 AUTHOR
823              
824             Copyright (C) Institute of Physics Publishing 2000-2011
825              
826             Peter Haworth
827              
828             You may use and distribute this module according to the same terms
829             that Perl is distributed under.
830              
831