Mozilla::Mechanize::Input - A small class to interface with the Input objects


Mozilla-Mechanize documentation Contained in the Mozilla-Mechanize distribution.

Index


Code Index:

NAME

Top

Mozilla::Mechanize::Input - A small class to interface with the Input objects

SYNOPSIS

Top

sorry, read the source for now

DESCRIPTION

Top

The Mozilla::Mechanize::Input object is a thin wrapper around HTML input elements.

METHODS

Top

Mozilla::Mechanize::Input->new($input_node, $moz)

Initialize a new object. $input_node is a Mozilla::DOM::HTMLElement (Mozilla::DOM::HTMLElement) (or a node that can be QueryInterfaced to one); specifically, it must be an HTMLInputElement, an HTMLButtonElement, an HTMLSelectElement, or an HTMLTextAreaElement. $moz is a Mozilla::Mechanize object. (This latter is a hack for `click', so that new pages can load in the browser. The GUI has to be able to enter its main loop. If you don't plan to use that method, you don't have to pass it in.)

$input->name

Return the input-control name.

$input->type

Return the type of the input control. Note: for <select>, this returns 'select-one' for single select, and 'select-multiple' for multiple. (I don't know why.)

$input->value( [$value] )

Get/Set the value of the input control.

$input->select_value( [$value] )

Mark all options with $value as selected and unselect all other options.

$input->radio_value( [$value] )

Locate all radio-buttons with the same name within this form. Now uncheck all values that are not equal to $value.

$input->click

Calls the click() method on the actual object.

COPYRIGHT AND LICENSE

Top


Mozilla-Mechanize documentation Contained in the Mozilla-Mechanize distribution.
package Mozilla::Mechanize::Input;
use strict;
use warnings;

# $Id: Input.pm,v 1.4 2005/10/07 12:17:24 slanning Exp $

sub new {
    my $class = shift;
    my $node = shift;
    my $moz = shift;

    my $iid;

    # turn the Node into the appropriate HTMLElement
    if (lc $node->GetNodeName eq 'input') {
        $iid = Mozilla::DOM::HTMLInputElement->GetIID;
    } elsif (lc $node->GetNodeName eq 'button') {
        $iid = Mozilla::DOM::HTMLButtonElement->GetIID;
    } elsif (lc $node->GetNodeName eq 'select') {
        $iid = Mozilla::DOM::HTMLSelectElement->GetIID;
    } elsif (lc $node->GetNodeName eq 'textarea') {
        $iid = Mozilla::DOM::HTMLTextAreaElement->GetIID;
    } else {
        my $errstr = "Invalid Input node";
        defined($moz) ? $moz->die($errstr) : die($errstr);
    }
    my $input = $node->QueryInterface($iid);

    my $self = { input => $input };
    $self->{moz} = $moz if defined $moz;
    bless($self, $class);
}

sub name {
    my $self = shift;
    my $input = $self->{input};
    return $input->GetAttribute('name');
}

sub type {
    my $self = shift;
    my $input = $self->{input};
    my $tagname = lc $input->GetNodeName;
    if ($tagname eq 'select') {
        if ($input->GetMultiple) {
            return 'select-multiple';
        } else {
            # I don't know what this is about,
            # but it works like Win32::IE::Mechanize
            return 'select-one';
        }
    } else {
        return $input->GetAttribute('type');
    }
}

sub value {
    my $self = shift;
    my $input = $self->{input};

    my $type = $self->type || '';
    $type =~ /^select/i and return $self->select_value( @_ );
    $type =~ /^radio/i  and return $self->radio_value( @_ );

    if (@_ && defined $_[0]) {
        my $value = shift;
        $input->SetValue($value);
    }
    return $input->GetValue;
}

sub select_value {
    my $self = shift;
    my $input = $self->{input};

    # XXX: I think this could be done better, but I just ported it straight

    my %vals;
    my @options = $input->GetOptions;

    if ( @_ ) {
        my @values = @_;
        if ( @values == 1 && ref $values[0] eq 'HASH' ) {
            my @ords = ref $values[0]->{n}
                ? @{ $values[0]->{n} } : $values[0]->{n};
            @values = ();
            foreach my $i ( @ords ) {
                ($i > 0) && ($i <= @options) and
                  push @values, $options[$i - 1]->GetValue;
            }
        }
        @values = @{ $values[0] } if @values == 1 && ref $values[0];

        # Make sure only the last value is set for:
        # select-one type with multiple values;
        # XXX: not sure if same type in Mozilla
        @values = ( $values[-1] ) if lc($self->type) eq 'select-one';

        %vals = map { ( $_ => undef ) } @values;

        for ( my $i = 0; $i < @options; $i++ ) {
            $options[$i]->SetSelected(exists $vals{ $options[$i]->GetValue });
        }
    } else {
        for ( my $i = 0; $i < @options; $i++ ) {
            $options[$i]->GetSelected and
              $vals{ $options[$i]->GetValue } = 1;
        }
    }

    return keys %vals;
}

sub radio_value {
    my $self = shift;
    my $input = $self->{input};

    return unless $self->type =~ /^radio/i;

    my $form = Mozilla::Mechanize::Form->new($input->GetForm, $self->{moz});
    my @radios = $form->_radio_group($self->name);

    if (@_) {
        my $value = shift;
        for (@radios) {
            $_->SetChecked(($_->GetValue eq $value) || 0);
        }
    }
    my ($value) = map($_->GetValue, grep($_->GetChecked, @radios));
    return $value;
}

sub click {
    my $self = shift;
    my $input = $self->{input};
    $input->Click();

    # XXX: if they didn't pass $moz to `new', they're stuck..
    my $moz = $self->{moz} || return;
    $moz->_wait_while_busy();
}


1;

__END__