Form Class

This class was inspired by the HTML_QuickForm pear package. By the time I found out about it my code had become completely unmanageable, and the Quickform class held the promise of making my life so much easier. I was disheartened to discover that the HTML QuickForm class(es) were humongous, and required a ton of pear code besides. It didn't sit well with my KISS philosophy, so I decided to write my own class. This class does everything I had ever hoped the HTML Quickform would do and more. The great thing about this class is that it is easy enough to wrap your head around in case you need to make any changes.

With this class you will be able to create the following form fields:

Radio Buttons and Check Boxes
'radio' - Radio button(s) for a user to select one option from a set of alternatives.
'checkbox' - Checkbox(es) for a user to select one or more options from a set of alternatives.
'multicheck' - An array of checkboxes.

Select Form Fields
'select' - A menu from which a single selection can be made.
'multiselect' - A menu from which multiple selections can be made.
'hierselect' - Two select menus with the first menu controlling the options of the second menu.

Text Fields
'text' - A single line text input box.
'multitext' - An array of text fields.
'password' - A text field - only the input shows up as dots.
'file' - A file upload prompt.
'textarea' - Text fields that can span several lines.
'calendar' - A date input box with a helpful calendar using the jQuery datepicker widget.

Form Fields
'hidden' - To submit information not entered by the visitor.
'submit' - A button to submit the form to the server.

In addition it offers:

  • Complete file upload management
  • Easy integration with reCAPTCHA
  • Client side validation using the jQuery Form Validation plugin
  • Automatic server-side validation and filtering of all submitted data
  • Total control over the form layout
  • Clean (x)html code that validates

This class takes all of the form-related events of creating the form, filtering, validating, and processing the data, and puts it all into one object and one PHP page. This class will make your code more reliable, consistent, and simple.

object Form ( [ string $class ] )

Creates a new form object.

$class You can give your form a class name here.
Example
$form = new Form('awesome');

required ( array $required )

This method will not allow the form to be processed until all of the required fields have their appropriate values

$required An array of required form input names, ie. these fields must not be empty.
Note: multicheck, multiselect, multitext, hidden, and submit field types can not be required.
Example
$form->required(array('name', 'email', 'password'));

array values ( [ array $values ) ]

This method is to preselect the values of form inputs.

$values An array ('name'=>'value') of form default values.
This is optional in case you just want to return the array.
Note: multicheck and multitext values cannot be preselected here.
Returns The current array of 'name' and 'value' form default values.
Example
$form->values(array('name=>'user', 'email'=>'your@email.com'));

check ( array $check )

These are the form inputs you want to check and make sure that they have the kind of values you expect of them.

$check An array('name'=>'filter') of the form values you want returned. Refer to the data method of the Validation Class for the available filters and how to format them (don't worry, it's easy). You can also give the name of another form field to filter the value against. eg. to confirm a password or email address.
Example
$form->check(array('name'=>'', 'email'=>'email', 'password'=>'pass'));

process ( array $process )

To process[] multicheck and multitext input. We have this method because of the browsers bad habit of not returning multicheck values that are unselected. It is not necessary, but if you have multitext inputs with all of the same array keys, you might as well include them here with the multichecks. Don't forget to include a $form->field('hidden', 'process', $key) with each multicheck.

$process An array ('name'=>'filter') of the form values you want to process.
Example
$form->process(array('delete'=>'YN'));

upload ( array $upload [, integer $filesize= 5 ] )

This method will make sure the file(s) are of the correct type, and if so upload them to your uploads folder. If successful it will add to the $vars array returned by the $form->validate() function the files name. If unsuccessful it will trigger an error to alert you of what is happening, and inform the user they need to try again (if the field is required).

$upload An array ('name'=>'types') of files to upload.
type(s): (can also be it's own array)
'jpg' - jpeg, jpg, pjpeg
'gif'
'png'
'bmp' - bitmap
'swf' - flash
'doc' - ms word
'txt'
'pdf'
'ppt' - powerpoint
'xls' - excel
'xml'
'mpeg' - all types
'mov' - quicktime videos
'zip'
$filesize The maximum file size your form will upload in megabytes - the math is done in house to give the browser what it wants in bytes. Default is 5.
Example
$form->upload(array('image'=>array('jpg', 'gif', 'png')), 2);

array validate ( string $form [, string $function= 'escape_data' ] )

This is where you collect all of the user-submitted information, process it, then send them on their merry way.

$form The name of the form. Must be the same as the $name indicated in the $form->header() method coming up.
$function This function will filter all form data. The default is 'escape_data' which will make all of the submitted form data safe to insert into a MySQL database.
Returns An array of 3 values:
1) A $vars['name'] = $value array of all of the $form->check(), $form->process(), and $form->upload() methods previously called.
2) An $errors array that you don't need to worry about. You only need to know that it is empty which means it is safe to process all $vars.
3) An $eject string to know where to send the user so that they can't hurt themselves by resubmitting the same form over and over again when they click their browsers back button.
Example
list($vars, $errors, $eject) = $form->validate('formname'); 
if (!empty($vars) && empty($errors)) { 
  $html .= '<pre>' . print_r($vars, true) . '</pre>'; 
  // $page->eject ($eject, 'Thanks!<br />Your form submission was successful.'); 
}

array error ( [ string $name [, string $message ]] )

If you have your own special validation routine, this method allows you to do your thing, make a custom error, and have your user try again.

$name The name of the form element you would like to reject.
$message A note to the user on how they can make things right.
Returns An array of errors, if any, so that you can call this method one last time at the end of your conditionals and get a yea or nay on whether you should proceed or not.
Example
if ($vars['name'] != 'what I like') { 
  $form->error('name', 'Sorry Charlie, try again.'); 
} 
if (empty($form->error())  { // Continue . . .

prompt ( integer $size )

This gives your form a nice layout by lining up your prompts and fields into separate columns down the page.

$size The size (in pixels) that you would like your prompts to occupy.
Example
$form->prompt(100);

string header ( string $name [, string $method= 'post' [, string $action ]] )

This is what gets the party started. Everything until now was just setting up for the action.

$name The name of the form. Make sure it is the same as you called in $form->validate ($form).
$method Either 'get', or 'post'. Default is 'post'.
$action It's best to leave this blank. The form will automatically process itself where it is but with an added parameter so that after you process the form and $page->eject() them, they will go back to the same page only the browser is tricked so that when the user pushes the back button, your form isn't resubmitted with all the same old information.
Returns A string of code to add to your $html.
Example
$html .= $form->header('formname');

string field ( string $type, string $name [, string $prompt [, string or array $options [, integer $key ]]] )

This method creates the actual form fields. You tell it the $type of field, what you want to $name it, $prompt the user so they know what to input, and give them (including the input field) their $options. There's a lot you can do with this method so we're just going to take it one type at a time.

$type Radio Buttons and Check Boxes
'radio' - Radio button(s) for a user to select one option from a set of alternatives.
'checkbox' - Checkbox(es) for a user to select one or more options from a set of alternatives.
'multicheck' - An array of checkboxes.

Select Form Fields
'select' - A menu from which a single selection can be made.
'multiselect' - A menu from which multiple selections can be made.
'hierselect' - Two select menus with the first menu controlling the options of the second menu.

Text Fields
'text' - A single line text input box.
'multitext' - An array of text fields.
'password' - A text field - only the input shows up as dots.
'file' - A file upload prompt.
'textarea' - Text fields that can span several lines.
'calendar' - A date input box with a helpful calendar using the jQuery datepicker widget.

Form Fields
'hidden' - To submit information not entered by the visitor.
'submit' - A button to submit the form to the server.
$name This field's input name and id. If this is a hidden field whose name is 'process', it will be turned to an array ('process[]').
$prompt Comes right before the form field to let the user know what to input, except for the 'hidden' form field where the $prompt is it's value.
$options This means different things to different types. Click on each field type for clarification.
$key This is the (optional) array key for 'multicheck' and 'multitext' form fields.
Returns A string of code to add to your $html.

string field ( 'radio', string $name, string $prompt, array $values )

$values An array of values for each button in the group.
Example
$html .= $form->field('radio', 'gender', 'Gender:', array('M'=>'Male', 'F'=>'Female'));

string field ( 'checkbox', string $name, string $prompt, array $values )

$values A key and value pair giving a single $value=>$description combo.
Example
$html .= $form->field('checkbox', 'terms', '', array('Y'=>'I accept your terms and conditions');

string field ( 'multicheck', string $name, string $prompt, string $value [, integer $key ] )

$value The checkbox's value.
$key This is an optional array key. If you include it then don't forget the hidden process field.
Example
$html .= $form->field('multicheck', 'add', 'Four', 'Y', 4) . $form->field('hidden', 'process', 4); 
$html .= $form->field('multicheck', 'add', 'Eight', 'Y', 8) . $form->field('hidden', 'process', 8); 
$html .= $form->field('multicheck', 'add', 'Fifteen', 'Y', 15) . $form->field('hidden', 'process', 15);

string field ( 'select', string $name, string $prompt, array $values )

$values An array of values.
Example
$html .= $form->field('select', 'color', 'Personality:', array('r'=>'Red', 'b'=>'Blue', 'w'=>'White', 'y'=>'Yellow'));

string field ( 'multiselect', string $name, string $prompt, array $values )

$values An array of values.
Example
$html .= $form->field('multiselect', 'lost', 'Candidates:', array(4=>'John Locke', 8=>'Hugo Reyes', 15=>'James Ford', 16=>'Sayid Jarrah', 23=>'Jack Shephard', 42=>'Jin & Sun Kwon'));

string field ( 'hierselect', string $name, string $prompt, array $values )

$values A multi-dimensional array including a 'hier' key of the next select menus name.
Example
$categories = array(); 
$subcategories = array(); 
 
#-- Our Multi-Dimensional Array for the Hierselect Category --# 
$categories['hier'] = 'subcategory'; 
$categories[0] = array(1=>'Planes', 2=>'Trains',  3=>'Automobiles'); 
$categories[1] = array(1=>'Cessna 172', 2=>'Learjet', 3=>'Boeing 747'); 
$categories[2] = array(4=>'Amtrak', 5=>'The Alaska Railroad', 6=>'Bullet Train'); 
$categories[3] = array(7=>'Volkswagen Beetle', 8=>'Hummer', 9=>'Bugatti Veyron'); 
$values = $form->values(); 
if (isset($values['category'])) { // This is to preload the subcategories if a category has already been selected 
  $selected = $values['category']; 
  $subcategories = $categories[$selected]; 
} 
 
$html .= $form->field('hierselect', 'category', 'Category:', $categories)) . '<br />'; 
$html .= $form->field('select', 'subcategory', 'Subcategory:', $subcategories));

string field ( 'text', string $name [, string $prompt [, array $options ]] )

$options Default: array('width'=>200, 'maxlength'=>50)
Example
$html .= $form->field('text', 'email', 'Email:', array('width'=>250, 'maxlength'=>60));

string field ( 'multitext', string $name [, string $prompt [, array $options [, integer $key ]]] )

$options Default: array('width'=>250, 'maxlength'=>50, 'value'=>'')
Multitext values can't be preselected unless you do so here.
$key This is an optional array key.
Example
$html .= $form->field('multitext', 'amount', 'Item 16:', array('width'=>50, 'maxlength'=>10), 16); 
$html .= $form->field('multitext', 'amount', 'Item 23:', array('width'=>50, 'maxlength'=>10), 23); 
$html .= $form->field('multitext', 'amount', 'Item 42:', array('width'=>50, 'maxlength'=>10, 'value'=>108), 42);

string field ( 'password', string $name [, string $prompt [, array $options ]] )

$options Default: array('width'=>100, 'maxlength'=>20)
Example
$html .= $form->field('password', 'password', 'Password:');

string field ( 'file', string $name [, string $prompt [, array $option ]] )

$option Default: array('size'=>50)
Example
$html .= $form->field('file', 'image', 'Image:');

string field ( 'textarea', string $name [, string $prompt [, array $options ]] )

$options Default: array('width'=>400, 'height'=>200)
Example
$html .= $form->field('textarea', 'comments', 'Comments:<br />');

string field ( 'calendar', string $name [, string $prompt ] )

Example
$html .= $form->field('calendar', 'date', 'Date:');

string field ( 'hidden', string $name, string $value [, array $option ] )

$value The hidden input's value.
$option This is where you can give your hidden input field an id for javascript's sake.
ie. array('id'=>'accessible');
Example
$html .= $form->field ('hidden', 'secret', 'value');

string field ( 'submit', string $name [, string $prompt ] )

$name The name of your submit button.
$prompt Put '&nbsp;' here if you've set a value for the $form->prompt() and want the submit button to be inline with the form fields.
Example
$html .= $form->field('submit', 'Submit');

string recaptcha ( )

Automatic and easy integration with reCAPTCHA. Check it out at their site recaptcha.net. All you need to do is sign up and include their functions at the top of your page. Don't forget to add 'recaptcha' to your required array.

Returns A string of code to add to your $html.
Example
$form->required(array('recaptcha')); // Declare this before you validate the form. 
$html .= $form->recaptcha();

string close ( )

Closes up shop, and finishes your form's code.

Returns A string of code to add to your $html.
Example
$html .= $form->close();
Click to Download the PHP Form Class

 Subscribe to our feed

form.js

/* 
 * jQuery validation plug-in 1.7 
 * 
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ 
 * http://docs.jquery.com/Plugins/Validation 
 * 
 * Copyright (c) 2006 - 2008 Jörn Zaefferer 
 * 
 * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $ 
 * 
 * Dual licensed under the MIT and GPL licenses: 
 *   http://www.opensource.org/licenses/mit-license.php 
 *   http://www.gnu.org/licenses/gpl.html 
 */ 
(function($){$.extend($.fn,{validate:function(options){if(!this.length){options&&options.debug&&window.console&&console.warn("nothing selected, can't validate, returning nothing");return;}var validator=$.data(this[0],'validator');if(validator){return validator;}validator=new $.validator(options,this[0]);$.data(this[0],'validator',validator);if(validator.settings.onsubmit){this.find("input, button").filter(".cancel").click(function(){validator.cancelSubmit=true;});if(validator.settings.submitHandler){this.find("input, button").filter(":submit").click(function(){validator.submitButton=this;});}this.submit(function(event){if(validator.settings.debug)event.preventDefault();function handle(){if(validator.settings.submitHandler){if(validator.submitButton){var hidden=$("<input type='hidden'/>").attr("name",validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);}validator.settings.submitHandler.call(validator,validator.currentForm);if(validator.submitButton){hidden.remove();}return false;}return true;}if(validator.cancelSubmit){validator.cancelSubmit=false;return handle();}if(validator.form()){if(validator.pendingRequest){validator.formSubmitted=true;return false;}return handle();}else{validator.focusInvalid();return false;}});}return validator;},valid:function(){if($(this[0]).is('form')){return this.validate().form();}else{var valid=true;var validator=$(this[0].form).validate();this.each(function(){valid&=validator.element(this);});return valid;}},removeAttrs:function(attributes){var result={},$element=this;$.each(attributes.split(/\s/),function(index,value){result[value]=$element.attr(value);$element.removeAttr(value);});return result;},rules:function(command,argument){var element=this[0];if(command){var settings=$.data(element.form,'validator').settings;var staticRules=settings.rules;var existingRules=$.validator.staticRules(element);switch(command){case"add":$.extend(existingRules,$.validator.normalizeRule(argument));staticRules[element.name]=existingRules;if(argument.messages)settings.messages[element.name]=$.extend(settings.messages[element.name],argument.messages);break;case"remove":if(!argument){delete staticRules[element.name];return existingRules;}var filtered={};$.each(argument.split(/\s/),function(index,method){filtered[method]=existingRules[method];delete existingRules[method];});return filtered;}}var data=$.validator.normalizeRules($.extend({},$.validator.metadataRules(element),$.validator.classRules(element),$.validator.attributeRules(element),$.validator.staticRules(element)),element);if(data.required){var param=data.required;delete data.required;data=$.extend({required:param},data);}return data;}});$.extend($.expr[":"],{blank:function(a){return!$.trim(""+a.value);},filled:function(a){return!!$.trim(""+a.value);},unchecked:function(a){return!a.checked;}});$.validator=function(options,form){this.settings=$.extend(true,{},$.validator.defaults,options);this.currentForm=form;this.init();};$.validator.format=function(source,params){if(arguments.length==1)return function(){var args=$.makeArray(arguments);args.unshift(source);return $.validator.format.apply(this,args);};if(arguments.length>2&&params.constructor!=Array){params=$.makeArray(arguments).slice(1);}if(params.constructor!=Array){params=[params];}$.each(params,function(i,n){source=source.replace(new RegExp("\\{"+i+"\\}","g"),n);});return source;};$.extend($.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:true,errorContainer:$([]),errorLabelContainer:$([]),onsubmit:true,ignore:[],ignoreTitle:false,onfocusin:function(element){this.lastActive=element;if(this.settings.focusCleanup&&!this.blockFocusCleanup){this.settings.unhighlight&&this.settings.unhighlight.call(this,element,this.settings.errorClass,this.settings.validClass);this.errorsFor(element).hide();}},onfocusout:function(element){if(!this.checkable(element)&&(element.name in this.submitted||!this.optional(element))){this.element(element);}},onkeyup:function(element){if(element.name in this.submitted||element==this.lastElement){this.element(element);}},onclick:function(element){if(element.name in this.submitted)this.element(element);else if(element.parentNode.name in this.submitted)this.element(element.parentNode);},highlight:function(element,errorClass,validClass){$(element).addClass(errorClass).removeClass(validClass);},unhighlight:function(element,errorClass,validClass){$(element).removeClass(errorClass).addClass(validClass);}},setDefaults:function(settings){$.extend($.validator.defaults,settings);},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",accept:"Please enter a value with a valid extension.",maxlength:$.validator.format("Please enter no more than {0} characters."),minlength:$.validator.format("Please enter at least {0} characters."),rangelength:$.validator.format("Please enter a value between {0} and {1} characters long."),range:$.validator.format("Please enter a value between {0} and {1}."),max:$.validator.format("Please enter a value less than or equal to {0}."),min:$.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:false,prototype:{init:function(){this.labelContainer=$(this.settings.errorLabelContainer);this.errorContext=this.labelContainer.length&&this.labelContainer||$(this.currentForm);this.containers=$(this.settings.errorContainer).add(this.settings.errorLabelContainer);this.submitted={};this.valueCache={};this.pendingRequest=0;this.pending={};this.invalid={};this.reset();var groups=(this.groups={});$.each(this.settings.groups,function(key,value){$.each(value.split(/\s/),function(index,name){groups[name]=key;});});var rules=this.settings.rules;$.each(rules,function(key,value){rules[key]=$.validator.normalizeRule(value);});function delegate(event){var validator=$.data(this[0].form,"validator"),eventType="on"+event.type.replace(/^validate/,"");validator.settings[eventType]&&validator.settings[eventType].call(validator,this[0]);}$(this.currentForm).validateDelegate(":text, :password, :file, select, textarea","focusin focusout keyup",delegate).validateDelegate(":radio, :checkbox, select, option","click",delegate);if(this.settings.invalidHandler)$(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler);},form:function(){this.checkForm();$.extend(this.submitted,this.errorMap);this.invalid=$.extend({},this.errorMap);if(!this.valid())$(this.currentForm).triggerHandler("invalid-form",[this]);this.showErrors();return this.valid();},checkForm:function(){this.prepareForm();for(var i=0,elements=(this.currentElements=this.elements());elements[i];i++){this.check(elements[i]);}return this.valid();},element:function(element){element=this.clean(element);this.lastElement=element;this.prepareElement(element);this.currentElements=$(element);var result=this.check(element);if(result){delete this.invalid[element.name];}else{this.invalid[element.name]=true;}if(!this.numberOfInvalids()){this.toHide=this.toHide.add(this.containers);}this.showErrors();return result;},showErrors:function(errors){if(errors){$.extend(this.errorMap,errors);this.errorList=[];for(var name in errors){this.errorList.push({message:errors[name],element:this.findByName(name)[0]});}this.successList=$.grep(this.successList,function(element){return!(element.name in errors);});}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors();},resetForm:function(){if($.fn.resetForm)$(this.currentForm).resetForm();this.submitted={};this.prepareForm();this.hideErrors();this.elements().removeClass(this.settings.errorClass);},numberOfInvalids:function(){return this.objectLength(this.invalid);},objectLength:function(obj){var count=0;for(var i in obj)count++;return count;},hideErrors:function(){this.addWrapper(this.toHide).hide();},valid:function(){return this.size()==0;},size:function(){return this.errorList.length;},focusInvalid:function(){if(this.settings.focusInvalid){try{$(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin");}catch(e){}}},findLastActive:function(){var lastActive=this.lastActive;return lastActive&&$.grep(this.errorList,function(n){return n.element.name==lastActive.name;}).length==1&&lastActive;},elements:function(){var validator=this,rulesCache={};return $([]).add(this.currentForm.elements).filter(":input").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){!this.name&&validator.settings.debug&&window.console&&console.error("%o has no name assigned",this);if(this.name in rulesCache||!validator.objectLength($(this).rules()))return false;rulesCache[this.name]=true;return true;});},clean:function(selector){return $(selector)[0];},errors:function(){return $(this.settings.errorElement+"."+this.settings.errorClass,this.errorContext);},reset:function(){this.successList=[];this.errorList=[];this.errorMap={};this.toShow=$([]);this.toHide=$([]);this.currentElements=$([]);},prepareForm:function(){this.reset();this.toHide=this.errors().add(this.containers);},prepareElement:function(element){this.reset();this.toHide=this.errorsFor(element);},check:function(element){element=this.clean(element);if(this.checkable(element)){element=this.findByName(element.name)[0];}var rules=$(element).rules();var dependencyMismatch=false;for(method in rules){var rule={method:method,parameters:rules[method]};try{var result=$.validator.methods[method].call(this,element.value.replace(/\r/g,""),element,rule.parameters);if(result=="dependency-mismatch"){dependencyMismatch=true;continue;}dependencyMismatch=false;if(result=="pending"){this.toHide=this.toHide.not(this.errorsFor(element));return;}if(!result){this.formatAndAdd(element,rule);return false;}}catch(e){this.settings.debug&&window.console&&console.log("exception occured when checking element "+element.id 
+", check the '"+rule.method+"' method",e);throw e;}}if(dependencyMismatch)return;if(this.objectLength(rules))this.successList.push(element);return true;},customMetaMessage:function(element,method){if(!$.metadata)return;var meta=this.settings.meta?$(element).metadata()[this.settings.meta]:$(element).metadata();return meta&&meta.messages&&meta.messages[method];},customMessage:function(name,method){var m=this.settings.messages[name];return m&&(m.constructor==String?m:m[method]);},findDefined:function(){for(var i=0;i<arguments.length;i++){if(arguments[i]!==undefined)return arguments[i];}return undefined;},defaultMessage:function(element,method){return this.findDefined(this.customMessage(element.name,method),this.customMetaMessage(element,method),!this.settings.ignoreTitle&&element.title||undefined,$.validator.messages[method],"<strong>Warning: No message defined for "+element.name+"</strong>");},formatAndAdd:function(element,rule){var message=this.defaultMessage(element,rule.method),theregex=/\$?\{(\d+)\}/g;if(typeof message=="function"){message=message.call(this,rule.parameters,element);}else if(theregex.test(message)){message=jQuery.format(message.replace(theregex,'{$1}'),rule.parameters);}this.errorList.push({message:message,element:element});this.errorMap[element.name]=message;this.submitted[element.name]=message;},addWrapper:function(toToggle){if(this.settings.wrapper)toToggle=toToggle.add(toToggle.parent(this.settings.wrapper));return toToggle;},defaultShowErrors:function(){for(var i=0;this.errorList[i];i++){var error=this.errorList[i];this.settings.highlight&&this.settings.highlight.call(this,error.element,this.settings.errorClass,this.settings.validClass);this.showLabel(error.element,error.message);}if(this.errorList.length){this.toShow=this.toShow.add(this.containers);}if(this.settings.success){for(var i=0;this.successList[i];i++){this.showLabel(this.successList[i]);}}if(this.settings.unhighlight){for(var i=0,elements=this.validElements();elements[i];i++){this.settings.unhighlight.call(this,elements[i],this.settings.errorClass,this.settings.validClass);}}this.toHide=this.toHide.not(this.toShow);this.hideErrors();this.addWrapper(this.toShow).show();},validElements:function(){return this.currentElements.not(this.invalidElements());},invalidElements:function(){return $(this.errorList).map(function(){return this.element;});},showLabel:function(element,message){var label=this.errorsFor(element);if(label.length){label.removeClass().addClass(this.settings.errorClass);label.attr("generated")&&label.html(message);}else{label=$("<"+this.settings.errorElement+"/>").attr({"for":this.idOrName(element),generated:true}).addClass(this.settings.errorClass).html(message||"");if(this.settings.wrapper){label=label.hide().show().wrap("<"+this.settings.wrapper+"/>").parent();}if(!this.labelContainer.append(label).length)this.settings.errorPlacement?this.settings.errorPlacement(label,$(element)):label.insertAfter(element);}if(!message&&this.settings.success){label.text("");typeof this.settings.success=="string"?label.addClass(this.settings.success):this.settings.success(label);}this.toShow=this.toShow.add(label);},errorsFor:function(element){var name=this.idOrName(element);return this.errors().filter(function(){return $(this).attr('for')==name;});},idOrName:function(element){return this.groups[element.name]||(this.checkable(element)?element.name:element.id||element.name);},checkable:function(element){return/radio|checkbox/i.test(element.type);},findByName:function(name){var form=this.currentForm;return $(document.getElementsByName(name)).map(function(index,element){return element.form==form&&element.name==name&&element||null;});},getLength:function(value,element){switch(element.nodeName.toLowerCase()){case'select':return $("option:selected",element).length;case'input':if(this.checkable(element))return this.findByName(element.name).filter(':checked').length;}return value.length;},depend:function(param,element){return this.dependTypes[typeof param]?this.dependTypes[typeof param](param,element):true;},dependTypes:{"boolean":function(param,element){return param;},"string":function(param,element){return!!$(param,element.form).length;},"function":function(param,element){return param(element);}},optional:function(element){return!$.validator.methods.required.call(this,$.trim(element.value),element)&&"dependency-mismatch";},startRequest:function(element){if(!this.pending[element.name]){this.pendingRequest++;this.pending[element.name]=true;}},stopRequest:function(element,valid){this.pendingRequest--;if(this.pendingRequest<0)this.pendingRequest=0;delete this.pending[element.name];if(valid&&this.pendingRequest==0&&this.formSubmitted&&this.form()){$(this.currentForm).submit();this.formSubmitted=false;}else if(!valid&&this.pendingRequest==0&&this.formSubmitted){$(this.currentForm).triggerHandler("invalid-form",[this]);this.formSubmitted=false;}},previousValue:function(element){return $.data(element,"previousValue")||$.data(element,"previousValue",{old:null,valid:true,message:this.defaultMessage(element,"remote")});}},classRuleSettings:{required:{required:true},email:{email:true},url:{url:true},date:{date:true},dateISO:{dateISO:true},dateDE:{dateDE:true},number:{number:true},numberDE:{numberDE:true},digits:{digits:true},creditcard:{creditcard:true}},addClassRules:function(className,rules){className.constructor==String?this.classRuleSettings[className]=rules:$.extend(this.classRuleSettings,className);},classRules:function(element){var rules={};var classes=$(element).attr('class');classes&&$.each(classes.split(' '),function(){if(this in $.validator.classRuleSettings){$.extend(rules,$.validator.classRuleSettings[this]);}});return rules;},attributeRules:function(element){var rules={};var $element=$(element);for(method in $.validator.methods){var value=$element.attr(method);if(value){rules[method]=value;}}if(rules.maxlength&&/-1|2147483647|524288/.test(rules.maxlength)){delete rules.maxlength;}return rules;},metadataRules:function(element){if(!$.metadata)return{};var meta=$.data(element.form,'validator').settings.meta;return meta?$(element).metadata()[meta]:$(element).metadata();},staticRules:function(element){var rules={};var validator=$.data(element.form,'validator');if(validator.settings.rules){rules=$.validator.normalizeRule(validator.settings.rules[element.name])||{};}return rules;},normalizeRules:function(rules,element){$.each(rules,function(prop,val){if(val===false){delete rules[prop];return;}if(val.param||val.depends){var keepRule=true;switch(typeof val.depends){case"string":keepRule=!!$(val.depends,element.form).length;break;case"function":keepRule=val.depends.call(element,element);break;}if(keepRule){rules[prop]=val.param!==undefined?val.param:true;}else{delete rules[prop];}}});$.each(rules,function(rule,parameter){rules[rule]=$.isFunction(parameter)?parameter(element):parameter;});$.each(['minlength','maxlength','min','max'],function(){if(rules[this]){rules[this]=Number(rules[this]);}});$.each(['rangelength','range'],function(){if(rules[this]){rules[this]=[Number(rules[this][0]),Number(rules[this][1])];}});if($.validator.autoCreateRanges){if(rules.min&&rules.max){rules.range=[rules.min,rules.max];delete rules.min;delete rules.max;}if(rules.minlength&&rules.maxlength){rules.rangelength=[rules.minlength,rules.maxlength];delete rules.minlength;delete rules.maxlength;}}if(rules.messages){delete rules.messages;}return rules;},normalizeRule:function(data){if(typeof data=="string"){var transformed={};$.each(data.split(/\s/),function(){transformed[this]=true;});data=transformed;}return data;},addMethod:function(name,method,message){$.validator.methods[name]=method;$.validator.messages[name]=message!=undefined?message:$.validator.messages[name];if(method.length<3){$.validator.addClassRules(name,$.validator.normalizeRule(name));}},methods:{required:function(value,element,param){if(!this.depend(param,element))return"dependency-mismatch";switch(element.nodeName.toLowerCase()){case'select':var val=$(element).val();return val&&val.length>0;case'input':if(this.checkable(element))return this.getLength(value,element)>0;default:return $.trim(value).length>0;}},remote:function(value,element,param){if(this.optional(element))return"dependency-mismatch";var previous=this.previousValue(element);if(!this.settings.messages[element.name])this.settings.messages[element.name]={};previous.originalMessage=this.settings.messages[element.name].remote;this.settings.messages[element.name].remote=previous.message;param=typeof param=="string"&&{url:param}||param;if(previous.old!==value){previous.old=value;var validator=this;this.startRequest(element);var data={};data[element.name]=value;$.ajax($.extend(true,{url:param,mode:"abort",port:"validate"+element.name,dataType:"json",data:data,success:function(response){validator.settings.messages[element.name].remote=previous.originalMessage;var valid=response===true;if(valid){var submitted=validator.formSubmitted;validator.prepareElement(element);validator.formSubmitted=submitted;validator.successList.push(element);validator.showErrors();}else{var errors={};var message=(previous.message=response||validator.defaultMessage(element,"remote"));errors[element.name]=$.isFunction(message)?message(value):message;validator.showErrors(errors);}previous.valid=valid;validator.stopRequest(element,valid);}},param));return"pending";}else if(this.pending[element.name]){return"pending";}return previous.valid;},minlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)>=param;},maxlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)<=param;},rangelength:function(value,element,param){var length=this.getLength($.trim(value),element);return this.optional(element)||(length>=param[0]&&length<=param[1]);},min:function(value,element,param){return this.optional(element)||value>=param;},max:function(value,element,param){return this.optional(element)||value<=param;},range:function(value,element,param){return this.optional(element)||(value>=param[0]&&value<=param[1]);},email:function(value,element){return this.optional(element)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);},url:function(value,element){return this.optional(element)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);},date:function(value,element){return this.optional(element)||!/Invalid|NaN/.test(new Date(value));},dateISO:function(value,element){return this.optional(element)||/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);},number:function(value,element){return this.optional(element)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);},digits:function(value,element){return this.optional(element)||/^\d+$/.test(value);},creditcard:function(value,element){if(this.optional(element))return"dependency-mismatch";if(/[^0-9-]+/.test(value))return false;var nCheck=0,nDigit=0,bEven=false;value=value.replace(/\D/g,"");for(var n=value.length-1;n>=0;n--){var cDigit=value.charAt(n);var nDigit=parseInt(cDigit,10);if(bEven){if((nDigit*=2)>9)nDigit-=9;}nCheck+=nDigit;bEven=!bEven;}return(nCheck%10)==0;},accept:function(value,element,param){param=typeof param=="string"?param.replace(/,/g,'|'):"png|jpe?g|gif";return this.optional(element)||value.match(new RegExp(".("+param+")$","i"));},equalTo:function(value,element,param){var target=$(param).unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){$(element).valid();});return value==target.val();}}});$.format=$.validator.format;})(jQuery);;(function($){var ajax=$.ajax;var pendingRequests={};$.ajax=function(settings){settings=$.extend(settings,$.extend({},$.ajaxSettings,settings));var port=settings.port;if(settings.mode=="abort"){if(pendingRequests[port]){pendingRequests[port].abort();}return(pendingRequests[port]=ajax.apply(this,arguments));}return ajax.apply(this,arguments);};})(jQuery);;(function($){if(!jQuery.event.special.focusin&&!jQuery.event.special.focusout&&document.addEventListener){$.each({focus:'focusin',blur:'focusout'},function(original,fix){$.event.special[fix]={setup:function(){this.addEventListener(original,handler,true);},teardown:function(){this.removeEventListener(original,handler,true);},handler:function(e){arguments[0]=$.event.fix(e);arguments[0].type=fix;return $.event.handle.apply(this,arguments);}};function handler(e){e=$.event.fix(e);e.type=fix;return $.event.handle.call(this,e);}});};$.extend($.fn,{validateDelegate:function(delegate,type,handler){return this.bind(type,function(event){var target=$(event.target);if(target.is(delegate)){return handler.apply(target,arguments);}});}});})(jQuery); 
 
jQuery.validator.addMethod("alpha", function(value, element) { 
	return this.optional(element) || /^[a-z\s]+$/i.test(value); 
}, "Letters only please");  
 
jQuery.validator.addMethod("alphanumeric", function(value, element) { 
	return this.optional(element) || /^[a-z0-9\s]+$/i.test(value); 
}, "Letters and numbers only please");   
 
jQuery.validator.addMethod("alphapunctuation", function(value, element) { 
	return this.optional(element) || /^[a-z.,?!:;\-_()\[\]'\"/\s]+$/i.test(value); 
}, "Letters and punctuation only please"); 
 
jQuery.validator.addMethod("alphanumericpunctuation", function(value, element) { 
	return this.optional(element) || /^[a-z0-9.,?!:;\-_()\[\]'\"/\s]+$/i.test(value); 
}, "Letters, numbers and punctuation only please"); 
 
jQuery.validator.addMethod("password", function(value, element) { 
	return this.optional(element) || /^[\S]{6,}$/.test(value); 
}, "At least 6 characters with no spaces please"); 
 
(function() { 
	 
	function stripHtml(value) { 
		// remove html tags and space chars 
		return value.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;|&#160;/gi, ' ') 
		// remove numbers and punctuation 
		.replace(/[0-9.(),;:!?%#$'"_+=\/-]*/g,''); 
	} 
	 
	jQuery.validator.addMethod("maxWords", function(value, element, params) {  
	    return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length < params;  
	}, jQuery.validator.format("Please enter {0} words or less."));  
	  
	jQuery.validator.addMethod("minWords", function(value, element, params) {  
	    return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length >= params;  
	}, jQuery.validator.format("Please enter at least {0} words."));  
	  
	jQuery.validator.addMethod("rangeWords", function(value, element, params) {  
	    return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length >= params[0] && value.match(/bw+b/g).length < params[1];  
	}, jQuery.validator.format("Please enter between {0} and {1} words.")); 
 
})(); 
 
function errorMessages (error, element) { 
  var field = element.attr("name"); 
  $("#"+field+"Error").empty(); 
  error.prependTo($("#"+field+"Error")); 
} 
 
function formField (action, field, require) { 
  if (action == 'enable') { 
    $("#"+field).removeAttr("disabled").removeAttr("readonly").css("background-color", "#FFF"); 
    if (require === true) $("#"+field).addClass("reqd").rules("add",{required:true}); 
  } else if (action == 'disable') { 
    $("#"+field).val("").attr({"disabled":"disabled", "readonly":"readonly"}).css("background-color", "#CCC").removeClass("reqd error").rules("remove", "required"); 
    $("#"+field+"Error").empty(); 
  } 
} 
 
function validateCaptcha (form) { 
  var captcha = $.ajax({ 
    type: "POST", 
    url: location.href, 
    data: "recaptcha_challenge_field=" + $("input#recaptcha_challenge_field").val() + "&recaptcha_response_field=" + $("input#recaptcha_response_field").val() + "&ajax=request", 
    async: false 
  }).responseText; 
  if (captcha == "success") { 
    $(this.form).submit(); 
    return true; 
  } else { 
    $("#recaptchaError").empty().prepend(captcha); 
    Recaptcha.reload(); 
    return false; 
  } 
} 
 
(function($) { 
  $.fn.hierSelect = function(select, options) { 
    $(this).change(function() { 
      var id = $(this).val(); 
      var hier = $("select[name=" + select + "]"); 
      hier.each(function(){ 
        hier.children().remove(); 
        if (id != "") $.each(options[id], function(key,value){hier.append($("<option>").attr("value",key).html(value));}); 
      }); 
    }); 
  }; 
})(jQuery);

Form.php

<?php 
 
/* 
 *    author:		Kyle Gadd 
 *    documentation:	http://www.php-ease.com/classes/form.html 
 * 
 *    This program is free software: you can redistribute it and/or modify 
 *    it under the terms of the GNU General Public License as published by 
 *    the Free Software Foundation, either version 3 of the License, or 
 *    (at your option) any later version. 
 * 
 *    This program is distributed in the hope that it will be useful, 
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *    GNU General Public License for more details. 
 * 
 *    You should have received a copy of the GNU General Public License 
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */ 
 
include_once ('Page.php'); 
include_once ('Validation.php'); 
 
class Form { 
 
  private $required = array(); 
  private $values = array(); 
  private $check = array(); 
  private $process = array(); 
  private $upload = array(); 
  private $filesize = false; 
  private $vars = array(); 
  private $errors = array(); 
  private $headervars = ''; 
  private $prompt = ''; 
 
  function __construct ($class='') { 
    if (!empty($class)) $this->headervars = ' class="' . $class . '"'; 
  } 
 
  public function required ($required) { 
    if (is_array($required)) { 
      foreach ($required as $value) { 
        $this->required[] = $value; 
        // if ($value == 'recaptcha') include_once (BASE . 'include/functions/recaptcha.php'); 
      } 
    } 
  } 
 
  public function values ($values=array()) { 
    if (!empty($values) && is_array($values)) foreach ($values as $name => $value) $this->values[$name] = $value; 
    return $this->values; 
  } 
 
  public function check ($check) { 
    if (is_array($check)) foreach ($check as $name => $filter) $this->check[$name] = $filter; 
  } 
 
  public function process ($process) { 
    if (is_array($process)) foreach ($process as $name => $filter) $this->process[$name] = $filter; 
  } 
 
  public function upload ($upload, $filesize=5) { 
    if (is_array($upload)) foreach ($upload as $name => $filter) $this->upload[$name] = $filter; 
    if ($filesize > 0) $this->filesize = $filesize; 
  } 
 
  public function validate ($form, $function='escape_data') { 
    if (empty($function) || !function_exists($function)) $function = false; 
    $validate = new Validation; 
    if (in_array('recaptcha', $this->required)) { 
      $error = $validate->recaptcha(); 
      if (!empty($error)) $this->errors['recaptcha'] = $error; 
    } 
    $validate->jquery($form, $this->check, $this->required, $this->upload); 
    list($vars, $errors, $eject) = $validate->form(array('post'=>$form), $this->check, $this->required); 
    $this->errors = array_merge($this->errors, $errors); 
    foreach ($vars as $name => $value) { 
      if (is_array($value)) { 
        foreach ($value as $key => $data) { 
          $this->vars[$name][$key] = ($function) ? $function($data) : $data; // to ship out 
          $this->values[$name][$key] = $data; // to preselect 
        } 
      } else { 
        $this->vars[$name] = ($function) ? $function($value) : $value; // to ship out 
        $this->values[$name] = $value; // to preselect 
      } 
    } 
    if (isset($_POST['process'])) { 
      foreach ($this->process as $name => $filter) { 
        foreach ($_POST['process'] as $id) { 
          $value = (isset($_POST[$name][$id]) && !empty($_POST[$name][$id])) ? $validate->data($filter, $_POST[$name][$id]) : $validate->data($filter, ''); // so we at least get the default value of $filter 
          $this->vars['process'][$id][$name] = ($function) ? $function($value) : $value; // ship only, no preselect 
        } 
      } 
    } 
    foreach ($this->upload as $file => $types) { 
      list($filename, $error) = $validate->upload($file, $types); 
      if (!empty($filename)) { 
        $this->vars[$file] = $filename; 
      } elseif (!empty($error)) { 
        if (in_array($file, $this->required)) $this->errors[$file] = $error; 
        trigger_error("The file name '{$_FILES[$file]['name']}', type '{$_FILES[$file]['type']}', size '{$_FILES[$file]['size']}', and tmp_name '{$_FILES[$file]['tmp_name']}' had the following error: {$error}"); 
      } 
    } 
    unset($validate); 
    return array($this->vars, $this->errors, $eject); 
  } 
 
  public function error ($name='', $message='') { 
    if (!empty($name)) $this->errors[$name] = $message; 
    return $this->errors; 
  } 
 
  public function prompt ($size) { 
    $this->prompt = (int) $size . 'px'; 
  } 
 
  public function header ($name, $method='post', $action='') { 
    global $page; 
    if (empty($method) || $method != 'get') $method = 'post'; 
    if (!empty($name) && empty($action) && $method == 'post') { 
      $action = $page->url('add', '', 'submitted', $name); 
    } 
    $form = "\n  " . '<form id="'.$name.'" method="'.$method.'" action="'.$action.'"'; 
    if ($this->filesize && $method == 'post') { 
      $form .= ' enctype="multipart/form-data"'; 
      $maxsize = $this->hidden('MAX_FILE_SIZE', $this->filesize * 1024000, ''); 
    } 
    $form .= $this->headervars . '>'; 
    $form .= '<fieldset style="border:0px; padding:0px;"><legend style="display:none;">&nbsp;</legend>'; 
    if (isset($maxsize)) $form .= $maxsize; 
    $form .= $this->hidden($name, 'true', ''); 
    if (!empty($this->prompt)) { 
      $page->link('<style type="text/css"> #' . $name . ' label.prompt { width:' . $this->prompt . '; display:inline-block; } </style>'); 
    } 
    return $form; 
  } 
 
  public function field ($type, $name, $prompt='', $options='', $key='') { 
    $field = "\n  "; 
    if (!in_array($type, array('calendar', 'checkbox', 'file', 'hidden', 'hierselect', 'multicheck', 'multiselect', 'multitext', 'password', 'radio', 'select', 'submit', 'text', 'textarea')) || empty($name)) return $field; 
    if (!in_array($type, array('hidden', 'multicheck', 'multiselect', 'multitext', 'submit'))) { 
      $field .= '<span id="' . $name . 'Error">'; 
      if (isset($this->errors[$name])) { 
        if (in_array($type, array('hierselect', 'select'))) $this->errors[$name] = 'Please make a selection.'; 
        $field .= '<label class="error">' . $this->errors[$name] . '</label>'; 
      } 
      $field .= '</span>'; 
      if (in_array($name, $this->required) && !empty($prompt)) $prompt = '<span class="required">*</span> ' . $prompt; 
    } 
    if ($type == 'checkbox') { 
      return $field . $this->$type($name, $prompt, $options); 
    } elseif ($type == 'hidden') { 
      return $this->$type($name, $prompt, $options); 
    } elseif ($type == 'multicheck') { 
      return $this->$type($name, $prompt, $options, $key); 
    } elseif ($type == 'multitext') { 
      return $this->$type($name, $prompt, $options, $key); 
    } elseif ($type == 'radio') { 
      return $field . $this->$type($name, $prompt, $options); 
    } elseif ($type == 'submit') { 
      return $this->$type($name, $prompt); 
    } else { 
      if (!empty($prompt)) { 
        $br = (substr($prompt, -6) == '<br />') ? '<br />' : ''; 
        if (!empty($br)) $prompt = substr($prompt, 0, -6); 
        $field .= '<label for="' . $name . '" class="prompt">' . trim($prompt) . '</label>' . $br; 
      } 
      return $field . $this->$type($name, $options); 
    } 
  } 
 
  public function recaptcha () { 
    $field = "\n  "; 
    if (!function_exists('recaptcha_get_html')) return $field; 
    $field .= '<div id="recaptchaError">'; 
    if (isset($this->errors['recaptcha'])) $field .= '<label class="error">' . $this->errors['recaptcha'] . '</label>'; 
    $field .= '</div>'; 
    $field .= recaptcha_get_html (RECAPTCHA_PUBLIC_KEY); 
    return $field; 
  } 
 
  public function close ($html='') { 
    $form = $html; 
    $form .= '</fieldset>'; 
    $form .= "\n  " . '</form>'; 
    return $form; 
  } 
 
  #--Private Form Functions--# 
 
  private function calendar ($name, $options) { 
    global $page; 
    $page->jquery('$("#' . $name . '").datepicker({onClose:function(){$(this).valid();}});'); 
    return $this->text($name, array('width'=>100, 'maxlength'=>10)); 
    return $form; 
  } 
 
  private function checkbox ($name, $prompt, $options) { 
    $field = ''; 
    if (is_array($options)) { 
      list($value, $description) = each($options); // only one at a time 
      if (!empty($prompt)) $field .= '<label for="' . $name . '" class="prompt">' . $prompt . '</label>'; 
      $field .= '<label><input type="checkbox" id="'.$name.'" name="'.$name.'" value="'.$value.'"' . $this->defaultValue('checkbox', $name, $value) . ' /> ' . $description . '</label>'; 
    } 
    return $field; 
  } 
 
  private function file ($name, $options) { 
    $width = (isset($options['size'])) ? $options['size'] : 50; 
    return '<input type="file" id="'.$name.'" name="'.$name.'" size="'.$width.'" />'; 
  } 
 
  private function hidden ($name, $prompt, $options) { 
    if ($name == 'process') $name = 'process[]'; 
    $id = (isset($options['id'])) ? ' id="' . $options['id'] . '"' : ' '; // for javascript 
    return '<input type="hidden" name="'.$name.'" value="'.$prompt.'"' . $id . '/>'; 
  } 
 
  private function hierselect ($name, $options) { 
    global $page; 
    $json = array(); 
    foreach ($options[0] as $id => $main) { 
      $hier = (isset($options['empty'])) ? array() : array(''=>'&nbsp;'); 
      if (isset($options[$id])) foreach ($options[$id] as $key => $value) $hier[$key] = $value; 
      $json[$id] = $hier; 
    } 
    $page->jquery('$("#' . $name . '").hierSelect("' . $options['hier'] . '", ' . json_encode($json) . ');'); 
    $select = $options[0]; 
    if (isset($options['empty'])) $select['empty'] = false; 
    return $this->select($name, $select); 
  } 
 
  private function multicheck ($name, $prompt, $options, $key) { 
    $field = '<input type="checkbox" name="'.$name.'['.$key.']" value="'.$options.'" />'; 
    if (!empty($prompt)) $field = "<label>{$field} {$prompt}</label>"; 
    return $field; 
  } 
 
  private function multiselect ($name, $options) { 
    $size = (count($options) < 15) ? count($options) : 15; 
    $field = '<select id="'.$name.'" name="'.$name.'[]" multiple="multiple" size="'.$size.'">'; 
    foreach ($options as $key => $value) if (!empty($key)) $field .= '<option value="'.$key.'"' . $this->defaultValue('select', $name, $key) . '>'.$value.'</option>'; 
    $field .= '</select>'; 
    return $field; 
  } 
 
  private function multitext ($name, $prompt, $options, $key) { 
    $class = (isset($options['class'])) ? ' class="' . $options['class'] . '"' : ' '; 
    $width = 'style="width:250px;"'; 
    if (isset($options['width'])) $width = 'style="width:' . $options['width'] . 'px;"'; 
    if (isset($options['size'])) $width = 'size="' . $options['size'] . '"'; 
    $maxlength = (isset($options['maxlength'])) ? $options['maxlength'] : 50; 
    $value = (isset($options['value']) && !empty($options['value'])) ? stripslashes(htmlspecialchars(htmlspecialchars_decode($options['value']))) : ''; 
    $field = (!empty($prompt)) ? '<label class="prompt">' . $prompt . '</label>' : ''; 
    return $field . '<input type="text"' . $class . 'name="'.$name.'['.$key.']" '.$width.' maxlength="'.$maxlength.'" value="'.$value.'" />'; 
  } 
 
  private function password ($name, $options) { 
    $width = 'style="width:100px;"'; 
    if (isset($options['width'])) $width = 'style="width:' . $options['width'] . 'px;"'; 
    if (isset($options['size'])) $width = 'size="' . $options['size'] . '"'; 
    $maxlength = (isset($options['maxlength'])) ? $options['maxlength'] : 20; 
    return '<input type="password" id="'.$name.'" name="'.$name.'" '.$width.' maxlength="'.$maxlength.'" />'; 
  } 
 
  private function radio ($name, $prompt, $options) { 
    $field = ''; 
    if (!empty($prompt)) $field .= '<label class="prompt">' . trim($prompt) . '</label>'; 
    $radios = array(); 
    foreach ($options as $value => $description) { 
      $radios[] = '<label><input type="radio" name="'.$name.'" value="'.$value.'"' . $this->defaultValue('radio', $name, $value) . ' /> ' . $description . '</label>'; 
    } 
    if (!empty($prompt)) { 
      $combine = (!empty($this->prompt)) ? '<br /><label class="prompt">&nbsp;</label>' : '&nbsp;&nbsp;&nbsp;'; 
      $field .= implode($combine, $radios); 
    } else { 
      $field .= implode('<br />', $radios); 
    } 
    return $field; 
  } 
 
  private function select ($name, $options) { 
    $field = '<select id="'.$name.'" name="'.$name.'"'; 
    if (isset($onchange)) $field .= $onchange; 
    if (in_array($name, $this->required)) $field .= ' title="Please make a selection."'; 
    $field .= (isset($options['empty'])) ? '>' : '><option value="">&nbsp;</option>'; 
    foreach ($options as $key => $value) { 
      if ($key != 'empty') $field .= '<option value="'.$key.'"' . $this->defaultValue('select', $name, $key) . '>'.$value.'</option>'; 
    } 
    $field .= '</select>'; 
    return $field; 
  } 
 
  private function submit ($name, $prompt) { 
    $field = "\n  "; 
    if (!empty($prompt)) $field .= '<label class="prompt">' . $prompt . '</label>'; 
    return $field . '<input type="submit" name="submit" class="submit" value="'.$name.'" />'; 
  } 
 
  private function text ($name, $options) { 
    $width = 'style="width:200px;"'; 
    if (isset($options['width'])) $width = 'style="width:' . $options['width'] . 'px;"'; 
    if (isset($options['size'])) $width = 'size="' . $options['size'] . '"'; 
    $maxlength = (isset($options['maxlength'])) ? $options['maxlength'] : 50; 
    return '<input type="text" id="'.$name.'" name="'.$name.'" '.$width.' maxlength="'.$maxlength.'"' . $this->defaultValue('text', $name) . ' />'; 
  } 
 
  private function textarea ($name, $options) { 
    $cols = (isset($options['cols'])) ? $options['cols'] : 60; 
    $rows = (isset($options['rows'])) ? $options['rows'] : 7; 
    $width = (isset($options['width'])) ? $options['width'] : 400; 
    $height = (isset($options['height'])) ? $options['height'] : 200; 
    if (isset($options['cols']) && !isset($options['width'])) $width = false; 
    if (isset($options['rows']) && !isset($options['height'])) $height = false; 
    $dimensions = ' cols="' . $cols . '" rows="' . $rows . '"'; // because these are required attributes 
    if ($width || $height) { 
      $dimensions .= ' style="'; 
      if ($width) $dimensions .= 'width:' . $width . 'px;'; 
      if ($height) $dimensions .= 'height:' . $height . 'px;'; 
      $dimensions .= '"'; 
    } 
    return '<textarea id="'.$name.'" name="'.$name.'"' . $dimensions . '>' . $this->defaultValue('textarea', $name) . '</textarea>'; 
  } 
 
  private function defaultValue ($type, $name, $select='') { 
    $default = ''; 
    if (isset($this->values[$name]) || isset($_POST[$name])) { 
      $selected = (isset($_POST[$name])) ? $_POST[$name] : $this->values[$name]; 
      if (empty($select)) { // then this is a text field 
        if (!isset($_POST[$name])) $selected = htmlspecialchars_decode($selected); 
        $value = stripslashes(htmlspecialchars($selected)); 
      } else { // we may preselect this option 
        if (is_array($selected)) { 
          $value = (in_array($select, $selected)) ? true : false; 
        } else { 
          $value = ($selected == $select) ? true : false; 
        } 
      } 
      if (!empty($value)) { 
        switch ($type) { 
          case 'checkbox': $default .= ' checked="checked"'; break; 
          case 'radio': $default .= ' checked="checked"'; break; 
          case 'select': $default .= ' selected="selected"'; break; 
          case 'text': $default .= ' value="' . $value . '"'; break; 
          case 'textarea': $default .= $value; break; 
        } 
      } 
    } 
    return $default; 
  } 
 
} 
 
?>

comments powered by Disqus
Copyright © 2011 PHP-Ease.com - PHP Made Easy