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   20 use strict;
  6         7  
  6         151  
16 6     6   18 use warnings;
  6         5  
  6         145  
17 6     6   17 no warnings 'uninitialized';
  6         5  
  6         170  
18              
19 6     6   19 use CGI::FormBuilder::Util;
  6         4  
  6         586  
20 6     6   23 use CGI::FormBuilder::Field;
  6         6  
  6         107  
21 6     6   18 use base 'CGI::FormBuilder::Field';
  6         6  
  6         4801  
22              
23              
24             our $VERSION = '3.10';
25              
26             sub script {
27 46     46 0 46 my $self = shift;
28 46         130 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         48 my $jsfunc = '';
37 46         99 my $jsfield = tovar($name);
38 46         49 my $close_brace = '';
39 46         93 my $in = indent(my $idt = 1); # indent
40              
41 46         107 my $alertstr = escapejs($self->jsmessage); # handle embedded '
42 46         56 $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         148 $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       79 if ($self->other) {
61 2         4 my $oth = $self->othername;
62 2         7 $jsfunc .= <
63             if ($jsfield == '$oth') $jsfield = form.elements['$oth'].value;
64             EOJS
65             }
66              
67 46         75 $close_brace = <
68              
69             } // if
70             } // for $name
71             EOJS
72              
73             # required?
74 46 100       172 $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         105 $in = indent($idt += 2);
84              
85 46         105 return $self->jsfield($jsfunc, $close_brace, $in);
86             }
87              
88             *render = \&tag;
89             sub tag {
90 48     48 1 104 local $^W = 0; # -w sucks
91 48         45 my $self = shift;
92 48         118 my $attr = $self->attr;
93              
94 48         199 my $jspre = $self->{_form}->jsprefix;
95              
96 48         52 my $tag = '';
97 48         98 my @value = $self->tag_value; # sticky is different in
98 48         141 my @opt = $self->options;
99 48         163 debug 2, "my(@opt) = \$field->options";
100              
101             # Add in our "Other:" option if applicable
102 48 100       106 push @opt, [$self->othername, $self->{_form}{messages}->form_other_default]
103             if $self->other;
104              
105 48         142 debug 2, "$self->{name}: generating $attr->{type} input type";
106              
107 48         45 my $checkbox_table = 0; # toggle
108 48         41 my $checkbox_col = 0;
109 48 100       182 if ($self->columns > 0) {
110 32         55 $checkbox_table = 1;
111 32         83 my $c = $self->{_form}->class('_columns');
112 32         82 $tag .= $self->{_form}->table(class => $c) . "\n";
113             }
114              
115 48 50       105 belch "$self->{name}: No options specified for 'radio' field" unless @opt;
116 48         72 for my $opt (@opt) {
117             # Divide up checkboxes in a user-controlled manner
118 148 100       202 if ($checkbox_table) {
119 104 100       326 $tag .= " ".htmltag('tr')."\n" if $checkbox_col % $self->columns == 0;
120 104         198 $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         275 my($o,$n) = optval($opt);
126              
127             # Must use defined() or else labels of "0" are lost
128 148 100       249 unless (defined($n)) {
129 114         139 $n = $attr->{labels}{$o};
130 114 50       275 unless (defined($n)) {
131 114 100       361 $n = $self->nameopts ? toname($o) : $o;
132             }
133             }
134              
135             ismember($o, @value) ? $attr->{checked} = 'checked'
136 148 100       261 : delete $attr->{checked};
137              
138             # reset some attrs
139 148         160 $attr->{value} = $o;
140 148 50       198 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       296 $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     311 if ($self->other && $self->javascript) {
151 10         18 my $b = $self->othername; # box
152 10 100       37 if ($n eq $self->{_form}{messages}->form_other_default) {
153             # turn on when they click the "_other" field
154 2         5 $attr->{onclick} = "${jspre}other_on('$b')";
155             } else {
156             # turn off when they select any, well, others
157 8         16 $attr->{onclick} = "${jspre}other_off('$b')";
158             }
159             }
160              
161             # Each radio/checkbox gets a human thingy with
162 148         472 $tag .= $self->add_before_option;
163 148         269 $tag .= htmltag('input', $attr);
164             $tag .= $checkbox_table
165 148 100       320 ? (htmltag('/td')."\n ".htmltag('td').$self->{_form}->font) : ' ';
166 148         333 my $c = $self->{_form}->class('_option');
167 148 100       279 $tag .= htmltag('label', for => $attr->{id}, class => $c)
168             . ($self->cleanopts ? escapehtml($n) : $n)
169             . htmltag('/label');
170 148         512 $tag .= $self->add_after_option;
171              
172 148 50       408 $tag .= '
' if $self->linebreaks;
173              
174 148 100       213 if ($checkbox_table) {
175 104         72 $checkbox_col++;
176 104         152 $tag .= htmltag('/td');
177 104 100       294 $tag .= "\n ".htmltag('/tr') if $checkbox_col % $self->columns == 0;
178             }
179 148         244 $tag .= "\n";
180             }
181 48 50 66     181 $tag .= ' '.htmltag('/tr') if $checkbox_table && ($checkbox_col % $self->columns > 0);
182 48 100       110 $tag .= ' '.htmltag('/table') if $checkbox_table;
183              
184             # add an additional tag for our _other field
185 48 100       99 $tag .= ' ' . $self->othertag if $self->other;
186              
187 48         158 debug 2, "$self->{name}: generated tag = $tag";
188 48         287 return $tag; # always return scalar tag
189             }
190              
191             1;
192              
193             __END__