File Coverage

lib/CGI/FormBuilder/Field/radio.pm
Criterion Covered Total %
statement 86 87 98.8
branch 41 46 89.1
condition 5 9 55.5
subroutine 8 8 100.0
pod 1 2 50.0
total 141 152 92.7


line stmt bran cond sub pod time code
1              
2             ###########################################################################
3             # Copyright (c) Nate Wiger http://nateware.com. All Rights Reserved.
4             # Please visit http://formbuilder.org for tutorials, support, and examples.
5             ###########################################################################
6              
7             # The majority of this module's methods (including new) are
8             # inherited directly from ::base, since they involve things
9             # which are common, such as parameter parsing. The only methods
10             # that are individual to different fields are those that affect
11             # the rendering, such as script() and tag()
12              
13             package CGI::FormBuilder::Field::radio;
14              
15 6     6   36 use strict;
  6         12  
  6         320  
16 6     6   32 use warnings;
  6         12  
  6         218  
17 6     6   38 no warnings 'uninitialized';
  6         10  
  6         225  
18              
19 6     6   321 use CGI::FormBuilder::Util;
  6         13  
  6         1052  
20 6     6   34 use CGI::FormBuilder::Field;
  6         12  
  6         157  
21 6     6   34 use base 'CGI::FormBuilder::Field';
  6         11  
  6         17428  
22              
23              
24             our $VERSION = '3.09';
25              
26             sub script {
27 46     46 0 100 my $self = shift;
28 46         157 my $name = $self->name;
29              
30             # The way script() works is slightly backwards: First the
31             # type-specific JS DOM code is generated, then this is
32             # passed as a string to Field->jsfield, which wraps this
33             # in the generic handling.
34              
35             # Holders for different parts of JS code
36 46         100 my $jsfunc = '';
37 46         183 my $jsfield = tovar($name);
38 46         91 my $close_brace = '';
39 46         255 my $in = indent(my $idt = 1); # indent
40              
41 46         214 my $alertstr = escapejs($self->jsmessage); # handle embedded '
42 46         98 $alertstr .= '\n';
43              
44             #
45             # Get field from radio buttons or checkboxes.
46             # Must cycle through all again to see which is checked. Yeesh.
47             #
48              
49 46         279 $jsfunc .= <
50             // $name: radio group or multiple checkboxes
51             var $jsfield = null;
52             var selected_$jsfield = 0;
53             for (var loop = 0; loop < form.elements['$name'].length; loop++) {
54             if (form.elements['$name']\[loop].checked) {
55             $jsfield = form.elements['$name']\[loop].value;
56             selected_$jsfield++;
57             EOJS
58              
59             # Add catch for "other" if applicable
60 46 100       165 if ($self->other) {
61 2         7 my $oth = $self->othername;
62 2         8 $jsfunc .= <
63             if ($jsfield == '$oth') $jsfield = form.elements['$oth'].value;
64             EOJS
65             }
66              
67 46         130 $close_brace = <
68              
69             } // if
70             } // for $name
71             EOJS
72              
73             # required?
74 46 100       255 $close_brace .= <required;
75             if (! selected_$jsfield) {
76             alertstr += '$alertstr';
77             invalid++;
78             invalid_fields.push('$jsfield');
79             }
80             EOJS
81              
82             # indent the very last if/else tests so they're in the for loop
83 46         171 $in = indent($idt += 2);
84              
85 46         188 return $self->jsfield($jsfunc, $close_brace, $in);
86             }
87              
88             *render = \&tag;
89             sub tag {
90 48     48 1 176 local $^W = 0; # -w sucks
91 48         106 my $self = shift;
92 48         227 my $attr = $self->attr;
93              
94 48         329 my $jspre = $self->{_form}->jsprefix;
95              
96 48         105 my $tag = '';
97 48         181 my @value = $self->tag_value; # sticky is different in
98 48         188 my @opt = $self->options;
99 48         334 debug 2, "my(@opt) = \$field->options";
100              
101             # Add in our "Other:" option if applicable
102 48 100       232 push @opt, [$self->othername, $self->{_form}{messages}->form_other_default]
103             if $self->other;
104              
105 48         255 debug 2, "$self->{name}: generating $attr->{type} input type";
106              
107 48         87 my $checkbox_table = 0; # toggle
108 48         84 my $checkbox_col = 0;
109 48 100       271 if ($self->columns > 0) {
110 32         52 $checkbox_table = 1;
111 32         120 my $c = $self->{_form}->class('_columns');
112 32         166 $tag .= $self->{_form}->table(class => $c) . "\n";
113             }
114              
115 48 50       194 belch "$self->{name}: No options specified for 'radio' field" unless @opt;
116 48         126 for my $opt (@opt) {
117             # Divide up checkboxes in a user-controlled manner
118 148 100       470 if ($checkbox_table) {
119 104 100       535 $tag .= " ".htmltag('tr')."\n" if $checkbox_col % $self->columns == 0;
120 104         311 $tag .= ' '.htmltag('td') . $self->{_form}->font;
121             }
122             # Since our data structure is a series of ['',''] things,
123             # we get the name from that. If not, then it's a list
124             # of regular old data that we toname() if nameopts => 1
125 148         498 my($o,$n) = optval($opt);
126              
127             # Must use defined() or else labels of "0" are lost
128 148 100       349 unless (defined($n)) {
129 114         316 $n = $attr->{labels}{$o};
130 114 50       445 unless (defined($n)) {
131 114 100       588 $n = $self->nameopts ? toname($o) : $o;
132             }
133             }
134              
135 148 100       500 ismember($o, @value) ? $attr->{checked} = 'checked'
136             : delete $attr->{checked};
137              
138             # reset some attrs
139 148         284 $attr->{value} = $o;
140 148 50       307 if (@opt == 1) {
141             # single option checkboxes do not modify id
142 0   0     0 $attr->{id} ||= tovar($attr->{name});
143             } else {
144             # all others add the current option name
145 148 100       634 $attr->{id} = tovar($o eq $self->othername
146             ? "_$attr->{name}" : "$attr->{name}_$o");
147             }
148              
149             # Special event handling for our _other field
150 148 100 100     556 if ($self->other && $self->javascript) {
151 10         27 my $b = $self->othername; # box
152 10 100       57 if ($n eq $self->{_form}{messages}->form_other_default) {
153             # turn on when they click the "_other" field
154 2         11 $attr->{onclick} = "${jspre}other_on('$b')";
155             } else {
156             # turn off when they select any, well, others
157 8         23 $attr->{onclick} = "${jspre}other_off('$b')";
158             }
159             }
160              
161             # Each radio/checkbox gets a human thingy with
162 148         749 $tag .= $self->add_before_option;
163 148         432 $tag .= htmltag('input', $attr);
164 148 100       580 $tag .= $checkbox_table
165             ? (htmltag('/td')."\n ".htmltag('td').$self->{_form}->font) : ' ';
166 148         573 my $c = $self->{_form}->class('_option');
167 148 100       504 $tag .= htmltag('label', for => $attr->{id}, class => $c)
168             . ($self->cleanopts ? escapehtml($n) : $n)
169             . htmltag('/label');
170 148         890 $tag .= $self->add_after_option;
171              
172 148 50       723 $tag .= '
' if $self->linebreaks;
173              
174 148 100       358 if ($checkbox_table) {
175 104         123 $checkbox_col++;
176 104         278 $tag .= htmltag('/td');
177 104 100       514 $tag .= "\n ".htmltag('/tr') if $checkbox_col % $self->columns == 0;
178             }
179 148         406 $tag .= "\n";
180             }
181 48 50 66     317 $tag .= ' '.htmltag('/tr') if $checkbox_table && ($checkbox_col % $self->columns > 0);
182 48 100       189 $tag .= ' '.htmltag('/table') if $checkbox_table;
183              
184             # add an additional tag for our _other field
185 48 100       271 $tag .= ' ' . $self->othertag if $self->other;
186              
187 48         294 debug 2, "$self->{name}: generated tag = $tag";
188 48         529 return $tag; # always return scalar tag
189             }
190              
191             1;
192              
193             __END__