extended select() support
[perl/html-form-simple.git] / lib / HTML / Form / Simple.pm
index 6e84888296e51a5deb508b6232f69a0c00c085cf..57b2a918b6f2a1351abdadc515de642598f9fb3b 100644 (file)
@@ -28,7 +28,7 @@ sub tag {
 
        # add booleans
        delete $attr->{$_} and $return .= ' '.$_
-               for qw(disabled readonly);
+               for qw(selected checked disabled readonly);
 
        $return .= sprintf ' %s="%s"', $_, $self->quote($attr->{$_})
                for sort grep { defined $attr->{$_} } keys %$attr;
@@ -107,15 +107,92 @@ sub select {
 
        if (ref $value eq 'HASH') {
                $attr = $value;
+               $value = delete $attr->{value};
        }
        else {
                $attr ||= {};
+               delete $attr->{value};
        }
        $attr->{name} = $name;
+       $attr->{id}   = $attr->{name} unless defined $attr->{id};
+       $attr->{type} = 'select' unless defined $attr->{type};
+
+       my @options = map { ref $_ ? $_ : {value => $_} } @$rows;
+
+       if ($attr->{type} eq 'select') {
+               delete $attr->{type};
+               if (defined $value) {
+                       for (@options) {
+                               $_->{selected} = 1 if defined $_->{value} and $_->{value} eq $value;
+                       }
+               }
+               my @return = (
+                       $self->tag(select => $attr),
+                       (map { $self->tag(option => $_) } @options),
+                       '</select>',
+               );
+               return wantarray ? @return : join('', @return);
+       }
+       else {
+               if (defined $attr->{id}) {
+                       defined $_->{id} or defined $_->{value} and $_->{id} = $attr->{id}.'_'.$_->{value}
+                               for @options;
+               }
+               if (defined $attr->{label}) {
+                       defined $_->{value} and not defined $_->{label}
+                               and $_->{label} = $attr->{label}->{$_->{value}}
+                                       for @options;
+                       delete $attr->{label};
+               }
+               if (defined $value) {
+                       for (@options) {
+                               $_->{checked} = 1 if defined $_->{value} and $_->{value} eq $value;
+                       }
+               }
+               $_ = {%$attr, %$_} for @options;
+               my @return = map {
+                       my $label = delete $_->{label};
+                       defined $label && $label ne ''
+                               ? '<label>'.$self->tag(input => $_)." $label</label>"
+                               :           $self->tag(input => $_)
+               } @options;
+               return wantarray ? @return : join('', @return);
+       }
+}
+
+sub radio {
+       my ($self, $name, $value, $attr) = @_;
+
+       if (ref $value eq 'HASH') {
+               $attr = $value;
+       }
+       else {
+               $attr ||= {};
+               $attr->{value} = $value;
+       }
 
-       return $self->tag(select => $attr) . join('',
-               map { $self->tag(option => (ref $_ ? $_ : {value => $_})) } @$rows
-       ) . '</select>';
+       $self->select($name, [$attr], {type => 'radio'});
+}
+
+sub check {
+       my ($self, $name, $label, $checked, $attr) = @_;
+
+       if (ref $label eq 'HASH') {
+               $attr = $label;
+               undef $label;
+       }
+       elsif (ref $checked eq 'HASH') {
+               $attr = $checked;
+               $attr->{label} = $label;
+       }
+       else {
+               $attr ||= {};
+               $attr->{checked} = $checked;
+               $attr->{label} = $label;
+       }
+       $attr->{value} = '1' unless exists $attr->{value};
+
+       $self->select($name, [$attr], {type => 'checkbox'});
 }
 
 1;
@@ -135,9 +212,15 @@ HTML::Form::Simple
                [ Message => $input->text(
                        msg => 'Textarea default', {rows => 4, style => 'background:red'}
                ) ],
-               [ Colour => $input->select(
+               [ Gender => join ' or ', $input->radio(
+                       sex => ['m', 'f']
+               ) ],
+               [ Colour => scalar $input->select(
                        favcolour => [qw(Blue Green Red)], 'Green'
                ) ],
+               [ Options => $input->check(
+                       spam => 'Receive weekly newsletter'
+               ) ],
        );
        say $input->stop; # </form>