diff --git a/docs/gotcha.txt b/docs/gotcha.txt
index 707712bc8..58fdbe16d 100644
--- a/docs/gotcha.txt
+++ b/docs/gotcha.txt
@@ -7,6 +7,14 @@ upgrading from one version to the next, or even between multiple
versions. Be sure to heed the warnings contained herein as they will
save you many hours of grief.
+4.7.0
+--------------------------------------------------------------------
+ * WebGUI::HTMLForm->radioList has been changed to correct an API
+ error. However, if your applications use this method, this
+ change will break your application. If you do not use any
+ third-party or custom plug-ins, you can disregard this
+ warning.
+
4.6.3
--------------------------------------------------------------------
* It has been reported that some people had a duplicate key error
@@ -17,7 +25,6 @@ save you many hours of grief.
patches, or just moving forward. Either way will produce
the same result.
-
4.6.0
--------------------------------------------------------------------
* The runHourly scheduler has been updated to allow for more
diff --git a/lib/WebGUI/Form.pm b/lib/WebGUI/Form.pm
new file mode 100644
index 000000000..01844fee5
--- /dev/null
+++ b/lib/WebGUI/Form.pm
@@ -0,0 +1,1196 @@
+package WebGUI::Form;
+
+=head1 LEGAL
+
+ -------------------------------------------------------------------
+ WebGUI is Copyright 2001-2002 Plain Black LLC.
+ -------------------------------------------------------------------
+ Please read the legal notices (docs/legal.txt) and the license
+ (docs/license.txt) that came with this distribution before using
+ this software.
+ -------------------------------------------------------------------
+ http://www.plainblack.com info@plainblack.com
+ -------------------------------------------------------------------
+
+=cut
+
+use strict;
+use WebGUI::DateTime;
+use WebGUI::International;
+use WebGUI::Session;
+use WebGUI::SQL;
+use WebGUI::URL;
+
+=head1 NAME
+
+ Package WebGUI::Form
+
+=head1 SYNOPSIS
+
+ use WebGUI::Form;
+
+ WebGUI::Form::checkbox({name=>"whichOne", value=>"red"});
+ WebGUI::Form::checkList({name=>"dayOfWeek", options=>\%days});
+ WebGUI::Form::combo({name=>"fruit",options=>\%fruit});
+ WebGUI::Form::date({name=>"endDate", value=>$endDate});
+ WebGUI::Form::email({name=>"emailAddress"});
+ WebGUI::Form::file({name=>"image"});
+ WebGUI::Form::group({name=>"groupToPost"});
+ WebGUI::Form::hidden({name=>"wid",value=>"55"});
+ WebGUI::Form::HTMLArea({name=>"description"});
+ WebGUI::Form::integer({name=>"size"});
+ WebGUI::Form::interval({name=>"timeToLive", interval=>12, units=>"hours"});
+ WebGUI::Form::password({name=>"identifier"});
+ WebGUI::Form::phone({name=>"cellPhone"});
+ WebGUI::Form::radio({name=>"whichOne", value=>"red"});
+ WebGUI::Form::radioList({name="dayOfWeek", options=>\%days});
+ WebGUI::Form::selectList({name=>"dayOfWeek", options=>\%days, value=>\@array"});
+ WebGUI::Form::submit;
+ WebGUI::Form::text({name=>"firstName"});
+ WebGUI::Form::textarea({name=>"emailMessage"});
+ WebGUI::Form::url({name=>"homepage"});
+ WebGUI::Form::yesNo({name=>"happy"});
+ WebGUI::Form::zipcode({name=>"workZip"});
+
+=head1 DESCRIPTION
+
+ Base forms package. Eliminates some of the normal code work that goes
+ along with creating forms. Used by the PowerForm package.
+
+=head1 METHODS
+
+ All of the functions in this package accept the input of a hash
+ reference containing the parameters to populate the form element.
+ These functions are available from this package:
+
+=cut
+
+#-------------------------------------------------------------------
+sub _fixQuotes {
+ my $value = shift;
+ $value =~ s/\"/\"\;/g;
+ return $value;
+}
+
+#-------------------------------------------------------------------
+
+=head2 checkbox ( hashRef )
+
+ Returns a checkbox form element.
+
+=item name
+
+ The name field for this form element.
+
+=item checked
+
+ If you'd like this box to be defaultly checked, set this to "1".
+
+=item value
+
+ The default value for this form element. Defaults to "1".
+
+=item extras
+
+ If you want to add anything special to this form element like
+ javascript actions, or stylesheet information, you'd add it in
+ here as follows:
+
+ 'onChange="this.form.submit()"'
+
+=cut
+
+sub checkbox {
+ my ($checkedText, $value);
+ $checkedText = ' checked="1"' if ($_[0]->{checked});
+ $value = $_[0]->{value} || 1;
+ return '{extras}.'>';
+}
+
+#-------------------------------------------------------------------
+
+=head2 checkList ( hashRef )
+
+ Returns checkbox list.
+
+=item name
+
+ The name field for this form element.
+
+=item options
+ The list of options for this list. Should be passed as a
+ hash reference.
+
+=item value
+
+ The default value(s) for this form element. This should be passed
+ as an array reference.
+
+=item vertical
+
+ If set to "1" the radio button elements will be laid out
+ horizontally. Defaults to "0".
+
+=item extras
+
+ If you want to add anything special to this form element like
+ javascript actions, or stylesheet information, you'd add it in
+ here as follows:
+
+ 'onChange="this.form.submit()"'
+
+=cut
+
+sub checkList {
+ my ($output, $checked, $key, $item);
+ foreach $key (keys %{$_[0]->{options}}) {
+ $checked = 0;
+ foreach $item (@{$_[0]->{value}}) {
+ if ($item eq $key) {
+ $checked = 1;
+ }
+ }
+ $output .= checkbox({
+ name=>$_[0]->{name},
+ value=>$key,
+ extras=>$_[0]->{extras},
+ checked=>$checked
+ });
+ $output .= ${$_[0]->{options}}{$key}.' ';
+ $output .= ' ' if ($_[0]->{vertical});
+ }
+ return $output;
+}
+
+#-------------------------------------------------------------------
+
+=head2 combo ( hashRef )
+
+ Returns a select list and a text field. If the
+ text box is filled out it will have a value stored in "name"_new.
+
+=item name
+
+ The name field for this form element.
+
+=item options
+ The list of options for the select list. Should be passed as a
+ hash reference.
+
+=item value
+
+ The default value(s) for this form element. This should be passed
+ as an array reference.
+
+=item size
+
+ The number of characters tall this form element should be. Defaults
+ to "1".
+
+=item multiple
+
+ A boolean value for whether this select list should allow multiple
+ selections. Defaults to "0".
+
+=item extras
+
+ If you want to add anything special to this form element like
+ javascript actions, or stylesheet information, you'd add it in
+ here as follows:
+
+ 'onChange="this.form.submit()"'
+
+=cut
+
+sub combo {
+ my ($output, $size);
+ $_[0]->{options}->{''} = '['.WebGUI::International::get(582).']';
+ $_[0]->{options}->{_new_} = WebGUI::International::get(581).'->';
+ $output = selectList({
+ name=>$_[0]->{name},
+ value=>$_[0]->{value},
+ multiple=>$_[0]->{multiple},
+ extras=>$_[0]->{extras}
+ });
+ $size = $session{setting}{textBoxSize}-5;
+ $output .= text({name=>$_[0]->{name}."_new",size=>$size});
+ return $output;
+}
+
+#-------------------------------------------------------------------
+
+=head2 date ( hashRef )
+
+ Returns a date field.
+
+=item name
+
+ The name field for this form element.
+
+=item value
+
+ The default date. Pass as an epoch value. Defaults to today.
+
+=item extras
+
+ If you want to add anything special to this form element like
+ javascript actions, or stylesheet information, you'd add it in
+ here as follows:
+
+ 'onChange="this.form.submit()"'
+
+=item size
+
+ The number of characters wide this form element should be. There
+ should be no reason for anyone to specify this.
+
+=item noDate
+
+ By default a date is placed in the "value" field. Set this to "1"
+ to turn off the default date.
+
+=cut
+
+sub date {
+ my ($subtext, $noDate, $class, $output, $name, $label, $extras, $size, $value);
+ $value = epochToSet($_[0]->{value});
+ $size = $_[0]->{size} || 10;
+ $value = "" if ($_[0]->{noDate});
+ $output = text({
+ name=>$_[0]->{name},
+ value=>$value,
+ size=>$size,
+ maxlength=>10,
+ extras=>$_[0]->{extras}
+ });
+ $output .= '';
+ return $output;
+}
+
+
+
+#-------------------------------------------------------------------
+
+=head2 email ( hashRef )
+
+ Adds an email address row to this form.
+
+=item name
+
+ The name field for this form element.
+
+=item value
+
+ The default value for this form element.
+
+=item maxlength
+
+ The maximum number of characters to allow in this form element.
+
+=item extras
+
+ If you want to add anything special to this form element like
+ javascript actions, or stylesheet information, you'd add it in
+ here as follows:
+
+ 'onChange="this.form.submit()"'
+
+=item size
+
+ The number of characters wide this form element should be. There
+ should be no reason for anyone to specify this.
+
+=cut
+
+sub email {
+ my ($output);
+ $output = '';
+ $output .= text({
+ name=>$_[0]->{name},
+ value=>$_[0]->{value},
+ extras=>' onChange="emailCheck(this.value)" '.$_[0]->{extras}
+ });
+ return $output;
+}
+
+
+#-------------------------------------------------------------------
+
+=head2 file ( hashRef )
+
+ Returns a file upload field.
+
+=item name
+
+ The name field for this form element.
+
+=item extras
+
+ If you want to add anything special to this form element like
+ javascript actions, or stylesheet information, you'd add it in
+ here as follows:
+
+ 'onChange="this.form.submit()"'
+
+=item size
+
+ The number of characters wide this form element should be. There
+ should be no reason for anyone to specify this.
+
+=cut
+
+sub file {
+ my ($size);
+ $size = $_[0]->{size} || $session{setting}{textBoxSize} || 30;
+ return '{extras}.'>';
+}
+
+#-------------------------------------------------------------------
+
+=head2 formHeader ( hashRef )
+
+ Returns a form header.
+
+=item action
+
+ The form action. Defaults to the current page.
+
+=item method
+
+ The form method. Defaults to "POST".
+
+=item enctype
+
+ The form enctype. Defaults to "multipart/form-data".
+
+=item extras
+
+ If you want to add anything special to the form header like
+ javascript actions or stylesheet info, then use this.
+
+=cut
+
+sub formHeader {
+ my ($action, $method, $enctype);
+ $action = $_[0]->{action} || WebGUI::URL::page();
+ $method = $_[0]->{method} || "POST";
+ $enctype = $_[0]->{enctype} || "multipart/form-data";
+ return '
';
- bless {_noTable => $noTable, _header => $header, _footer => $footer, _data => ''}, $class;
+ bless {_noTable => $noTable, _header => $header, _footer => $footer, _data => ''}, $self;
}
#-------------------------------------------------------------------
-=head2 password ( name [ label, value, subtext, maxlength, extras, size ] )
+=head2 password ( name [ label, value, subtext, maxlength, extras, size, uiLevel ] )
Adds a password row to this form.
@@ -935,29 +966,40 @@ sub new {
should be no reason for anyone to specify this. Defaults to "30"
unless overridden in the settings.
+=item uiLevel
+
+ The UI level for this field. See the WebGUI developer's site for
+ details. Defaults to "0".
+
=cut
sub password {
- my ($subtext, $class, $output, $name, $label, $extras, $size, $maxLength, $value);
- $class = shift;
- $name = shift;
- $label = shift;
- $value = shift;
- $value = _fixQuotes($value);
- $subtext = shift;
- $maxLength = shift || 35;
- $extras = shift;
- $size = shift || $session{setting}{textBoxSize} || 30;
- $output = '';
- $output .= _subtext($subtext);
- $output = _tableFormRow($label,$output) unless ($class->{_noTable});
- $class->{_data} .= $output;
+ my ($output);
+ my ($self, @p) = @_;
+ my ($name, $label, $value, $subtext, $maxlength, $extras, $size, $uiLevel) =
+ rearrange([name, label, value, subtext, maxlength, extras, size, uiLevel], @p);
+ if (_uiLevelChecksOut($uiLevel)) {
+ $output = WebGUI::Form::password({
+ name=>$name,
+ value=>$value,
+ size=>$size,
+ maxlength=>$maxlength,
+ extras=>$extras
+ });
+ $output .= _subtext($subtext);
+ $output = $self->_tableFormRow($label,$output);
+ } else {
+ $output = WebGUI::Form::hidden({
+ name=>$name.'_interval',
+ value=>$value
+ });
+ }
+ $self->{_data} .= $output;
}
#-------------------------------------------------------------------
-=head2 phone ( name [ label, value, maxlength, extras, subtext, size ] )
+=head2 phone ( name [ label, value, maxlength, extras, subtext, size, uiLevel ] )
Adds a text row to this form.
@@ -995,24 +1037,35 @@ sub password {
The number of characters wide this form element should be. There
should be no reason for anyone to specify this.
+=item uiLevel
+
+ The UI level for this field. See the WebGUI developer's site for
+ details. Defaults to "0".
+
=cut
sub phone {
- my ($subtext, $class, $output, $name, $label, $extras, $size, $maxLength, $value);
- $class = shift;
- $name = shift;
- $label = shift;
- $value = shift;
- $value = _fixQuotes($value);
- $maxLength = shift || 30;
- $extras = shift;
- $subtext = shift;
- $size = shift || $session{setting}{textBoxSize} || 30;
- $output .= '';
- $output .= _subtext($subtext);
- $output = _tableFormRow($label,$output) unless ($class->{_noTable});
- $class->{_data} .= $output;
+ my ($output);
+ my ($self, @p) = @_;
+ my ($name, $label, $value, $maxlength, $extras, $subtext, $size, $uiLevel) =
+ rearrange([name, label, value, maxlength, extras, subtext, size, uiLevel], @p);
+ if (_uiLevelChecksOut($uiLevel)) {
+ $output = WebGUI::Form::phone({
+ name=>$name,
+ value=>$value,
+ size=>$size,
+ maxlength=>$maxlength,
+ extras=>$extras
+ });
+ $output .= _subtext($subtext);
+ $output = $self->_tableFormRow($label,$output);
+ } else {
+ $output = WebGUI::Form::hidden({
+ name=>$name.'_interval',
+ value=>$value
+ });
+ }
+ $self->{_data} .= $output;
}
#-------------------------------------------------------------------
@@ -1024,9 +1077,7 @@ sub phone {
=cut
sub print {
- my ($class);
- $class = shift;
- return $class->{_header}.$class->{_data}.$class->{_footer};
+ return $_[0]->{_header}.$_[0]->{_data}.$_[0]->{_footer};
}
#-------------------------------------------------------------------
@@ -1039,14 +1090,12 @@ sub print {
=cut
sub printRowsOnly {
- my ($class);
- $class = shift;
- return $class->{_data};
+ return $_[0]->{_data};
}
#-------------------------------------------------------------------
-=head2 radio ( name [ label, checked, value, subtext, extras ] )
+=head2 radio ( name [ label, checked, value, subtext, extras, uiLevel ] )
Adds a radio button row to this form.
@@ -1079,27 +1128,41 @@ sub printRowsOnly {
'onChange="this.form.submit()"'
+=item uiLevel
+
+ The UI level for this field. See the WebGUI developer's site for
+ details. Defaults to "0".
+
=cut
sub radio {
- my ($subtext, $checkedText, $class, $output, $name, $label, $extras, $checked, $value);
- $class = shift;
- $name = shift;
- $label = shift;
- $checked = shift;
- $checkedText = ' checked="1"' if ($checked);
- $value = shift;
- $subtext = shift;
- $extras = shift;
- $output = '';
- $output .= _subtext($subtext);
- $output = _tableFormRow($label,$output) unless ($class->{_noTable});
- $class->{_data} .= $output;
+ my ($output);
+ my ($self, @p) = @_;
+ my ($name, $label, $checked, $value, $subtext, $extras, $uiLevel) =
+ rearrange([name, label, checked, value, subtext, extras, uiLevel], @p);
+ if (_uiLevelChecksOut($uiLevel)) {
+ $output = WebGUI::Form::checkbox({
+ name=>$name,
+ value=>$value,
+ checked=>$checked,
+ extras=>$extras
+ });
+ $output .= _subtext($subtext);
+ $output = $self->_tableFormRow($label,$output);
+ } else {
+ if ($checked) {
+ $output = WebGUI::Form::hidden({
+ name=>$name,
+ value=>$value
+ });
+ }
+ }
+ $self->{_data} .= $output;
}
#-------------------------------------------------------------------
-=head2 radioList ( name, options [ label, value, vertical, extras, subtext ] )
+=head2 radioList ( name, options [ label, value, vertical, extras, subtext, uiLevel ] )
Adds a radio button list row to this form.
@@ -1108,6 +1171,7 @@ sub radio {
The name field for this form element.
=item options
+
The list of options for this list. Should be passed as a
hash reference.
@@ -1117,8 +1181,7 @@ sub radio {
=item value
- The default value(s) for this form element. This should be passed
- as an array reference.
+ The default value for this form element.
=item vertical
@@ -1138,52 +1201,64 @@ sub radio {
Extra text to describe this form element or to provide special
instructions.
+=item uiLevel
+
+ The UI level for this field. See the WebGUI developer's site for
+ details. Defaults to "0".
+
=cut
sub radioList {
- my ($label, $subtext, $class, $output, $vertical, $value, $key, $item, $name, $options, $extras);
- $class = shift;
- $name = shift;
- $options = shift;
- $label = shift;
- $value = shift;
- $vertical = shift;
- $extras = shift;
- $subtext = shift;
- foreach $key (keys %{$options}) {
- $output .= ''.${$options}{$key}.' ';
- $output .= ' ' if ($vertical);
+ my ($output);
+ my ($self, @p) = @_;
+ my ($name, $options, $label, $value, $vertical, $extras, $subtext, $uiLevel) =
+ rearrange([name, options, label, value, vertical, extras, subtext, uiLevel], @p);
+ if (_uiLevelChecksOut($uiLevel)) {
+ $output = WebGUI::Form::checkList({
+ name=>$name,
+ options=>$options,
+ value=>$value,
+ vertical=>$vertical,
+ extras=>$extras
+ });
+ $output .= _subtext($subtext);
+ $output = $self->_tableFormRow($label,$output);
+ } else {
+ hiddenList({
+ options=>$options,
+ value=>[$value]
+ });
}
- $output .= _subtext($subtext);
- $output = _tableFormRow($label,$output) unless ($class->{_noTable});
- $class->{_data} .= $output;
+ $self->{_data} .= $output;
}
#-------------------------------------------------------------------
-=head2 raw ( value )
+=head2 raw ( value, uiLevel )
Adds raw data to the form. This is primarily useful with the
printRowsOnly method and if you generate your own form elements.
+=item uiLevel
+
+ The UI level for this field. See the WebGUI developer's site for
+ details. Defaults to "0".
+
=cut
sub raw {
- my ($class, $output, $value);
- $class = shift;
- $value = shift;
- $class->{_data} .= $value;
+ my ($output);
+ my ($self, @p) = @_;
+ my ($value, $uiLevel) = rearrange([value, uiLevel], @p);
+ if (_uiLevelChecksOut($uiLevel)) {
+ $self->{_data} .= $value;
+ }
+ $self->{_data} .= $output;
}
#-------------------------------------------------------------------
-=head2 readOnly ( value [ label, subtext ] )
+=head2 readOnly ( value [ label, subtext, uiLevel ] )
Adds a read only row to this form. This is mainly used for
displaying not editable properties, but it can also be used to
@@ -1202,23 +1277,29 @@ sub raw {
Extra text to describe this form element or to provide special
instructions.
+=item uiLevel
+
+ The UI level for this field. See the WebGUI developer's site for
+ details. Defaults to "0".
+
=cut
sub readOnly {
- my ($output, $subtext, $class, $label, $value);
- $class = shift;
- $value = shift;
- $label = shift;
- $subtext = shift;
- $output = $value;
- $output .= _subtext($subtext);
- $output = _tableFormRow($label,$output) unless ($class->{_noTable});
- $class->{_data} .= $output;
+ my ($output);
+ my ($self, @p) = @_;
+ my ($value, $label, $subtext, $uiLevel) =
+ rearrange([value, label, subtext, uiLevel], @p);
+ if (_uiLevelChecksOut($uiLevel)) {
+ $output = $value;
+ $output .= _subtext($subtext);
+ $output = $self->_tableFormRow($label,$output);
+ }
+ $self->{_data} .= $output;
}
#-------------------------------------------------------------------
-=head2 select ( name, options [ label, value, size, multiple, extras, subtext ] )
+=head2 select ( name, options [ label, value, size, multiple, extras, subtext, uiLevel ] )
Adds a select list row to this form.
@@ -1262,34 +1343,36 @@ sub readOnly {
Extra text to describe this form element or to provide special
instructions.
+=item uiLevel
+
+ The UI level for this field. See the WebGUI developer's site for
+ details. Defaults to "0".
+
=cut
sub select {
- my ($label, $subtext, $class, $output, $value, $key, $item, $name, $options, $size, $multiple, $extras);
- $class = shift;
- $name = shift;
- $options = shift;
- $label = shift;
- $value = shift;
- $size = shift || 1;
- $multiple = shift;
- $multiple = ' multiple="1"' if ($multiple);
- $extras = shift;
- $subtext = shift;
- $output = '