Chapter 3 - Pursue Über Form

Create the ultimate form using all basic html form elements. Make several required fields, allow all fields the ability to be “sticky”. Use a function to generate all form fields. Validate all data and present errors and messages to user based on their submission.

Output
Bicycle Survey
  1. How far do you ride your bike in an average week? (in miles) *




  2. What's the single longest bike ride you've ever done? (in miles) *





  3. Describe yourself as a biker *
  4. Type(s) of bicycles you own. (Select all that apply) *










  5. How do you use your bicycle? (check all that apply) *





  6. Are you comfortable riding on the city streets? *




  7. In the city, where do you mainly ride your bike?
  8. Are you in favor of bike lanes in the city?



  9. How confident are you riding your bike? (0=not confident at all and 100=I can slalom no handed on a fixie going down hill.)
    0100
  10. What's your favorite thing about riding your bike?
  11. If you'd like to receive results of this survey, please provide your email address
Source
<?php # Chapter 3 Pursue - extra credit 
/**
* recursive function that outputs a single input form element or multiple elements (as in a radio group) if passed an array
*
* @param string $type the value of the input type attribute(text,radio,checkbox,password,submit,reset,etc...)
* @param mixed $value the value passed to the server upon submission
* @param mixed $label the label for the input, can be null
* @param string $name the name used to identify this input element on the form, the key in the submission array
* @param array $attr any further attributes this input element requires in an associative array
* @param integer $count used to prevent input id from being output more than once for radio or checkbox inputs
*/
function create_input($type, $value ,$label, $name, $attr=array(),$count=1) {
	$valid_types = array('text','radio','checkbox','button','hidden','password','reset','submit','file','image');
	$valid_types_HTML5 = array('range','tel','number','search','color','date','datetime','datetime-local','month','week','time','url','email');
	if(in_array($type,$valid_types) || in_array($type, $valid_types_HTML5)) {
		$name_str=str_replace('[]','',$name);//remove the array notifier to allow match in POST variable
		if(is_array($value)) {
			$input = array_combine($value,$label);
			foreach ($input as $val_key=>$val_label) {
				create_input($type,$val_key,$val_label, $name, $attr=array(),$count);
				echo "<br />";
				$count++;
			}
			return;
		}
		echo '<input id="'.$name_str.'-'.$count.'" type="'.$type.'" name="' .$name.'"';
		// set submitted value if $_POST:
		if(isset($_POST[$name_str])){
			if($_POST[$name_str] == $value && $type=='radio') {
				echo ' checked="checked"';
			} elseif ($type=='checkbox'){
				if((is_array($_POST[$name_str]) && in_array($value,$_POST[$name_str])) || $value==$_POST[$name_str]){
					echo ' checked="checked"';
				} 	
			} else {
				$value = $_POST[$name_str];
			}
		}
		echo ' value="'.$value.'"';
		//include any additional attributes from the associative array
		if(!empty($attr)){
			foreach($attr as $key=>$value){
				echo " $key='$value'";
			}
		}
		echo " />";
		echo $label?'<label for="'.$name_str.'-'.$count.'">'.$label.'</label>':'';
	} else {
		// echo "This is not a valid input type.";
	}
}
/**
 * outputs a select form element
 *  
 * @param  string $name the name of the select element
 * @param  array  $val_list the array of option values
 * @param  array  $text_list the array of option labels(text presented to user)
 * @param  array  $attr an associative array of any further needed attributes
 * @param  string $selected_default the value of the default selected option
 */
function create_select($name, $val_list=array(), $text_list=array(), $attr=array(), $selected_default=null) {
	$name_str=str_replace('[]','',$name);//remove the array notifier to allow match in POST variable
	echo '<select name="' .$name.'"';
	//include any additional attributes from the associative array
	if(!empty($attr)){
		foreach($attr as $key=>$value){
			echo " $key='$value'";
		}
	}
	echo '>';
	//output the options 
	$options = array_combine($val_list, $text_list);
	if(!empty($attr) && (in_array('required', $attr))) {
		echo '<option value="">Please select</option>';
	}
	foreach($options as $key=>$value){
		echo "<option";
		if( isset($_POST[$name_str]) && ($_POST[$name_str]==$key || (is_array($_POST[$name_str]) && in_array($key,$_POST[$name_str]))) ) {
			echo ' selected="selected"'; 
		} elseif(!isset($_POST[$name_str]) && $selected_default==$key) {
			echo ' selected="selected"';
		}
		echo ' value="'.$key.'">'.$value.'</option>';
	}
	echo "</select>";
}
/**
 * output a textarea form element
 * @param  string  $name the name of the element
 * @param  integer $rows the number of rows
 * @param  integer $cols the number of columns
 * @param  string  $value the value used to fill the textarea
 * @param  array   $attr an associative array containing any further attributes (rec placeholder as default textarea fill)
 */
function create_textarea($name, $rows = 4, $cols = 30, $value = '', $attr = array() ) {
	echo "<textarea name=$name rows=$rows cols=$cols";
	if(!empty($attr)){
		foreach($attr as $key=>$value){
			echo " $key='$value'";
		}
	}
	echo ">";
	if(isset($_POST[$name])){
		$value=html_entity_decode($_POST[$name]);
		echo $value;
	}
	echo "</textarea>";
}

function isValidEmail($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL) && preg_match('/@.+\./', $email);
}
$error = array();
$message= '';
// Check for form submission, validate data and format error messages
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
	$distance = (isset($_POST['distance']))?$_POST['distance']:null;
	$longest = (isset($_POST['longest']))?$_POST['longest']:null;
	$experience = (isset($_POST['experience']))?implode(',',$_POST['experience']):null;
	$bike_style = (isset($_POST['bike_style']))?implode(',',$_POST['bike_style']):null;
	$use = (isset($_POST['use']))?implode(',',$_POST['use']):null;
	$comfort = (isset($_POST['comfort']))?$_POST['comfort']:null;
	$location = (isset($_POST['location']))?$_POST['location']:null;
	$bike_lanes = (isset($_POST['bike_lanes']))?$_POST['bike_lanes']:null;
	$message .= ($bike_lanes=='yes')?'<br />Thanks for supporting bike lanes in your community!':'';
	$skill = (isset($_POST['skill']))?$_POST['skill']:null;
	$comment = (isset($_POST['comment']))?htmlentities(str_replace('|','-', $_POST['comment'])):null;
	if(isset($_POST['email_address']) && $_POST['email_address']!='' ) {
		$email = (filter_var($_POST['email_address'], FILTER_VALIDATE_EMAIL))?$_POST['email_address']:null;
		if($email==null) {
			$error['email']="Not a valid email address.";
		} else {
			$message .= "<br />An email with our survey results will be sent to $email .(not really)";
		}
	} else {
		$email = null;
	}
	if(!$distance || !$longest || !$experience || !$bike_style || !$use || !$comfort) {
		$error['required'] = '<p class="error">Please complete all <span class="required">required*</span> fields.</p>';
	}
	if(empty($error)) {
		$_POST['submitted']  = 'true';
		$message = '<p>Thanks for your contribution to our survey! '.$message.'</p><p>Your input will be added anonymously to our study.</p>';
		echo '<div class="message">'.$message.'</div>';
		// save data as pipe delimeted csv to .txt file for future processing.
		$data = $distance.'|'.$longest.'|'.$experience.'|'.$bike_style.'|'.$use.'|'.$comfort.'|'.$location.'|'.$bike_lanes.'|'.$skill.'|'.$comment.'|'.$email."\n";
		$handle = fopen(CHAPTER_PATH.'/'.$chapter.'/survey_results.txt', "a") or die("Couldn't open for writing.");
		fwrite($handle, $data) or die("Couldn't append values to file!");
		fclose($handle);
	} else {
		echo '<p class="error">Your submission could not be completed.<br />Please double check your entries and try again.</p>';
		echo (isset($error['required']))?'<p>'.$error['required'].'</p>':'';
	}	
} 
?>
<form id="bike_survey" name="bike_survey" novalidate action="#" method="post">
	<fieldset><legend>Bicycle Survey</legend>
		<ol class="form-data">
		<li>
			<div class="form-question">
				How far do you ride your bike in an average week? (in miles)
				<span class="required">*</span>
			</div>
			<div class="form-response">
			<?php 
				$distance_val = array('1','2','3','4');
				$distance_label = array('&lt;10','10-25','26-50','&gt;50');
				create_input('radio',$distance_val,$distance_label,'distance',array('required'=>'required'));
			?>
			</div>
		</li>
		<li>
			<div class="form-question">
				What's the single longest bike ride you've ever done? (in miles)
				<span class="required">*</span>
			</div>
			<div class="form-response">
			<?php 
			$longest_val = array('1','2','3','4','5');
			$longest_label = array('&lt;10','10-25','26-50','51-100','I\'ve done extensive touring.');
			create_input('radio',$longest_val,$longest_label,'longest',array('required'=>'required'));
			?>
			</div>
		</li>
		<li>
			<div class="form-question">
				Describe yourself as a biker
				<span class="required">*</span>
			</div>
			<div class="form-response">
			<?php 
			$experience_val = array('none','casual','commuter','athlete');
			$experience_label = array('Not a cyclist','Casual rider','Dedicated commuter','Competitive athlete');
			create_select('experience[]',$experience_val,$experience_label,array('required'=>'required'));?>
			</div>
		</li>
		<li>
			<div class="form-question">
				Type(s) of bicycles you own. (Select all that apply)
				<span class="required">*</span>
			</div>
			<div class="form-response">
			<?php
			$bike_style_val= array('road','single-speed','cruiser','hybrid','cargo','mountain','fixed','folding','chopper','none');
			$bike_style_label= array('Road/Touring','Single Speed','Cruiser','Hybrid','Cargo','Mountain','Fixed Gear','Folding','Chopper','I don\'t own a bicycle.');
			create_input('checkbox',$bike_style_val,$bike_style_label,'bike_style[]',array('required'=>'required'));
			?>
			</div>
		</li>
		<li>
			<div class="form-question">
				How do you use your bicycle? (check all that apply)
				<span class="required">*</span>
			</div>
			<div class="form-response">
			<?php 
			$use_val = array('transport','leisure','exercise','competition','hauling');
			$use_label = array('Transportation','Leisure','Exercise','Competition','Hauling');
			create_input('checkbox',$use_val,$use_label,'use[]',array('required'=>'required'));
			?>
			</div>
		</li>
		<li>
			<div class="form-question">
				Are you comfortable riding on the city streets?
				<span class="required">*</span>
			</div>
			<div class="form-response">
			<?php
			$comfort_val=array('100','66','33','1');
			$comfort_label = array("Yes - I ride everywhere and assert my legal rights.","Yes but I avoid streets with lots of traffic.","No - I avoid riding on the street.","No - I don't ride on the street because it is too dangerous.");
			create_input("radio",$comfort_val,$comfort_label,'comfort',array('required'=>'required'));
			?>
			</div>
		</li>
		<li>
			<div class="form-question">
				In the city, where do you mainly ride your bike?
			</div>
			<div class="form-response">
			<?php
			$locations = array("road","bike_lanes","bike_paths","sidewalk");
			$text = array("On the road with other vehicular traffic","Only on streets with designated bike lanes","On bike trails or dedicated bike paths","On the sidewalk");
			create_select('location',$locations,$text,null);?>
			</div>
		</li>
		<li>
			<div class="form-question">
				Are you in favor of bike lanes in the city?
			</div>
			<div class="form-response">
			<?php create_input('radio',array('yes','no','undecided'),array('Yes','No - there is not enough room for cars and bikes to share the city streets.','Undecided'),'bike_lanes');?>
			</div>
		</li>
		<li>
			<div class="form-question">
				How confident are you riding your bike? (0=not confident at all and 100=I can slalom no handed on a fixie going down hill.)
			</div>
			<div class="form-response">
			0<?php create_input('range','50','','skill',array('min'=>'0','max'=>'100','step'=>'10'))?>100
			</div>
		</li>
		<li>
			<div class="form-question">
				What's your favorite thing about riding your bike?
			</div>
			<div class="form-response">
			<?php create_textarea('comment',5,50,'',array('placeholder'=>'I love to ride my bike because...'));?>
			</div>
		</li>
		<li>
			<div class="form-question">
				If you'd like to receive results of this survey, please provide your email address
			</div>
			<div class="form-response">
			<?php create_input('email',null,'Your email','email_address',array('placeholder'=>'example@yourdomain.com','size'=>'60'));?>
			<?php echo (isset($error['email'])?'<div class="error">'.$error['email'].'</div>':''); ?>
			</div>
		</li>
	</ol>
	</fieldset>
		<?php ($_SERVER['REQUEST_METHOD'] != 'POST')?create_input('reset','Reset','','reset',''):''; //only sets values to original if form has not yet been submitted. ?>
		<?php create_input('hidden','false','','submitted'); ?>
		<?php ($_SERVER['REQUEST_METHOD'] != 'POST' || $_POST['submitted'] == 'false')?create_input('submit','Submit','','submit',''):''; ?>
</form>