package HTML::DisableForm;
use strict;
use warnings;
use base qw/HTML::Parser/;
our $VERSION = 0.01;
my %can_disable = (
input => 1,
textarea => 1,
select => 1,
);
sub new {
my $class = shift;
my $self = $class->SUPER::new(api_version => 3);
$self->handler(start => \&_handle_start, "self, tagname, attr, text");
$self->handler(end => \&_handle_end, "self, tagname, text");
$self->handler(default => \&_handle_default, "self, text");
$self->attr_encoded(1);
bless $self, $class;
}
sub readonly_form {
my ($self, %option) = @_;
$self->disable_form(%option, readonly => 1);
}
sub disable_form {
my ($self, %option) = @_;
$self->{target} = $option{target} if $option{target};
$self->{readonly} = 1 if $option{readonly};
$self->_set_options_map($_, $option{$_}) for qw/ignore_fields ignore_forms/;
$self->_parse(%option);
delete $self->{output};
}
sub _set_options_map {
my ($self, $name, $value) = @_;
return unless defined $value;
my %options_map = map { $_ => 1 } ref $value eq 'ARRAY' ? @$value : $value;
$self->{$name} = \%options_map;
}
sub _parse {
my $self = shift;
my %option = @_;
if (my $file = $option{file}){
$self->parse_file($file);
} elsif (my $scalarref = $option{scalarref}){
$self->parse($$scalarref);
} elsif (my $arrayref = $option{arrayref}){
$self->parse($_) for @$arrayref;
}
}
sub _can_disable {
my ($self, $tagname, $attr) = @_;
$can_disable{$tagname} or return;
return 0 if defined $self->{target} && !$self->{current_form};
if (my $current_form = $self->{current_form}) {
if (defined $self->{target}) {
$current_form eq $self->{target} ? return 1 : return 0;
}
return 0 if $self->{ignore_forms}->{$current_form};
}
if ($attr->{name}) {
return 0 if $self->{ignore_fields}->{$attr->{name}};
}
return 1;
}
sub _handle_start {
my ($self, $tagname, $attr, $text) = @_;
$self->{current_form} = $attr->{name} || $attr->{id} || ''
if $tagname eq 'form';
if ($self->_can_disable($tagname, $attr)) {
$self->{output} .= "<$tagname";
while (my ($key, $value) = each %$attr) {
next if $key eq '/';
$self->{output} .= sprintf qq( %s="%s"), $key, $value;
}
$self->{output} .= $self->{readonly} ? ' readonly="readonly"' : ' disabled="disabled"';
$self->{output} .= ' /' if $attr->{'/'};
$self->{output} .= '>';
} else {
$self->{output} .= $text;
}
}
sub _handle_end {
my ($self, $tagname, $text) = @_;
delete $self->{current_form}
if $tagname eq 'form' and exists $self->{current_form};
$self->{output} .= $text;
}
sub _handle_default {
my ($self, $text) = @_;
$self->{output} .= $text;
}
1;
__END__
=head1 NAME
HTML::DisableForm - Manipulate disabled/readonly HTML Forms
=head1 SYNOPSIS
use HTML::DisableForm;
my $df = new HTML::DisableForm;
my $output = $dif->disable_form(scalarref => \$html);
=head1 DESCRIPTION
This module automatically makes form controlls disable/readonly.
=head1 METHODS
=head2 new
Creates a new HTML::DisableForm object
$df = new HTML::DisableForm
=head2 disable_form
Returns HTML with disabled forms. This method can take some type of
argument for a HTML document.
$output = $df->disable_form(scalarref => \$html);
$output = $df->disable_form(file => "/path/to/document.html");
$output = $df->disable_form(arrayref => \@html);
Specify readonly flag if you want to makes it readonly instead of disable.
$output = $df->disable_form(arrayref => \@html);
Suppose you have multiple forms in a html and among them there is only
one form you want to disable, specify target.
$output = $df->disable_form(
scalarref => \$html,
target => 'foo',
);
If there are some forms you want to ignore, specify their names as
ignore_forms.
$output = $df->disable_form(
scalarref => \$html,
ignore_forms => [qw/foo bar/],
);
You can also ignore fields what you want.
$output = $df->disable_form(
scalarref => \$html,
ignore_fields => [qw/name password/],
);
=head2 readonly_form
This method equals to C with a readonly flag.
=head1 TODO
More tests.
=head1 AUTHOR
Naoya Ito C<< >>
=head1 LICENCE AND COPYRIGHT
Copyright (c) 2006, Naoya Ito C<< >>. All rights reserved.
This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself. See L.
=cut