CGI::Ex::Validate - another form validator - but it does javascript in parallel
use CGI::Ex::Validate; ### THE SHORT my $errobj = CGI::Ex::Validate->new->validate($form, $val_hash); ### THE LONG my $form = CGI->new; # OR # my $form = CGI::Ex->new; # OR CGI::Ex->get_form; # OR # my $form = {key1 => 'val1', key2 => 'val2'}; ### simplest my $val_hash = { username => { required => 1, max_len => 30, field => 'username', # field is optional in this case - will use key name }, email => { required => 1, max_len => 100, }, email2 => { validate_if => 'email', equals => 'email', }, }; ### ordered my $val_hash = { 'group order' => [qw(username email email2)], username => {required => 1, max_len => 30}, email => ..., email2 => ..., }; ### ordered again my $val_hash = { 'group fields' => [{ field => 'username', # field is not optional in this case required => 1, max_len => 30, }, { field => 'email', required => 1, max_len => 100, }, { field => 'email2', validate_if => 'email', equals => 'email', }], }; my $vob = CGI::Ex::Validate->new; my $errobj = $vob->validate($form, $val_hash); # OR # my $errobj = $vob->validate($form, "/somefile/somewhere.val"); # import config using yaml file # OR # my $errobj = $vob->validate($form, "/somefile/somewhere.pl"); # import config using perl file # OR # my $errobj = $vob->validate($form, "--- # a yaml document\n"); # import config using yaml str if ($errobj) { my $error_heading = $errobj->as_string; # OR "$errobj"; my $error_list = $errobj->as_array; # ordered list of what when wrong my $error_hash = $errobj->as_hash; # hash of arrayrefs of errors } else { # form passed validation } ### will add an error for any form key not found in $val_hash my $vob = CGI::Ex::Validate->new({no_extra_keys => 1}); my $errobj = $vob->validate($form, $val_hash);
CGI::Ex::Validate is one of many validation modules. It aims to have all of the basic data validation functions, avoid adding all of the millions of possible types, while still giving the capability for the developer to add their own types.
CGI::Ex::Validate can work in a simple way like all of the other validators do. However, it also allows for grouping of validation items and conditional validation of groups or individual items. This is more in line with the normal validation procedures for a website.
It also has full support for providing the same validation in javascript. It provides methods for attaching the javascript to existing forms.
new
Used to instantiate the object. Arguments are either a hash, or hashref, or nothing at all. Keys of the hash become the keys of the object.
get_validation
Given a filename or YAML string will return perl hash. If more than one group is contained in the file, it will return an arrayref of hashrefs.
my $ref = $self->get_validation($file);
get_validation_keys
Given a filename or YAML string or a validation hashref, will return all of the possible keys found in the validation hash. This can be used to check to see if extra items have been passed to validate. If a second argument contains a form hash is passed, get_validation_keys will only return the keys of groups that were validated.
my $key_hashref = $self->get_validation_keys($val_hash);
The values of the hash are the names of the fields.
validate
Arguments are a form hashref or cgi object, a validation hashref or filename, and an optional what_was_validated arrayref. If a CGI object is passed, CGI::Ex::get_form will be called on that object to turn it into a hashref. If a filename is given for the validation, get_validation will be called on that filename. If the what_was_validated_arrayref is passed - it will be populated (pushed) with the field hashes that were actually validated (anything that was skipped because of validate_if will not be in the array).
If the form passes validation, validate will return undef. If it fails validation, it will return a CGI::Ex::Validate::Error object. If the 'raise_error' general option has been set, validate will die with a CGI::Ex::validate::Error object as the value.
my $err_obj = $self->validate($form, $val_hash); # OR # $self->{raise_error} = 1; # raise error can also be listed in the val_hash eval { $self->validate($form, $val_hash) }; if ($@) { my $err_obj = $@; }
generate_js
Requires JSON or YAML to work properly (see JSON or YAML).
Takes a validation hash, a form name, and an optional javascript uri path and returns Javascript that can be embedded on a page and will perform identical validations as the server side. The validation can be any validation hash (or arrayref of hashes. The form name must be the name of the form that the validation will act upon - the name is used to register an onsubmit function. The javascript uri path is used to embed the locations two external javascript source files.
The javascript uri path is highly dependent upon the server configuration and therefore must be configured manually. It may be passed to generate_js, or it may be specified in $JS_URI_PATH. There are two files included with this module that are needed - CGI/Ex/yaml_load.js and CGI/Ex/validate.js. When generating the js code, generate_js will look in $JS_URI_PATH_YAML and $JS_URI_PATH_VALIDATE. If either of these are not set, generate_js will default to "$JS_URI_PATH/CGI/Ex/yaml_load.js" and "$JS_URI_PATH/CGI/Ex/validate.js".
$self->generate_js($val_hash, 'my_form', "/cgi-bin/js") # would generate something like the following... <script src="/cgi-bin/js/CGI/Ex/yaml_load.js"></script> <script src="/cgi-bin/js/CGI/Ex/validate.js"></script> ... more js follows ... $CGI::Ex::Validate::JS_URI_PATH = "/stock/js"; $CGI::Ex::Validate::JS_URI_PATH_YAML = "/js/yaml_load.js"; $self->generate_js($val_hash, 'my_form') # would generate something like the following... <script src="/js/yaml_load.js"></script> <script src="/stock/js/CGI/Ex/validate.js"></script> ... more js follows ...
Referencing yaml_load.js and validate.js can be done in any of several ways. They can be copied to or symlinked to a fixed location in the servers html directory. They can also be printed out by a cgi. The method ->print_js has been provided in CGI::Ex for printing js files found in the perl hierarchy. See CGI::Ex for more details. The $JS_URI_PATH of "/cgi-bin/js" could contain the following:
->print_js
#!/usr/bin/perl -w use strict; use CGI::Ex; ### path_info should contain something like /CGI/Ex/yaml_load.js my $info = $ENV{PATH_INFO} || ''; die "Invalid path" if $info !~ m|^(/\w+)+.js$|; $info =~ s|^/+||; CGI::Ex->new->print_js($info); exit;
The print_js method in CGI::Ex is designed to cache the javascript in the browser (caching is suggested as they are medium sized files).
->cgix
Returns a CGI::Ex object. Used internally.
The validation hash may be passed as a perl a hashref or as a filename, or as a YAML document string. If it is a filename, it will be translated into a hash using the %EXT_HANDLER for the extension on the file. If there is no extension, it will use $DEFAULT_EXT as a default.
The validation "hash" may also be an arrayref of hashrefs. In this case, each arrayref is treated as a group and is validated separately. A group can have a validate_if function that allows for that particular group to apply only if certain conditions are met.
Each hashref that is passed as a validation hash is treated as a group. Keys matching the regex m/^group\s+(\w+)$/ are reserved and are counted as GROUP OPTIONS. Keys matching the regex m/^general\s+(\w+)$/ are reserved and are counted as GENERAL OPTIONS. Other keys (if any, should be keys that need validation).
If the GROUP OPTION 'group validate_if' is set, the group will only be validated if the conditions are met. Any group with out a validate_if fill be automatically validated.
Each of the items listed in the group will be validated. The validation order is determined in one of three ways:
# order will be (username, password, 'm/\w+_foo/', somethingelse) { 'group title' => "User Information", 'group fields' => [ {field => 'username', required => 1}, {field => 'password', required => 1}, {field => 'm/\w+_foo/', required => 1}, ], somethingelse => {required => 1}, }
# order will be (username, password, 'm/\w+_foo/', somethingelse) { 'group title' => "User Information", 'group order' => [qw(username password), 'm/\w+_foo/'], username => {required => 1}, password => {required => 1}, 'm/\w+_foo/' => {required => 1}, somethingelse => {required => 1}, }
# order will be ('m/\w+_foo/', password, somethingelse, username) { 'group title' => "User Information", username => {required => 1}, password => {required => 1}, 'm/\w+_foo/' => {required => 1}, somethingelse => {required => 1}, }
Each of the individual field validation hashrefs should contain the types listed in VALIDATION TYPES.
Optionally the 'group fields' or the 'group order' may contain the word 'OR' as a special keyword. If the item preceding 'OR' fails validation the item after 'OR' will be tested instead. If the item preceding 'OR' passes validation the item after 'OR' will not be tested.
'group order' => [qw(zip OR postalcode state OR region)],
Each individual validation hashref will operate on the field contained in the 'field' key. This key may also be a regular expression in the form of 'm/somepattern/'. If a regular expression is used, all keys matching that pattern will be validated.
This section lists the available validation types. Multiple instances of the same type may be used for some validation types by adding a number to the type (ie match, match2, match232, match_94). Multiple instances are validated in sorted order. Types that allow multiple values are:
compare custom equals match max_in_set min_in_set replace required_if sql type validate_if
validate_if
If validate_if is specified, the field will only be validated if the conditions are met. Works in JS.
validate_if => {field => 'name', required => 1, max_len => 30} # Will only validate if the field "name" is present and is less than 30 chars. validate_if => 'name', # SAME as validate_if => {field => 'name', required => 1}, validate_if => '! name', # SAME as validate_if => {field => 'name', max_in_set => '0 of name'}, validate_if => {field => 'country', compare => "eq US"}, # only if country's value is equal to US validate_if => {field => 'country', compare => "ne US"}, # if country doesn't equal US validate_if => {field => 'password', match => 'm/^md5\([a-z0-9]{20}\)$/'}, # if password looks like md5(12345678901234567890) { field => 'm/^(\w+)_pass/', validate_if => '$1_user', required => 1, } # will validate foo_pass only if foo_user was present.
The validate_if may also contain an arrayref of validation items. So that multiple checks can be run. They will be run in order. validate_if will return true only if all options returned true.
validate_if => ['email', 'phone', 'fax']
Optionally, if validate_if is an arrayref, it may contain the word 'OR' as a special keyword. If the item preceding 'OR' fails validation the item after 'OR' will be tested instead. If the item preceding 'OR' passes validation the item after 'OR' will not be tested.
validate_if => [qw(zip OR postalcode)],
required_if
Requires the form field if the condition is satisfied. The conditions available are the same as for validate_if. This is somewhat the same as saying:
validate_if => 'some_condition', required => 1 required_if => 'some_condition',
If a regex is used for the field name, the required_if field will have any match patterns swapped in.
{ field => 'm/^(\w+)_pass/', required_if => '$1_user', }
This example would require the "foobar_pass" field to be set if the "foobar_user" field was passed.
required
Requires the form field to have some value. If the field is not present, no other checks will be run.
min_values
max_values
Allows for specifying the maximum number of form elements passed. max_values defaults to 1 (You must explicitly set it higher to allow more than one item by any given name).
min_in_set
max_in_set
Somewhat like min_values and max_values except that you specify the fields that participate in the count. Also - entries that are not defined or do not have length are not counted. An optional "of" can be placed after the number for human readability.
min_in_set => "2 of foo bar baz", # two of the fields foo, bar or baz must be set # same as min_in_set => "2 foo bar baz", # same as min_in_set => "2 OF foo bar baz", validate_if => {field => 'whatever', max_in_set => '0 of whatever'}, # only run validation if there were zero occurrences of whatever
enum
Allows for checking whether an item matches a set of options. In perl the value may be passed as an arrayref. In the conf or in perl the value may be passed of the options joined with ||.
{ field => 'password_type', enum => 'plaintext||crypt||md5', # OR enum => [qw(plaintext crypt md5)], }
equals
Allows for comparison of two form elements. Can have an optional !.
{ field => 'password', equals => 'password_verify', }, { field => 'domain1', equals => '!domain2', # make sure the fields are not the same }
min_len and max_len
Allows for check on the length of fields
{ field => 'site', min_len => 4, max_len => 100, }
match
Allows for regular expression comparison. Multiple matches may be concatenated with ||. Available in JS.
{ field => 'my_ip', match => 'm/^\d{1,3}(\.\d{1,3})3$/', match_2 => '!/^0\./ || !/^192\./', }
compare
Allows for custom comparisons. Available types are >, <, >=, <=, !=, ==, gt, lt, ge, le, ne, and eq. Comparisons also work in the JS.
{ field => 'my_number', match => 'm/^\d+$/', compare1 => '> 100', compare2 => '< 255', compare3 => '!= 150', }
sql
SQL query based - not available in JS. The database handle will be looked for in the value $self->{dbhs}->{foo} if sql_db_type is set to 'foo', otherwise it will default to $self->{dbh}. If $self->{dbhs}->{foo} or $self->{dbh} is a coderef - they will be called and should return a dbh.
{ field => 'username', sql => 'SELECT COUNT(*) FROM users WHERE username = ?', sql_error_if => 1, # default is 1 - set to 0 to negate result # sql_db_type => 'foo', # will look for a dbh under $self->{dbhs}->{foo} }
custom
Custom value - not available in JS. Allows for extra programming types. May be either a boolean value predetermined before calling validate, or may be a coderef that will be called during validation. If coderef is called, it will be passed the field name, the form value for that name, and a reference to the field validation hash. If the custom type returns false the element fails validation and an error is added.
{ field => 'username', custom => sub { my ($key, $val, $type, $field_val_hash) = @_; # do something here return 0; }, }
custom_js
Custom value - only available in JS. Allows for extra programming types. May be either a boolean value pre-determined before calling validate, or may be section of javascript that will be eval'ed. The last value (return value) of the eval'ed javascript will determine if validation passed. A false value indicates the value did not pass validation. A true value indicates that it did. See the t/samples/js_validate_3.html page for a sample of usage.
{ field => 'date', required => 1, match => 'm|^\d\d\d\d/\d\d/\d\d$|', match_error => 'Please enter date in YYYY/MM/DD format', custom_js => " var t=new Date(); var y=t.getYear()+1900; var m=t.getMonth() + 1; var d=t.getDate(); if (m<10) m = '0'+m; if (d<10) d = '0'+d; (value > ''+y+'/'+m+'/'+d) ? 1 : 0; ", custom_js_error => 'The date was not greater than today.', }
type
Allows for more strict type checking. Currently supported types include CC (credit card). Other types will be added upon request provided we can add a perl and a javascript version.
{ field => 'credit_card', type => 'CC', }
field
Specify which field to work on. Key may be a regex in the form 'm/\w+_user/'. This key is required if 'group fields' is used or if validate_if or required_if are used. It can optionally be used with other types to specify a different form element to operate on. On errors, if a non-default error is found, $field will be swapped with the value found in field.
The field name may also be a regular expression in the form of 'm/somepattern/'. If a regular expression is used, all keys matching that pattern will be validated.
name
Name to use for errors. If a name is not specified, default errors will use "The field $field" as the name. If a non-default error is found, $name will be swapped with this name.
delegate_error
This option allows for any errors generated on a field to delegate to a different field. If the field name was a regex, any patterns will be swapped into the delegate_error value. This option is generally only useful with the as_hash method of the error object (for inline errors).
{ field => 'zip', match => 'm/^\d{5}/', }, { field => 'zip_plus4', match => 'm/^\d{4}/', delegate_error => 'zip', }, { field => 'm/^(id_[\d+])_user$/', delegate_error => '$1', },
exclude_js
This allows the cgi to do checking while keeping the checks from being run in JavaScript
{ field => 'cgi_var', required => 1, exclude_js => 1, }
exclude_cgi
This allows the js to do checking while keeping the checks from being run in the cgi
{ field => 'js_var', required => 1, exclude_cgi => 1, }
The following types will modify the form value before it is processed. They work in both the perl and in javascript as well. The javascript version changes the actual value in the form on appropriate form types.
do_not_trim
By default, validate will trim leading and trailing whitespace from submitted values. Set do_not_trim to 1 to allow it to not trim.
{field => 'foo', do_not_trim => 1}
replace
Pass a swap pattern to change the actual value of the form. Any perl regex can be passed but it is suggested that javascript compatible regexes are used to make generate_js possible.
{field => 'foo', replace => 's/(\d{3})(\d{3})(\d{3})/($1) $2-$3/'}
default
Set item to default value if there is no existing value (undefined or zero length string).
{field => 'country', default => 'EN'}
to_upper_case
to_lower_case
Do what they say they do.
untaint
Requires that the validated field has been also checked with an enum, equals, match, compare, custom, or type check. If the field has been checked and there are no errors - the field is "untainted."
This is for use in conjunction with perl's -T switch.
Failed validation results in an error an error object created via the new_error method. The default error class is CGI::Ex::Validate::Error.
The error object has several methods for determining what the errors were.
as_array
Returns an array or arrayref (depending on scalar context) of errors that occurred in the order that they occurred. Individual groups may have a heading and the entire validation will have a heading (the default heading can be changed via the 'as_array_title' general option). Each error that occurred is a separate item and are pre-pended with 'as_array_prefix' (which is a general option - default is ' '). The as_array_ options may also be set via a hashref passed to as_array. as_array_title defaults to 'Please correct the following items:'.
### if this returns the following my $array = $err_obj->as_array; # $array looks like # ['Please correct the following items:', ' error1', ' error2'] ### then this would return the following my $array = $err_obj->as_array({ as_array_prefix => ' - ', as_array_title => 'Something went wrong:', }); # $array looks like # ['Something went wrong:', ' - error1', ' - error2']
as_string
Returns values of as_array joined with a newline. This method is used as the stringification for the error object. Values of as_array are joined with 'as_string_join' which defaults to "\n". If 'as_string_header' is set, it will be pre-pended onto the error string. If 'as_string_footer' is set, it will be appended onto the error string.
### if this returns the following my $string = $err_obj->as_string; # $string looks like # "Please correct the following items:\n error1\n error2" ### then this would return the following my $string = $err_obj->as_string({ as_array_prefix => ' - ', as_array_title => 'Something went wrong:', as_string_join => '<br />', as_string_header => '<span class="error">', as_string_footer => '</span>', }); # $string looks like # '<span class="error">Something went wrong:<br /> - error1<br /> - error2</span>'
as_hash
Returns a hash or hashref (depending on scalar context) of errors that occurred. Each key is the field name of the form that failed validation with 'as_hash_suffix' added on as a suffix. as_hash_suffix is available as a general option and may also be passed in via a hashref as the only argument to as_hash. The default value is '_error'. The values of the hash are arrayrefs of errors that occurred to that form element.
By default as_hash will return the values of the hash as arrayrefs (a list of the errors that occurred to that key). It is possible to also return the values as strings. Three options are available for formatting: 'as_hash_header' which will be pre-pended onto the error string, 'as_hash_footer' which will be appended, and 'as_hash_join' which will be used to join the arrayref. The only argument required to force the stringification is 'as_hash_join'.
### if this returns the following my $hash = $err_obj->as_hash; # $hash looks like # {key1_error => ['error1', 'error2']} ### then this would return the following my $hash = $err_obj->as_hash({ as_hash_suffix => '_foo', as_hash_join => '<br />', as_hash_header => '<span class="error">' as_hash_footer => '</span>' }); # $hash looks like # {key1_foo => '<span class="error">error1<br />error2</span>'}
Any key in a validation hash matching the pattern m/^group\s+(\w+)$/ is considered a group option. The current know options are:
'group title'
Used as a group section heading when as_array or as_string is called by the error object.
'group order'
Order in which to validate key/value pairs of group.
'group fields'
Arrayref of validation items to validate.
'group validate_if'
Conditions that will be checked to see if the group should be validated. If no validate_if option is found, the group will be validated.
Any key in a validation hash matching the pattern m/^general\s+(\w+)$/ is considered a general option. General options will also be looked for in the Validate object ($self) and can be set when instantiating the object ($self->{raise_error} is equivalent to $valhash->{'general raise_error'}). The current know options are:
General options may be set in any group using the syntax:
'general general_option_name' => 'general_option_value'
They will only be set if the group's validate_if is successful or if the group does not have a validate_if. It is also possible to set a "group general" option using the following syntax:
'group general_option_name' => 'general_option_value'
These items will only be set if the group fails validation. If a group has a validate_if block and passes validation, the group items will not be used. This is so that a failed section can have its own settings. Note though that the last option found will be used and that items set in $self override those set in the validation hash.
Options may also be set globally before calling validate by populating the %DEFAULT_OPTIONS global hash.
'general raise_error'
If raise_error is true, any call to validate that fails validation will die with an error object as the value.
'general no_extra_fields'
If no_extra_fields is true, validate will add errors for any field found in form that does not have a field_val hashref in the validation hash. Default is false. If no_extra_fields is set to 'used', it will check for any keys that were not in a group that was validated.
An important exception to this is that field_val hashrefs or field names listed in a validate_if or required_if statement will not be included. You must have an explicit entry for each key.
'general \w+_error'
These items allow for an override of the default errors.
'general required_error' => '$name is really required', 'general max_len_error' => '$name must be shorter than $value characters', # OR # my $self = CGI::Ex::Validate->new({ max_len_error => '$name must be shorter than $value characters', });
'general as_array_title'
Used as the section title for all errors that occur, when as_array or as_string is called by the error object.
'general as_array_prefix'
Used as prefix to individual errors that occur, when as_array or as_string is called by the error object. Each individual error will be prefixed with this string. Headings will not be prefixed. Default is ' '.
'general as_string_join'
When as_string is called, the values from as_array will be joined with as_string_join. Default value is "\n".
'general as_string_header'
If set, will be pre-pended onto the string when as_string is called.
'general as_string_footer'
'general as_hash_suffix'
Added on to key names during the call to as_hash. Default is '_error'.
'general as_hash_join'
By default, as_hash will return hashref values that are errors joined with the default as_hash_join value of <br />. It can also return values that are arrayrefs of the errors. This can be done by setting as_hash_join to a non-true value (for example '')
'general as_hash_header'
If as_hash_join has been set to a true value, as_hash_header may be set to a string that will be pre-pended on to the error string.
'general as_hash_footer'
If as_hash_join has been set to a true value, as_hash_footer may be set to a string that will be postpended on to the error string.
'general no_inline'
If set to true, the javascript validation will not attempt to generate inline errors. Default is true. Inline errors are independent of confirm and alert errors.
'general no_confirm'
If set to true, the javascript validation will try to use an alert instead of a confirm to inform the user of errors. Alert and confirm are independent or inline errors. Default is false.
'general no_alert'
If set to true, the javascript validation will not show an alert box when errors occur. Default is false. This option only comes into play if no_confirm is also set. This option is independent of inline errors. Although it is possible to turn off all errors by setting no_inline, no_confirm, and no_alert all to 1, it is suggested that at least one of the error reporting facilities is left on.
It is possible to have a group that contains nothing but general options.
my $val_hash = [ {'general error_title' => 'The following things went wrong', 'general error_prefix' => ' - ', 'general raise_error' => 1, 'general name_suffix' => '_foo_error', 'general required_error' => '$name is required', }, {'group title' => 'User Information', username => {required => 1}, email => {required => 1}, password => {required => 1}, }, ];
CGI::Ex::Validate provides for having duplicate validation on the client side as on the server side. Errors can be shown in any combination of inline and confirm, inline and alert, inline only, confirm only, alert only, and none. These combinations are controlled by the general options no_inline, no_confirm, and no_alert. Javascript validation can be generated for a page using the ->generate_js Method of CGI::Ex::Validate. It is also possible to store the validation inline with the html. This can be done by giving each of the elements to be validated an attribute called "validation", or by setting a global javascript variable called "document.validation" or "var validation". An html file containing this validation will be read in using CGI::Ex::Conf::read_handler_html.
->generate_js
All inline html validation must be written in yaml.
It is anticipated that the html will contain something like either of the following examples:
<script src="/cgi-bin/js/CGI/Ex/yaml_load.js"></script> <script src="/cgi-bin/js/CGI/Ex/validate.js"></script> <script> // \n\ allows all browsers to view this as a single string document.validation = "\n\ general no_confirm: 1\n\ general no_alert: 1\n\ group order: [username, password]\n\ username:\n\ required: 1\n\ max_len: 20\n\ password:\n\ required: 1\n\ max_len: 30\n\ "; if (document.check_form) document.check_form('my_form_name'); </script>
Alternately we can use element attributes:
<form name="my_form_name"> Username: <input type=text size=20 name=username validation=" required: 1 max_len: 20 "><br> <span class=error id=username_error>[% username_error %]</span><br> Password: <input type=text size=20 name=password validation=" required: 1 max_len: 30 "><br> <span class=error id=password_error>[% password_error %]</span><br> <input type=submit> </form> <script src="/cgi-bin/js/CGI/Ex/yaml_load.js"></script> <script src="/cgi-bin/js/CGI/Ex/validate.js"></script> <script> if (document.check_form) document.check_form('my_form_name'); </script>
The read_handler_html from CGI::Ex::Conf will find either of these types of validation.
If inline errors are asked for, each error that occurs will attempt to find an html element with its name as the id. For example, if the field "username" failed validation and created a "username_error", the javascript would set the html of <span id="username_error"></span> to the error message.
It is suggested to use something like the following so that you can have inline javascript validation as well as report validation errors from the server side as well.
<span class=error id=password_error>[% password_error %]</span><br>
If the javascript fails for some reason, the form should still be able to submit as normal (fail gracefully).
If the confirm option is used, the errors will be displayed to the user. If they choose OK they will be able to try and fix the errors. If they choose cancel, the form will submit anyway and will rely on the server to do the validation. This is for fail safety to make sure that if the javascript didn't validate correctly, the user can still submit the data.
Thanks to Eamon Daly for providing bug fixes for bugs in validate.js caused by HTML::Prototype.
Paul Seamons
This module may be distributed under the same terms as Perl itself.
To install CGI::Ex, copy and paste the appropriate command in to your terminal.
cpanm
cpanm CGI::Ex
CPAN shell
perl -MCPAN -e shell install CGI::Ex
For more information on module installation, please visit the detailed CPAN module installation guide.