File Coverage

blib/lib/HTML/Widget.pm
Criterion Covered Total %
statement 269 273 98.5
branch 88 110 80.0
condition 21 35 60.0
subroutine 35 35 100.0
pod 22 22 100.0
total 435 475 91.5


line stmt bran cond sub pod time code
1             package HTML::Widget;
2              
3 88     88   2742347 use warnings;
  88         218  
  88         3139  
4 88     88   559 use strict;
  88         172  
  88         3405  
5 88     88   506 use base 'HTML::Widget::Accessor';
  88         168  
  88         66852  
6 88     88   77127 use HTML::Widget::Result;
  88         301  
  88         1477  
7 88     88   4429 use Scalar::Util 'blessed';
  88         173  
  88         11199  
8 88     88   595 use Carp qw/croak/;
  88         146  
  88         5484  
9              
10             # For PAR
11             use Module::Pluggable::Fast
12 88         849 search =>
13             [qw/HTML::Widget::Element HTML::Widget::Constraint HTML::Widget::Filter/],
14 88     88   121286 require => 1;
  88         643335  
15              
16             __PACKAGE__->plugins;
17              
18             __PACKAGE__->mk_accessors(
19             qw/container indicator query subcontainer uploads strict empty_errors
20             element_container_class xhtml_strict unwrapped explicit_ids/
21             );
22             __PACKAGE__->mk_ro_accessors(qw/implicit_subcontainer/);
23              
24             # Custom attr_accessor for id provided later
25             __PACKAGE__->mk_attr_accessors(qw/action enctype method/);
26              
27 88     88   11458 use overload '""' => sub { return shift->attributes->{id} }, fallback => 1;
  88     2   200  
  88         1015  
  2         173  
28              
29             *const = \&constraint;
30             *elem = \&element;
31             *name = \&id;
32             *tag = \&container;
33             *subtag = \&subcontainer;
34             *result = \&process;
35             *indi = \&indicator;
36             *constrain_all = \*constraint_all;
37              
38             our $VERSION = '1.11';
39              
40             =head1 NAME
41              
42             HTML::Widget - HTML Widget And Validation Framework
43              
44             =head1 NOTE
45              
46             L is no longer under active development and the current
47             maintainers are instead pursuing an intended replacement (see the
48             L for details).
49              
50             Volunteer maintainers / developers for L, please contact
51             the L.
52              
53             =head1 SYNOPSIS
54              
55             use HTML::Widget;
56              
57             # Create a widget
58             my $w = HTML::Widget->new('widget')->method('get')->action('/');
59              
60             # Add a fieldset to contain the elements
61             my $fs = $w->element( 'Fieldset', 'user' )->legend('User Details');
62              
63             # Add some elements
64             $fs->element( 'Textfield', 'age' )->label('Age')->size(3);
65             $fs->element( 'Textfield', 'name' )->label('Name')->size(60);
66             $fs->element( 'Submit', 'ok' )->value('OK');
67              
68             # Add some constraints
69             $w->constraint( 'Integer', 'age' )->message('No integer.');
70             $w->constraint( 'Not_Integer', 'name' )->message('Integer.');
71             $w->constraint( 'All', 'age', 'name' )->message('Missing value.');
72              
73             # Add some filters
74             $w->filter('Whitespace');
75              
76             # Process
77             my $result = $w->process;
78             my $result = $w->process($query);
79              
80              
81             # Check validation results
82             my @valid_fields = $result->valid;
83             my $is_valid = $result->valid('foo');
84             my @invalid_fields = $result->have_errors;
85             my $is_invalid = $result->has_errors('foo');;
86              
87             # CGI.pm-compatible! (read-only)
88             my $value = $result->param('foo');
89             my @params = $result->param;
90              
91             # Catalyst::Request-compatible
92             my $value = $result->params->{foo};
93             my @params = keys %{ $result->params };
94              
95              
96             # Merge widgets (constraints and elements will be appended)
97             $widget->merge($other_widget);
98              
99              
100             # Embed widgets (as fieldset)
101             $widget->embed($other_widget);
102              
103              
104             # Get list of elements
105             my @elements = $widget->get_elements;
106              
107             # Get list of constraints
108             my @constraints = $widget->get_constraints;
109              
110             # Get list of filters
111             my @filters = $widget->get_filters;
112              
113              
114             # Complete xml result
115             [% result %]
116             [% result.as_xml %]
117              
118              
119             # Iterate over elements
120            
121             [% FOREACH element = result.elements %]
122             [% element.field_xml %]
123             [% element.error_xml %]
124             [% END %]
125            
126              
127              
128             # Iterate over validation errors
129             [% FOREACH element = result.have_errors %]
130            

131             [% element %]:
132            
133             [% FOREACH error = result.errors(element) %]
134            
  • 135             [% error.name %]: [% error.message %] ([% error.type %])
    136            
    137             [% END %]
    138            
    139            

    140             [% END %]
    141              
    142            

    143             [% FOREACH element = result.have_errors %]
    144             [% IF result.error( element, 'Integer' ) %]
    145            
  • [% element %] has to be an integer.
  • 146             [% END %]
    147             [% END %]
    148            

    149              
    150             [% FOREACH error = result.errors %]
    151            
  • [% error.name %]: [% error.message %] ([% error.type %])
  • 152             [% END %]
    153              
    154              
    155             # XML output looks like this (easy to theme with css)
    156            
    157            
    158            
    159             class="labels_with_errors">
    160             Age
    161            
    162             (Required)
    163            
    164            
    165            
    166             value="24" class="Textfield" />
    167            
    168            
    169            
    170            
    171             Contains digit characters.
    172            
    173            
    174            
    175             Name
    176            
    177             value="sri" class="Textfield" />
    178            
    179            
    180            
    181            
    182            
    183              
    184             =head1 DESCRIPTION
    185              
    186             Create easy to maintain HTML widgets!
    187              
    188             Everything is optional, use validation only or just generate forms,
    189             you can embed and merge them later.
    190              
    191             The API was designed similar to other popular modules like
    192             L and L,
    193             L is also built in (and much faster).
    194              
    195             This Module is very powerful, don't misuse it as a template system!
    196              
    197             =head1 METHODS
    198              
    199             =head2 new
    200              
    201             Arguments: $name, \%attributes
    202              
    203             Return Value: $widget
    204              
    205             Create a new HTML::Widget object. The name parameter will be used as the
    206             id of the form created by the to_xml method.
    207              
    208             The C argument is equivalent to using the L
    209             method.
    210              
    211             =cut
    212              
    213             sub new {
    214 106     106 1 25052 my ( $self, $name, $attrs ) = @_;
    215              
    216 106   33     1128 $self = bless {}, ( ref $self || $self );
    217 106         930 $self->container('form');
    218 106         20036 $self->subcontainer('fieldset');
    219 106 100       1587 $self->name( defined $name ? $name : 'widget' );
    220              
    221 106 100       411 if ( defined $attrs ) {
    222 1 50       5 croak 'attributes argument must be a hash-reference'
    223             if ref($attrs) ne 'HASH';
    224              
    225 1         15 $self->attributes->{$_} = $attrs->{$_} for keys %$attrs;
    226             }
    227              
    228 106         471 return $self;
    229             }
    230              
    231             =head2 action
    232              
    233             Arguments: $uri
    234              
    235             Return Value: $uri
    236              
    237             Get/Set the action associated with the form. The default is no action,
    238             which causes most browsers to submit to the current URI.
    239              
    240             =head2 attributes
    241              
    242             =head2 attrs
    243              
    244             Arguments: %attributes
    245              
    246             Arguments: \%attributes
    247              
    248             Return Value: $widget
    249              
    250             Arguments: none
    251              
    252             Return Value: \%attributes
    253              
    254             Accepts either a list of key/value pairs, or a hash-ref.
    255              
    256             $w->attributes( $key => $value );
    257             $w->attributes( { $key => $value } );
    258              
    259             Returns the C<$widget> object, to allow method chaining.
    260              
    261             As of v1.10, passing a hash-ref no longer deletes current
    262             attributes, instead the attributes are added to the current attributes
    263             hash.
    264              
    265             This means the attributes hash-ref can no longer be emptied using
    266             C<< $w->attributes( { } ); >>. Instead, you may use
    267             C<< %{ $w->attributes } = (); >>.
    268              
    269             As a special case, if no arguments are passed, the return value is a
    270             hash-ref of attributes instead of the object reference. This provides
    271             backwards compatability to support:
    272              
    273             $w->attributes->{key} = $value;
    274              
    275             L is an alias for L.
    276              
    277             =head2 container
    278              
    279             Arguments: $tag
    280              
    281             Return Value: $tag
    282              
    283             Get/Set the tag used to contain the XML output when as_xml is called on the
    284             HTML::Widget object.
    285             Defaults to C
    .
    286              
    287             =head2 element_container_class
    288              
    289             Arguments: $class_name
    290              
    291             Return Value: $class_name
    292              
    293             Get/Set the container_class override for all elements in this widget. If set to
    294             non-zero value, process will call $element->container_class($class_name) for
    295             each element. Defaults to not set.
    296              
    297             See L.
    298              
    299             =head2 elem
    300              
    301             =head2 element
    302              
    303             Arguments: $type, $name, \%attributes
    304              
    305             Return Value: $element
    306              
    307             Add a new element to the Widget. Each element must be given at least a type.
    308             The name is used to generate an id attribute on the tag created for the
    309             element, and for form-specific elements is used as the name attribute. The
    310             returned element object can be used to set further attributes, please see
    311             the individual element classes for the methods specific to each one.
    312              
    313             The C argument is equivalent to using the
    314             L method.
    315              
    316             If the element starts with a name other than C,
    317             you can fully qualify the name by using a unary plus:
    318              
    319             $self->element( "+Fully::Qualified::Name", $name );
    320              
    321             The type can be one of the following:
    322              
    323             =over 4
    324              
    325             =item L
    326              
    327             my $e = $widget->element('Block');
    328              
    329             Add a Block element, which by default will be rendered as a C
    .
    330              
    331             my $e = $widget->element('Block');
    332             $e->type('img');
    333              
    334             =item L
    335              
    336             my $e = $widget->element( 'Button', 'foo' );
    337             $e->value('bar');
    338              
    339             Add a button element.
    340              
    341             my $e = $widget->element( 'Button', 'foo' );
    342             $e->value('bar');
    343             $e->content('arbitrary markup');
    344             $e->type('submit');
    345              
    346             Add a button element which uses a C
    347             C tag. The value of C is not html-escaped, so may contain
    348             html markup.
    349              
    350             =item L
    351              
    352             my $e = $widget->element( 'Checkbox', 'foo' );
    353             $e->comment('(Required)');
    354             $e->label('Foo');
    355             $e->checked('checked');
    356             $e->value('bar');
    357              
    358             Add a standard checkbox element.
    359              
    360             =item L
    361              
    362             my $e = $widget->element( 'Fieldset', 'foo' );
    363             $e->legend('Personal details');
    364             $e->element('Textfield', 'name');
    365             $e->element('Textarea', 'address');
    366              
    367             Adds a nested fieldset element, which can contain further elements.
    368              
    369             =item L
    370              
    371             my $e = $widget->element( 'Hidden', 'foo' );
    372             $e->value('bar');
    373              
    374             Add a hidden field. This field is mainly used for passing previously gathered
    375             data between multiple page forms.
    376              
    377             =item L
    378              
    379             my $e = $widget->element( 'Password', 'foo' );
    380             $e->comment('(Required)');
    381             $e->fill(1);
    382             $e->label('Foo');
    383             $e->size(23);
    384             $e->value('bar');
    385              
    386             Add a password field. This is a text field that will not show the user what
    387             they are typing, but show asterisks instead.
    388              
    389             =item L
    390              
    391             my $e = $widget->element( 'Radio', 'foo' );
    392             $e->comment('(Required)');
    393             $e->label('Foo');
    394             $e->checked('checked');
    395             $e->value('bar');
    396              
    397             Add a radio button to a group. Radio buttons with the same name will work as
    398             a group. That is, only one item in the group will be "on" at a time.
    399              
    400             =item L
    401              
    402             my $e = $widget->element( 'RadioGroup', 'name' );
    403             $e->comment('(Required)');
    404             $e->label('Foo'); # Label for whole radio group
    405             $e->value('bar'); # Currently selected value
    406             $e->labels([qw/Fu Bur Garch/]); # default to ucfirst of values
    407              
    408             This is a shortcut to add multiple radio buttons with the same name at the
    409             same time. See above.
    410              
    411             =item L
    412              
    413             $e = $widget->element( 'Reset', 'foo' );
    414             $e->value('bar');
    415              
    416             Create a reset button. The text on the button will default to "Reset", unless
    417             you call the value() method. This button resets the form to its original
    418             values.
    419              
    420             =item L
    421              
    422             my $e = $widget->element( 'Select', 'foo' );
    423             $e->comment('(Required)');
    424             $e->label('Foo');
    425             $e->size(23);
    426             $e->options( foo => 'Foo', bar => 'Bar' );
    427             $e->selected(qw/foo bar/);
    428              
    429             Create a dropdown or multi-select list element with multiple options. Options
    430             are supplied in a key => value list, in which the keys are the actual selected
    431             IDs, and the values are the strings displayed in the dropdown.
    432              
    433             =item L
    434              
    435             my $e = $widget->element( 'Span' );
    436             $e->content('bar');
    437              
    438             Create a simple span tag, containing the given content. Spans cannot be
    439             constrained as they are not entry fields.
    440              
    441             The content may be a string, an L object,
    442             or an array-ref of L objects.
    443              
    444             =item L
    445              
    446             $e = $widget->element( 'Submit', 'foo' );
    447             $e->value('bar');
    448              
    449             Create a submit button. The text on the button will default to "Submit", unless
    450             you call the value() method.
    451              
    452             $e = $widget->element( 'Submit', 'foo' );
    453             $e->value('bar');
    454             $e->src('image.png');
    455             $e->width(100);
    456             $e->height(35);
    457              
    458             Create an image submit button. The button will be displayed as an image,
    459             using the file at url C.
    460              
    461             =item L
    462              
    463             my $e = $widget->element( 'Textarea', 'foo' );
    464             $e->comment('(Required)');
    465             $e->label('Foo');
    466             $e->cols(30);
    467             $e->rows(40);
    468             $e->value('bar');
    469             $e->wrap('wrap');
    470              
    471             Create a textarea field. This is a multi-line input field for text.
    472              
    473             =item L
    474              
    475             my $e = $widget->element( 'Textfield', 'foo' );
    476             $e->comment('(Required)');
    477             $e->label('Foo');
    478             $e->size(23);
    479             $e->maxlength(42);
    480             $e->value('bar');
    481              
    482             Create a single line text field.
    483              
    484             =item L
    485              
    486             my $e = $widget->element( 'Upload', 'foo' );
    487             $e->comment('(Required)');
    488             $e->label('Foo');
    489             $e->accept('text/html');
    490             $e->maxlength(1000);
    491             $e->size(23);
    492              
    493             Create a field for uploading files. This will probably be rendered as a
    494             textfield, with a button for choosing a file.
    495              
    496             Adding an Upload element automatically calls
    497             C<< $widget->enctype('multipart/form-data') >> for you.
    498              
    499             =back
    500              
    501             =cut
    502              
    503             sub element {
    504 203     203 1 1845 my ( $self, $type, $name, $attrs ) = @_;
    505              
    506 203         706 my $abs = $type =~ s/^\+//;
    507 203 100       1008 $type = "HTML::Widget::Element::$type" unless $abs;
    508              
    509 203         1870 my $element = $self->_instantiate( $type, { name => $name } );
    510              
    511 203 100       94525 $element->{_anonymous} = 1 if !defined $name;
    512              
    513 203 100 66     3331 if ( $element->isa('HTML::Widget::Element::Block')
    514             and not $element->{_pseudo_block} )
    515             {
    516              
    517 8         17 push @{ $self->{_elements} }, $element;
      8         32  
    518              
    519             }
    520             else {
    521 195 50       962 croak "'$type' element not permitted at top level in xhtml_strict mode"
    522             if $self->xhtml_strict;
    523              
    524 195         1822 my $implicit_subcontainer = $self->_get_implicit_subcontainer;
    525 195         1625 $implicit_subcontainer->push_content($element);
    526             }
    527              
    528 203 100       1736 if ( defined $attrs ) {
    529 1 50       5 croak 'attributes argument must be a hash-reference'
    530             if ref($attrs) ne 'HASH';
    531              
    532 1         13 $element->attributes->{$_} = $attrs->{$_} for keys %$attrs;
    533             }
    534              
    535 203         1006 return $element;
    536             }
    537              
    538             sub _first_element {
    539 224     224   1538 return $_[0]->{_elements}->[0];
    540             }
    541              
    542             sub _get_implicit_subcontainer {
    543 199     199   433 my $self = shift;
    544 199 100       728 return $self->_first_element if ( $self->implicit_subcontainer );
    545              
    546 89 50       976 if ( $self->_first_element ) {
    547 0         0 croak
    548             "already a top-level container when trying to setup implicit container";
    549             }
    550              
    551 89         300 $self->{implicit_subcontainer} = 1;
    552 89         212 my $container;
    553 89 100       462 if ( $self->subcontainer eq 'fieldset' ) {
    554 88         1312 $container = $self->_instantiate('HTML::Widget::Element::Fieldset');
    555             }
    556             else {
    557 1         14 $container = $self->_instantiate('HTML::Widget::Element::Block');
    558 1         12 $container->type( $self->subcontainer );
    559             }
    560              
    561             # Save away the parent widget's name for possible later use in
    562             # H::W::Element::Block.
    563 89         537 $container->name( '_implicit_' . $self->name );
    564 89         679 push @{ $self->{_elements} }, $container;
      89         356  
    565 89         333 return $container;
    566             }
    567              
    568             =head2 id
    569              
    570             =head2 name
    571              
    572             Arguments: $name
    573              
    574             Return Value: $name
    575              
    576             Get or set the widget id.
    577              
    578             L is an alias for L.
    579              
    580             =cut
    581              
    582             # Yuck - the name bodge above requires this nasty if uncommonly used fixup
    583             sub id {
    584 200     200 1 2244 my $self = shift;
    585 200 100 66     1089 if ( $self->implicit_subcontainer
          66        
    586             and $_[0]
    587             and $_[0] ne $self->{attributes}->{id} )
    588             {
    589 2         31 my $curr = $self->{attributes}->{id};
    590              
    591             # fix up legacy widget names
    592 2         52 map { $_->name( '_implicit_' . $_[0] ); }
      2         11  
    593 2         6 grep { $_->name =~ /^_implicit_$curr/; } @{ $self->{_elements} };
      2         6  
    594             }
    595 200 100 66     10604 return ( $self->{attributes}->{id} || $self ) unless @_ > 0;
    596 108 50       771 $self->{attributes}->{id} = ( @_ == 1 ? $_[0] : [@_] );
    597 108         283 return $self;
    598             }
    599              
    600             =head2 get_elements
    601              
    602             Arguments: %options
    603              
    604             Return Value: @elements
    605              
    606             my @elements = $self->get_elements;
    607            
    608             my @elements = $self->get_elements( type => 'Textfield' );
    609            
    610             my @elements = $self->get_elements( name => 'username' );
    611              
    612             Returns a list of all elements added to the widget.
    613              
    614             If a 'type' argument is given, only returns the elements of that type.
    615              
    616             If a 'name' argument is given, only returns the elements with that name.
    617              
    618             =cut
    619              
    620             sub get_elements {
    621 14     14 1 9575 my ( $self, %opt ) = @_;
    622              
    623 14         25 my @elements;
    624 14 50       65 @elements = @{ $self->{_elements} } if $self->{_elements};
      14         43  
    625 14 50       64 @elements = @{ $self->_first_element->content }
      14         130  
    626             if $self->implicit_subcontainer;
    627              
    628 14         135 return _search_elements( \%opt, @elements );
    629             }
    630              
    631             sub _search_elements {
    632 60     60   138 my ( $opt, @elements ) = @_;
    633              
    634 60 100       182 if ( exists $opt->{type} ) {
    635 5         21 my $type = "HTML::Widget::Element::" . $opt->{type};
    636              
    637 5         17 @elements = grep { $_->isa($type) } @elements;
      19         155  
    638             }
    639              
    640 60 100       175 if ( exists $opt->{name} ) {
    641 463 50       5795 @elements = grep {
    642 50         252 defined($_->name) && $_->name eq $opt->{name}
    643             } @elements;
    644             }
    645              
    646 60         884 return @elements;
    647             }
    648              
    649             =head2 get_elements_ref
    650              
    651             Arguments: %options
    652              
    653             Return Value: \@elements
    654              
    655             Accepts the same arguments as L, but returns an arrayref
    656             of results instead of a list.
    657              
    658             =cut
    659              
    660             sub get_elements_ref {
    661 1     1 1 6 my $self = shift;
    662              
    663 1         4 return [ $self->get_elements(@_) ];
    664             }
    665              
    666             =head2 get_element
    667              
    668             Arguments: %options
    669              
    670             Return Value: $element
    671              
    672             my $element = $self->get_element;
    673            
    674             my $element = $self->get_element( type => 'Textfield' );
    675            
    676             my $element = $self->get_element( name => 'username' );
    677              
    678             Similar to get_elements(), but only returns the first element in the list.
    679              
    680             Accepts the same arguments as get_elements().
    681              
    682             =cut
    683              
    684             sub get_element {
    685 5     5 1 5053 my ( $self, %opt ) = @_;
    686              
    687 5         19 return ( $self->get_elements(%opt) )[0];
    688             }
    689              
    690             =head2 find_elements
    691              
    692             Arguments: %options
    693              
    694             Return Value: @elements
    695              
    696             Similar to L, and accepts the same arguments, but performs a
    697             recursive search through block-level elements.
    698              
    699             =cut
    700              
    701             sub find_elements {
    702 46     46 1 138 my ( $self, %opt ) = @_;
    703              
    704 46         60 my @elements = map { $_->find_elements } @{ $self->{_elements} };
      46         204  
      46         120  
    705              
    706 46         163 return _search_elements( \%opt, @elements );
    707             }
    708              
    709             =head2 const
    710              
    711             =head2 constraint
    712              
    713             Arguments: $type, @field_names
    714              
    715             Return Value: $constraint
    716              
    717             Set up a constraint on one or more elements. When process() is called on the
    718             Widget object, with a $query object, the parameters of the query are checked
    719             against the specified constraints. The L object is
    720             returned to allow setting of further attributes to be set. The string 'Not_'
    721             can be prepended to each type name to negate the effects. Thus checking for a
    722             non-integer becomes 'Not_Integer'.
    723              
    724             If the constraint package name starts with something other than
    725             C, you can fully qualify the name by using a
    726             unary plus:
    727              
    728             $self->constraint( "+Fully::Qualified::Name", @names );
    729              
    730             Constraint checking is done after all L have been
    731             applied.
    732              
    733             @names should contain a list of element names that the constraint applies to.
    734             The type of constraint can be one of:
    735              
    736             =over 4
    737              
    738             =item L
    739              
    740             my $c = $widget->constraint( 'All', 'foo', 'bar' );
    741              
    742             The fields passed to the "All" constraint are those which are required fields
    743             in the form.
    744              
    745             =item L
    746              
    747             my $c = $widget->constraint( 'AllOrNone', 'foo', 'bar' );
    748              
    749             If any of the fields passed to the "AllOrNone" constraint are filled in, then
    750             they all must be filled in.
    751              
    752             =item L
    753              
    754             my $c = $widget->constraint( 'Any', 'foo', 'bar' );
    755              
    756             At least one or more of the fields passed to this constraint must be filled.
    757              
    758             =item L
    759              
    760             my $c = $widget->constraint( 'ASCII', 'foo' );
    761              
    762             The fields passed to this constraint will be checked to make sure their
    763             contents contain ASCII characters.
    764              
    765             =item L
    766              
    767             my $c = $widget->constraint( 'Bool', 'foo' );
    768              
    769             The fields passed to this constraint will be checked to make sure their
    770             contents contain a C<1> or C<0>.
    771              
    772             =item L
    773              
    774             my $c = $widget->constraint( 'Callback', 'foo' )->callback(sub {
    775             my $value=shift;
    776             return 1;
    777             });
    778              
    779             This constraint allows you to provide your own callback sub for validation.
    780             The callback sub is called once for each submitted value of each named field.
    781              
    782             =item L
    783              
    784             my $c = $widget->constraint( 'CallbackOnce', 'foo' )->callback(sub {
    785             my $value=shift;
    786             return 1;
    787             });
    788              
    789             This constraint allows you to provide your own callback sub for validation.
    790             The callback sub is called once per call of L.
    791              
    792             =item L
    793              
    794             my $c = $widget->constraint( 'Date', 'year', 'month', 'day' );
    795              
    796             This constraint ensures that the three fields passed in are a valid date.
    797              
    798             =item L
    799              
    800             my $c =
    801             $widget->constraint( 'DateTime', 'year', 'month', 'day', 'hour',
    802             'minute', 'second' );
    803              
    804             This constraint ensures that the six fields passed in are a valid date and
    805             time.
    806              
    807             =item L
    808              
    809             my $c =
    810             $widget->constraint( 'DependOn', 'foo', 'bar' );
    811              
    812             If the first field listed is filled in, all of the others are required.
    813              
    814             =item L
    815              
    816             my $c = $widget->constraint( 'Email', 'foo' );
    817              
    818             Check that the field given contains a valid email address, according to RFC
    819             2822, using the L module.
    820              
    821             =item L
    822              
    823             my $c = $widget->constraint( 'Equal', 'foo', 'bar' );
    824             $c->render_errors( 'foo' );
    825              
    826             The fields passed to this constraint must contain the same information, or
    827             be empty.
    828              
    829             =item L
    830              
    831             my $c = $widget->constraint( 'HTTP', 'foo' );
    832              
    833             This constraint checks that the field(s) passed in are valid URLs. The regex
    834             used to test this can be set manually using the ->regex method.
    835              
    836             =item L
    837              
    838             my $c = $widget->constraint( 'In', 'foo' );
    839             $c->in( 'possible', 'values' );
    840              
    841             Check that a value is one of a specified set.
    842              
    843             =item L
    844              
    845             my $c = $widget->constraint( 'Integer', 'foo' );
    846              
    847             Check that the field contents are an integer.
    848              
    849             =item L
    850              
    851             my $c = $widget->constraint( 'Length', 'foo' );
    852             $c->min(23);
    853             $c->max(50);
    854              
    855             Ensure that the contents of the field are at least $min long, and no longer
    856             than $max.
    857              
    858             =item L
    859              
    860             my $c = $widget->constraint( 'Number', 'foo' );
    861              
    862             Ensure that the content of the field is a number.
    863              
    864             =item L
    865              
    866             my $c = $widget->constraint( 'Printable', 'foo' );
    867              
    868             The contents of the given field must only be printable characters. The regex
    869             used to test this can be set manually using the ->regex method.
    870              
    871             =item L
    872              
    873             my $c = $widget->constraint( 'Range', 'foo' );
    874             $c->min(23);
    875             $c->max(30);
    876              
    877             The contents of the field must be numerically within the given range.
    878              
    879             =item L
    880              
    881             my $c = $widget->constraint( 'Regex', 'foo' );
    882             $c->regex(qr/^\w+$/);
    883              
    884             Tests the contents of the given field(s) against a user supplied regex.
    885              
    886             =item L
    887              
    888             my $c = $widget->constraint( 'String', 'foo' );
    889              
    890             The field must only contain characters in \w. i.e. [a-zaZ0-9_]
    891              
    892             =item L
    893              
    894             my $c = $widget->constraint( 'Time', 'hour', 'minute', 'second' );
    895              
    896             The three fields passed to this constraint must constitute a valid time.
    897              
    898             =back
    899              
    900             =cut
    901              
    902             sub constraint {
    903 89     89 1 20851 my ( $self, $type, @names ) = @_;
    904 89 50       505 croak('constraint requires a constraint type') unless $type;
    905              
    906 89         271 my $abs = $type =~ s/^\+//;
    907              
    908 89         253 my $not = 0;
    909 89 100       607 if ( $type =~ /^Not_(\w+)$/i ) {
    910 2         5 $not++;
    911 2         11 $type = $1;
    912             }
    913              
    914 89 100       504 $type = "HTML::Widget::Constraint::$type" unless $abs;
    915              
    916 89         853 my $constraint = $self->_instantiate( $type, { names => \@names } );
    917 89         1785 $constraint->not($not);
    918 89         1305 push @{ $self->{_constraints} }, $constraint;
      89         354  
    919 89         622 return $constraint;
    920             }
    921              
    922             =head2 constraint_all
    923              
    924             =head2 constrain_all
    925              
    926             Arguments: @constraint_types
    927              
    928             Return Value: @constraints
    929              
    930             $w->element( Textfield => 'name' );
    931             $w->element( Textfield => 'password' );
    932             $w->constraint_all( 'All' );
    933              
    934             For each named type, add a constraint to all elements currently defined.
    935              
    936             Does not add a constraint for elements which return false for
    937             L; this includes
    938             L and any element that inherits from
    939             L.
    940              
    941             =cut
    942              
    943             sub constraint_all {
    944 1     1 1 7 my $self = shift;
    945 1         3 my @constraint;
    946              
    947 1         6 for my $element ( $self->find_elements ) {
    948 3 100       20 if ( $element->allow_constraint ) {
    949 2         12 for (@_) {
    950 2         12 push @constraint, $self->constraint( $_, $element->name );
    951             }
    952             }
    953             }
    954              
    955 1         4 return @constraint;
    956             }
    957              
    958             =head2 get_constraints
    959              
    960             Arguments: %options
    961              
    962             Return Value: @constraints
    963              
    964             my @constraints = $self->get_constraints;
    965            
    966             my @constraints = $self->get_constraints( type => 'Integer' );
    967              
    968             Returns a list of all constraints added to the widget.
    969              
    970             If a 'type' argument is given, only returns the constraints of that type.
    971              
    972             =cut
    973              
    974             sub get_constraints {
    975 12     12 1 3907 my ( $self, %opt ) = @_;
    976              
    977 12 100       63 if ( exists $opt{type} ) {
    978 4         12 my $type = "HTML::Widget::Constraint::$opt{type}";
    979              
    980 4         7 return grep { $_->isa($type) } @{ $self->{_constraints} };
      16         129  
      4         13  
    981             }
    982              
    983 8         24 return @{ $self->{_constraints} };
      8         65  
    984             }
    985              
    986             =head2 get_constraints_ref
    987              
    988             Arguments: %options
    989              
    990             Return Value: \@constraints
    991              
    992             Accepts the same arguments as L, but returns an arrayref
    993             of results instead of a list.
    994              
    995             =cut
    996              
    997             sub get_constraints_ref {
    998 1     1 1 4 my $self = shift;
    999              
    1000 1         6 return [ $self->get_constraints(@_) ];
    1001             }
    1002              
    1003             =head2 get_constraint
    1004              
    1005             Arguments: %options
    1006              
    1007             Return Value: $constraint
    1008              
    1009             my $constraint = $self->get_constraint;
    1010            
    1011             my $constraint = $self->get_constraint( type => 'Integer' );
    1012              
    1013             Similar to L, but only returns the first constraint in the
    1014             list.
    1015              
    1016             Accepts the same arguments as L.
    1017              
    1018             =cut
    1019              
    1020             sub get_constraint {
    1021 3     3 1 2607 my ( $self, %opt ) = @_;
    1022              
    1023 3         14 return ( $self->get_constraints(%opt) )[0];
    1024             }
    1025              
    1026             =head2 embed
    1027              
    1028             Arguments: @widgets
    1029              
    1030             Arguments: $element, @widgets
    1031              
    1032             Insert the contents of another widget object into this one. Each embedded
    1033             object will be represented as another set of fields (surrounded by a fieldset
    1034             tag), inside the created form. No copy is made of the widgets to embed, thus
    1035             calling as_xml on the resulting object will change data in the widget objects.
    1036              
    1037             With an element argument, the widgets are embedded into the provided element.
    1038             No checks are made on whether the provided element belongs to $self.
    1039              
    1040             Note that without an element argument, embed embeds into the top level
    1041             of the widget, and NOT into any subcontainer (whether created by you
    1042             or implicitly created). If this is not what you need, you can choose
    1043             one of:
    1044              
    1045             # while building $self:
    1046             $in_here = $self->element('Fieldset', 'my_fieldset');
    1047             # later:
    1048             $self->embed($in_here, @widgets);
    1049              
    1050             # these are equivalent:
    1051             $self->embed(($self->find_elements)[0], @widgets);
    1052             $self->embed_into_first(@widgets); # but this is faster!
    1053              
    1054             If you are just building a widget and do not need to import constraints
    1055             and filters from another widget, do not use embed at all, simply
    1056             assemble using the methods provided by L.
    1057              
    1058             =cut
    1059              
    1060             sub embed {
    1061 8     8 1 44 my ( $self, @widgets ) = @_;
    1062              
    1063 8         15 my $dest;
    1064 8 100       96 if ( $widgets[0]->isa('HTML::Widget::Element') ) {
    1065 1 50       8 croak "destination element is not a container"
    1066             unless $widgets[0]->isa('HTML::Widget::Element::NullContainer');
    1067 1         2 $dest = shift @widgets;
    1068             }
    1069              
    1070 8         22 for my $widget (@widgets) {
    1071              
    1072 8 100       25 if ($dest) {
    1073 1         1 $dest->push_content( @{ $widget->{_elements} } );
      1         6  
    1074             }
    1075             else {
    1076 7 50       29 push @{ $self->{_elements} }, @{ $widget->{_elements} }
      7         21  
      7         19  
    1077             if $widget->{_elements};
    1078             }
    1079              
    1080 8 100       39 push @{ $self->{_constraints} }, @{ $widget->{_constraints} }
      4         13  
      4         16  
    1081             if $widget->{_constraints};
    1082 8 100       35 push @{ $self->{_filters} }, @{ $widget->{_filters} }
      3         8  
      3         12  
    1083             if $widget->{_filters};
    1084             }
    1085 8         59 return $self;
    1086             }
    1087              
    1088             =head2 embed_into_first
    1089              
    1090             Arguments: @widgets
    1091              
    1092             As for L, but embed into the first subcontainer (fieldset) rather than
    1093             into the top level form.
    1094              
    1095             =cut
    1096              
    1097             sub embed_into_first {
    1098 1     1 1 8 my $self = shift;
    1099 1         3 my $dest = $self->_first_element;
    1100 1         6 return $self->embed( $dest, @_ );
    1101             }
    1102              
    1103             =head2 empty_errors
    1104              
    1105             Arguments: $bool
    1106              
    1107             Return Value: $bool
    1108              
    1109             After validation, if errors are found, a span tag is created with the id
    1110             "fields_with_errors". Set this value to cause the span tag to always be
    1111             generated.
    1112              
    1113             =head2 enctype
    1114              
    1115             Arguments: $enctype
    1116              
    1117             Return Value: $enctype
    1118              
    1119             Set/Get the encoding type of the form. This can be either
    1120             "application/x-www-form-urlencoded" which is the default, or
    1121             "multipart/form-data".
    1122             See L.
    1123              
    1124             If the widget contains an Upload element, the enctype is automatically set to
    1125             'multipart/form-data'.
    1126              
    1127             =head2 explicit_ids
    1128              
    1129             Argument: $bool
    1130              
    1131             Return Value: $bool
    1132              
    1133             When true; elements, fieldsets and blocks will not be given DOM id's, unless
    1134             explicitly set with L.
    1135              
    1136             $w->element( 'Textfield', 'foo', {id => 'my_id'} )
    1137              
    1138             The form itself will always be given an L, which is C by default.
    1139              
    1140             =head2 filter
    1141              
    1142             Arguments: $type, @field_names
    1143              
    1144             Return Value: $filter
    1145              
    1146             Add a filter. Like constraints, filters can be applied to one or more elements.
    1147             These are applied to actually change the contents of the fields, supplied by
    1148             the user before checking the constraints. It only makes sense to apply filters
    1149             to fields that can contain text - Password, Textfield, Textarea, Upload.
    1150              
    1151             If the filter starts with a name other than C,
    1152             you can fully qualify the name by using a unary plus:
    1153              
    1154             $self->filter( "+Fully::Qualified::Name", @names );
    1155              
    1156             There are currently two types of filter:
    1157              
    1158             =over 4
    1159              
    1160             =item L
    1161              
    1162             my $f = $widget->filter( 'Callback', 'foo' );
    1163             $f->callback( \&my_callback );
    1164              
    1165             Filter given field(s) using a user-defined subroutine.
    1166              
    1167             =item L
    1168              
    1169             my $f = $widget->filter( 'HTMLEscape', 'foo' );
    1170              
    1171             Escapes HTML entities in the given field(s).
    1172              
    1173             =item L
    1174              
    1175             my $f = $widget->filter( 'HTMLStrip', 'foo' );
    1176              
    1177             Strips HTML tags from the given field(s).
    1178              
    1179             my $f = $widget->filter( 'HTMLStrip', 'foo' );
    1180             $f->allow( 'p', 'br' );
    1181              
    1182             Specify a list of HTML tags which shouldn't be stripped.
    1183              
    1184             =item L
    1185              
    1186             my $f = $widget->filter( 'LowerCase', 'foo' );
    1187              
    1188             Make given field(s) all lowercase.
    1189              
    1190             =item L
    1191              
    1192             my $f = $widget->filter( 'TrimEdges', 'foo' );
    1193              
    1194             Removes whitespace from the beginning and end of the given field(s).
    1195              
    1196             =item L
    1197              
    1198             my $f = $widget->filter( 'UpperCase', 'foo' );
    1199              
    1200             Make given field(s) all uppercase.
    1201              
    1202             =item L
    1203              
    1204             my $f = $widget->filter( 'Whitespace', 'foo' );
    1205              
    1206             Removes all whitespace from the given field(s).
    1207              
    1208             =back
    1209              
    1210             =cut
    1211              
    1212             sub filter {
    1213 19     19 1 266 my ( $self, $type, @names ) = @_;
    1214              
    1215 19         61 my $abs = $type =~ s/^\+//;
    1216 19 50       94 $type = "HTML::Widget::Filter::$type" unless $abs;
    1217              
    1218 19         144 my $filter = $self->_instantiate( $type, { names => \@names } );
    1219 19         347 $filter->init($self);
    1220 19         31 push @{ $self->{_filters} }, $filter;
      19         64  
    1221 19         81 return $filter;
    1222             }
    1223              
    1224             =head2 filter_all
    1225              
    1226             Arguments: @filter_types
    1227              
    1228             Return Value: @filters
    1229              
    1230             $w->element( Textfield => 'name' );
    1231             $w->element( Textfield => 'age' );
    1232             $w->filter_all( 'Whitespace' );
    1233              
    1234             For each named type, add a filter to all elements currently defined.
    1235              
    1236             Does not add a filter for elements which return false for
    1237             C; this includes
    1238             L and any element that inherits from
    1239             L.
    1240              
    1241             =cut
    1242              
    1243             sub filter_all {
    1244 1     1 1 15 my $self = shift;
    1245 1         2 my @filter;
    1246              
    1247 1         6 for my $element ( $self->find_elements ) {
    1248 3 100       278 if ( $element->allow_filter ) {
    1249 2         18 for (@_) {
    1250 2         14 push @filter, $self->filter( $_, $element->name );
    1251             }
    1252             }
    1253             }
    1254              
    1255 1         5 return @filter;
    1256             }
    1257              
    1258             =head2 get_filters
    1259              
    1260             Arguments: %options
    1261              
    1262             Return Value: @filters
    1263              
    1264             my @filters = $self->get_filters;
    1265            
    1266             my @filters = $self->get_filters( type => 'Integer' );
    1267              
    1268             Returns a list of all filters added to the widget.
    1269              
    1270             If a 'type' argument is given, only returns the filters of that type.
    1271              
    1272             =cut
    1273              
    1274             sub get_filters {
    1275 8     8 1 5948 my ( $self, %opt ) = @_;
    1276              
    1277 8 100       36 if ( exists $opt{type} ) {
    1278 4         16 my $type = "HTML::Widget::Filter::$opt{type}";
    1279              
    1280 4         8 return grep { $_->isa($type) } @{ $self->{_filters} };
      16         130  
      4         13  
    1281             }
    1282              
    1283 4         10 return @{ $self->{_filters} };
      4         28  
    1284             }
    1285              
    1286             =head2 get_filters_ref
    1287              
    1288             Arguments: %options
    1289              
    1290             Return Value: \@filters
    1291              
    1292             Accepts the same arguments as L, but returns an arrayref
    1293             of results instead of a list.
    1294              
    1295             =cut
    1296              
    1297             sub get_filters_ref {
    1298 1     1 1 4 my $self = shift;
    1299              
    1300 1         7 return [ $self->get_filters(@_) ];
    1301             }
    1302              
    1303             =head2 get_filter
    1304              
    1305             Arguments: %options
    1306              
    1307             Return Value: $filter
    1308              
    1309             my @filters = $self->get_filter;
    1310            
    1311             my @filters = $self->get_filter( type => 'Integer' );
    1312              
    1313             Similar to L, but only returns the first filter in the
    1314             list.
    1315              
    1316             Accepts the same arguments as L.
    1317              
    1318             =cut
    1319              
    1320             sub get_filter {
    1321 3     3 1 3634 my ( $self, %opt ) = @_;
    1322              
    1323 3         14 return ( $self->get_filters(%opt) )[0];
    1324             }
    1325              
    1326             =head2 indi
    1327              
    1328             =head2 indicator
    1329              
    1330             Arguments: $field_name
    1331              
    1332             Return Value: $field_name
    1333              
    1334             Set/Get a boolean field. This is a convenience method for the user, so they
    1335             can keep track of which of many Widget objects were submitted. It is also
    1336             used by L
    1337              
    1338             =head2 legend
    1339              
    1340             Arguments: $legend
    1341              
    1342             Return Value: $legend
    1343              
    1344             Set/Get a legend for this widget. This tag is used to label the fieldset.
    1345              
    1346             =cut
    1347              
    1348             sub legend {
    1349 1     1 1 3 my ( $self, $legend ) = @_;
    1350              
    1351 1 50       7 croak "'legend' not permitted at top level in xhtml_strict mode"
    1352             if $self->xhtml_strict;
    1353              
    1354 1         10 my $top_level = $self->_get_implicit_subcontainer;
    1355 1 50       23 unless ( $top_level->can('legend') ) {
    1356 0         0 croak "implicit subcontainer does not support 'legend'";
    1357             }
    1358              
    1359 1         7 $top_level->legend($legend);
    1360 1         9 return $self;
    1361             }
    1362              
    1363             =head2 merge
    1364              
    1365             Arguments: @widgets
    1366              
    1367             Arguments: $element, @widgets
    1368              
    1369             Merge elements, constraints and filters from other widgets, into this one. The
    1370             elements will be added to the end of the list of elements that have been set
    1371             already.
    1372              
    1373             Without an element argument, and with standard widgets, the contents of the
    1374             first top-level element of each widget will be merged into the first
    1375             top-level element of this widget.
    1376             This emulates the previous behaviour.
    1377              
    1378             With an element argument, the widgets are merged into the named element.
    1379             No checks are made on whether the provided element belongs to $self.
    1380              
    1381             =cut
    1382              
    1383             sub merge {
    1384 5     5 1 26 my ( $self, @widgets ) = @_;
    1385              
    1386 5         8 my $dest;
    1387 5 50       53 if ( $widgets[0]->isa('HTML::Widget::Element') ) {
    1388 0 0       0 croak "destination element is not a container"
    1389             unless $widgets[0]->isa('HTML::Widget::Element::NullContainer');
    1390 0         0 $dest = shift @widgets;
    1391             }
    1392             else {
    1393 5         15 $dest = $self->_first_element;
    1394 5 50 66     33 croak "merge only supported if destination first element is container"
    1395             if $dest
    1396             and not $dest->isa('HTML::Widget::Element::NullContainer');
    1397              
    1398 5 100       20 $dest = $self->_get_implicit_subcontainer unless $dest;
    1399             }
    1400              
    1401 5         13 for my $widget (@widgets) {
    1402              
    1403 5         15 my $source = $widget->_first_element;
    1404 5 50 33     70 croak "merge only supported if source first element is container"
    1405             unless $source
    1406             and $source->isa('HTML::Widget::Element::NullContainer');
    1407              
    1408 5         8 $dest->push_content( @{ $source->content } );
      5         18  
    1409              
    1410 5 100       43 push @{ $self->{_constraints} }, @{ $widget->{_constraints} }
      3         9  
      3         12  
    1411             if $widget->{_constraints};
    1412 5 100       19 push @{ $self->{_filters} }, @{ $widget->{_filters} }
      3         9  
      3         11  
    1413             if $widget->{_filters};
    1414             }
    1415 5         15 return $self;
    1416             }
    1417              
    1418             =head2 method
    1419              
    1420             Arguments: $method
    1421              
    1422             Return Value: $method
    1423              
    1424             Set/Get the method used to submit the form. Can be set to either "post" or
    1425             "get". The default is "post".
    1426              
    1427             =head2 result
    1428              
    1429             =head2 process
    1430              
    1431             Arguments: $query, \@uploads
    1432              
    1433             Return Value: $result
    1434              
    1435             After finishing setting up the widget and all its elements, call to create
    1436             an L. If passed a C<$query> it will run filters and
    1437             validation on the parameters. The L object can
    1438             then be used to produce the HTML.
    1439              
    1440             L is an alias for L.
    1441              
    1442             =cut
    1443              
    1444             sub process {
    1445 217     217 1 141696 my ( $self, $query, $uploads ) = @_;
    1446              
    1447 217         1852 my $errors = {};
    1448 217   66     2219 $query ||= $self->query;
    1449 217   33     1992 $uploads ||= $self->uploads;
    1450              
    1451             # Some sane defaults
    1452 217 100       2198 if ( $self->container eq 'form' ) {
    1453 216   100     2728 $self->attributes->{method} ||= 'post';
    1454             }
    1455              
    1456 217         464 for my $element ( @{ $self->{_elements} } ) {
      217         726  
    1457 219         1930 $element->prepare($self);
    1458 219 100       1632 $element->init($self) unless $element->{_initialized};
    1459 219         717 $element->{_initialized}++;
    1460             }
    1461 217         605 for my $filter ( @{ $self->{_filters} } ) {
      217         726  
    1462 11         113 $filter->prepare($self);
    1463 11 50       177 $filter->init($self) unless $filter->{_initialized};
    1464 11         38 $filter->{_initialized}++;
    1465             }
    1466 217         610 for my $constraint ( @{ $self->{_constraints} } ) {
      217         652  
    1467 270         1484 $constraint->prepare($self);
    1468 270 100       1371 $constraint->init($self) unless $constraint->{_initialized};
    1469 270         761 $constraint->{_initialized}++;
    1470             }
    1471              
    1472 217         793 my @js_callbacks;
    1473 217         371 for my $constraint ( @{ $self->{_constraints} } ) {
      217         605  
    1474 270     161   1361 push @js_callbacks, sub { $constraint->process_js( $_[0] ) };
      161         1017  
    1475             }
    1476 217         458 my %params;
    1477 217 100       855 if ($query) {
    1478 171 50 33     2338 croak "Invalid query object"
    1479             unless blessed($query)
    1480             and $query->can('param');
    1481 171         756 my @params = $query->param;
    1482 171         2500 for my $param (@params) {
    1483 265         849 my @values = $query->param($param);
    1484 265 100       3933 $params{$param} = @values > 1 ? \@values : $values[0];
    1485             }
    1486 171         343 for my $filter ( @{ $self->{_filters} } ) {
      171         505  
    1487 11         283 $filter->process( \%params, $uploads );
    1488             }
    1489 171         434 for my $element ( @{ $self->{_elements} } ) {
      171         443  
    1490 171         1250 my $results = $element->process( \%params, $uploads );
    1491 171         309 for my $result ( @{$results} ) {
      171         707  
    1492 1         7 my $name = $result->name;
    1493 1         110 my $class = ref $element;
    1494 1         7 $class =~ s/^HTML::Widget::Element:://;
    1495 1         4 $class =~ s/::/_/g;
    1496 1 50       7 $result->type($class) if not defined $result->type;
    1497 1         10 push @{ $errors->{$name} }, $result;
      1         8  
    1498             }
    1499             }
    1500 171         433 for my $constraint ( @{ $self->{_constraints} } ) {
      171         495  
    1501 183         1075 my $results = $constraint->process( $self, \%params, $uploads );
    1502 183         1018 my $render = $constraint->render_errors;
    1503 3         10 my @render =
    1504 183 100       1679 ref $render ? @{$render}
        100          
    1505             : defined $render ? $render
    1506             : ();
    1507              
    1508 183         291 for my $result ( @{$results} ) {
      183         735  
    1509 111         518 my $name = $result->name;
    1510 111         5262 my $class = ref $constraint;
    1511 111         1328 $class =~ s/^HTML::Widget::Constraint:://;
    1512 111         470 $class =~ s/::/_/g;
    1513 111         1825 $result->type($class);
    1514 21         102 $result->no_render(1)
    1515 111 100 100     1869 if @render && !grep { $name eq $_ } @render;
    1516 111         759 push @{ $errors->{$name} }, $result;
      111         688  
    1517             }
    1518             }
    1519             }
    1520              
    1521 217 100       1046 return HTML::Widget::Result->new( {
    1522             attributes => $self->attributes,
    1523             container => $self->container,
    1524             _constraints => $self->{_constraints},
    1525             _elements => $self->{_elements},
    1526             _errors => $errors,
    1527             _js_callbacks => \@js_callbacks,
    1528             _params => \%params,
    1529             subcontainer => $self->subcontainer,
    1530             strict => $self->strict,
    1531             empty_errors => $self->empty_errors,
    1532             submitted => ( $query ? 1 : 0 ),
    1533             element_container_class => $self->element_container_class,
    1534             implicit_subcontainer => $self->implicit_subcontainer,
    1535             explicit_ids => $self->explicit_ids,
    1536             } );
    1537             }
    1538              
    1539             =head2 query
    1540              
    1541             Arguments: $query
    1542              
    1543             Return Value: $query
    1544              
    1545             Set/Get the query object to use for validation input. The query object can also
    1546             be passed to the process method directly.
    1547              
    1548             =head2 strict
    1549              
    1550             Arguments: $bool
    1551              
    1552             Return Value: $bool
    1553              
    1554             Only consider parameters that pass at least one constraint valid.
    1555              
    1556             =head2 subcontainer
    1557              
    1558             Arguments: $tag
    1559              
    1560             Return Value: $tag
    1561              
    1562             Set/Get the subcontainer tag to use.
    1563             Defaults to C
    .
    1564              
    1565             =head2 uploads
    1566              
    1567             Arguments: \@uploads
    1568              
    1569             Return Value: \@uploads
    1570              
    1571             Contains an arrayref of L compatible objects.
    1572              
    1573             =head2 xhtml_strict
    1574              
    1575             Arguments: $bool
    1576              
    1577             Return Value: $bool
    1578              
    1579             When C, it is an error to have any element at the top-level of the
    1580             widget which is not derived from L.
    1581             Currently, the only valid element supplied is the
    1582             L.
    1583              
    1584             When C, the top-level widget may not have a L/legend>.
    1585              
    1586             =head1 Frequently Asked Questions (FAQ)
    1587              
    1588             =head2 How do I add an onSubmit handler to my form?
    1589              
    1590             $widget->attributes( onsubmit => $javascript );
    1591              
    1592             See L.
    1593              
    1594             =head2 How do I add an onChange handler to my form field?
    1595              
    1596             $element->attributes( onchange => $javascript );
    1597              
    1598             See L.
    1599              
    1600             =head2 Element X does not have an accessor for Y!
    1601              
    1602             You can add any arbitrary attributes with
    1603             L.
    1604              
    1605             =head2 How can I add a tag which isn't included?
    1606              
    1607             You can either create your own element module files, and use them as you
    1608             would a standard element, or alternatively...
    1609              
    1610             You can call L on a
    1611             L element to change the rendered tag.
    1612              
    1613             $w->element('Block')->type('br');
    1614             # will render as
    1615            
    1616              
    1617             =head2 How can I render some elements in a HTML list?
    1618              
    1619             my $ul = $w->element('Block')->type('ul');
    1620             $ul->element('Block')->type('li')
    1621             ->element( Textfield => foo' );
    1622             $ul->element('Block')->type('li')
    1623             ->element( Textfield => 'bar' );
    1624            
    1625             # will render as
    1626            
    1627            
  • 1628            
    1629            
    1630            
  • 1631            
    1632            
    1633            
    1634              
    1635             =head1 SUPPORT
    1636              
    1637             Mailing list:
    1638              
    1639             L
    1640              
    1641             =head1 SUBVERSION REPOSITORY
    1642              
    1643             The publicly viewable subversion code repository is at
    1644             L.
    1645              
    1646             =head1 SEE ALSO
    1647              
    1648             L L L
    1649              
    1650             =head1 AUTHOR
    1651              
    1652             Sebastian Riedel, C
    1653              
    1654             =head1 LICENSE
    1655              
    1656             This library is free software, you can redistribute it and/or modify it under
    1657             the same terms as Perl itself.
    1658              
    1659             =cut
    1660              
    1661             1;