591 lines
15 KiB
Perl
591 lines
15 KiB
Perl
package WebGUI::Form::Control;
|
|
|
|
=head1 LEGAL
|
|
|
|
-------------------------------------------------------------------
|
|
WebGUI is Copyright 2001-2006 Plain Black Corporation.
|
|
-------------------------------------------------------------------
|
|
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::Grouping;
|
|
use WebGUI::Session;
|
|
use WebGUI::Operation::Shared;
|
|
|
|
=head1 NAME
|
|
|
|
Package WebGUI::Form::Control
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
Base class for all form field objects. Never use this class directly.
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
use base 'WebGUI::Form::Control';
|
|
|
|
...your methods here...
|
|
|
|
Subclasses will look like this:
|
|
|
|
use WebGUI::Form::subclass;
|
|
my $obj = WebGUI::Form::subclass->new(%params);
|
|
|
|
my $html = $obj->toHtml;
|
|
my $html = $obj->toHtmlAsHidden;
|
|
my $tableRows = $obj->toHtmlWithWrapper;
|
|
|
|
=head1 METHODS
|
|
|
|
The following methods are available via this package.
|
|
|
|
=cut
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 definition ( [ additionalTerms ] )
|
|
|
|
Defines the schema or parameters for a form field.
|
|
|
|
=head3 additionalTerms
|
|
|
|
An array reference containing a hash of hashes of parameter names and their definitions.
|
|
|
|
Example:
|
|
|
|
[{
|
|
myParam=>{
|
|
defaultValue=>undef
|
|
}
|
|
}]
|
|
|
|
By default all form fields have the following parameters:
|
|
|
|
=head4 name
|
|
|
|
The field name.
|
|
|
|
=head4 value
|
|
|
|
The starting value for the field.
|
|
|
|
=head4 defaultValue
|
|
|
|
If no starting value is specified, this will be used instead.
|
|
|
|
=head4 _defaulted
|
|
|
|
This flag indicates that the defaultValue was used. It is used by Form types that support
|
|
an initial blank field, instead of using a default, like WebGUI::Form::Date.pm
|
|
|
|
=head4 extras
|
|
|
|
Add extra attributes to the form tag like
|
|
|
|
onmouseover='doSomething()'
|
|
|
|
=head4 formName
|
|
|
|
The internationalized form name.
|
|
|
|
=head4 label
|
|
|
|
A text label that will be displayed if toHtmlWithWrapper() is called.
|
|
|
|
=head4 id
|
|
|
|
A unique identifier that can be used to identify this field with javascripts and cascading style sheets. Is autogenerated if not specified. The autogenerated version is the value of the name parameter concatinated with the string "_formId". So for a field called "title" it would be "title_formId".
|
|
|
|
=head4 idPrefix
|
|
|
|
If specified, this will be prepended to the id (whether autogenerated or not) to prevent overlap of two similar forms on the same page.
|
|
|
|
=head4 uiLevel
|
|
|
|
The UI Level that the user must meet or exceed if this field should be displayed with toHtmlWithWrapper() is called.
|
|
|
|
=head4 uiLevelOverride
|
|
|
|
An identifier that will be grabbed from the config file to determine the uiLevel. If the uiLevelOverride is "Article" and the name is "title" then the entry in the config file would look like:
|
|
|
|
Article_uiLevel = title => 5
|
|
|
|
=head4 subtext
|
|
|
|
A text string that will be appended after the field when toHtmlWithWrapper() is called.
|
|
|
|
=head4 labelClass
|
|
|
|
A stylesheet class assigned to the label with toHtmlWithWrapper() is called. Defaults to "formDescription".
|
|
|
|
=head4 fieldClass
|
|
|
|
A stylesheet class assigned to wrapper the field when toHtmlWithWrapper() is called. Defaults to "tableData".
|
|
|
|
=head4 rowClass
|
|
|
|
A stylesheet class assigned to each label/field pair.
|
|
|
|
=head4 hoverHelp
|
|
|
|
A text string that will pop up when the user hovers over the label when toHtmlWithWrapper() is called. This string should indicate how to use the field and is usually tied into the help system.
|
|
|
|
=head4 profileEnabled
|
|
|
|
Flag that tells the User Profile system that this is a valid form element in a User Profile
|
|
|
|
=cut
|
|
|
|
sub definition {
|
|
my $class = shift;
|
|
my $definition = shift || [];
|
|
push(@{$definition}, {
|
|
formName=>{
|
|
defaultValue=>'A name for this form was not supplied'
|
|
},
|
|
name=>{
|
|
defaultValue=>undef
|
|
},
|
|
value=>{
|
|
defaultValue=>undef
|
|
},
|
|
extras=>{
|
|
defaultValue=>undef
|
|
},
|
|
defaultValue=>{
|
|
defaultValue=>undef
|
|
},
|
|
_defaulted=>{
|
|
defaultValue=>0
|
|
},
|
|
label=>{
|
|
defaultValue=>undef
|
|
},
|
|
uiLevel=>{
|
|
defaultValue=>1
|
|
},
|
|
uiLevelOverride=>{
|
|
defaultValue=>undef
|
|
},
|
|
labelClass=>{
|
|
defaultValue=>"formDescription"
|
|
},
|
|
fieldClass=>{
|
|
defaultValue=>"tableData"
|
|
},
|
|
rowClass=>{
|
|
defaultValue=>undef
|
|
},
|
|
hoverHelp=>{
|
|
defaultValue=>undef
|
|
},
|
|
subtext=>{
|
|
defaultValue=>undef
|
|
},
|
|
id=>{
|
|
defaultValue=>undef
|
|
},
|
|
idPrefix=>{
|
|
defaultValue=>undef
|
|
},
|
|
profileEnabled=>{
|
|
defaultValue=>0
|
|
},
|
|
});
|
|
return $definition;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 displayForm ( )
|
|
|
|
This utility method is used to format values for the Profile system but can
|
|
be used in other areas as well. Most form elements will just return toHtml.
|
|
|
|
=cut
|
|
|
|
sub displayForm {
|
|
my ($self) = @_;
|
|
$self->toHtml;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 displayFormWithWrapper ( )
|
|
|
|
This utility method is used to format values for the Profile system but can
|
|
be used in other areas as well. Most form elements will just return displayForm.
|
|
|
|
=cut
|
|
|
|
sub displayFormWithWrapper {
|
|
my $self = shift;
|
|
if ($self->passUiLevelCheck) {
|
|
my ($fieldClass, $rowClass, $labelClass, $hoverHelp, $subtext) = $self->prepareWrapper;
|
|
return '<tr'.$rowClass.'>
|
|
<td'.$labelClass.$hoverHelp.' valign="top" style="width: 25%;">'.$self->get("label").'</td>
|
|
<td valign="top"'.$fieldClass.' style="width: 75%;">'.$self->displayForm().$subtext."</td>
|
|
</tr>\n";
|
|
} else {
|
|
return $self->toHtmlAsHidden;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 displayValue ( )
|
|
|
|
This utility method is used to format values for the Profile system. Most
|
|
form elements will just return their value.
|
|
|
|
=cut
|
|
|
|
sub displayValue {
|
|
my ($self) = @_;
|
|
return $self->get("value");
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 generateIdParameter ( name )
|
|
|
|
A class method that returns a value to be used as the autogenerated ID for this field instance. Unless overriden, it simply returns the name with "_formId" appended to it.
|
|
|
|
=head3 name
|
|
|
|
The name of the field.
|
|
|
|
=cut
|
|
|
|
sub generateIdParameter {
|
|
my $class = shift;
|
|
my $name = shift;
|
|
return $name."_formId";
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 get ( var )
|
|
|
|
Returns a property of this form object.
|
|
|
|
=head3 var
|
|
|
|
The variable name of the value to return.
|
|
|
|
=cut
|
|
|
|
sub get {
|
|
my $self = shift;
|
|
my $var = shift;
|
|
return $self->{_params}{$var};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getName ( )
|
|
|
|
Returns a human readable name for this form control type. You MUST override this method with your own when creating new form controls.
|
|
|
|
=cut
|
|
|
|
sub getName {
|
|
my $self = shift;
|
|
my $definition = $self->definition;
|
|
return $definition->[0]->{formName}->{defaultValue};
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 fixMacros ( string )
|
|
|
|
Returns the string having converted all macros in the string to HTML entities so that they won't be processed my the macro engine, but instead will be displayed.
|
|
|
|
=head3 string
|
|
|
|
The string to search for macros in.
|
|
|
|
=cut
|
|
|
|
sub fixMacros {
|
|
my $self = shift;
|
|
my $value = shift;
|
|
$value =~ s/\^/\&\#94\;/g;
|
|
return $value;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 fixQuotes ( string )
|
|
|
|
Returns the string having replaced quotes with HTML entities. This is important so not to screw up HTML attributes which use quotes as delimiters.
|
|
|
|
=head3 string
|
|
|
|
The string to search for quotes in.
|
|
|
|
=cut
|
|
|
|
sub fixQuotes {
|
|
my $self = shift;
|
|
my $value = shift;
|
|
$value =~ s/\"/\"\;/g;
|
|
return $value;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 fixSpecialCharacters ( string )
|
|
|
|
Returns a string having converted any characters that have special meaning in HTML to HTML entities. Currently the only character is ampersand.
|
|
|
|
=head3 string
|
|
|
|
The string to search for special characters in.
|
|
|
|
=cut
|
|
|
|
sub fixSpecialCharacters {
|
|
my $self = shift;
|
|
my $value = shift;
|
|
$value =~ s/\&/\&\;/g;
|
|
return $value;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 fixTags ( string )
|
|
|
|
Returns a string having converted HTML tags into HTML entities. This is useful when you have HTML that you need to render inside of a <textarea> for instance.
|
|
|
|
=head3 string
|
|
|
|
The string to search for HTML tags in.
|
|
|
|
=cut
|
|
|
|
sub fixTags {
|
|
my $self = shift;
|
|
my $value = shift;
|
|
$value =~ s/\</\<\;/g;
|
|
$value =~ s/\>/\>\;/g;
|
|
return $value;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getValueFromPost ( )
|
|
|
|
Retrieves a value from a form GET or POST and returns it. If the value comes back as undef, this method will return the defaultValue instead.
|
|
|
|
=cut
|
|
|
|
sub getValueFromPost {
|
|
my $self = shift;
|
|
my $formValue = $self->session->request->param($self->get("name"));
|
|
if (defined $formValue) {
|
|
return $formValue;
|
|
} else {
|
|
return $self->get("defaultValue");
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 new ( session, parameters )
|
|
|
|
Constructor. Creates a new form field object.
|
|
|
|
=head3 session
|
|
|
|
A reference to the current session.
|
|
|
|
=head3 parameters
|
|
|
|
Accepts any parameters specified by the definition() method. This parameter set can be specified by either a hash or hash reference, and can be tagged or not. Here are examples:
|
|
|
|
my $obj = $class->new({ name=>"this", value=>"that"});
|
|
my $obj = $class->new({ -name=>"this", -value=>"that"});
|
|
my $obj = $class->new(name=>"this", value=>"that");
|
|
my $obj = $class->new(-name=>"this", -value=>"that");
|
|
|
|
Please note that an id attribute is automatically added to every form element with a name of name_formId. So if your form element has a name of "description" then the id attribute assigned to it would be "description_formId".
|
|
|
|
=cut
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
my $session = shift;
|
|
my %raw;
|
|
# deal with a hash reference full of properties
|
|
if (ref $_[0] eq "HASH") {
|
|
%raw = %{$_[0]};
|
|
} else {
|
|
%raw = @_;
|
|
}
|
|
my %params;
|
|
foreach my $definition (reverse @{$class->definition}) {
|
|
foreach my $fieldName (keys %{$definition}) {
|
|
my $value = $raw{$fieldName};
|
|
# if we have no value, try the tagged name
|
|
unless (defined $value) {
|
|
$value = $raw{"-".$fieldName};
|
|
}
|
|
# if we still have no value try the default value for the field
|
|
unless (defined $value) {
|
|
$value = $definition->{$fieldName}{defaultValue};
|
|
}
|
|
# and finally, if we have a value, let's set it
|
|
if (defined $value) {
|
|
$params{$fieldName} = $value;
|
|
}
|
|
}
|
|
}
|
|
# if the value field is undefined, lets use the defaultValue field instead
|
|
# the _defaulted field is used to tell form fields that support noDate/noValue
|
|
# options whether the field can be safely cleared or not.
|
|
unless (exists $params{value}) {
|
|
$params{value} = $params{defaultValue};
|
|
$params{_defaulted} = 1;
|
|
}
|
|
# doesn't have an id specified, so let's give it one
|
|
unless ($params{id}) {
|
|
$params{id} = $class->generateIdParameter($params{name});
|
|
}
|
|
# preventing ID collisions
|
|
$params{id} = $params{idPrefix}.$params{id};
|
|
bless {_session=>$session, _params=>\%params}, $class;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 prepareWrapper ( )
|
|
|
|
Common code for preparing wrappers for *WithWrapper
|
|
|
|
=cut
|
|
|
|
sub prepareWrapper {
|
|
my $self = shift;
|
|
my $rowClass = $self->get("rowClass");
|
|
$rowClass = qq| class="$rowClass" | if($self->get("rowClass"));
|
|
my $labelClass = $self->get("labelClass");
|
|
$labelClass = qq| class="$labelClass" | if($self->get("labelClass"));
|
|
my $fieldClass = $self->get("fieldClass");
|
|
$fieldClass = qq| class="$fieldClass" | if($self->get("fieldClass"));
|
|
my $hoverHelp = $self->get("hoverHelp");
|
|
$hoverHelp =~ s/\r/ /g;
|
|
$hoverHelp =~ s/\n/ /g;
|
|
$hoverHelp =~ s/&/& amp;/g;
|
|
$hoverHelp =~ s/>/& gt;/g;
|
|
$hoverHelp =~ s/</& lt;/g;
|
|
$hoverHelp =~ s/&/&/g;
|
|
$hoverHelp =~ s/>/>/g;
|
|
$hoverHelp =~ s/</</g;
|
|
$hoverHelp =~ s/"/"/g;
|
|
$hoverHelp =~ s/'/\\'/g;
|
|
$hoverHelp =~ s/^\s+//;
|
|
$hoverHelp = qq| onmouseover="return escape('$hoverHelp')"| if ($hoverHelp);
|
|
my $subtext = $self->get("subtext");
|
|
$subtext = qq| <span class="formSubtext">$subtext</span>| if ($subtext);
|
|
return ($fieldClass, $rowClass, $labelClass, $hoverHelp, $subtext);
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 session ( )
|
|
|
|
Returns a reference to the session.
|
|
|
|
=cut
|
|
|
|
sub session {
|
|
my $self = shift;
|
|
return $self->{_session};
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 toHtml ( )
|
|
|
|
Renders the form field to HTML. This method should be overridden by all subclasses.
|
|
|
|
=cut
|
|
|
|
sub toHtml {
|
|
my $self = shift;
|
|
return $self->get("value");
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 toHtmlAsHidden ( )
|
|
|
|
Renders the form field to HTML as a hidden field rather than whatever field type it was supposed to be.
|
|
|
|
=cut
|
|
|
|
sub toHtmlAsHidden {
|
|
my $self = shift;
|
|
return '<input type="hidden" name="'.$self->get("name").'" value="'.$self->fixQuotes($self->fixMacros($self->fixSpecialCharacters($self->get("value")))).'" />'."\n";
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 toHtmlWithWrapper ( )
|
|
|
|
Renders the form field to HTML as a table row complete with labels, subtext, hoverhelp, etc.
|
|
|
|
=cut
|
|
|
|
sub toHtmlWithWrapper {
|
|
my $self = shift;
|
|
if ($self->passUiLevelCheck) {
|
|
my ($fieldClass, $rowClass, $labelClass, $hoverHelp, $subtext) = $self->prepareWrapper;
|
|
return '<tr'.$rowClass.'>
|
|
<td'.$labelClass.$hoverHelp.' valign="top" style="width: 25%;">'.$self->get("label").'</td>
|
|
<td valign="top"'.$fieldClass.' style="width: 75%;">'.$self->toHtml().$subtext."</td>
|
|
</tr>\n";
|
|
} else {
|
|
return $self->toHtmlAsHidden;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 passUiLevelCheck ( )
|
|
|
|
Renders the form field to HTML as a table row complete with labels, subtext, hoverhelp, etc.
|
|
|
|
=cut
|
|
|
|
sub passUiLevelCheck {
|
|
my $self = shift;
|
|
my $passUiLevelCheck = 0;
|
|
my $override = $self->session->config->get($self->get("uiLevelOverride")."_uiLevel")
|
|
if (defined $override && $override->{$self->get("name")}) { # use override if it exists
|
|
$passUiLevelCheck = ($override->{$self->get("name")} <= $self->session->user->profileField("uiLevel"));
|
|
} else { # use programmed default
|
|
$passUiLevelCheck = ($self->get("uiLevel") <= $self->session->user->profileField("uiLevel"));
|
|
}
|
|
$passUiLevelCheck = $self->session->user->isInGroup(3) unless ($passUiLevelCheck); # override if in admins group
|
|
return $passUiLevelCheck;
|
|
}
|
|
|
|
|
|
|
|
1;
|
|
|