Upon closer inspection of that oddity for FillInForm.pm that I was experiencing, it seemed that the status of the checkbox was *toggling* every time I submitted the form in that test script from my previous message. If I check the checkbox and submit, then it will be unchecked when it comes back, and vice versa. I hacked around the logic of FillInForm.pm a bit and now it seems to work fine on my system. This file goes in /usr/lib/perl5/site_perl/5.005/HTML/FillInForm.pm on my system (yours may vary). Does anyone else experience the same bug with FillInForm that I am experiencing? If so, does my patch fix the bug, and are there any bugs in my patch? -Philip Mak ([EMAIL PROTECTED])
package HTML::FillInForm; use integer; # no floating point math so far! use strict; # and no funny business, either. use Carp; # generate better errors with more context use HTML::Parser 3.08; # required for UNIVERSAL->can require 5.005; use vars qw($VERSION @ISA); $VERSION = '0.13'; @ISA = qw(HTML::Parser); sub new { my ($class) = @_; my $self = bless {}, $class; $self->init; $self->boolean_attribute_value('__BOOLEAN__'); return $self; } # a few shortcuts to fill() sub fill_file { my $self = shift; return $self->fill('file',@_); } sub fill_arrayref { my $self = shift; return $self->fill('arrayref',@_); } sub fill_scalarref { my $self = shift; return $self->fill('scalarref',@_); } sub fill { my ($self, %option) = @_; if (my $fdat = $option{fdat}){ $self->{fdat} = $fdat; } if(my $objects = $option{fobject}){ unless(ref($objects) eq 'ARRAY'){ $objects = [ $objects ]; } $self->{fdat} = {} unless exists $self->{fdat}; for my $object (@$objects){ # make sure objects in 'param_object' parameter support param() defined($object->can('param')) or croak("HTML::FillInForm->fill called with fobject option, containing object of type " . ref($object) . " which lacks a param() method!"); foreach my $k ($object->param()){ # we expect param to return an array if there are multiple values my @v = $object->param($k); $self->{fdat}->{$k} = scalar(@v)>1 ? \@v : $v[0]; } } } # # get data set from param() method # foreach my $key ($self->param){ # $self->{fdat}->{$key} = $self->param($key); # } # make sure method has data to fill in HTML form with! unless(exists $self->{fdat}){ croak("HTML::FillInForm->fillInForm() called without 'object' or 'fdat' parameter set"); } if(my $file = $option{file}){ $self->parse_file($file); } elsif (my $scalarref = $option{scalarref}){ $self->parse($$scalarref); } elsif (my $arrayref = $option{arrayref}){ for (@$arrayref){ $self->parse($_); } } return delete $self->{output}; } # handles opening HTML tags such as <input ...> sub start { my ($self, $tagname, $attr, $attrseq, $origtext) = @_; # HTML::Parser converts tagname to lowercase, so we don't need /i if ($self->{option_no_value}) { $self->{output} .= '>'; delete $self->{option_no_value}; } if ($tagname eq 'input'){ my $value = $self->{fdat}->{$attr->{'name'}}; # force hidden fields to have a value $value = '' if exists($attr->{'type'}) && $attr->{'type'} eq 'hidden' && ! exists $attr->{'value'} && ! defined $value; if (defined($value) || 1){ # check for input type, noting that default type is text if (!exists $attr->{'type'} || $attr->{'type'} =~ /^(text|textfield|hidden|password|)$/i){ $value = $value->[0] if ref($value) eq 'ARRAY'; $attr->{'value'} = $self->escapeHTML($value); } elsif (lc $attr->{'type'} eq 'radio'){ $value = $value->[0] if ref($value) eq 'ARRAY'; if ($attr->{'value'} eq $value){ $attr->{'checked'} = '__BOOLEAN__'; } else { delete $attr->{'checked'}; } } elsif (lc $attr->{'type'} eq 'checkbox'){ unless ( ref($value) eq 'ARRAY' ) { $value = [ $value ]; } $attr->{checked} = '__BOOLEAN__'; # Everything is checked to start foreach my $v ( @$value ) { if ( $attr->{'value'} eq $v ) { delete $attr->{'checked'}; } } # } else { # warn(qq(Input field of unknown type "$attr->{type}": $origtext)); } } $self->{output} .= "<$tagname"; while (my ($key, $value) = each %$attr) { if($value eq '__BOOLEAN__'){ # boolean attribute $self->{output} .= " $key"; } else { $self->{output} .= " $key" . qq(="$value"); } } $self->{output} .= ">"; } elsif ($tagname eq 'option'){ my $value = $self->{fdat}->{$self->{selectName}}; if (defined($value)){ unless ( ref($value) eq 'ARRAY' ) { $value = [ $value ]; } delete $attr->{selected} if exists $attr->{selected}; if($attr->{'value'}){ # option tag has value attr - <OPTION VALUE="foo">bar</OPTION> foreach my $v ( @$value ) { if ( $attr->{'value'} eq $v ) { $attr->{selected} = '__BOOLEAN__'; } } } else { # option tag has no value attr - <OPTION>bar</OPTION> # save for processing under text handler $self->{option_no_value} = $value; } } $self->{output} .= "<$tagname"; while (my ($key, $value) = each %$attr) { if($value eq '__BOOLEAN__'){ # boolean attribute $self->{output} .= " $key"; } else { $self->{output} .= " $key" . qq(="$value"); } } unless ($self->{option_no_value}){ # we can close option tag here $self->{output} .= ">"; } } elsif ($tagname eq 'textarea'){ if (defined(my $value = $self->{fdat}->{$attr->{'name'}})){ $value = $value->[0] if ref($value) eq 'ARRAY'; # <textarea> foobar </textarea> -> <textarea> $value </textarea> # we need to set outputText to 'no' so that 'foobar' won't be printed $self->{outputText} = 'no'; $self->{output} .= $origtext . $self->escapeHTML($value); } else { $self->{output} .= $origtext; } } elsif ($tagname eq 'select'){ $self->{selectName} = $attr->{'name'}; $self->{output} .= $origtext; } else { $self->{output} .= $origtext; } } # handles non-html text sub text { my ($self, $origtext) = @_; # just output text, unless replaced value of <textarea> tag unless(exists $self->{outputText} && $self->{outputText} eq 'no'){ if(exists $self->{option_no_value}){ # dealing with option tag with no value - <OPTION>bar</OPTION> my $values = $self->{option_no_value}; chomp(my $value = $origtext); foreach my $v ( @$values ) { if ( $value eq $v ) { $self->{output} .= " selected"; } } # close <OPTION> tag $self->{output} .= ">$origtext"; delete $self->{option_no_value}; } else { $self->{output} .= $origtext; } } } # handles closing HTML tags such as </textarea> sub end { my ($self, $tagname, $origtext) = @_; if ($self->{option_no_value}) { $self->{output} .= '>'; delete $self->{option_no_value}; } if($tagname eq 'select'){ delete $self->{selectName}; } elsif ($tagname eq 'textarea'){ delete $self->{outputText}; } $self->{output} .= $origtext; } sub escapeHTML { my ($self, $toencode) = @_; return undef unless defined($toencode); $toencode =~ s/&/&/g; $toencode =~ s/\"/"/g; $toencode =~ s/>/>/g; $toencode =~ s/</</g; return $toencode; } # param method - can be called in two forms # when passed two arguments ($name, $value), it sets the value of the # $name attributes to $value # when passwd one argument ($name), retrives the value of the $name attribute # WARNING: this method is undocumented and MAY GO AWAY #sub param { # my ($self, @p) = @_; # unless(@p){ # return () unless defined($self) && $self->{'.parameters'}; # return () unless @{$self->{'.parameters'}}; # return @{$self->{'.parameters'}}; # } # my ($name, $value); # if (@p > 1){ # ($name, $value) = @p; # $self->add_parameter($name); # $self->{param}->{$name} = $value; # } else { # $name = $p[0]; # } # # return $self->{param}->{$name}; #} #sub add_parameter { # my ($self, $param) = @_; # return unless defined $param; # push (@{$self->{'.parameters'}},$param) # unless defined($self->{$param}); #} 1; __END__ =head1 NAME HTML::FillInForm - Populates HTML Forms with CGI data. =head1 DESCRIPTION This module automatically inserts data from a previous HTML form into the HTML input, textarea and select tags. It is a subclass of L<HTML::Parser> and uses it to parse the HTML and insert the values into the form tags. One useful application is after a user submits an HTML form without filling out a required field. HTML::FillInForm can be used to redisplay the HTML form with all the form elements containing the submitted info. =head1 SYNOPSIS This examples fills data into a HTML form stored in C<$htmlForm> from CGI parameters that are stored in C<$q>. For example, it will set the value of any "name" textfield to "John Smith". my $q = new CGI; $q->param("name","John Smith"); my $fif = new HTML::FillInForm; my $output = $fif->fill(scalarref => \$html, fobject => $q); =head1 METHODS =over 4 =item new Call C<new()> to create a new FillInForm object: $fif = new HTML::FillInForm; =item fill To fill in a HTML form contained in a scalar C<$html>: $output = $fif->fill(scalarref => \$html, fobject => $q); Returns filled in HTML form contained in C<$html> with data from C<$q>. C<$q> is required to have a C<param()> method that works like CGI's C<param()>. $output = $fif->fill(scalarref => \$html, fobject => [$q1, $q2]); Note that you can pass multiple objects as an array reference. $output = $fif->fill(scalarref => \$html, fdat => \%fdat); Returns filled in HTML form contained in C<$html> with data from C<%fdat>. To pass multiple values using C<%fdat> use an array reference. Alternately you can use $output = $fif->fill(arrayref => \@array_of_lines, fobject => $q); and $output = $fif->fill(file => 'form.tmpl', fobject => $q); =back =head1 CALLING FROM OTHER MODULES =head2 Apache::PageKit To use HTML::FillInForm in L<Apache::PageKit> is easy. It is automatically called for any page that includes a <form> tag. It can be turned on or off by using the C<fill_in_form> configuration option. =head2 Apache::ASP v2.09 and above HTML::FillInForm is now integrated with Apache::ASP. To activate, use PerlSetVar FormFill 1 $Response->{FormFill} = 1 =head1 SEE ALSO L<HTML::Parser> =head1 VERSION This documentation describes HTML::FillInForm module version 0.13. =head1 SECURITY Note that you might want to think about caching issues if you have password fields on your page. There is a discussion of this issue at http://www.perlmonks.org/index.pl?node_id=70482 In summary, some browsers will cache the output of CGI scripts, and you can control this by setting the Expires header. For example, use C<-expires> in L<CGI.pm> or set C<browser_cache> to I<no> in Config.xml file of L<Apache::PageKit>. =head1 BUGS Please submit any bug reports to [EMAIL PROTECTED] =head1 NOTES Requires Perl 5.005 and L<HTML::Parser> version 3.08. I wrote this module because I wanted to be able to insert CGI data into HTML forms, but without combining the HTML and Perl code. CGI.pm and Embperl allow you so insert CGI data into forms, but require that you mix HTML with Perl. =head1 AUTHOR (c) 2000, 2001 Thomas J. Mather, [EMAIL PROTECTED] All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 CREDITS Fixes, Bug Reports, Docs have been generously provided by: Patrick Michael Kane Tom Lancaster Martin H Sluka Jim Miner Ade Olonoh Tatsuhiko Miyagawa Mark Stosberg Paul Lindner Joseph Yanni Thanks!
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]