File Coverage

blib/lib/HTML/FormHandler/Render/Simple.pm
Criterion Covered Total %
statement 146 178 82.0
branch 43 56 76.7
condition 17 24 70.8
subroutine 16 20 80.0
pod 11 17 64.7
total 233 295 78.9


line stmt bran cond sub pod time code
1             package HTML::FormHandler::Render::Simple;
2             # ABSTRACT: simple rendering role
3             $HTML::FormHandler::Render::Simple::VERSION = '0.40067';
4 8     8   11298 use Moose::Role;
  8         11  
  8         59  
5              
6             requires( 'sorted_fields', 'field' );
7              
8 8     8   28147 use HTML::FormHandler::Render::Util ('process_attrs', 'ucc_widget');
  8         12  
  8         51  
9              
10              
11              
12             sub render {
13 6     6 1 1535 my $self = shift;
14 6         63 my $output = $self->render_start;
15              
16 6         28 $output .= $self->render_form_errors;
17              
18 6         32 foreach my $field ( $self->sorted_fields ) {
19 39         108 $output .= $self->render_field($field);
20             }
21              
22 6         74 $output .= $self->render_end;
23 6         95 return $output;
24             }
25              
26              
27             sub render_form_errors {
28 6     6 0 13 my $self = shift;
29              
30 6 100       54 return '' unless $self->has_form_errors;
31 1         2 my $output = "\n<div class=\"form_errors\">";
32             $output .= qq{\n<span class="error_message">$_</span>}
33 1         8 for $self->all_form_errors;
34 1         2 $output .= "\n</div>";
35 1         3 return $output;
36             }
37              
38             sub render_field {
39 96     96 1 589 my ( $self, $field ) = @_;
40              
41 96 100       306 if ( ref( \$field ) eq 'SCALAR' ) {
42 2         14 $field = $self->field($field);
43             }
44 96 50 33     735 die "must pass field to render_field"
45             unless ( defined $field && $field->isa('HTML::FormHandler::Field') );
46             # widgets should be in camel case, since they are Perl package names
47 96         3035 my $widget = ucc_widget($field->widget);
48 96 100       238 return '' if $widget eq 'no_render';
49 91         96 my $rendered_field;
50 91         148 my $form_render = 'render_' . $widget;
51 91 100       385 if ( $self->can($form_render) ) {
    50          
52 90         238 $rendered_field = $self->$form_render($field);
53             }
54             elsif ( $field->can('render') ) {
55 1         7 $rendered_field = $field->render;
56             }
57             else {
58 0         0 die "No widget method found for '$widget' in H::F::Render::Simple";
59             }
60 91         307 return $self->wrap_field( $field, $rendered_field );
61             }
62              
63             sub wrap_field {
64 67     67 0 92 my ( $self, $field, $rendered_field ) = @_;
65              
66 67 50       293 return "\n$rendered_field" if $field->uwrapper eq 'none';
67 67 50       1823 return "\n$rendered_field" if ! $field->do_wrapper;
68              
69 67         95 my $output = "\n";
70              
71 67         243 my $wrapper_tag = $field->get_tag('wrapper_tag');
72 67 50 66     312 $wrapper_tag ||= $field->has_flag('is_repeatable') ? 'fieldset' : 'div';
73 67         335 my $attrs = process_attrs($field->wrapper_attributes);
74              
75 67         191 $output .= qq{<$wrapper_tag$attrs>};
76 67 100 66     256 if( $wrapper_tag eq 'fieldset' ) {
    100 66        
77 2         12 $output .= '<legend>' . $field->loc_label . '</legend>';
78             }
79             elsif ( ! $field->get_tag('label_none') && $field->do_label && length( $field->label ) > 0 ) {
80 57         185 $output .= "\n" . $self->render_label($field);
81             }
82              
83 67         143 $output .= "\n$rendered_field";
84             $output .= qq{\n<span class="error_message">$_</span>}
85 67         456 for $field->all_errors;
86              
87 67         144 $output .= "\n</$wrapper_tag>";
88              
89 67         319 return "$output";
90             }
91              
92             sub render_text {
93 43     43 1 57 my ( $self, $field ) = @_;
94 43         176 my $output = '<input type="' . $field->input_type . '" name="';
95 43         1169 $output .= $field->html_name . '"';
96 43         1100 $output .= ' id="' . $field->id . '"';
97 43 100       1123 $output .= ' size="' . $field->size . '"' if $field->size;
98 43 100       1105 $output .= ' maxlength="' . $field->maxlength . '"' if $field->maxlength;
99 43         152 $output .= ' value="' . $field->html_filter($field->fif) . '"';
100 43         157 $output .= process_attrs($field->element_attributes);
101 43         107 $output .= ' />';
102 43         77 return $output;
103             }
104              
105             sub render_password {
106 0     0 1 0 my ( $self, $field ) = @_;
107 0         0 my $output = '<input type="password" name="';
108 0         0 $output .= $field->html_name . '"';
109 0         0 $output .= ' id="' . $field->id . '"';
110 0 0       0 $output .= ' size="' . $field->size . '"' if $field->size;
111 0 0       0 $output .= ' maxlength="' . $field->maxlength . '"' if $field->maxlength;
112 0         0 $output .= ' value="' . $field->html_filter($field->fif) . '"';
113 0         0 $output .= process_attrs($field->element_attributes);
114 0         0 $output .= ' />';
115 0         0 return $output;
116             }
117              
118             sub render_hidden {
119 5     5 1 10 my ( $self, $field ) = @_;
120 5         8 my $output = '<input type="hidden" name="';
121 5         150 $output .= $field->html_name . '"';
122 5         130 $output .= ' id="' . $field->id . '"';
123 5         27 $output .= ' value="' . $field->html_filter($field->fif) . '"';
124 5         33 $output .= process_attrs($field->element_attributes);
125 5         14 $output .= ' />';
126 5         14 return $output;
127             }
128              
129             sub render_select {
130 14     14 1 21 my ( $self, $field ) = @_;
131              
132 14         435 my $multiple = $field->multiple;
133 14         367 my $id = $field->id;
134 14         325 my $output = '<select name="' . $field->html_name . '"';
135 14         51 $output .= qq{ id="$id"};
136 14 100       51 $output .= ' multiple="multiple"' if $multiple == 1;
137 14 100       384 $output .= ' size="' . $field->size . '"' if $field->size;
138 14         66 my $html_attributes = process_attrs($field->element_attributes);
139 14         33 $output .= $html_attributes;
140 14         21 $output .= '>';
141 14         21 my $index = 0;
142 14 50       446 if( defined $field->empty_select ) {
143 0         0 $output .= '<option value="">' . $field->_localize($field->empty_select) . '</option>';
144             }
145 14         68 my $fif = $field->fif;
146 14         22 my %fif_lookup;
147 14 100       49 @fif_lookup{@$fif} = () if $multiple;
148 14         20 foreach my $option ( @{ $field->{options} } ) {
  14         36  
149 47         78 my $value = $option->{value};
150 47         1415 $output .= '<option value="'
151             . $field->html_filter($value)
152             . qq{" id="$id.$index"};
153 47 100 66     114 if( defined $option->{disabled} && $option->{disabled} ) {
154 4         9 $output .= ' disabled="disabled"';
155             }
156 47 50       74 if ( defined $fif ) {
157 47 100 66     169 if ( $multiple && exists $fif_lookup{$value} ) {
    100          
158 8         10 $output .= ' selected="selected"';
159             }
160             elsif ( $fif eq $value ) {
161 4         9 $output .= ' selected="selected"';
162             }
163             }
164 47         51 $output .= $html_attributes;
165 47         60 my $label = $option->{label};
166 47 50       1279 $label = $field->_localize($label) if $field->localize_labels;
167 47         1374 $output .= '>' . ( $field->html_filter($label) ) . '</option>';
168 47         68 $index++;
169             }
170 14         25 $output .= '</select>';
171 14         50 return $output;
172             }
173              
174             sub render_checkbox {
175 10     10 1 14 my ( $self, $field ) = @_;
176              
177 10         302 my $output = '<input type="checkbox" name="' . $field->html_name . '"';
178 10         284 $output .= ' id="' . $field->id . '"';
179 10         368 $output .= ' value="' . $field->html_filter($field->checkbox_value) . '"';
180 10 100       64 $output .= ' checked="checked"' if $field->fif eq $field->checkbox_value;
181 10         65 $output .= process_attrs($field->element_attributes);
182 10         24 $output .= ' />';
183 10         27 return $output;
184             }
185              
186             sub render_radio_group {
187 5     5 1 13 my ( $self, $field ) = @_;
188              
189 5         12 my $output = " <br />";
190 5         10 my $index = 0;
191 5         9 foreach my $option ( @{ $field->options } ) {
  5         148  
192 10         247 my $id = $field->id . ".$index";
193 10         357 $output .= qq{<label for="$id"><input type="radio" value="} . $field->html_filter($option->{value}) . '"';
194 10         235 $output .= ' name="' . $field->html_name . '" id="' . "$id\"";
195 10 100       39 $output .= ' checked="checked"' if $option->{value} eq $field->fif;
196 10         16 $output .= ' />';
197 10         294 $output .= $field->html_filter($option->{label}) . '</label><br />';
198 10         21 $index++;
199             }
200 5         12 return $output;
201             }
202              
203             sub render_textarea {
204 5     5 1 11 my ( $self, $field ) = @_;
205 5   100     37 my $fif = $field->fif || '';
206 5         126 my $id = $field->id;
207 5   100     148 my $cols = $field->cols || 10;
208 5   100     175 my $rows = $field->rows || 5;
209 5         121 my $name = $field->html_name;
210              
211 5         39 my $output =
212             qq(<textarea name="$name" id="$id" )
213             . process_attrs($field->element_attributes)
214             . qq(rows="$rows" cols="$cols">)
215             . $field->html_filter($fif)
216             . q(</textarea>);
217              
218 5         17 return $output;
219             }
220              
221             sub render_upload {
222 0     0 0 0 my ( $self, $field ) = @_;
223              
224 0         0 my $output;
225 0         0 $output = '<input type="file" name="';
226 0         0 $output .= $field->html_name . '"';
227 0         0 $output .= ' id="' . $field->id . '"';
228 0         0 $output .= process_attrs($field->element_attributes);
229 0         0 $output .= ' />';
230 0         0 return $output;
231             }
232              
233             sub render_label {
234 81     81 0 109 my ( $self, $field ) = @_;
235              
236 81         353 my $attrs = process_attrs( $field->label_attributes );
237 81         382 my $label = $field->html_filter($field->loc_label);
238 81 100       2498 $label .= $field->get_tag('label_after')
239             if( $field->tag_exists('label_after') );
240 81 50       2337 my $label_tag = $field->tag_exists('label_tag') ? $field->get_tag('label_tag') : 'label';
241 81         1920 return qq{<$label_tag$attrs for="} . $field->id . qq{">$label</$label_tag>};
242             }
243              
244             sub render_compound {
245 3     3 1 8 my ( $self, $field ) = @_;
246              
247 3         7 my $output = '';
248 3         22 foreach my $subfield ( $field->sorted_fields ) {
249 9         37 $output .= $self->render_field($subfield);
250             }
251 3         14 return $output;
252             }
253              
254             sub render_submit {
255 5     5 1 11 my ( $self, $field ) = @_;
256              
257 5         11 my $output = '<input type="submit" name="';
258 5         151 $output .= $field->html_name . '"';
259 5         132 $output .= ' id="' . $field->id . '"';
260 5         39 $output .= process_attrs($field->element_attributes);
261 5         162 $output .= ' value="' . $field->html_filter($field->_localize($field->value)) . '" />';
262 5         13 return $output;
263             }
264              
265             sub render_reset {
266 0     0 0   my ( $self, $field ) = @_;
267              
268 0           my $output = '<input type="reset" name="';
269 0           $output .= $field->html_name . '"';
270 0           $output .= ' id="' . $field->id . '"';
271 0           $output .= process_attrs($field->element_attributes);
272 0           $output .= ' value="' . $field->html_filter($field->value) . '" />';
273 0           return $output;
274             }
275              
276             sub render_captcha {
277 0     0 0   my ( $self, $field ) = @_;
278              
279 0           my $output .= '<img src="' . $self->captcha_image_url . '"/>';
280 0           $output .= '<input id="' . $field->id . '" name="';
281 0           $output .= $field->html_name . '"/>';
282 0           return $output;
283             }
284              
285              
286 8     8   12733 use namespace::autoclean;
  8         21  
  8         73  
287             1;
288              
289             __END__
290              
291             =pod
292              
293             =encoding UTF-8
294              
295             =head1 NAME
296              
297             HTML::FormHandler::Render::Simple - simple rendering role
298              
299             =head1 VERSION
300              
301             version 0.40067
302              
303             =head1 SYNOPSIS
304              
305             This is a Moose role that is an example of a simple rendering
306             routine for L<HTML::FormHandler>. It's here as an example of
307             how to write a custom renderer in one package, if you prefer
308             that to using the widgets. It won't always be updated with
309             improvements by default, because it was becoming a lot of work to update
310             the rendering in multiple places.
311              
312             For a 'MyApp::Form::Renderer' which you've created and modified,
313             in your Form class:
314              
315             package MyApp::Form::Silly;
316             use Moose;
317             extends 'HTML::FormHandler::Model::DBIC';
318             with 'MyApp::Form::Renderers';
319              
320             In a template:
321              
322             [% form.render %]
323              
324             The widgets are rendered with C<< $field->render >>; rendering
325             routines from a class like this use C<< $form->render_field('field_name') >>
326             to render individual fields:
327              
328             [% form.render_field( 'title' ) %]
329              
330             =head1 DESCRIPTION
331              
332             This role provides HTML output routines for the 'widget' types
333             defined in the provided FormHandler fields. Each 'widget' name
334             has a 'widget_$name' method here.
335              
336             These widget routines output strings with HTML suitable for displaying
337             form fields.
338              
339             The widget for a particular field can be defined in the form. You can
340             create additional widget routines in your form for custom widgets.
341              
342             The fill-in-form values ('fif') are cleaned with the 'render_filter'
343             method of the base field class. You can change the filter to suit
344             your own needs: see L<HTML::FormHandler::Manual::Rendering>
345              
346             =head2 render
347              
348             To render all the fields in a form in sorted order (using
349             'sorted_fields' method).
350              
351             =head2 render_start, render_end
352              
353             These use the methods in L<HTML::FormHandler::Widget::Form::Simple> now. If
354             you want to customize them, copy them to your own package.
355              
356             Will render the beginning and ending <form> tags and fieldsets. Allows for easy
357             splitting up of the form if you want to hand-render some of the fields.
358              
359             [% form.render_start %]
360             [% form.render_field('title') %]
361             <insert specially rendered field>
362             [% form.render_field('some_field') %]
363             [% form.render_end %]
364              
365             =head2 render_field
366              
367             Render a field passing in a field object or a field name
368              
369             $form->render_field( $field )
370             $form->render_field( 'title' )
371              
372             =head2 render_text
373              
374             Output an HTML string for a text widget
375              
376             =head2 render_password
377              
378             Output an HTML string for a password widget
379              
380             =head2 render_hidden
381              
382             Output an HTML string for a hidden input widget
383              
384             =head2 render_select
385              
386             Output an HTML string for a 'select' widget, single or multiple
387              
388             =head2 render_checkbox
389              
390             Output an HTML string for a 'checkbox' widget
391              
392             =head2 render_radio_group
393              
394             Output an HTML string for a 'radio_group' selection widget.
395             This widget should be for a field that inherits from 'Select',
396             since it requires the existence of an 'options' array.
397              
398             =head2 render_textarea
399              
400             Output an HTML string for a textarea widget
401              
402             =head2 render_compound
403              
404             Renders field with 'compound' widget
405              
406             =head2 render_submit
407              
408             Renders field with 'submit' widget
409              
410             =head1 AUTHOR
411              
412             FormHandler Contributors - see HTML::FormHandler
413              
414             =head1 COPYRIGHT AND LICENSE
415              
416             This software is copyright (c) 2016 by Gerda Shank.
417              
418             This is free software; you can redistribute it and/or modify it under
419             the same terms as the Perl 5 programming language system itself.
420              
421             =cut