File Coverage

blib/lib/HTML/FormFu/Element/Date.pm
Criterion Covered Total %
statement 221 233 94.8
branch 63 78 80.7
condition 17 23 73.9
subroutine 32 32 100.0
pod 1 6 16.6
total 334 372 89.7


line stmt bran cond sub pod time code
1 23     23   6414 use strict;
  23         137  
  23         1293  
2              
3             package HTML::FormFu::Element::Date;
4             $HTML::FormFu::Element::Date::VERSION = '2.07';
5             # ABSTRACT: 3 select menu multi-field
6              
7 23     23   503 use Moose;
  23         53  
  23         232  
8 23     23   163622 use MooseX::Attribute::Chained;
  23         276  
  23         1040  
9              
10             extends 'HTML::FormFu::Element::Multi';
11              
12 23     23   147 use HTML::FormFu::Util qw( _filter_components _parse_args );
  23         591  
  23         1673  
13 23     23   8064 use DateTime;
  23         4073289  
  23         1331  
14 23     23   14200 use DateTime::Format::Builder;
  23         1628888  
  23         191  
15 23     23   14961 use DateTime::Format::Natural;
  23         797798  
  23         1738  
16 23     23   235 use DateTime::Locale;
  23         57  
  23         617  
17 23     23   136 use Moose::Util qw( apply_all_roles );
  23         54  
  23         528  
18 23     23   8159 use Scalar::Util qw( blessed );
  23         63  
  23         1234  
19 23     23   147 use List::Util 1.45 qw( all none uniq );
  23         612  
  23         1563  
20 23     23   156 use Carp qw( croak );
  23         52  
  23         7042  
21              
22             __PACKAGE__->mk_attrs(qw( day month year ));
23              
24             has auto_inflate => ( is => 'rw', traits => ['Chained'] );
25             has default_natural => ( is => 'rw', traits => ['Chained'] );
26             has default_datetime_args => ( is => 'rw', traits => ['Chained'] );
27             has printf_day => ( is => 'rw', traits => ['Chained'] );
28             has printf_month => ( is => 'rw', traits => ['Chained'] );
29             has printf_year => ( is => 'rw', traits => ['Chained'] );
30              
31             has _known_fields => ( is => 'rw' );
32              
33             has strftime => (
34             is => 'rw',
35             default => '%d-%m-%Y',
36             lazy => 1,
37             traits => ['Chained'],
38             );
39              
40             *default = \&value;
41              
42             # build get_Xs methods
43             for my $method ( qw(
44             deflator filter
45             constraint inflator
46             validator transformer
47             ) )
48             {
49             my $sub = sub {
50 104     104   220 my $self = shift;
51 104         344 my %args = _parse_args(@_);
52 104         349 my $get_method = "get_${method}s";
53              
54 104         275 my $accessor = "_${method}s";
55 104         179 my @x = @{ $self->$accessor };
  104         3550  
56 104         219 push @x, map { @{ $_->$get_method(@_) } } @{ $self->_elements };
  369         531  
  369         1221  
  104         2934  
57              
58 104         336 return _filter_components( \%args, \@x );
59             };
60              
61             my $name = __PACKAGE__ . "::get_${method}s";
62              
63             ## no critic (ProhibitNoStrict);
64 23     23   200 no strict 'refs';
  23         53  
  23         56224  
65              
66             *{$name} = $sub;
67             }
68              
69             after BUILD => sub {
70             my ( $self, $args ) = @_;
71              
72             $self->printf_day('%d');
73             $self->printf_month('%d');
74             $self->printf_year('%d');
75              
76             $self->_known_fields( [qw( day month year )] );
77              
78             $self->field_order( [qw( day month year )] );
79              
80             $self->day( { prefix => [], } );
81              
82             $self->month( { prefix => [], } );
83              
84             $self->year(
85             { prefix => [],
86             less => 0,
87             plus => 10,
88             reverse => 0,
89             } );
90              
91             return;
92             };
93              
94             sub value {
95 168     168 0 955 my ( $self, $value ) = @_;
96              
97 168 100       545 if ( @_ > 1 ) {
98 27         92 $self->{value} = $value;
99              
100             # if we're already built - i.e. process() has ben called,
101             # call default() on our children
102              
103 27 100       55 if ( @{ $self->_elements } ) {
  27         971  
104 7         39 $self->_date_defaults;
105              
106 7         13 my @order = @{ $self->field_order };
  7         30  
107              
108 7         53 for my $i ( 0 .. $#order ) {
109 31         57 my $field = $order[$i];
110              
111 31         67 my $printf_method = "printf_$field";
112              
113             my $default
114             = $value
115             ? sprintf( $self->$printf_method, $self->$field->{default} )
116 31 100       237 : undef;
117              
118 31         887 $self->_elements->[$i]->default($default);
119             }
120             }
121              
122 27         227 return $self;
123             }
124              
125 141         1334 return $self->{value};
126             }
127              
128             sub _add_elements {
129 47     47   139 my ($self) = @_;
130              
131 47         1535 $self->_elements( [] );
132              
133 47         275 $self->_date_defaults;
134              
135 47         103 for my $order ( @{ $self->field_order } ) {
  47         152  
136 172         647 my $method = "_add_$order";
137              
138 172         986 $self->$method;
139             }
140              
141 47 100 100     2154 if ( $self->auto_inflate
142 20         179 && !@{ $self->get_inflators( { type => "DateTime" } ) } )
143             {
144 10         58 _add_inflator($self);
145             }
146              
147 47         170 return;
148             }
149              
150             sub _date_defaults {
151 54     54   204 my ($self) = @_;
152              
153 54         154 my $default;
154              
155 54 100 100     229 if ( defined( $default = $self->default ) && length $default ) {
    100          
156              
157 38 100 66     1217 if ( !$self->form->submitted || $self->render_processed_value ) {
158 32         70 for my $deflator ( @{ $self->_deflators } ) {
  32         1038  
159 1         8 $default = $deflator->process($default);
160             }
161             }
162              
163 38         773 my $is_blessed = blessed($default);
164              
165 38 100 33     365 if ( !$is_blessed || ( $is_blessed && !$default->isa('DateTime') ) ) {
      66        
166 19         144 my $builder = DateTime::Format::Builder->new;
167 19         911 $builder->parser( { strptime => $self->strftime } );
168              
169 19         35137 $default = $builder->parse_datetime($default);
170             }
171             }
172             elsif ( defined( $default = $self->default_natural ) ) {
173 3         7 my $parser;
174              
175 3 100       83 if ( defined( my $datetime_args = $self->default_datetime_args ) ) {
176 2 100       9 if ( exists $datetime_args->{set_time_zone} ) {
177 1         3 my $tz = $datetime_args->{set_time_zone};
178 1         15 $parser = DateTime::Format::Natural->new( time_zone => $tz );
179             }
180             else {
181 1         15 $parser = DateTime::Format::Natural->new;
182             }
183             }
184             else {
185 1         27 $parser = DateTime::Format::Natural->new;
186             }
187 3         73981 $default = $parser->parse_datetime($default);
188             }
189             else {
190 13         34 $default = undef;
191             }
192              
193 54 100       34825 if ( defined $default ) {
194              
195 41 100       1638 if ( defined( my $datetime_args = $self->default_datetime_args ) ) {
196 2         10 for my $key ( keys %$datetime_args ) {
197 2         13 $default->$key( $datetime_args->{$key} );
198             }
199             }
200              
201 41         574 for my $field ( @{ $self->field_order } ) {
  41         187  
202 153         644 $self->$field->{default} = $default->$field;
203             }
204             }
205              
206 54         229 return;
207             }
208              
209             sub _add_day {
210 43     43   120 my ($self) = @_;
211              
212 43         163 my $day = $self->day;
213              
214 43         204 my $day_name = $self->_build_name('day');
215              
216             my @day_prefix
217             = ref $day->{prefix}
218 31         152 ? @{ $day->{prefix} }
219 43 100       248 : $day->{prefix};
220              
221 43 50       174 if ( exists $day->{prefix_loc} ) {
222             @day_prefix
223             = ref $day->{prefix_loc}
224 0         0 ? map { $self->form->localize($_) } @{ $day->{prefix_loc} }
  0         0  
225 0 0       0 : $self->form->localize( $day->{prefix_loc} );
226             }
227              
228 43         169 @day_prefix = map { [ '', $_ ] } @day_prefix;
  12         55  
229              
230             my $element = $self->element(
231             { type => 'Select',
232             name => $day_name,
233 1333         2931 options => [ @day_prefix, map { [ $_, $_ ] } 1 .. 31 ],
234             attributes => $day->{attributes},
235              
236 43 100       170 defined $day->{default} ? ( default => $day->{default} ) : (),
237             } );
238              
239 43         563 apply_all_roles( $element, 'HTML::FormFu::Role::Element::MultiElement' );
240              
241 43         719276 return;
242             }
243              
244             sub _add_month {
245 47     47   154 my ($self) = @_;
246              
247 47         274 my $month = $self->month;
248              
249 47         233 my $month_name = $self->_build_name('month');
250              
251 47         223 my @months = _build_month_list($self);
252              
253             my @month_prefix
254             = ref $month->{prefix}
255 33         137 ? @{ $month->{prefix} }
256 47 100       245 : $month->{prefix};
257              
258 47 50       214 if ( exists $month->{prefix_loc} ) {
259             @month_prefix
260             = ref $month->{prefix_loc}
261 0         0 ? map { $self->form->localize($_) } @{ $month->{prefix_loc} }
  0         0  
262 0 0       0 : $self->form->localize( $month->{prefix_loc} );
263             }
264              
265 47         145 @month_prefix = map { [ '', $_ ] } @month_prefix;
  14         65  
266              
267 47         189 my $options = [ @month_prefix, map { [ $_ + 1, $months[$_] ] } 0 .. 11 ];
  564         1334  
268              
269             my $element = $self->element(
270             { type => 'Select',
271             name => $month_name,
272             options => $options,
273             attributes => $month->{attributes},
274              
275 47 100       600 defined $month->{default} ? ( default => $month->{default} ) : (),
276             } );
277              
278 47         334 apply_all_roles( $element, 'HTML::FormFu::Role::Element::MultiElement' );
279              
280 47         666454 return;
281             }
282              
283             sub _add_year {
284 47     47   156 my ($self) = @_;
285              
286 47         287 my $year = $self->year;
287              
288 47         218 my $year_name = $self->_build_name('year');
289              
290             my $year_ref
291             = defined $year->{reference}
292             ? $year->{reference}
293 47 100       3207 : ( localtime(time) )[5] + 1900;
294              
295             my @years
296             = defined $year->{list}
297 36         203 ? @{ $year->{list} }
298 47 100       361 : ( $year_ref - $year->{less} ) .. ( $year_ref + $year->{plus} );
299              
300 47 100       242 if ( $year->{reverse} ) {
301 1         3 @years = reverse(@years);
302             }
303              
304             my @year_prefix
305             = ref $year->{prefix}
306 33         121 ? @{ $year->{prefix} }
307 47 100       289 : $year->{prefix};
308              
309 47 50       197 if ( exists $year->{prefix_loc} ) {
310             @year_prefix
311             = ref $year->{prefix_loc}
312 0         0 ? map { $self->form->localize($_) } @{ $year->{prefix_loc} }
  0         0  
313 0 0       0 : $self->form->localize( $year->{prefix_loc} );
314             }
315              
316 47         142 @year_prefix = map { [ '', $_ ] } @year_prefix;
  14         71  
317              
318             my $element = $self->element(
319             { type => 'Select',
320             name => $year_name,
321 403         1222 options => [ @year_prefix, map { [ $_, $_ ] } @years ],
322             attributes => $year->{attributes},
323              
324 47 100       219 defined $year->{default} ? ( default => $year->{default} ) : (),
325             } );
326              
327 47         404 apply_all_roles( $element, 'HTML::FormFu::Role::Element::MultiElement' );
328              
329 47         654968 return;
330             }
331              
332             sub _build_month_list {
333 47     47   135 my ($self) = @_;
334              
335 47         191 my $month = $self->month;
336 47         108 my @months;
337              
338 47 50       231 if ( defined $month->{names} ) {
339 0         0 @months = @{ $month->{names} };
  0         0  
340             }
341             else {
342 47         355 my $languages = $self->form->languages;
343 47 50       240 if ( ref $languages ne 'ARRAY' ) {
344 0         0 $languages = [$languages];
345             }
346              
347 47         175 for my $lang (@$languages) {
348 47         90 my $loc;
349              
350 47         112 eval { $loc = DateTime::Locale->load($lang) };
  47         545  
351 47 50       2472 if ( !$@ ) {
352             @months
353             = $month->{short_names}
354 14         114 ? @{ $loc->month_format_abbreviated }
355 47 100       218 : @{ $loc->month_format_wide };
  33         246  
356              
357 47         586 @months = map {ucfirst} @months;
  564         1122  
358              
359 47         169 last;
360             }
361             }
362             }
363              
364 47         289 return @months;
365             }
366              
367             sub _build_number_list {
368 19     19   101 my ( $self, $start, $end, $interval ) = @_;
369              
370 19   100     161 $interval ||= 1;
371              
372 19         41 my @list;
373              
374 19         76 for ( my $i = $start; $i <= $end; $i += $interval ) {
375 1034         1790 push @list, $i;
376             }
377              
378 19         119 return @list;
379             }
380              
381             sub _build_name {
382 172     172   561 my ( $self, $type ) = @_;
383              
384             my $name
385             = defined $self->$type->{name}
386             ? $self->$type->{name}
387 172 50       547 : sprintf "%s_%s", $self->name, $type;
388              
389 172         521 return $name;
390             }
391              
392             sub _add_inflator {
393 10     10   30 my ($self) = @_;
394              
395 10         347 $self->inflator(
396             { type => "DateTime",
397             parser => { strptime => $self->strftime, },
398             strptime => $self->strftime,
399             } );
400              
401 10         49 return;
402             }
403              
404             sub field_order {
405 173     173 1 486 my ( $self, @order ) = @_;
406              
407 173 100       507 if ( @_ > 1 ) {
408 60 50 33     387 if ( @order == 1 && ref( $order[0] ) eq 'ARRAY' ) {
409 60         131 @order = @{ $order[0] };
  60         213  
410             }
411              
412 60         144 for my $field (@order) {
413             croak "unknown field type: '$field'"
414 206 100   486   664 if none { $field eq $_ } @{ $self->_known_fields };
  486         1460  
  206         5846  
415             }
416              
417 59 100       637 croak 'repeated field type'
418             if scalar( uniq @order ) != scalar(@order);
419              
420 58         246 $self->{field_order} = \@order;
421              
422 58         585 return $self;
423             }
424             else {
425 113         425 return $self->{field_order};
426             }
427             }
428              
429             sub process {
430 47     47 0 154 my ( $self, @args ) = @_;
431              
432 47         258 $self->_add_elements;
433              
434 47         502 return $self->SUPER::process(@args);
435             }
436              
437             sub process_input {
438 18     18 0 48 my ( $self, $input ) = @_;
439              
440 18         41 my %value;
441              
442 18         36 my @order = @{ $self->field_order };
  18         68  
443              
444 18         82 for my $i ( 0 .. $#order ) {
445 63         134 my $field = $order[$i];
446              
447 63         1916 my $name = $self->_elements->[$i]->nested_name;
448              
449 63         286 $value{$field} = $self->get_nested_hash_value( $input, $name );
450             }
451              
452 18 100 100 55   148 if ( ( all {defined} values %value )
  55         188  
453 50     50   134 && all {length} values %value )
454             {
455 14         30 my $dt;
456              
457 14         37 eval {
458 14         51 $dt = DateTime->new( map { $_, $value{$_} } keys %value );
  49         191  
459             };
460              
461 14         5887 my $value;
462              
463 14 100       53 if ($@) {
464 3         117 $value = $self->strftime;
465             }
466             else {
467 11         396 $value = $dt->strftime( $self->strftime );
468             }
469              
470 14         890 $self->set_nested_hash_value( $input, $self->nested_name, $value );
471             }
472              
473 18         165 return $self->SUPER::process_input($input);
474             }
475              
476             sub render_data {
477 47     47 0 277 return shift->render_data_non_recursive(@_);
478             }
479              
480             sub render_data_non_recursive {
481 47     47 0 125 my ( $self, $args ) = @_;
482              
483             my $render = $self->SUPER::render_data_non_recursive(
484 47 50       112 { elements => [ map { $_->render_data } @{ $self->_elements } ],
  179         803  
  47         1641  
485             $args ? %$args : (),
486             } );
487              
488 47         229 return $render;
489             }
490              
491             __PACKAGE__->meta->make_immutable;
492              
493             1;
494              
495             __END__
496              
497             =pod
498              
499             =encoding UTF-8
500              
501             =head1 NAME
502              
503             HTML::FormFu::Element::Date - 3 select menu multi-field
504              
505             =head1 VERSION
506              
507             version 2.07
508              
509             =head1 SYNOPSIS
510              
511             ---
512             elements:
513             - type: Date
514             name: birthdate
515             label: 'Birthdate:'
516             day:
517             prefix: "- Day -"
518             month:
519             prefix: "- Month -"
520             year:
521             prefix: "- Year -"
522             less: 70
523             plus: 0
524             auto_inflate: 1
525              
526             =head1 DESCRIPTION
527              
528             Creates a L<multi|HTML::FormFu::Element::Multi> element containing 3 select
529             menus for the day, month and year.
530              
531             A date element named C<foo> would result in 3 select menus with the names
532             C<foo_day>, C<foo_month> and C<foo_year>. The names can instead be
533             overridden by the C<name> value in L</day>, L</month> and L</year>.
534              
535             This element automatically merges the input parameters from the select
536             menu into a single date parameter (and doesn't delete the individual menu's
537             parameters).
538              
539             =head1 METHODS
540              
541             =head2 default
542              
543             Arguments: DateTime object
544              
545             Arguments: $date_string
546              
547             Accepts either a L<DateTime> object, or a string containing a date, matching
548             the L</strftime> format. Overwrites any default value set in L</day>,
549             L</month> or L</year>.
550              
551             =head2 default_natural
552              
553             Arguments: $date_string
554              
555             - type: Date
556             default_natural: 'today'
557              
558             Accepts a date/time string suitable for passing to
559             L<DateTime::Format::Natural/parse_datetime>.
560              
561             =head2 default_datetime_args
562              
563             - type: Date
564             default_natural: 'today'
565             default_datetime_args:
566             set_time_zone: 'Europe/London'
567              
568             Accepts a hashref of method-names / values that will be called on the
569             L</default> L<DateTime|DateTime> object, before the select fields' values
570             are set from it.
571              
572             =head2 strftime
573              
574             Default Value: "%d-%m-%Y"
575              
576             The format of the date as returned by L<HTML::FormFu/params>, if
577             L</auto_inflate> is not set.
578              
579             If L</auto_inflate> is used, this is still the format that the parameter
580             will be in prior to the DateTime inflator being run; which is
581             what any L<Filters|HTML::FormFu::Filter> and
582             L<Constraints|HTML::FormFu::Constraint> will receive.
583              
584             =head2 day
585              
586             Arguments: \%setting
587              
588             Set values effecting the C<day> select menu. Known keys are:
589              
590             =head3 name
591              
592             Override the auto-generated name of the select menu.
593              
594             =head3 default
595              
596             Set the default value of the select menu
597              
598             =head3 prefix
599              
600             Arguments: $value
601              
602             Arguments: \@values
603              
604             A string or arrayref of strings to be inserted into the start of the select
605             menu.
606              
607             Each value is only used as the label for a select item - the value for each
608             of these items is always the empty string C<''>.
609              
610             =head3 prefix_loc
611              
612             Arguments: $localization_key
613              
614             Arguments: \@localization_keys
615              
616             A localized string or arrayref of localized strings to be inserted into the
617             start of the select menu.
618              
619             Each value is localized and then only used as the label for a select item
620             - the value for each of these items is always the empty string C<''>.
621              
622             Use C<prefix_loc> insted of C<prefix>.
623              
624             =head2 month
625              
626             Arguments: \%setting
627              
628             Set values effecting the C<month> select menu. Known keys are:
629              
630             =head3 name
631              
632             Override the auto-generated name of the select menu.
633              
634             =head3 default
635              
636             Set the default value of the select menu
637              
638             =head3 prefix
639              
640             Arguments: $value
641              
642             Arguments: \@values
643              
644             A string or arrayref of strings to be inserted into the start of the select
645             menu.
646              
647             Each value is only used as the label for a select item - the value for each
648             of these items is always the empty string C<''>.
649              
650             =head3 prefix_loc
651              
652             Arguments: $localization_key
653              
654             Arguments: \@localization_keys
655              
656             A localized string or arrayref of localized strings to be inserted into the
657             start of the select menu.
658              
659             Each value is localized and then only used as the label for a select item
660             - the value for each of these items is always the empty string C<''>.
661              
662             Use C<prefix_loc> insted of C<prefix>.
663              
664             =head3 names
665              
666             Arguments: \@months
667              
668             A list of month names used for the month menu.
669              
670             If not set, the list of month names is obtained from L<DateTime::Locale>
671             using the locale set in L<HTML::FormFu/languages>.
672              
673             =head3 short_names
674              
675             Argument: bool
676              
677             If true (and C<months> is not set) the list of abbreviated month names is
678             obtained from L<DateTime::Locale> using the locale set in
679             L<HTML::FormFu/languages>.
680              
681             =head2 year
682              
683             Arguments: \%setting
684              
685             Set values effecting the C<year> select menu. Known keys are:
686              
687             =head3 name
688              
689             Override the auto-generated name of the select menu.
690              
691             =head3 default
692              
693             Set the default value of the select menu
694              
695             =head3 prefix
696              
697             Arguments: $value
698              
699             Arguments: \@values
700              
701             A string or arrayref of strings to be inserted into the start of the select
702             menu.
703              
704             Each value is only used as the label for a select item - the value for each
705             of these items is always the empty string C<''>.
706              
707             =head3 prefix_loc
708              
709             Arguments: $localization_key
710              
711             Arguments: \@localization_keys
712              
713             A localized string or arrayref of localized strings to be inserted into the
714             start of the select menu.
715              
716             Each value is localized and then only used as the label for a select item
717             - the value for each of these items is always the empty string C<''>.
718              
719             Use C<prefix_loc> insted of C<prefix>.
720              
721             =head3 list
722              
723             Arguments: \@years
724              
725             A list of years used for the year menu.
726              
727             If this is set, C<reference>, C<less> and C<plus> are ignored.
728              
729             =head3 reference
730              
731             Arguments: $year
732              
733             Default Value: the current year, calculated from L<time()|perlfunc/time()>
734              
735             If C<list> is not set, the list is created from the range of
736             C<reference - year_less> to C<reference + year_plus>.
737              
738             =head3 less
739              
740             Arguments: $count
741              
742             Default Value: 0
743              
744             =head3 plus
745              
746             Arguments: $count
747              
748             Default Value: 10
749              
750             =head3 reverse
751              
752             Arguments: bool
753              
754             Default Value: 0
755              
756             If true, the list of years is listed in reverse (decreasing) order.
757              
758             =head2 field_order
759              
760             Arguments: \@fields
761              
762             Default Value: ['day', 'month', 'year']
763              
764             Specify the order of the date fields in the rendered HTML.
765              
766             Not all 3 fields are required. No single field can be used more than once.
767              
768             =head2 auto_inflate
769              
770             If true, a L<DateTime Inflator|HTML::FormFu::Inflator::DateTime> will
771             automatically be added to the element, and it will be given a formatter so
772             that stringification will result in the format specified in L</strftime>.
773              
774             If you require the DateTime Inflator to have a different stringification
775             format to the format used internally by your Filters and Constraints, then
776             you must explicitly add your own DateTime Inflator, rather than using
777             L</auto_inflate>.
778              
779             =head1 CAVEATS
780              
781             Although this element inherits from L<HTML::FormFu::Element::Block>, its
782             behaviour for the methods
783             L<filterE<sol>filters|HTML::FormFu/filters>,
784             L<constraintE<sol>constraints|HTML::FormFu/constraints>,
785             L<inflatorE<sol>inflators|HTML::FormFu/inflators>,
786             L<validatorE<sol>validators|HTML::FormFu/validators> and
787             L<transformerE<sol>transformers|HTML::FormFu/transformers> is more like that of
788             a L<field element|HTML::FormFu::Role::Element::Field>, meaning all processors are
789             added directly to the date element, not to its select-menu child elements.
790              
791             This element's L<get_elements|HTML::FormFu/get_elements> and
792             L<get_all_elements|HTML::FormFu/get_all_elements> are inherited from
793             L<HTML::FormFu::Element::Block>, and so have the same behaviour. However, it
794             overrides the C<get_fields|HTML::FormFu/get_fields> method, such that it
795             returns both itself and its child elements.
796              
797             =head1 SEE ALSO
798              
799             Is a sub-class of, and inherits methods from
800             L<HTML::FormFu::Role::Element::Field>,
801             L<HTML::FormFu::Element::Multi>,
802             L<HTML::FormFu::Element::Block>,
803             L<HTML::FormFu::Element>
804              
805             L<HTML::FormFu>
806              
807             =head1 AUTHOR
808              
809             Carl Franks, C<cfranks@cpan.org>
810              
811             =head1 LICENSE
812              
813             This library is free software, you can redistribute it and/or modify it under
814             the same terms as Perl itself.
815              
816             =head1 AUTHOR
817              
818             Carl Franks <cpan@fireartist.com>
819              
820             =head1 COPYRIGHT AND LICENSE
821              
822             This software is copyright (c) 2018 by Carl Franks.
823              
824             This is free software; you can redistribute it and/or modify it under
825             the same terms as the Perl 5 programming language system itself.
826              
827             =cut