Skip to content

Commit

Permalink
simplify val semantics
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Jul 23, 2014
1 parent a324e15 commit d602e07
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 87 deletions.
73 changes: 19 additions & 54 deletions lib/Mojo/DOM.pm
Expand Up @@ -179,20 +179,21 @@ sub type {
sub val {
my $self = shift;

# Element
return $self->_val unless $self->type eq 'form';

# Form
my $form = {};
_pair($form, $_->{name}, $_->_val) for $self->find('select, textarea')->each;
_input($form, $_)
for $self->find('input:not([type=button], [type=submit], [type="reset"])')
->each;
my $e = $self->at(
'button[type="submit"], button:not([type]), input[type=submit]');
_input($form, $e) if $e;

return $form;
# "option"
my $type = $self->type;
return $self->{value} // $self->text if $type eq 'option';

# "select"
if ($type eq 'select') {
my @values = $self->find('option[selected]')->val->each;
return @values ? @values > 1 ? \@values : $values[0] : undef;
}

# "textarea"
return $self->text if $type eq 'textarea';

# "input" or "button"
return $type eq 'input' || $type eq 'button' ? $self->{value} : undef;
}

sub wrap { shift->_wrap(0, @_) }
Expand Down Expand Up @@ -272,13 +273,6 @@ sub _delegate {
return $self;
}

sub _input {
my ($form, $e) = @_;
my $type = $e->{type} // '';
_pair($form, $e->{name}, $e->_val)
if ($type ne 'radio' && $type ne 'checkbox') || defined $e->{checked};
}

sub _link {
my ($children, $parent) = @_;

Expand Down Expand Up @@ -306,8 +300,6 @@ sub _offset {
return $i;
}

sub _pair { $_[0]->{$_[1]} = $_[2] if defined $_[1] && defined $_[2] }

sub _parent { $_[0]->tree->[$_[0]->node eq 'tag' ? 3 : 2] }

sub _parse { Mojo::DOM::HTML->new(xml => shift->xml)->parse(shift)->tree }
Expand Down Expand Up @@ -381,26 +373,6 @@ sub _text {
return $text;
}

sub _val {
my $self = shift;

# "option"
my $type = $self->type;
return $self->{value} // $self->text if $type eq 'option';

# "select"
if ($type eq 'select') {
my @values = $self->find('option[selected]')->val->each;
return @values ? @values > 1 ? \@values : $values[0] : undef;
}

# "textarea"
return $self->text if $type eq 'textarea';

# "input" or "button"
return $type eq 'input' || $type eq 'button' ? $self->{value} : undef;
}

sub _wrap {
my ($self, $content, $new) = @_;

Expand Down Expand Up @@ -876,21 +848,14 @@ This element's type.
my $value = $dom->val;
Extract values from C<button>, C<form>, C<input>, C<option>, C<select> and
C<textarea> elements or return C<undef> if this element has no value. In the
case of C<select>, find an C<option> element with C<selected> attribute and
return its value or an array reference with all values if there are more than
one. In the case of C<form>, find all elements mentioned before that would be
submitted by pressing the first button and return a hash reference with their
names and values.
Extract values from C<button>, C<input>, C<option>, C<select> and C<textarea>
elements or return C<undef> if this element has no value. In the case of
C<select>, find an C<option> element with C<selected> attribute and return its
value or an array reference with all values if there are more than one.
# "b"
$dom->parse('<form><input name="a" value="b"></form>')->at('input')->val;
# "b"
$dom->parse('<form action="/"><input name="a" value="b"></form>')
->at('form')->val->{a};
=head2 wrap
$dom = $dom->wrap('<div></div>');
Expand Down
45 changes: 12 additions & 33 deletions t/mojo/dom.t
Expand Up @@ -2309,9 +2309,7 @@ $dom = Mojo::DOM->new(<<EOF);
<p>Test</p>
<input type="text" name="a" value="A" />
<input type="checkbox" checked name="b" value="B">
<input type="checkbox" name="c" value="C">
<input type="radio" name="d" value="D">
<input type="radio" checked name="e" value="E">
<input type="radio" checked name="c" value="C">
<select name="f">
<option value="F">G</option>
<optgroup>
Expand All @@ -2321,44 +2319,25 @@ $dom = Mojo::DOM->new(<<EOF);
<option value="J" selected>K</option>
</select>
<select name="n"><option>N</option></select>
<select name="l"><option selected>L</option></select>
<select name="d"><option selected>D</option></select>
<textarea name="m">M</textarea>
<input type="button" name="s" value="S" />
<button name="o" value="O">No!</button>
<input type="submit" name="p" value="P" />
</form>
<form id="button">
<button type="reset" name="r" value="R">No!</button>
<button type="button" name="q" value="Q">No!</button>
<button type="submit" name="s" value="S">Yes!</button>
</form>
<form id="input">
<input type="button" name="t" value="T">
<input type="reset" name="u" value="U">
<input type="submit" name="v" value="V">
</form>
<form id="empty"></form>
EOF
is $dom->at('p')->val, undef, 'no value';
is_deeply $dom->at('form')->val,
{a => 'A', f => ['I', 'J'], l => 'L', m => 'M', o => 'O'}, 'right values';
is $dom->at('input')->val, 'A', 'right value';
is $dom->find('input')->[2]->val, 'C', 'right value';
is $dom->find('input')->[3]->val, 'D', 'right value';
EOF
is $dom->at('p')->val, undef, 'no value';
is $dom->at('input')->val, 'A', 'right value';
is $dom->at('input:checked')->val, 'B', 'right value';
is $dom->at('input:checked[type=radio]')->val, 'C', 'right value';
is_deeply $dom->find('select')->first->val, ['I', 'J'], 'right values';
is $dom->at('select option')->val, 'F', 'right value';
is $dom->at('select option')->val, 'F', 'right value';
is $dom->at('select optgroup option:not([selected])')->val, 'H', 'right value';
is $dom->find('select')->[1]->val, undef, 'no value';
is $dom->find('select')->[1]->at('option')->val, 'N', 'right value';
is $dom->find('select')->last->val, 'L', 'right value';
is $dom->find('select')->last->val, 'D', 'right value';
is $dom->at('textarea')->val, 'M', 'right value';
is $dom->at('form')->find('input')->[-2]->val, 'S', 'right value';
is $dom->at('form')->find('input')->last->val, 'P', 'right value';
is_deeply $dom->at('#button')->val, {s => 'S'}, 'right values';
is $dom->at('#button [type=button]')->val, 'Q', 'right value';
is_deeply $dom->at('#input')->val, {v => 'V'}, 'right values';
is $dom->at('#input [type=button]')->val, 'T', 'right value';
is $dom->at('#input [type=reset]')->val, 'U', 'right value';
is_deeply $dom->at('#empty')->val, {}, 'no values';
is $dom->at('button')->val, 'O', 'right value';
is $dom->find('form input')->last->val, 'P', 'right value';

# Slash between attributes
$dom = Mojo::DOM->new('<input /type=checkbox / value="/a/" checked/><br/>');
Expand Down

0 comments on commit d602e07

Please sign in to comment.