Subject: | Selecting buttons to click(): asking for the button name isn't always sufficient |
I've got a form with two submit buttons; the one that you click
changes the run_mode parameter in the submission. (This is useful for
CGI::Application.) Thus, both submit buttons have a name of 'mode',
and different values.
click() takes the name of a button, but that's all. This works fine
if I want to click the first 'mode' button, but there's no means to
press the second button.
The documentation for HTML::Form says that when you've got multiple
inputs with the same name, that you should use find_input(name,
form_element_type, index) to get the button:
my $button = $agent->{form}->find_input('mode', 'submit', 2);
and then click that. Integrating this with WWW::Mechanize, I've
hacked up this:
=head2 $agent->find_input_and_click($button, $index, $type, $x, $y);
Searches the form for a specific button, and then clicks it.
The first argument is the name of the button to be clicked.
The second and third arguments allow you to specify the
index number and element type of the desired button. (If omitted,
they default to '1' and 'submit', respectively.) The fourth and
fifth arguments (also optional) specify the (x,y) coordinates of
the click.
Returns an HTTP::Response object.
=cut
sub find_input_and_click {
my ($self, $name, $number, $type, $x, $y) = @_;
for ($x, $y) { $_ = 1 unless defined; }
$type ||= 'submit';
$self->{uri} = $self->{form}->uri;
my $button = $self->{form}->find_input($name, $type, $number);
$self->{req} = $button->click($self->{form}, $x, $y);
return $self->_do_request();
}
# N.b.: $number doesn't get defaulted to 1 in this method, but in
# HTML::Form::find_input().
The one big problem can see with this, is that I'd also like to have a 'find_input_by_value_and_click()' (ugh). Maybe it'd be better to
provide simple wrappers to find_input/find_input_by_value from HTML::Form:
sub find_input {
my ($self, $name, $type, $number) = @_;
return $self->{form}->find_input($name, $type, $number);
}
sub find_input_by_value {
my ($self, $name, $type, $value) = @_;
return $self->{form}->find_input_by_value($name, $type, $value);
}
...and then just expand click() to take a button ref:
sub click {
my ($self, $button, $x, $y) = @_;
for ($x, $y) { $_ = 1 unless defined; }
$self->_push_page_stack();
$self->{uri} = $self->{form}->uri;
if ($button and ref($button)
and ref($button) eq 'HTML::Form::SubmitInput') {
$self->{req} = $button->click($self->{form}, $x, $y);
} else {
$self->{req} = $self->{form}->click($button, $x, $y);
}
return $self->_do_request();
}
(Or else have a distinct click_button() method that only takes the
button object, leaving the regular click('button name string') alone.)