Subject: | problems with click/submit() in WWW::Mechanize |
So, I've finally started using WWW::Mechanize, and immediately ran
into two problems, both with submit().
One form I use relies upon javascript to make form submissions via
onChange handlers; the form has no submit button. But
WWW::Mechanize::submit() is just a wrapper for click('submit'). Thus,
if I try to submit the form when the form has no submit button, I get
a croak from HTML::Form:
No clickable input with name submit at /usr/local/dnpl/lib/WWW/Mechanize.pm
line 374
# Looks like your test died before it could output anything.
(The first line comes from line 447 of HTML::Form 1.00, inside its own
click().)
My second problem is related: I often use submit buttons that aren't
named 'submit', so that $agent->submit() comes back with the same
error about no clickable input with the name 'submit'.
It doesn't seem difficult to make WWW::Mechanize do the right thing.
The following would solve my problem:
sub submit_without_clicking {
my ($self) = shift;
$self->_push_page_stack;
$self->{uri} = $self->{form}->uri;
$self->{req} = $self->{form}->make_request;
return $self->_do_request;
}
But, besides the awful name, creating two parallel methods that both
handle form submission, with just one minor change between them, is
bad coding.
The patch I've enclosed handles this by expanding upon submit(),
allowing it to take arguments:
$agent->submit('Some name');
This submits to a form button that has the given name. The coder
could just use $agent->click('Some name') instead, but this strikes me
as superior; the button name is a UI decision that may be under the
control of web designers, and this way you could manage name changes
via a variable, e.g. $agent->submit($button_name). (Alternatively,
maybe you should just never use submit() at all unless you absolutely
know that the button will be called 'submit', and instead just use
click(). If so, that's an awkward, counter-intuitive API, IMHO.)
$agent->submit(undef);
This forces the form to submit, without attempting to press any
buttons. click() gets changed to handle this, which poses a potential
backward incompatibility: click(), with no arguments, is supposed to
press the first button it finds. I've modified click() to distinguish
between click(undef) and click(). (This also treats
my @l = ();
click(@l);
the same as click().)
The patch includes POD changes.
Let me know what you think of this, even if you think it's a bad
way to deal with these problems.
--- Mechanize.pm~ Wed Mar 12 16:05:21 2003
+++ Mechanize.pm Wed Mar 12 15:57:31 2003
@@ -371,21 +371,36 @@
for ($x, $y) { $_ = 1 unless defined; }
$self->_push_page_stack();
$self->{uri} = $self->{form}->uri;
- $self->{req} = $self->{form}->click($button, $x, $y);
+ if (not defined $button and scalar(@_) == 2) {
+ $self->{req} = $self->{form}->make_request;
+ } else {
+ $self->{req} = $self->{form}->click($button, $x, $y);
+ }
return $self->_do_request();
}
=head2 $agent->submit()
-Shortcut for $a->click("submit")
+Shortcut for $a->click("submit").
+
+To submit a form by clicking a button that isn't named 'submit', either
+use click() or specify the name of the submit button as the argument:
+
+ $agent->submit('Submit Button Name');
+
+To submit a form without clicking any button (as in the case of a form
+that uses javascript on a non-button form element to submit itself):
+
+ $agent->submit(undef);
=cut
sub submit {
my ($self) = shift;
- return $self->click("submit");
+ return $self->click(scalar @_ ? @_ : "submit");
}
+
=head2 $agent->back();
The equivalent of hitting the "back" button in a browser. Returns to