This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/Mojo/DOM.pm b/lib/Mojo/DOM.pm | |
index 740633241..35520515e 100644 | |
--- a/lib/Mojo/DOM.pm | |
+++ b/lib/Mojo/DOM.pm | |
@@ -161,8 +161,11 @@ sub type { shift->tree->[0] } | |
sub val { | |
my $self = shift; | |
+ # "form" | |
+ return $self->_form(@_) if (my $tag = $self->tag) eq 'form'; | |
+ | |
# "option" | |
- return $self->{value} // $self->text if (my $tag = $self->tag) eq 'option'; | |
+ return $self->{value} // $self->text if $tag eq 'option'; | |
# "input" ("type=checkbox" and "type=radio") | |
my $type = $self->{type} // ''; | |
@@ -173,7 +176,7 @@ sub val { | |
return $tag eq 'textarea' ? $self->text : $self->{value} if $tag ne 'select'; | |
# "select" | |
- my $v = $self->find('option:checked')->map('val'); | |
+ my $v = $self->find('option:checked:not([disabled])')->map('val'); | |
return exists $self->{multiple} ? $v->size ? $v->to_array : undef : $v->last; | |
} | |
@@ -241,6 +244,35 @@ sub _delegate { | |
return $self; | |
} | |
+sub _form { | |
+ my ($self, $selector) | |
+ = (shift, shift // 'button, input[type=submit], input[type=image]'); | |
+ | |
+ my $form = {}; | |
+ if (my $e = $self->at($selector)) { _input($form, $e) } | |
+ _input($form, $_) for $self->find('select, textarea')->each; | |
+ my $input | |
+ = $self->find('input:not([type=button], [type=image], [type=submit])'); | |
+ for my $e ($input->each) { | |
+ my $type = $e->{type} // ''; | |
+ _input($form, $e) | |
+ if ($type ne 'radio' && $type ne 'checkbox') || defined $e->{checked}; | |
+ } | |
+ | |
+ return $form; | |
+} | |
+ | |
+sub _input { | |
+ my ($form, $input) = @_; | |
+ | |
+ my ($name, $value) = ($input->{name}, $input->val); | |
+ $form->{$name} | |
+ = exists $form->{$name} | |
+ ? [ref $form->{$name} ? @{$form->{$name}} : $form->{$name}, $value] | |
+ : $value | |
+ if defined $name && defined $value && !exists $input->{disabled}; | |
+} | |
+ | |
sub _link { | |
my ($parent, @children) = @_; | |
diff --git a/t/mojo/dom.t b/t/mojo/dom.t | |
index 27c77ee16..4e8c69aec 100644 | |
--- a/t/mojo/dom.t | |
+++ b/t/mojo/dom.t | |
@@ -2209,6 +2209,7 @@ $dom = Mojo::DOM->new(<<EOF); | |
<form action="/foo"> | |
<p>Test</p> | |
<input type="text" name="a" value="A" /> | |
+ <input type=text name="a" value="A2"> | |
<input type="checkbox" name="q"> | |
<input type="checkbox" checked name="b" value="B"> | |
<input type="radio" name="r"> | |
@@ -2221,6 +2222,7 @@ $dom = Mojo::DOM->new(<<EOF); | |
<optgroup> | |
<option>H</option> | |
<option selected>I</option> | |
+ <option selected disabled>V</option> | |
</optgroup> | |
<option value="J" selected>K</option> | |
</select> | |
@@ -2232,6 +2234,7 @@ $dom = Mojo::DOM->new(<<EOF); | |
</select> | |
<textarea name="m">M</textarea> | |
<button name="o" value="O">No!</button> | |
+ <input type=text name="x" value="X" disabled> | |
<input type="submit" name="p" value="P" /> | |
</form> | |
EOF | |
@@ -2256,6 +2259,10 @@ is $dom->at('input[name=r]')->val, 'on', 'right value'; | |
is $dom->at('input[name=s]')->val, undef, 'no value'; | |
is $dom->at('input[name=t]')->val, '', 'right value'; | |
is $dom->at('input[name=u]')->val, undef, 'no value'; | |
+is_deeply $dom->at('form')->val, | |
+ {a => ['A', 'A2'], d => 'D', f => ['I', 'J'], m => 'M', o => 'O'}, 'right structure'; | |
+is_deeply $dom->at('form')->val('input[type=submit]'), | |
+ {a => ['A', 'A2'], d => 'D', f => ['I', 'J'], m => 'M', p => 'P'}, 'right structure'; | |
# PoCo example with whitespace-sensitive text | |
$dom = Mojo::DOM->new(<<EOF); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment