diff --git a/lib/Mojo/DOM.pm b/lib/Mojo/DOM.pm
index 927d5e8..e982333 100644
--- a/lib/Mojo/DOM.pm
+++ b/lib/Mojo/DOM.pm
@@ -176,6 +176,25 @@ sub type {
return $self;
}
+sub val {
+ my $self = shift;
+
+ # Element
+ return $self->_val unless $self->type eq 'form';
+
+ # Form
+ my ($form, $val) = ({});
+ for my $e ($self->find('select, textarea')->each) {
+ $form->{$e->{name}} = $val if defined($val = $e->_val);
+ }
+ for my $e ($self->find('input')->each) {
+ next if +(grep { $_ eq $e->{type} || '' } qw( radio checkbox )) && !defined $self->{checked};
+ $form->{$e->{name}} = $val if defined($val = $e->_val);
+ }
+
+ return %$form ? $form : undef;
+}
+
sub wrap { shift->_wrap(0, @_) }
sub wrap_content { shift->_wrap(1, @_) }
@@ -353,6 +372,25 @@ sub _text {
return $text;
}
+sub _val {
+ my $self = shift;
+
+ # "option"
+ return $self->{value} // $self->text if $self->type eq 'option';
+
+ # "textarea"
+ return $self->text if $self->type eq 'textarea';
+
+ # "select"
+ if ($self->type eq 'select') {
+ my @values = map { $_->val } $self->find('option[selected]')->each;
+ return !@values ? undef : @values == 1 ? $values[1] : \@values;
+ }
+
+ # "input"
+ return $self->{value};
+}
+
sub _wrap {
my ($self, $content, $new) = @_;
@@ -824,6 +862,22 @@ This element's type.
# List types of child elements
say $dom->children->type;
+=head2 val
+
+ my $value = $dom->val;
+
+Extract values from C<form>, C<input>, C<select>, C<option> and C<textarea>
+elements or return C<undef>.
+
+In case of C<select> this method will find all the C<option>s that is selected.
+Returns a plain string if only one option was found, returns C<undef> if no
+options was found and returns an array ref if more than one option was found.
+
+In case of C<form> it will fetch the values from all the form field elements
+that is checked, selected or has a value and return them in a hash ref
+structure, where the keys are field names and the values are as described
+above.
+
=head2 wrap
$dom = $dom->wrap('<div></div>');