################################################################################ # # File name: StickyForms.pm # Project: HTML::StickyForms # # Author: Peter Haworth # Date created: 06/06/2000 # # $Id: StickyForms.pm,v 1.3 2005/10/19 16:24:20 pmh Exp $ # # Copyright Peter Haworth 2001 # You may use and distribute this module according to the same terms # that Perl is distributed under. # ################################################################################ package HTML::StickyForms; use strict; use vars qw( $VERSION ); # Use the same version as HTML::StickyForm $VERSION=0.07; ################################################################################ # Class method: new($request) # Description: Return a new HTML::StickyForms object # $request may be an instance of CGI (new or old) or Apache::Request # Author: Peter Haworth sub new{ my($class,$req)=@_; my $type; if(!$req){ $type='empty'; }elsif(UNIVERSAL::isa($req,'Apache::Request')){ $type='apreq'; }elsif(UNIVERSAL::isa($req,'CGI') || UNIVERSAL::isa($req,'CGI::State')){ $type='CGI'; }else{ # XXX Maybe this should die? return undef; } my $self=bless { req => $req, type => $type, values_as_labels => 0, well_formed => '', },$class; # Count submitted fields $self->set_sticky; $self; } ################################################################################ # Method: set_sticky([BOOL]) # Description: Count the number of parameters set in the request # Author: Peter Haworth sub set_sticky{ my $self=shift; return $self->{params}=!!$_[0] if @_; $self->{params}=()=$self->{type} eq 'empty' ? () : $self->{req}->param; } ################################################################################ # Method: values_as_labels([BOOL]) # Description: Set/Get the values_as_labels attribute # Author: Peter Haworth. Idea from Thomas Klausner (domm@zsi.at) sub values_as_labels{ my $self=shift; return $self->{values_as_labels}=$_[0] if @_; $self->{values_as_labels}; } ################################################################################ # Method: well_formed([BOOL]) # Description: Set/Get the well_formed attribute # Author: Peter Haworth sub well_formed{ my $self=shift; return !!($self->{well_formed}=$_[0] ? '/' : '') if @_; !!$self->{well_formed}; } ################################################################################ # Method: trim_params() # Description: Trim leading and trailing whitespace from all submitted values # Author: Peter Haworth sub trim_params{ my($self)=@_; my $req=$self->{req}; my $type=$self->{type}; return if $type eq 'empty'; foreach my $k($req->param){ my @v=$req->param($k); my $changed; foreach(@v){ $changed+= s/^\s+//s + s/\s+$//s; } if($changed){ if($type eq 'apreq'){ # XXX This should work, but doesn't # $req->param($k,\@v); # This does work, though if(@v==1){ $req->param($k,$v[0]); }else{ my $tab=$req->parms; $tab->unset($k); foreach(@v){ $tab->add($k,$_); } } }else{ $req->param($k,@v) } } } } ################################################################################ # Subroutine: _escape($string) # Description: Escape HTML-special characters in $string # Author: Peter Haworth sub _escape($){ $_[0]=~s/([<>&"\177-\377])/sprintf "&#%d;",ord $1/ge; } ################################################################################ # Method: text(%args) # Description: Return an HTML field # Special %args elements: # type => type attribute value, defaults to "text" # default => value attribute value, if sticky values not present # Author: Peter Haworth sub text{ my($self,%args)=@_; my $type=delete $args{type} || 'text'; my $name=delete $args{name}; my $value=delete $args{default}; $value=$self->{req}->param($name) if $self->{params}; _escape($name); _escape($value); my $field=qq({well_formed}>"; } ################################################################################ # Method: password(%args) # Description: Return an HTML field # As text() # Author: Peter Haworth sub password{ my $self=shift; $self->text(@_,type => 'password'); } ################################################################################ # Method: textarea(%args) # Description: Return an HTML "; } ################################################################################ # Method: checkbox(%args) # Description: Return a single HTML tag # Special %args elements: # checked => whether the box is checked, if sticky values not present # Author: Peter Haworth sub checkbox{ my($self,%args)=@_; my $name=delete $args{name}; my $value=delete $args{value}; my $checked=delete $args{checked}; $checked=$self->{req}->param($name) eq $value if $self->{params}; _escape($name); _escape($value); my $field=qq({well_formed}>"; } ################################################################################ # Method: checkbox_group(%args) # Description: Return a group of HTML tags # Special %args elements: # type => defaults to "checkbox" # value/values => arrayref of field values, defaults to label keys # label/labels => hashref of field names, no default # escape => whether to escape HTML characters in labels # default/defaults => arrayref of selected values, if no sticky values # linebreak => whether to add
s after each checkbox # values_as_labels => override the values_as_labels attribute # Author: Peter Haworth sub checkbox_group{ my($self,%args)=@_; my $type=delete $args{type} || 'checkbox'; my $name=delete $args{name}; my $labels=delete $args{labels} || delete $args{label} || {}; my $escape=delete $args{escape}; my $values=delete $args{values} || delete $args{value} || [keys %$labels]; my $defaults=delete $args{exists $args{defaults} ? 'defaults' : 'default'}; $defaults=[] unless defined $defaults; $defaults=[$defaults] if ref($defaults) ne 'ARRAY'; my $br=delete $args{linebreak} ? "{well_formed}>" : ''; my $v_as_l=$self->{values_as_labels}; if(exists $args{values_as_labels}){ $v_as_l=delete $args{values_as_labels}; } my %checked=map { ; $_ => 1 } $self->{params} ? $self->{req}->param($name) : @$defaults; _escape($name); my $field=qq({$value} ? $value : $labels->{$value})=~/\S/ ){ _escape($label) if $escape; $field.=$label; } $field.=$br; push @checkboxes,$field; } return @checkboxes if wantarray; return join '',@checkboxes; } ################################################################################ # Method: radio_group(%args) # Description: Return a group of HTML tags # Special %args elements: # value/values => arrayref of field values, defaults to label keys # label/labels => hashref of field labels, no default # escape => whether to escape HTML characters in labels # defaults/default => selected value, if no sticky values # linebreak => whether to add
s after each checkbox # Author: Peter Haworth sub radio_group{ my($self,%args)=@_; $self->checkbox_group(%args,type => 'radio'); } ################################################################################ # Method: select(%args) # Description: Return an HTML {$value} ? $value : $labels->{$value})=~/\S/ ){ _escape($label); $field.=$label; } $field.="\n"; } $field.=""; $field; } ################################################################################ # Return true to require 1; __END__ =head1 NAME HTML::StickyForms - HTML form generation for CGI or mod_perl =head1 SYNOPSIS # mod_perl example use HTML::StickyForms; use Apache::Request; sub handler{ my($r)=@_; $r=Apache::Request->new($r); my $f=HTML::StickyForms->new($r); $r->send_http_header; print "
", "Text field:", $f->text(name => 'field1', size => 40, default => 'default value'), "
Text area:", $f->textarea(name => 'field2', cols => 60, rows => 5, default => 'stuff'), "
Radio buttons:", $f->radio_group(name => 'field3', values => [1,2,3], labels => { 1=>'one', 2=>'two', 3=>'three' }, default => 2), "
Single checkbox:", $f->checkbox(name => 'field4', value => 'xyz', checked => 1), "
Checkbox group:", $f->checkbox_group(name => 'field5', values => [4,5,6], labels => { 4=>'four', 5=>'five', 6=>'six' }, defaults => [5,6]), "
Password field:", $f->password(name => 'field6', size => 20), '
', '
', ; return OK; } =head1 THIS MODULE IS DEPRECATED This version has exactly the same functionality as version 0.06, and exists only to provide more visibility to its successor, L. The new module tidies up a few interface inconsistencies which couldn't be done without breaking backwards compatibility with the existing module, hence the name change. The new module provides a more consistent API, which allows stickiness to be varied on a per-method basis in an obvious manner. It also diverges slightly from the previous dogma of only supplying methods which strictly benefit from stickiness, as it now provides convenience methods for generating password, hidden and submit elements, as well as the form element itself. This allows cleaner code to be written, since the whole form can now be generated using a single API. Objects created by the new module have the C attribute enabled by default, since most widely-used browsers can handle this now. Finally, the trim_params() method has been removed from the new module, since this would be better located in a module geared towards parameter validation. =head1 DESCRIPTION This module provides a simple interface for generating HTML EFORME fields, with default values chosen from the previous form submission. This module was written with mod_perl in mind, but works equally well with CGI.pm, including the new 3.x version. The module does not provide methods for generating all possible form fields, only those which benefit from having default values overridden by the previous form submission. This means that, unlike CGI.pm, there are no routines for generating EFORME tags, hidden fields or submit fields. Also this module's interface is much less flexible than CGI.pm's. This was done mainly to keep the size and complexity down. =head2 METHODS =over 4 =item HTML::StickyForms-Enew($req) Creates a new form generation object. The single argument can be an Apache::Request object, a CGI object (v2.x), a CGI::State object (v3.x), or an object of a subclass of any of the above. As a special case, if the argument is C or C<''>, the object created will behave as if a request object with no submitted fields was given. =item $f-Eset_sticky([BOOL]) If a true argument is passed, the form object will be sticky, using the request object's parameters to fill the form. If a false argument is passed, the form object will not be sticky, using the user-supplied default values to fill the form. If no argument is passed, the request object's parameters are counted, and the form object is made sticky if one or more parameters are present, non-sticky otherwise. This method is called by the constructor when a form object is created, so it is not usually necessary to call it explicitly. However, it may be necessary to call this method if parameters are set with the C method after the form object is created. =item $f-Etrim_params() Removes leading and trailing whitespace from all submitted values. =item $f-Evalues_as_labels([BOOL]) With no arguments, this method returns the C attribute. This attribute determines what to do when a value has no label in the C, C and C methods. If this attribute is false (the default), no labels will be automatically generated. If it is true, labels will default to the corresponding value if they are not supplied by the user. If an argument is passed, it is used to set the C attribute. =item $f-Ewell_formed([BOOL]) With no arguments, this method return the C attribute. This attribute determines whether to generate well-formed XML, by including the trailing slash in non-container elements. If this attribute is false, no slashes are added - this is the default, since some older browsers don't behave sensibly in the face of such elements. If true, all elements will be well-formed. If an argument is passed, it is used to set the C attribute. =item $f-Etext(%args) Generates an EINPUTE tag, with a type of C<"text">. All arguments are used directly to generate attributes for the tag, with the following exceptions: =over 8 =item type, Defaults to C<"text"> =item name, The value passed will have all HTML-special characters escaped. =item default, Specifies the default value of the field if no fields were submitted in the request object passed to C. The value used will have all HTML-special characters escaped. =back =item $f-Epassword(%args) As C, but generates a C<"password"> type field. =item $f-Etextarea(%args) Generates a ETEXTAREAE container. All arguments are used directly to generate attributes for the start tag, except for: =over 8 =item name. This value will be HTML-escaped. =item default. Specifies the default contents of the container if no fields were submitted. The value used will be HTML-escaped. =back =item $f-Echeckbox(%args) Generates a single C<"checkbox"> type EINPUTE tag. All arguments are used directly to generate attributes for the tag, except for: =over 8 =item name, value The values passed will be HTML-escaped. =item checked Specifies the default state of the field if no fields were submitted. =back =item $f-Echeckbox_group(%args) Generates a group of C<"checkbox"> type EINPUTE tags. If called in list context, returns a list of tags, otherwise a single string containing all tags. All arguments are used directly to generate attributes in each tag, except for the following: =over 8 =item type Defaults to C<"checkbox">. =item name This value will be HTML-escaped. =item values, or value An arrayref of values. One tag will be generated for each element. The values will be HTML-escaped. Defaults to label keys. =item labels, or label A hashref of labels. Each tag generated will be followed by the label keyed by the value. If no label is present for a given value, no label will be generated. Defaults to an empty hashref. =item escape If this value is true, the labels will be HTML-escaped. =item defaults, or default A single value or arrayref of values to be checked if no fields were submitted. Defaults to an empty arrayref. =item linebreak If true, each tag/label will be followed by a EBRE tag. =item values_as_labels Overrides the form object's C attribute. =back =item $f-Eradio_group(%args) As C, but generates C<"radio"> type tags. =item $f-Eselect(%args) Generates a ESELECTE tags. All arguments are used directly to generate attributes in the ESELECTE tag, except for the following: =over 8 =item name: This value will be HTML-escaped. =item values or value An arrayref of values. One EOPTIONE tag will be created inside the ESELECTE tag for each element. The values will be HTML-escaped. Defaults to label keys. =item labels or label A hashref of labels. Each EOPTIONE tag generated will contain the label keyed by its value. If no label is present for a given value, no label will be generated. Defaults to an empty hashref. =item defaults or default A single value or arrayref of values to be selected if no fields were submitted. Defaults to an empty arrayref. =item multiple If a true value is passed, the C attribute is set. =item values_as_labels, Overrides the form object's C attribute. =back =back =head1 AUTHOR Copyright (C) Institute of Physics Publishing 2000-2005 Peter Haworth You may use and distribute this module according to the same terms that Perl is distributed under.