File Coverage

lib/CGI/FormBuilder/Template/Builtin.pm
Criterion Covered Total %
statement 129 136 94.8
branch 74 100 74.0
condition 10 21 47.6
subroutine 8 8 100.0
pod 0 3 0.0
total 221 268 82.4


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             package CGI::FormBuilder::Template::Builtin;
8              
9             =head1 NAME
10              
11             CGI::FormBuilder::Template::Builtin - Builtin HTML rendering
12              
13             =head1 SYNOPSIS
14              
15             my $form = CGI::FormBuilder->new;
16             $form->render;
17              
18             =cut
19              
20 4     4   23 use Carp;
  4         7  
  4         3393  
21 4     4   37 use strict;
  4         9  
  4         152  
22 4     4   22 use warnings;
  4         10  
  4         151  
23 4     4   20 no warnings 'uninitialized';
  4         6  
  4         168  
24              
25 4     4   25 use CGI::FormBuilder::Util;
  4         14  
  4         11637  
26              
27              
28             our $VERSION = '3.09';
29              
30             sub new {
31 58     58 0 110 my $self = shift;
32 58   33     345 my $class = ref($self) || $self;
33 58 50       227 my %opt = @_ if @_ > 1;
34 58         301 return bless \%opt, $class;
35             }
36              
37             sub prepare {
38 58     58 0 96 my $self = shift;
39 58         98 my $form = shift;
40              
41 58         130 my @html = (); # joined with newline
42              
43             # Opening CGI/title gunk
44 58         251 my $hd = $form->header;
45 58 100       176 if (defined $hd) {
46 14         61 push @html, $form->dtd, htmltag('head');
47 14 50       72 push @html, htmltag('title') . $form->title . htmltag('/title')
48             if $form->title;
49              
50             # stylesheet path if specified
51 14 100 100     89 if ($form->{stylesheet} && $form->{stylesheet} ne 1) {
52             # user-specified path
53 4         33 push @html, htmltag('link', { rel => 'stylesheet',
54             type => 'text/css',
55             href => $form->{stylesheet} });
56             }
57             }
58              
59             # JavaScript validate/head functions
60 58         246 my $js = $form->script;
61 58 100       211 push @html, $js if $js;
62              
63             # Opening HTML if so requested
64 58         281 my $font = $form->font;
65 58 50       191 my $fcls = $font ? htmltag('/font') : '';
66 58 100       165 if (defined $hd) {
67 14         49 push @html, htmltag('/head'), $form->body;
68 14 50       45 push @html, $font if $font;
69 14 50       54 push @html, htmltag('h3') . $form->title . htmltag('/h3')
70             if $form->title;
71             }
72              
73             # Include warning if noscript
74 58 100       228 push @html, $form->noscript if $js;
75              
76             # Put id's around state tags if so required
77 58         104 my($stid, $keid);
78 58 100       281 if (my $fn = $form->name) {
79 8         43 $stid = tovar("${fn}$form->{statename}");
80 8         46 $keid = tovar("${fn}$form->{extraname}");
81             }
82              
83             # Begin form
84 58         270 my $txt = $form->text;
85 58 100       173 push @html, $txt if $txt;
86 58         218 push @html, $form->start;
87              
88             # Put id's around state tags if they exist
89 58 50       324 if (my $st = $form->statetags) {
90 58         822 push @html,
91             $form->div(id => $form->idname($form->statename),
92             class => $form->class($form->statename)) .
93             $st . htmltag('/div');
94             }
95 58 100       295 if (my $ke = $form->keepextras) {
96 4         42 push @html,
97             $form->div(id => $form->idname($form->extraname),
98             class => $form->class($form->extraname)) .
99             $ke . htmltag('/div');
100             }
101              
102             # Render hidden fields first
103 58         107 my @unhidden;
104 58         289 for my $field ($form->fieldlist) {
105 169 100       3557 push(@unhidden, $field), next if $field->type ne 'hidden';
106 2         12 push @html, $field->tag; # no label/etc for hidden fields
107             }
108              
109             # Support fieldset => 'name' to organize by fieldset on the fly
110 58         415 my $legend = $form->fieldsets;
111              
112             # Get table stuff and reused calls
113 58         498 my $table = $form->table(id => $form->idname($form->bodyname), class => $form->class);
114 58         150 my $tabn = 1;
115 58 100       184 push @html, $table if $table;
116              
117             # Render regular fields in table
118 58         90 my $lastset;
119 58         128 for my $field (@unhidden) {
120 167 100       1010 if (my $set = $field->fieldset) {
    100          
121             # hooks (hack?) for fieldsets
122 9 100       32 if ($set ne $lastset) {
123             # close any open tables/fieldsets
124 4 100       16 if ($lastset) {
    50          
125 3 50       16 push @html, htmltag('/table') if $table;
126 3         11 push @html, htmltag('/fieldset');
127 3         11 push @html, htmltag('/div');
128             } elsif ($table) {
129             # Catch in case we have an empty table - ie the previous
130             # element is just . This workaround is needed
131             # in case the user wants to mix fields with/without
132             # fieldsets in the same form
133 1 50       7 if ($html[-1] =~ /^
134 1         2 pop @html;
135             } else {
136             # close non-fieldset table
137 0         0 push @html, htmltag('/table');
138             }
139             }
140              
141             # Wrap fieldset in a
to allow jquery #tabs
142 4         34 push @html, $form->div(id => $form->idname($form->tabname.$tabn++),
143             class => $form->class($form->tabname));
144              
145 4         19 (my $sn = lc $set) =~ s/\W+/_/g;
146 4         20 push @html, htmltag('fieldset', id => $form->idname("_$sn"),
147             class => $form->class('_set'));
148 4 50 33     24 push @html, htmltag('legend') . ($legend->{$set}||$set) . htmltag('/legend')
149             if defined $legend->{$set};
150              
151             # Wrap fields in a table
152 4 50       23 push @html, $form->table if $table;
153              
154 4         10 $lastset = $set;
155             }
156             } elsif ($lastset) {
157             # ended
defs before form has ended
158             # remaining fields are not in a fieldset
159 1 50       8 push @html, htmltag('/table') if $table;
160 1         6 push @html, htmltag('/fieldset');
161 1         5 push @html, htmltag('/div');
162 1 50       5 push @html, $table if $table;
163 1         3 undef $lastset; # avoid dup below
164             }
165              
166 167         656 debug 2, "render: attacking normal field '$field'";
167 167 50 33     565 next if $field->static > 1 && ! $field->tag_value; # skip missing static vals
168              
169 167 100       356 if ($table) {
170 165         540 push @html, $form->tr(id => $form->idname("_$field", $form->rowname));
171              
172 165         1015 my $cl = $form->class($form->labelname);
173 165         658 my $row = ' ' . $form->td(id => $form->idname("_$field", $form->labelname),
174             class => $cl) . $font;
175 165 100 66     1090 if ($field->invalid) {
    100          
176 2         10 $row .= $form->invalid_tag($field->label);
177             } elsif ($field->required && ! $field->static) {
178 34         126 $row .= $form->required_tag($field->label);
179             } else {
180 129         511 $row .= $field->label;
181             }
182 165         613 $row .= $fcls . htmltag('/td');
183 165         364 push @html, $row;
184              
185             # tag plus optional errors and/or comments
186 165         229 $row = '';
187 165 100       930 if ($field->invalid) {
188 2         11 $row .= ' ' . $field->message;
189             }
190 165 100       696 if ($field->comment) {
191 11 50       43 $row .= ' ' . $field->comment unless $field->static;
192             }
193 165         737 $row = $field->tag . $row;
194 165         869 $cl = $form->class($form->{fieldname});
195 165         795 push @html, (' ' . $form->td(id => $form->idname("_$field", $form->fieldname),
196             class => $cl) . $font
197             . $row . $fcls . htmltag('/td'));
198 165         618 push @html, htmltag('/tr');
199             } else {
200             # no table
201 2         5 my $row = $font;
202 2 50 33     13 if ($field->invalid) {
    50          
203 0         0 $row .= $form->invalid_tag($field->label);
204             } elsif ($field->required && ! $field->static) {
205 0         0 $row .= $form->required_tag($field->label);
206             } else {
207 2         11 $row .= $field->label;
208             }
209 2         5 $row .= $fcls;
210 2         6 push @html, $row;
211 2         12 push @html, $field->tag;
212 2 50       13 push @html, $field->message if $field->invalid;
213 2 50       12 push @html, $field->comment if $field->comment;
214 2 50       26 push @html, '
' if $form->linebreaks;
215             }
216             }
217              
218             # Close fieldset before [Submit] if using fieldsets
219 58 50       197 if ($lastset) {
220 0 0       0 push @html, htmltag('/table') if $table;
221 0         0 push @html, htmltag('/fieldset');
222 0         0 push @html, htmltag('/div');
223 0         0 undef $table; # avoid dup
below
224             }
225              
226             # Throw buttons in a colspan
227 58         329 my $buttons = $form->reset . $form->submit;
228 58 100       282 if ($buttons) {
229 55         126 my $row = '';
230 55 100       199 if ($table) {
231 53         236 my $c = $form->class($form->{submitname});
232 53 100       256 my %a = $c ? () : (align => 'center');
233 53         499 $row .= $form->tr(id => $form->idname($form->submitname, $form->rowname)) . "\n "
234             . $form->td(id => $form->idname($form->submitname, $form->fieldname),
235             class => $c, colspan => 2, %a) . $font;
236             } else {
237             # wrap in a
for fieldsets
238 2         10 $row .= $form->div(id => $form->idname('_controls'),
239             class => $form->class('_controls'));
240             }
241 55         275 $row .= $buttons;
242 55 100       160 if ($table) {
243 53 50       150 $row .= htmltag('/font') if $font;
244 53 50       237 $row .= htmltag('/td') . "\n" . htmltag('/tr') if $table;
245             } else {
246 2         9 $row .= htmltag('/div');
247             }
248 55         162 push @html, $row;
249             }
250              
251             # Properly nest closing tags
252 58 100       255 push @html, htmltag('/table') if $table;
253 58         186 push @html, htmltag('/form'); # $form->end
254 58 50 33     186 push @html, htmltag('/font') if $font && defined $hd;
255 58 100       182 push @html, htmltag('/body'),htmltag('/html') if defined $hd;
256              
257             # Always return scalar since print() is a list function
258 58         1320 return $self->{output} = join("\n", @html) . "\n"
259             }
260              
261             sub render {
262 58     58 0 96 my $self = shift;
263 58         513 return $self->{output};
264             }
265              
266             1;
267             __END__