# 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;
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;
[ 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>
use Test::More;
-plan tests => 31;
+plan tests => 43;
use_ok('HTML::Form::Simple');
# select
-is(
- $form->select,
- '<select></select>', # malformed html: at least 1 option required
+is_deeply(
+ [ $form->select ],
+ [ qw(<select> </select>) ], # malformed html: at least 1 option required
'empty select'
);
-is(
- $form->select(undef, [], '', {name => ''}),
- '<select></select>',
+is_deeply(
+ [ $form->select(undef, [], '', {name => '', class => ''}) ],
+ [ qw(<select> </select>) ],
'explicit empty select'
);
-is(
- $form->select(undef, [undef]),
- '<select><option></select>',
+is_deeply(
+ [ $form->select(undef, [undef]) ],
+ [ qw(<select> <option> </select>) ],
'minimal select'
);
-is(
- $form->select(foo => [1..2]),
- '<select name="foo"><option value="1"><option value="2"></select>',
+is_deeply(
+ [ $form->select(foo => [1, 2]) ],
+ [
+ '<select id="foo" name="foo">',
+ '<option value="1">', '<option value="2">',
+ '</select>'
+ ],
'select contents'
);
+is_deeply(
+ [ $form->select(foo => [1, 2], 3) ],
+ [
+ '<select id="foo" name="foo">',
+ '<option value="1">', '<option value="2">',
+ '</select>'
+ ],
+ 'select invalid default'
+);
+
+is_deeply(
+ [ $form->select(undef, [1, 2], 2) ],
+ [
+ '<select>',
+ '<option value="1">', '<option selected value="2">',
+ '</select>'
+ ],
+ 'select default'
+);
+
+is_deeply(
+ [
+ $form->select(foo => [
+ '<">', {value => 2, disabled => 1, selected => 0, class => 1}, {selected => 1}
+ ], '2', {id => '', class => 'a <b', value => 1})
+ ],
+ [
+ '<select class="a <b" name="foo">',
+ '<option value="<">">',
+ '<option selected disabled class="1" value="2">',
+ '<option selected>',
+ '</select>'
+ ],
+ 'complex select'
+);
+
+is(
+ scalar $form->select(foo => [1, 2]),
+ '<select id="foo" name="foo"><option value="1"><option value="2"></select>',
+ 'select scalar'
+);
+
+# radio
+
+is_deeply(
+ [ $form->select(foo => [1], {type => 'radio'}) ],
+ [ '<input id="foo_1" name="foo" type="radio" value="1">' ],
+ 'input select'
+);
+
+is_deeply(
+ [
+ $form->select(foo => [
+ 1, {value => 2, name => '', label => ''}, {value => 3, id => '', type => ''}
+ ], {type => 'checkbox', label => {3 => 'test', 2 => 'ignore'}, value => '1'})
+ ],
+ [
+ '<input checked id="foo_1" name="foo" type="checkbox" value="1">',
+ '<input id="foo_2" name="" type="checkbox" value="2">',
+ '<label><input name="foo" value="3"> test</label>',
+ ],
+ 'input selects'
+);
+
+is(
+ $form->radio(foo => 1),
+ '<input id="foo_1" name="foo" type="radio" value="1">',
+ 'radio method'
+);
+
+is(
+ $form->radio(undef, {checked => 1}),
+ '<input checked type="radio">',
+ 'simple radio button'
+);
+
+is(
+ $form->check('foo'),
+ '<input id="foo_1" name="foo" type="checkbox" value="1">',
+ 'check method'
+);
+
+is(
+ $form->check(foo => 'test', {value => undef}),
+ '<label><input id="foo" name="foo" type="checkbox"> test</label>',
+ 'check parameters'
+);
+
+is(
+ $form->check(undef, '', 1),
+ '<input checked type="checkbox" value="1">',
+ 'simple checkbox'
+);
+
+TODO: {
+ local $TODO = 'shorthand';
+is_deeply(
+ [ $form->check(undef, ['', '<">']) ],
+ [
+ '<input checked type="checkbox" value="1">',
+ '<label><input checked type="checkbox" value="2"> <"></label>',
+ ],
+ 'multiple checkboxes'
+);
+};
+
#TODO