• Feed RSS
Showing posts with label PHP. Show all posts
Showing posts with label PHP. Show all posts

PHP Database Access: Are You Doing It Correctly?

We've covered PHP's PDO API a couple of times here on Nettuts+, but, generally, those articles focused more on the theory, and less on the application. This article will fix that!
To put it plainly, if you're still using PHP's old mysql API to connect to your databases, read on!


What?

It's possible that, at this point, the only thought in your mind is, "What the heck is PDO?" Well, it's one of PHP's three available APIs for connecting to a MySQL database. "Three," you say? Yes; many folks don't know it, but there are three different APIs for connecting:
  • mysql
  • mysqli – MySQL Improved
  • pdo – PHP Data Objects
The traditional mysql API certainly gets the job done, and has become so popular largely due to the fact that it makes the process of retrieving some records from a database as easy as possible. For example:
/*
 * Anti-Pattern
 */

# Connect
mysql_connect('localhost', 'username', 'password') or die('Could not connect: ' . mysql_error());

# Choose a database
mysql_select_db('someDatabase') or die('Could not select database');

# Perform database query
$query = "SELECT * from someTable";
$result = mysql_query($query) or die('Query failed: ' . mysql_error());

# Filter through rows and echo desired information
while ($row = mysql_fetch_object($result)) {
    echo $row->name;
}
Yes, the code above is fairly simple, but it does come with its significant share of downsides.
  • Deprecated: Though it hasn't been officially deprecated – due to widespread use – in terms of best practice and education, it might as well be.
  • Escaping: The process of escaping user input is left to the developer – many of which don't understand or know how to sanitize the data.
  • Flexibility: The API isn't flexible; the code above is tailor-made for working with a MySQL database. What if you switch?
PDO, or PHP Data Objects, provides a more powerful API that doesn't care about the driver you use; it's database agnostic. Further, it offers the ability to use prepared statements, virtually eliminating any worry of SQL injection.

How?

When I was first learning about the PDO API, I must admit that it was slightly intimidating. This wasn't because the API was overly complicated (it's not) – it's just that the old myqsl API was so dang easy to use!
Don't worry, though; follow these simple steps, and you'll be up and running in no time.

Connect

So you already know the legacy way of connecting to a MySQL database:
# Connect
mysql_connect('localhost', 'username', 'password') or die('Could not connect: ' . mysql_error());
With PDO, we create a new instance of the class, and specify the driver, database name, username, and password – like so:
$conn = new PDO('mysql:host=localhost;dbname=myDatabase', $username, $password);
Don't let that long string confuse you; it's really very simple: we specify the name of the driver (mysql, in this case), followed by the required details (connection string) for connecting to it.
What's nice about this approach is that, if we instead wish to use a sqlite database, we simply update the DSN, or "Data Source Name," accordingly; we're not dependent upon MySQL in the way that we are when use functions, like mysql_connect.

Errors

But, what if there's an error, and we can't connect to the database? Well, let's wrap everything within a try/catch block:
try {
    $conn = new PDO('mysql:host=localhost;dbname=myDatabase', $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
    echo 'ERROR: ' . $e->getMessage();
}
That's better! Please note that, by default, the default error mode for PDO is PDO::ERRMODE_SILENT. With this setting left unchanged, you'll need to manually fetch errors, after performing a query.
echo $conn->errorCode();
echo $conn->errorInfo();
Instead, a better choice, during development, is to update this setting to PDO::ERRMODE_EXCEPTION, which will fire exceptions as they occur. This way, any uncaught exceptions will halt the script.
For reference, the available options are:
  • PDO::ERRMODE_SILENT
  • PDO::ERRMODE_WARNING
  • PDO::ERRMODE_EXCEPTION

Fetch

At this point, we've created a connection to the database; let's fetch some information from it. There's two core ways to accomplish this task: query and execute. We'll review both.

Query

/*
 * The Query Method
 * Anti-Pattern
 */

$name = 'Joe'; # user-supplied data

try {
    $conn = new PDO('mysql:host=localhost;dbname=myDatabase', $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $data = $conn->query('SELECT * FROM myTable WHERE name = ' . $conn->quote($name));

    foreach($data as $row) {
        print_r($row);
    }
} catch(PDOException $e) {
    echo 'ERROR: ' . $e->getMessage();
}
Though this works, notice that we're still manually escaping the user's data with the PDO::quote method. Think of this method as, more or less, the PDO equivalent to use mysql_real_escape_string; it will both escape and quote the string that you pass to it. In situations, when you're binding user-supplied data to a SQL query, it's strongly advised that you instead use prepared statements. That said, if your SQL queries are not dependent upon form data, the query method is a helpful choice, and makes the process of looping through the results as easy as a foreach statement.

Prepared Statements

/*
 * The Prepared Statements Method
 * Best Practice
 */

$id = 5;
try {
    $conn = new PDO('mysql:host=localhost;dbname=myDatabase', $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);    

    $stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
    $stmt->execute(array('id' => $id));

    while($row = $stmt->fetch()) {
        print_r($row);
    }
} catch(PDOException $e) {
    echo 'ERROR: ' . $e->getMessage();
}
In this example, we're using the prepare method to, literally, prepare the query, before the user's data has been attached. With this technique, SQL injection is virtually impossible, because the data doesn't ever get inserted into the SQL query, itself. Notice that, instead, we use named parameters (:id) to specify placeholders.
Alternatively, you could use ? parameters, however, it makes for a less-readable experience. Stick with named parameters.
Next, we execute the query, while passing an array, which contains the data that should be bound to those placeholders.
$stmt->execute(array('id' => $id));
An alternate, but perfectly acceptable, approach would be to use the bindParam method, like so:
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();

Specifying the Ouput

After calling the execute method, there are a variety of different ways to receive the data: an array (the default), an object, etc. In the example above, the default response is used: PDO::FETCH_ASSOC; this can easily be overridden, though, if necessary:
while($row = $stmt->fetch(PDO::FETCH_OBJ)) {
    print_r($row);
}
Now, we've specified that we want to interact with the result set in a more object-oriented fashion. Available choices include, but not limited to:
  • PDO::FETCH_ASSOC: Returns an array.
  • PDO::FETCH_BOTH: Returns an array, indexed by both column-name, and 0-indexed.
  • PDO::FETCH_BOUND: Returns TRUE and assigns the values of the columns in your result set to the PHP variables to which they were bound.
  • PDO::FETCH_CLASS: Returns a new instance of the specified class.
  • PDO::FETCH_OBJ: Returns an anonymous object, with property names that correspond to the columns.
One problem with the code above is that we aren't providing any feedback, if no results are returned. Let's fix that:
$stmt->execute(array('id' => $id));

# Get array containing all of the result rows
$result = $stmt->fetchAll();

# If one or more rows were returned...
if ( count($result) ) {
    foreach($result as $row) {
        print_r($row);
    }
} else {
    echo "No rows returned.";
}
At this point, our full code should look like so:
$id = 5;
  try {
    $conn = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password);
    $stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
    $stmt->execute(array('id' => $id));

    $result = $stmt->fetchAll();

    if ( count($result) ) {
      foreach($result as $row) {
        print_r($row);
      }
    } else {
      echo "No rows returned.";
    }
  } catch(PDOException $e) {
      echo 'ERROR: ' . $e->getMessage();
  }

Multiple Executions

The PDO extension becomes particularly powerful when executing the same SQL query multiple times, but with different parameters.
try {
  $conn = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password);
  $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  # Prepare the query ONCE
  $stmt = $conn->prepare('INSERT INTO someTable VALUES(:name)');
  $stmt->bindParam(':name', $name);

  # First insertion
  $name = 'Keith';
  $stmt->execute();

  # Second insertion
  $name = 'Steven';
  $stmt->execute();
} catch(PDOException $e) {
  echo $e->getMessage();
}
Once the query has been prepared, it can be executed multiple times, with different parameters. The code above will insert two rows into the database: one with a name of “Kevin,” and the other, “Steven.”

CRUD

Now that you have the basic process in place, let’s quickly review the various CRUD tasks. As you’ll find, the required code for each is virtually identical.

Create (Insert)

try {
  $pdo = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password);
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  $stmt = $pdo->prepare('INSERT INTO someTable VALUES(:name)');
  $stmt->execute(array(
    ':name' => 'Justin Bieber'
  ));

  # Affected Rows?
  echo $stmt->rowCount(); // 1
} catch(PDOException $e) {
  echo 'Error: ' . $e->getMessage();

Update

$id = 5;
$name = "Joe the Plumber";

try {
  $pdo = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password);
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  $stmt = $pdo->prepare('UPDATE someTable SET name = :name WHERE id = :id');
  $stmt->execute(array(
    ':id'   => $id,
    ':name' => $name
  ));

  echo $stmt->rowCount(); // 1
} catch(PDOException $e) {
  echo 'Error: ' . $e->getMessage();
}

Delete

$id = 5; // From a form or something similar

try {
  $pdo = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password);
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  $stmt = $pdo->prepare('DELETE FROM someTable WHERE id = :id');
  $stmt->bindParam(':id', $id); // this time, we'll use the bindParam method
  $stmt->execute();

  echo $stmt->rowCount(); // 1
} catch(PDOException $e) {
  echo 'Error: ' . $e->getMessage();
}

Object Mapping

One of the neatest aspects of PDO (mysqli, as well) is that it gives us the ability to map the query results to a class instance, or object. Here’s an example:
class User {
  public $first_name;
  public $last_name;

  public function full_name()
  {
    return $this->first_name . ' ' . $this->last_name;
  }
}

try {
  $pdo = new PDO('mysql:host=localhost;dbname=someDatabase', $username, $password);
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  $result = $pdo->query('SELECT * FROM someTable');

  # Map results to object
  $result->setFetchMode(PDO::FETCH_CLASS, 'User');

  while($user = $result->fetch()) {
    # Call our custom full_name method
    echo $user->full_name();
  }
} catch(PDOException $e) {
  echo 'Error: ' . $e->getMessage();
}

Closing Thoughts

Bottom line: if you’re still using that old mysql API for connecting to your databases, stop. Though it hasn’t yet been deprecated, in terms of education and documentation, it might as well be. Your code will be significantly more secure and streamlined if you adopt the PDO extension.
read more

How to Process Credit Cards with PayPal Payments Pro Using PHP

PayPal is one of the most popular payment processing platforms available today for many reasons. Its ease of use and its connection to the eBay platform are just the tip of the iceberg. While one of its most popular features is the ability to simply sign in to your PayPal account to submit payments, merchants using PayPal can also accept credit cards directly just like a traditional merchant account solution would provide.

PayPal calls this solution Payments Pro, and I’m going to show you exactly how you can process credit cards directly with PayPal’s API using their Payments Pro web service API’s.

Step 1: Setup the Directory Structure

The first thing I like to do with any project is to create a basic structure organized for the project.  In this case, our structure is very simple as our project will consist of only 2 files:
Directory Structure
 As you might have guessed, we’ll be storing our configuration information in config.php, and we’ll actually handle the processing code in process-credit-card.php.

Step 2: Setup the Config File

Our /includes/config.php file will house our values for the PayPal API information we need including the end-point URL, API version, and our API username, password, and signature that we’ll be using. 
// Set sandbox (test mode) to true/false.
$sandbox = TRUE;

// Set PayPal API version and credentials.
$api_version = '85.0';
$api_endpoint = $sandbox ? 'https://api-3t.sandbox.paypal.com/nvp' : 'https://api-3t.paypal.com/nvp';
$api_username = $sandbox ? 'SANDBOX_USERNAME_GOES_HERE' : 'LIVE_USERNAME_GOES_HERE';
$api_password = $sandbox ? 'SANDBOX_PASSWORD_GOES_HERE' : 'LIVE_PASSWORD_GOES_HERE';
$api_signature = $sandbox ? 'SANDBOX_SIGNATURE_GOES_HERE' : 'LIVE_SIGNATURE_GOES_HERE';
Reviewing the config.php code, you can see that first we set a variable for $sandbox.  For now, we’ll leave this to TRUE because we want to interact with PayPal’s sandbox (test) servers for development purposes.  You’ll need to remember to change this to FALSE when you’re ready to move your project to a live server.
Then, based on the value of $sandbox we’re setting values to other variables for our API information.  You’ll just want to fill in those placeholders with your own details accordingly.  Now we’re ready to build our credit card processing script.

Step 3: Create an API Request

Now we can begin to build our process-credit-card.php page.  The first thing we need to do here is include our config file.
// Include config file
require_once('includes/config.php');
Next, we need to build a name-value-pair string that includes all of the data we need to send PayPal in order to process this payment.  A name-value-pair string looks just like something you might see when passing data via URL parameters.  We just need to make sure our parameter names are in all caps.
PARAM1=value1&PARAM2=value2&PARAM3=value3…etc.
So, you might be thinking to yourself “How do I know what to use for my variable names in my string?”  The good news is PayPal provides very good documentation on this.  We can see all of the possible variables that we can pass PayPal including customer details, order item details, and credit card information.  Some of this information is required in order to process a payment, but many of the variables available are optional.  For demonstration purposes, we’ll keep this pretty simple and just pass the required information.
We’ll store all of our request parameters in an array so that we can loop through this array to easily generate our NVP string.  All requests require the following parameters by default:
  • METHOD – The name of the API call you’re making.
  • USER – The API username
  • PWD – The API password
  • SIGNATURE – The API signature
  • VERSION – The API version
Then you can refer to the PayPal documentation for any API request you’d like to make to see what other parameters should be included.  For the sake of this demonstration, our array will be built as follows.
// Store request params in an array
$request_params = array
     (
     'METHOD' => 'DoDirectPayment',
     'USER' => $api_username,
     'PWD' => $api_password,
     'SIGNATURE' => $api_signature,
     'VERSION' => $api_version,
     'PAYMENTACTION' => 'Sale',
     'IPADDRESS' => $_SERVER['REMOTE_ADDR'],
     'CREDITCARDTYPE' => 'MasterCard',
     'ACCT' => '5522340006063638',
     'EXPDATE' => '022013',
     'CVV2' => '456',
     'FIRSTNAME' => 'Tester',
     'LASTNAME' => 'Testerson',
     'STREET' => '707 W. Bay Drive',
     'CITY' => 'Largo',
     'STATE' => 'FL',
     'COUNTRYCODE' => 'US',
     'ZIP' => '33770',
     'AMT' => '100.00',
     'CURRENCYCODE' => 'USD',
     'DESC' => 'Testing Payments Pro'
     );
You’ll notice we’re using our config variables from config.php, and then I’m simply loading static data for the other values.  In a standard project, though, you’ll most likely be populating these values with form data, session data, or some other form of dynamic data.
Now we can simply loop through this array to generate our NVP string.
// Loop through $request_params array to generate the NVP string.
$nvp_string = '';
foreach($request_params as $var=>$val)
{
 $nvp_string .= '&'.$var.'='.urlencode($val);
}
The value of $nvp_string is now:
METHOD=DoDirectPayment&USER=sandbo*****e.com&PWD=12***74&SIGNATURE=AiKZ******6W18v&VERSION=85.0&PAYMENTACTION=Sale&IPADDRESS=72.135.111.9&CREDITCARDTYPE=MasterCard&ACCT=5522340006063638&EXPDATE=022013&CVV2=456&FIRSTNAME=Tester&LASTNAME=Testerson&STREET=707+W.+Bay+Drive&CITY=Largo&STATE=FL&COUNTRYCODE=US&ZIP=33770&AMT=100.00&CURRENCYCODE=USD&DESC=Testing+Payments+Pro
This string is what we’ll send to PayPal for our request.

Step 4: Send the HTTP Request to PayPal

Now that our NVP string is ready to go we need to send this to the PayPal server to be processed accordingly.  To do this, we’ll use PHP’s CURL methods.
// Send NVP string to PayPal and store response
$curl = curl_init();
  curl_setopt($curl, CURLOPT_VERBOSE, 1);
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
  curl_setopt($curl, CURLOPT_TIMEOUT, 30);
  curl_setopt($curl, CURLOPT_URL, $api_endpoint);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $nvp_string);

$result = curl_exec($curl);
curl_close($curl);
Here you can see that we’ve setup CURL with a few simple options and we’re using our $api_endpoint and $nvp_string variables accordingly.
This data will be sent over to PayPal and we will receive the API response back in our $result variable so that we can see the result and send the user to a successful or failure page based on whether or not the call succeeded or not.

Step 5: Parse the API Response

The value that we get back in $result from the previous step will be an NVP string just like the one we generated and sent to PayPal.  When we run our current script we get a successful response back that looks like this:
TIMESTAMP=2012%2d04%2d16T07%3a59%3a36Z&CORRELATIONID=9eb40cd84a7d3&ACK=Success&VERSION=85%2e0&BUILD=2764190&AMT=100%2e00&CURRENCYCODE=USD&AVSCODE=X&CVV2MATCH=M&TRANSACTIONID=160896645A8111040
One very simple way to parse this result is to use PHP’s parse_str() function.  This will load all of the response data into PHP variables matching the names and values returned in the response.  For example, if we do the following:
// Parse the API response
  $nvp_response_array = parse_str($result);
  
We would end up with access to the following PHP variables:
  • $TIMESTAMP
  • $CORRELATIONID
  • $ACK
  • $VERSION
  • $BUILD
  • $AMT
  • $CURRENCYCODE
  • $AVSCODE
  • $CVV2MATCH
  • $TRANSACTIONID
We can then proceed to use these variables to present information back to our customer, populate values in email receipts we’d like to generate, update database information, or anything else we need to do once an order is completed.
The $ACK value is what will tell us whether or not the API call was successful or not.  Values for $ACK can be:
  • Success
  • SuccessWithWarning
  • Failure
  • FailureWithWarning
  •   You can simply redirect your user where they need to go and show them information based on this value. A failing API call will result in additional parameters that provide information about why the transaction failed.  If I run this test again with an invalid credit card number, for example, I get the following response back from PayPal:
    TIMESTAMP=2012%2d04%2d16T08%3a08%3a52Z&CORRELATIONID=590d41dbb31e0&ACK=Failure&VERSION=85%2e0&BUILD=2764190&L_ERRORCODE0=10527&L_SHORTMESSAGE0=Invalid%20Data&L_LONGMESSAGE0=This%20transaction%20cannot%20be%20processed%2e%20Please%20enter%20a%20valid%20credit%20card%20number%20and%20type%2e&L_SEVERITYCODE0=Error&AMT=100%2e00&CURRENCYCODE=USD
    Now, when we use parse_str() we end up with the following PHP variables available to us:
    • $TIMESTAMP
    • $CORRELATIONID
    • $ACK
    • $VERSION
    • $BUILD
    • $L_ERRORCODE0
    • $L_SHORTMESSAGE0
    • $L_LONGMESSAGE0
    • $L_SEVERITYCODE0
    • $AMT
    • $CURRENCYCODE
    In this case, $ACK shows a Failure so we know the call did not succeed and we can check the error parameters for more details about what went wrong.

    Additional Data Parsing Option

    While the previous method of parsing the response works just fine, I personally prefer to work with data arrays.  As such, I use the following function to convert the PayPal response into an array.
    // Function to convert NTP string to an array
    function NVPToArray($NVPString)
    {
     $proArray = array();
     while(strlen($NVPString))
     {
      // name
      $keypos= strpos($NVPString,'=');
      $keyval = substr($NVPString,0,$keypos);
      // value
      $valuepos = strpos($NVPString,'&') ? strpos($NVPString,'&'): strlen($NVPString);
      $valval = substr($NVPString,$keypos+1,$valuepos-$keypos-1);
      // decoding the respose
      $proArray[$keyval] = urldecode($valval);
      $NVPString = substr($NVPString,$valuepos+1,strlen($NVPString));
     }
     return $proArray;
    }
    
    This allows me to see all of the response data available by simply looking at the contents of the array: If I run my script again now I get the following result on screen:
    Array
    (
        [TIMESTAMP] => 2012-04-16T08:15:41Z
        [CORRELATIONID] => 9a652cbabfdd9
        [ACK] => Success
        [VERSION] => 85.0
        [BUILD] => 2764190
        [AMT] => 100.00
        [CURRENCYCODE] => USD
        [AVSCODE] => X
        [CVV2MATCH] => M
        [TRANSACTIONID] => 6VR832690S591564M
    )
    
    And If I were to cause an error again I get the following:
    Array
    (
        [TIMESTAMP] => 2012-04-16T08:18:46Z
        [CORRELATIONID] => 2db182b912a9
        [ACK] => Failure
        [VERSION] => 85.0
        [BUILD] => 2764190
        [L_ERRORCODE0] => 10527
        [L_SHORTMESSAGE0] => Invalid Data
        [L_LONGMESSAGE0] => This transaction cannot be processed. Please enter a valid credit card number and type.
        [L_SEVERITYCODE0] => Error
        [AMT] => 100.00
        [CURRENCYCODE] => USD
    )
    
    You can see this is a nice, easy to navigate result array that contains everything we might need to move the user through our application and update data sources as necessary.

    Conclusion

    As you can see, processing credit cards using PayPal Payments Pro is actually a very simple procedure.  It just involves a few standard steps for working with API web services, and a basic knowledge of working with array data can help as well. Good luck, and happy coding!
read more

Uploading Files with AJAX

"
I can’t seem to reach the end of the fun stuff you can do with emerging web technologies. Today, I’m going to show you how to do something that—until the last while—has been almost unprecedented: uploading files via AJAX.
Oh, sure, there have been hacks; but if you’re like me, and feel dirty every time you type iframe, you’re going to like this a lot. Join me after the jump!


Why don’t we get the bad news over with?
This doesn’t work in every browser. However, with some progressive enhancement (or whatever the current buzzword is), we’ll have an upload page that will work right back to IE6 (albeit without the AJAXy bits).
Our AJAX upload will work as long as FormData is available; otherwise, the user will get a normal upload.
There are three main components to our project.
  • The multiple attribute on the file input element.
  • The FileReader object from the new File API.
  • The FormData object from XMLHttpRequest2.
We use the multiple attribute to allow the user to select multiple files for upload (multiple file upload will work normally even if FormData isn’t available). As you’ll see, FileReader allows us to show the user thumbnails of the files they’re uploading (we’ll be expecting images).
None of our three features work in IE9, so all IE users will get a normal upload experience (though I understand support for `FileReader` is available in IE10 Dev Preview 2). FileReader doesn’t work in the latest version of Safari (5.1), so they won’t get the thumbnails, but they’ll get the AJAX upload and the confirmation message. Finally, Opera 10.50 has FileReader support but not FormData support, so they’ll get thumbnails, but normal uploads.
With that out of the way, let’s get coding!

Step 1: The Markup and Styling

Let’s start with some basic markup and styling. Of course, this isn’t the main part of this tutorial, I won’t treat you like a newbie.

The HTML

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8" />
 <title>HTML5 File API</title>
 <link rel="stylesheet" href="style.css" />
</head>
<body>
 <div id="main">
  <h1>Upload Your Images</h1>
  <form method="post" enctype="multipart/form-data"  action="upload.php">
   <input type="file" name="images" id="images" multiple />
   <button type="submit" id="btn">Upload Files!</button>
  </form>

  <div id="response"></div>
  <ul id="image-list">

  </ul>
 </div>

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
 <script src="upload.js"></script>
</body>
</html>
Pretty basic, eh? We’ve got a form that posts to upload.php, which we’ll look at in a second, and a single input element, of type file. Notice that it has the boolean multiple attribute, which allows the user to select multiple files at once.
That’s really all there is to see here. Let’s move on.

The CSS

body {
 font: 14px/1.5 helvetica-neue, helvetica, arial, san-serif;
 padding:10px;
}

h1 {
 margin-top:0;
}

#main {
 width: 300px;
 margin:auto;
 background: #ececec;
 padding: 20px;
 border: 1px solid #ccc;
}

#image-list {
 list-style:none;
 margin:0;
 padding:0;
}
#image-list li {
 background: #fff;
 border: 1px solid #ccc;
 text-align:center;
 padding:20px;
 margin-bottom:19px;
}
#image-list li img {
 width: 258px;
 vertical-align: middle;
 border:1px solid #474747;
}
Absolutely no shockers here.

Step 2: The PHP

We need to be able to handle the file uploads on the back end as well, so let’s cover that next.

upload.php

<?php

foreach ($_FILES["images"]["error"] as $key => $error) {
 if ($error == UPLOAD_ERR_OK) {
  $name = $_FILES["images"]["name"][$key];
  move_uploaded_file( $_FILES["images"]["tmp_name"][$key], "uploads/" . $_FILES['images']['name'][$key]);
 }
}

echo "<h2>Successfully Uploaded Images</h2>";
Bear in mind that these were the first lines of PHP I’d written in easily a year (I’m a Ruby guy). You should probably be doing a bit more for security; however, we’re simply making sure that there are no upload errors. If that’s the case, we use the built-in move_uploaded_file to move it to an uploads folder. Don’t forget to make sure that the folder is writable.
So, right now, we should have a working upload form. You choose an image (multiple, if you want to and your browser lets you), click the “Upload Files!” button, and you get the message “Successfully Uploaded Images.
Here’s what our mini-project looks like so far:
The styled form
But, come on, it’s 2011: we want more than that. You’ll notice that we’ve linked up jQuery and an upload.js file. Let’s crack that open now.

Step 3: The JavaScript

Let’s not waste time: here we go!
(function () {
 var input = document.getElementById("images"),
     formdata = false;

 if (window.FormData) {
  formdata = new FormData();
  document.getElementById("btn").style.display = "none";
 }

}();
Here’s what we start with. We create two variables: input is our file input element; formdata will be used to send the images to the server if the browser supports that. We initialize it to false and then check to see if the browser supports FormData; If it does, we create a new FormData object. Also, if we can submit the images with AJAX, we don’t need the “Upload Images!” button, so we can hide it. Why don’t we need it? Well, we’re going to auto-magically upload the images immediately after the user selects them.
The rest of the JavaScript will go inside your anonymous self-invoking function. We next create a little helper function that will show the images once the browser has them:
function showUploadedItem (source) {
 var list = document.getElementById("image-list"),
     li   = document.createElement("li"),
     img  = document.createElement("img");
  img.src = source;
  li.appendChild(img);
 list.appendChild(li);
}
The function takes one parameter: the image source (we’ll see how we get that soon). Then, we simply find the list in our markup and create a list item and image. We set the image source to the source we received, put the image in the list item, and put the list item in the list. Voila!
Next, we have to actually take the images, display them, and upload them. As we’ve said, we’ll do this when the onchange event is fired on the input element.
if (input.addEventListener) {
 input.addEventListener("change", function (evt) {
  var i = 0, len = this.files.length, img, reader, file;

  document.getElementById("response").innerHTML = "Uploading . . ."

  for ( ; i < len; i++ ) {
   file = this.files[i];

   if (!!file.type.match(/image.*/)) {

   }
  }

 }, false);
}
We don’t have to worry about IE’s proprietary event model, because IE9+ supports the standard addEventListener function.
There’s more, but let’s start with this. First off, we don’t have to worry about IE’s proprietary event model, because IE9+ supports the standard addEventListener function (and IE9 and down don’t support our new features).
So, what do we want to do when the user has selected files? First, we create a few variables. The only important one right now is len = this.files.length. The files that the user has selected will be accessible from the object this.files. Right now, we’re only concerned with the length property, so we can loop over the files …
… which is exactly what we’re doing next. Inside our loop, we set the current file to file for ease of access. Next thing we do is confirm that the file is an image. We can do this by comparing the type property with a regular expression. We’re looking for a type that starts with “image” and is followed by anything. (The double-bang in front just converts the result to a boolean.)
So, what do we do if we have an image on our hands?
if ( window.FileReader ) {
 reader = new FileReader();
 reader.onloadend = function (e) {
  showUploadedItem(e.target.result);
 };
 reader.readAsDataURL(file);
}
if (formdata) {
 formdata.append("images[]", file);
}
We check to see if the browser supports creating FileReader objects. If it does, we’ll create one.
Here’s how we use a FileReader object: We’re going to pass our file object to the reader.readAsDataURL method. This creates a data url for the uploaded image. It doesn’t work the way you might expect, though. The data url isn’t passed back from the function. Instead, the data url will be part of an event object.
With that in mind, we’ll need to register a function on the reader.onloadend event. This function takes an event object, by which we get the data url: it’s at e.target.result (yes, e.target is the reader object, but I had issues when using reader in place of e.target inside this function). We’re just going to pass this data url to our showUploadedItem function (which we wrote above).
Next, we check for the formdata object. Remember, if the browser supports FormData, formdata will be a FormData object; otherwise, it will be false. So, if we have a FormData object, we’re going to call the append method. The purpose of a FormData object is to hold values that you’re submitting via a form; so, the append method simply takes a key and a value. In our case, our key is images[]; by adding the square-brackets to the end, we make sure each time we append another value, we’re actually appending it to that array, instead of overwriting the image property.
We’re almost done. In our for loop, we’ve displayed each of the images for the user and added them to the formdata object. Now, we just need to upload the images. Outside the for loop, here’s the last piece of our puzzle:
if (formdata) {
 $.ajax({
  url: "upload.php",
  type: "POST",
  data: formdata,
  processData: false,
  contentType: false,
  success: function (res) {
   document.getElementById("response").innerHTML = res;
  }
 });
}
Again, we have to make sure we have FormData support; if we don’t, the “Upload Files!” button will be visible, and that’s how the user will upload the photos. However, if we have FormData support, we’ll take care of uploading via AJAX. We’re using jQuery to handle all the oddities of AJAX across browsers.
You’re probably familiar with jQuery’s $.ajax method: you pass it an options object. The url, type, and success properties should be obvious. The data property is our formdata object. Notice those processData and contentType properties. According to jQuery’s documentation, processData is true by default, and will process and transform the data into a query string. We don’t want to do that, so we set this to false. We’re also setting contentType to false to make sure that data gets to the server as we expect it to.
And that’s it. Now, when the user loads the page, they see this:
Tutorial Image
And after they select the images, they’ll see this:
Tutorial Image
And the images have been uploaded:
Tutorial Image

That’s a Wrap!

Uploading files via AJAX is pretty cool, and it’s great that these new technologies support that without the need for lengthy hacks. If you’ve got any questions about what we’ve done here, hit those comments! Thank you so much for reading!
"
read more

Get Back to the Basics with GetSimple CMS

"
It’s no secret that I am a huge WordPress advocate. It’s full-featured, extendable, and super powerful. However, depending on the project it could be overkill. You need space and a database backend, and you’ll end up with a lot of features that some clients might not use. Especially if you’re making a site that won’t be updated often, most of WordPress’ features will go untouched.
Luckily, there are a bunch of lightweight CMSs. One of them is GetSimple CMS, a promising newer CMS that . Today, we’ll take a closer look at that.
GetSimple CMS is a lightweight, XML based content management system (CMS) that is quick and easy to install, and even easier to use. Since there is no database, there is minimal necessary interaction with the server (just FTP), and its goal to cater to small (1-15 page) sites means that the features are only the ones necessary. Let’s take a look!

GetSimple CMS Homepage

Install and Setup

Install and setup is super easy. Just FTP the GetSimple CMS files to your server and visit the proper URL. The first time you’ll be taken to a 2 part install. The first part is making sure everything you need is on your server. The second part is the initial settings and actual install!

Install - Server Check
Once you complete the install, you’ll be emailed your username and password and you’ll be good to go! To get to the admin panel, point your browser to www.yoururl.com/admin/.

Install- Site Settings
On the admin panel, you’ll see tabs for: Pages, Files, Themes, Backups, and Plugins. You’ll also see a Settings link to the right. There is no dashboard like other popular CMSs. Just login and start editing!
Let’s go ahead and walk through the GetSimple CMS Admin!

Managing Pages

Obviously the most important part of the CMS is creating and managing pages. GetSimple CMS makes that incredible easy.

Pages Panel
Under the Pages tab you’ll see a list of your pages, the last time they were each updated, and a way to view and delete them. The only page you cannot delete is the one you’ve dedicated as the index page. Add a new page using the button on the right, click on a page title to edit the page itself.
When you go to a page’s editor (screen below is editing my “Hello World” page), you’re presented with an editor a few simple options for rich text (bold, underline, etc.) as well as a way to edit the HTML.

Page Editor
From here you can change the text of the page, format it as you’d like, add links, and insert already uploaded files (images, PDFs, etc.) into the post. To edit the source, simply click on the “Source” button. There are also some more ‘administrative’ options if you click the “Page Options” button.

Page Options
You can change the slug (for the URL), add keywords/tags and a description for SEO purposes, assign a parent page and template (if your theme support multiple page templates), and make the page private. There are also a few menu options for adding the page to the navigation and changing the menu text and order.
One issue I have with the page edit is while it’s very simple (which is good), you cannot upload files from the page editor. You have to do that in the Files section, which I feel creates too many steps to do something as easy as inserting an image. That being said, lets head on over to the Files tab.

Managing Files

Managing files in GetSimple CMS is incredibly easy; the interface, much like the manage pages tab, is clean and simple. There is a list of your files, each size, and the date each file was uploaded. There is also a way to delete each file.

Files Panel
You can upload files by clicking the Upload button on the right. It’s a flash uploader, so it supports adding several files at once. You can also upload any file type you’d like, though there is some added functionality if you upload images.
Clicking on most files will bring you to the file itself. However, for images GetSimple CMS has a basic image control panel where you can grab a set of links/html for the image as well as modify the thumbnail of the image.

Image Control Panel (image is a screenshot of the editor)
While CMSs like WordPress come with a full image editor, I like that GetSimple CMS stays true to its name and only includes the functionality needed here.

Themes

GetSimple CMS also allows you to manage themes. On the Theme page you’ll see a drop down to select any installed themes you have. To the right, you’ll see a number of options (including any theme specific options) to manage your themes.

Themes Panel
Most of the options are self explanatory, but I did want to mention the “Edit Components” area. GetSimple CMS allows you to create snippets of text/HTML that you can throw anywhere in your theme. Sidebar and Tagline are there by default, but you can create any kind of component you want and then insert it into the theme using the code provided to you.

Component Editor
This is a pretty interesting idea and while it might not be very user friendly to non-tech users, it can be incredibly handy for the developers who need to add a little something extra to a custom theme they’re developing.

Creating Themes

Creating themes could certainly be its own tutorial; however, I did want to touch on the topic for those looking to try out the CMS.
To create a theme, add a folder in GetSimple CMS’s /theme/ directory on your server. You only need one file: template.php. In it will go the mark-up that lays out eachpage.
GetSimple CMS will automatically add a new theme to the Theme tab, the name of the theme being the name of the directory you added (IE if the directory is named /Test/, the theme will be named Test).
Some other files worth including are (much like WordPress): header.php, footer.php, style.css, functions.php, and sidebar.php. If you’re familiar with WordPress, you’ll see GetSimple CMS is heavily influenced by it.
For a more comprehensive guide on GetSimple CMS theme development, you can visit the GetSimple CMS Wiki.

Backups

Under the Backups tab, you’ll find a list of older versions of your page, like a versioning system for pages you’ve created. This is a very nice touch by the developers of GetSimple CMS, who understand that..ummm…accidents happen.

Backups Panel
There is also an option under Backups called Website Archive, which will allow you to create a full, downloadable backup of the site.
Your server needs to support ZipArchive in order for Website Archive to work.

Plugins

The last major feature of GetSimple CMS is the Plugins manager. Much like WordPress, you can extend the functionality of GetSimple CMS by installing plugins.

Plugins Panel
To install a plugin, head on over to the GetSimple Plugin Directory, download the plugin and then upload it to GetSimple CMS’s /plugins/ folder on your sever. Then go to the Plugins tab and enable that plugin.

Settings

Finally, there is a simple Settings panel in GetSimple CMS.

Settings Panel
From here you can change the title of the site, create prettier links (permalinks), and change a few important settings like site URL, timezone, and admin password.
Again, there isn’t too much to the settings, but just enough. As the name suggests, the CMS keeps it simple!

Conclusion

GetSimple CMS is a lightweight, easy to install CMS with a very specific scope- allow people to update their website’s pages. While you can do other things like edit thumbnails and install plugins, GetSimple CMS is a lean way to allow non-tech people to update a site. Certain things, like installing themes and plugins, aren’t as easy as they would be on a full-featured CMS, so there may be a greater dependency on the developer. However GetSimple CMS can definitely serve a great niche- those who need a quick, lightweight site they want to update themselves without all of the bells and whistles of something like WordPress.
I can definitely see myself using GetSimple CMS for future projects. Have you ever tried out GetSimple CMS, or do you have any sites powered by it? We’d love to hear if you’re putting it to use, or plan to try it out in the near future!
"
read more

Build a Neat HTML5 Powered Contact Form

Build a Neat HTML5 Powered Contact Form: "
In this tutorial, we are going to learn how to create a swanky HTML5 AJAX powered contact form. The form will use some of the new HTML5 input elements and attributes, and will be validated using the browser’s built-in form validation.
We will use jQuery and Modernizr to help out with the older browsers, and PHP on the server side to validate the input.


Step 1: Getting Started

To begin, we need to setup our directory and files. To get started, I highly recommend the HTML5 boilerplate. This is a really good starting point for any HTML5 project and will save you a great deal of time. For this tutorial I chose ‘BOILERPLATE CUSTOM’.

HTML5 Boilerplate
For more information on the HTML5 boilerplate check out this guide on Nettuts+.
Once downloaded and unpacked, delete everything but index.html and the css and js folders. I also added a folder called img and a PHP file called process.php. We will use the img folder for storing image assets for our form, and process.php to handle all the server-side logic for the contact form. Here is what my directory structure looks like now:

Directory Structure
That’s all we need to get started! The HTML5 boilerplate includes an awesome CSS reset with sensible defaults and includes all the JS libraries (jQuery & Modernizr) we are going to be using today. All our JS files and CSS files have been hooked up in the index file. Now, it’s time to move on to the markup.


Step 2: The Form

Open index.html, and remove everything within the #container element. We’ll put our contact form inside this div:

<div id="contact-form" class="clearfix">
<h1>Get In Touch!</h1>
<h2>Fill out our super swanky HTML5 contact form below to get in touch with us! Please provide as much information as possible for us to help you with your enquiry :) </h2>
<ul id="errors" class="">
<li id="info">There were some problems with your form submission:</li>
</ul>
<p id="success">Thanks for your message! We will get back to you ASAP!</p>
<form method="post" action="process.php">
<label for="name">Name: <span class="required">*</span></label>
<input type="text" id="name" name="name" value="" placeholder="John Doe" required="required" autofocus="autofocus" />

<label for="email">Email Address: <span class="required">*</span></label>
<input type="email" id="email" name="email" value="" placeholder="johndoe@example.com" required="required" />

<label for="telephone">Telephone: </label>
<input type="tel" id="telephone" name="telephone" value="" />

<label for="enquiry">Enquiry: </label>
<select id="enquiry" name="enquiry">
<option value="general">General</option>
<option value="sales">Sales</option>
<option value="support">Support</option>
</select>

<label for="message">Message: <span class="required">*</span></label>
<textarea id="message" name="message" placeholder="Your message must be greater than 20 charcters" required="required" data-minlength="20"></textarea>

<span id="loading"></span>
<input type="submit" value="Holla!" id="submit-button" />
<p id="req-field-desc"><span class="required">*</span> indicates a required field</p>
</form>
</div>
This is all the HTML we will need for our form. Let’s look at each individual section:
ul#errors and p#success will be holders for our error and success messages. We will hide these by default with CSS, and display them with either JavaScript or PHP once the form has been submitted. For the name input, our only requirement is that it has been filled in.
In HTML5, we do this by adding the 'required' attribute. This will force the browser to check that this field has something in it before it allows the form to be submitted. The email field is similar, but as well as being required, we actually want to make sure it is an email address that was entered. To do this, we specify this input’s type as email, which is new in HTML5. Although telephone is not a required field, we are using the tel HTML5 input type for this.
Enquiry is a standard select element, and message is a typical textarea — nothing new here. To the textarea, we will set the required attribute to make sure the user enters some text.
In HTML5, there is a new attribute for textareas called maxlength. Yep, you guessed it, this lets us set a maximum number of characters we can write in the textarea. For some daft reason, the powers that be who made the HTML5 spec did not think we would need a minlength attribute (like we do now) and there is no attribute for this. So as a makeshift minlength attribute, we are going to use another new HTML5 attribute called a custom data attribute. This is basically any attribute name prefixed with the word ‘data-’. In our case we have appropriately chosen data-minlength. This lets us essentially create our own attributes.

Another thing worth noticing is that we are setting an attribute called placeholder on all of the input elements (except telephone) and the textarea. This is a new HTML5 input attribute. When the form is first displayed, the placeholder text will appear in the input, normally in a different font color. Then, when you focus the input, the placeholder text disappears. If you blur out without filling the field in, the placeholder text is put back in. This is a pretty cool effect, and can provide the user with a bit more information on what they need to do. Previously, this would have had to be done with JavaScript.

The final thing to notice is that the name input has an HTML5 attribute, called autofocus. When the page is first loaded, this input element is given focus immediately without the user having to do anything. This is also good for prompting the user to do something.

That’s all the HTML5-ness we are going to incorporate into our markup. For more detailed information on these new attributes and inputs checkout some of these links:





Step 3: Styling the Form


Here is our form, looking a little worse for wear…


Unstyled Form

It does not look too good at the moment, and it isn’t really doing our shiny new HTML5 goodness any justice, so let’s add some CSS. Open the style.css file. The file already contains some resets and defaults that will help us make our form x-browser compatible. Scroll down and look for a comment saying:

/*
// ========================================== \\
||                                              ||
||               Your styles !                  ||
||                                              ||
\\ ========================================== //
*/

Directly after it, paste in the following CSS:

#contact-form {
background-color:#F2F7F9;
width:465px;
padding:20px;
margin: 50px auto;
border: 6px solid #8FB5C1;
-moz-border-radius:15px;
-webkit-border-radius:15px;
border-radius:15px;
position:relative;
}

#contact-form h1 {
font-size:42px;
}

#contact-form h2 {
margin-bottom:15px;
font-style:italic;
font-weight:normal;
}

#contact-form input,
#contact-form select,
#contact-form textarea,
#contact-form label {
font-size:15px;
margin-bottom:2px;
}

#contact-form input,
#contact-form select,
#contact-form textarea {
width:450px;
border: 1px solid #CEE1E8;
margin-bottom:20px;
padding:4px;
}

#contact-form input:focus,
#contact-form select:focus,
#contact-form textarea:focus {
border: 1px solid #AFCDD8;
background-color: #EBF2F4;
}

#contact-form textarea {
height:150px;
resize: none;
}

#contact-form label {
display:block;
}

#contact-form .required {
font-weight:bold;
color:#F00;
}

#contact-form #submit-button {
width: 100px;
background-color:#333;
color:#FFF;
border:none;
display:block;
float:right;
margin-bottom:0px;
margin-right:6px;
background-color:#8FB5C1;
-moz-border-radius:8px;
}

#contact-form #submit-button:hover {
background-color: #A6CFDD;
}

#contact-form #submit-button:active {
position:relative;
top:1px;
}

#contact-form #loading {
width:32px;
height:32px;
background-image:url(../img/loading.gif);
display:block;
position:absolute;
right:130px;
bottom:16px;
display:none;
}

#errors {
border:solid 1px #E58E8E;
padding:10px;
margin:25px 0px;
display:block;
width:437px;
-webkit-border-radius:8px;
-moz-border-radius:8px;
border-radius:8px;
background:#FFE6E6 url(../img/cancel_48.png) no-repeat 405px center;
display:none;
}

#errors li {
padding:2px;
list-style:none;
}

#errors li:before {
content: ' - ';
}

#errors #info {
font-weight:bold;
}

#errors #info:before {
content: '';
}

#success {
border:solid 1px #83D186;
padding:25px 10px;
margin:25px 0px;
display:block;
width:437px;
-webkit-border-radius:8px;
-moz-border-radius:8px;
border-radius:8px;
background:#D3EDD3 url(../img/accepted_48.png) no-repeat 405px center;
font-weight:bold;
display:none;
}

#errors.visible, #success.visible {
display:block;
}

#req-field-desc {
font-style:italic;
}

/* Remove box shadow firefox, chrome and opera put around required fields. It looks rubbish. */
input:required, textarea:required {
-moz-box-shadow:none;
-webkit-box-shadow:none;
-o-box-shadow:none;
box-shadow:none;
}

/* Normalize placeholder styles */

/* chrome, safari */
::-webkit-input-placeholder {
color:#CCC;
font-style:italic;
}

/* mozilla */
input:-moz-placeholder, textarea:-moz-placeholder {
color:#CCC;
font-style:italic;
}

/* ie (faux placeholder) */
input.placeholder-text, textarea.placeholder-text  {
color:#CCC;
font-style:italic;
}

If you save and reload, your page should now look like so:


Styled Form

Now that looks better! The CSS is pretty standard, but I will go over a few things that are not so obvious:

#errors li:before {
content: ' - ';
}

This will put a dash next to our error validation messages. It’s basically replacing the bullet point in the list, I just think this looks better.

#contact-form #submit-button:active {
position:relative;
top:1px;
}

This will give us a nice ‘push-down’ effect when the submit button is active.

input:required, textarea:required {
-moz-box-shadow:none;
-webkit-box-shadow:none;
-o-box-shadow:none;
box-shadow:none;
}

All browsers (except IE) by default put a red box shadow around required elements. This looks a bit over the top in my opinion, so I am removing it. I have already indicated that the field is required by putting a red asterisk in the label.


Stupid looking required inputs

/* chrome, safari */
::-webkit-input-placeholder {
color:#CCC;
font-style:italic;
}

/* mozilla */
input:-moz-placeholder, textarea:-moz-placeholder {
color:#CCC;
font-style:italic;
}

/* ie (faux placeholder) */
input.placeholder-text, textarea.placeholder-text  {
color:#CCC;
font-style:italic;
}

This normalizes the appearance of the placeholder text on inputs and textareas. Here we are making it a light grey and italicizing it. This will give us consistency across all browsers except Opera, which does not support the styling of placeholders. IE just does not support the placeholder attribute. Fullstop. We will be using JavaScript to polyfill this. You can read more about styling HTML5 forms with CSS(2.1 + 3) here.

You will notice in the CSS that there are a few references to images. If you do not have these, simply download the source files for this tutorial and copy them over.

We’re done with the markup, and it’s looking pretty sweet. We’re going to create a PHP fallback in case the user’s browser does not support the new form input attributes (IE), or if the user has JavaScript disabled. We are going to write some JavaScript later to polyfill the features the browser lacks. But incase the user does not have a nice shiny new browser or JavaScript enabled, we still need to validate the form submission. We will do this serverside with PHP. We are also going to use it to email us the results of a valid form.




Step 4: Preparing For The Server Side Validation


Let’s dive straight in. Open up process.php and paste in the following:

<?php
if( isset($_POST) ){

//form validation vars
$formok = true;
$errors = array();

//sumbission data
$ipaddress = $_SERVER['REMOTE_ADDR'];
$date = date('d/m/Y');
$time = date('H:i:s');

//form data
$name = $_POST['name'];
$email = $_POST['email'];
$telephone = $_POST['telephone'];
$enquiry = $_POST['enquiry'];
$message = $_POST['message'];

//form validation to go here....

}

What we are saying here is: only execute this following code when the request method is POST. By default, if a form is posted to a PHP script, the form’s input values are stored in a super global array called $_POST. If nothing is posted, $_POST will not be an array, the if statement will equate to false and our code will not be run.

Once we have established that this is a POST request, we can start our form processing logic. The first thing we need to do is set two variables:

  • $formok: A boolean value we can check to see if the form was valid or not at the end of the script.
  • $errors: An array that we will use to store all of the problems with the form, as we are validating it.

After that, we set some general form submission data:

  • $ipaddress: User’s IP address which can be useful for blacklisting spam, cross referencing analytics data etc.
  • $date: The date the form was submitted. We use the date function to generate the date in UK format.
  • $time: The time the form was submitted. We use the date function to generate the time.

We could combine the date and time if we wanted:

$datetime = date('d/m/Y H:i:s');

I like to keep them separate so I can use them for other things, if required. The final set of variables we are setting are the values of the submitted form fields . We are accessing the $_POST array by passing in the form field name as the key to retrieve the data for each variable.




Step 5: Validating the $_POST Data


We are going to check each variable individually now to make sure their value is valid. If it’s not, we’ll set the $formok variable to false, and store an error message in the $errors array. We will start with the name field first.

//validate name is not empty
if(empty($name)){
$formok = false;
$errors[] = 'You have not entered a name';
}

Here, we are just making sure that $name actually has a value. If it does not, it means the user did not enter a name. We are using the empty() function to check for this. The [] after $errors is a shortcut to array_push (which is used to add an item to the end of an array). Next we will validate the email address:

//validate email address is not empty
if(empty($email)){
$formok = false;
$errors[] = 'You have not entered an email address';
//validate email address is valid
}elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)){
$formok = false;
$errors[] = 'You have not entered a valid email address';
}

We are going to check to see if a valid email address was actually entered. For this task, we are going to use the filter_var() function. Finally, we’ll need to validate the message.

//validate message is not empty
if(empty($message)){
$formok = false;
$errors[] = "You have not entered a message";
}
//validate message is greater than 20 charcters
elseif(strlen($message) < 20){
$formok = false;
$errors[] = "Your message must be greater than 20 characters";
}

Yet again, we are going to check to see if a message was entered. If something was entered, we want to make sure it’s greater than 20 characters. For this, we are going to use the strlen() function.

The telephone field and the enquiry field are not required fields, so no need to validate these. You could, if you wanted, but for the purpose of this tutorial I’m not.




Step 6: What to do Next…


Once we have validated our form results, we need to decide whether to send the user an email containing the form results or not. We kept track of the validity of the form using the $formok variable. If it is still equal to true, we want to submit the form results, otherwise we don’t.

This is the logic we are going to use to send the message (paste this in after we have done our validation):

//send email if all is ok
if($formok){
$headers = "From: info@example.com" . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

$emailbody = "<p>You have recieved a new message from the enquiries form on your website.</p>
<p><strong>Name: </strong> {$name} </p>
<p><strong>Email Address: </strong> {$email} </p>
<p><strong>Telephone: </strong> {$telephone} </p>
<p><strong>Enquiry: </strong> {$enquiry} </p>
<p><strong>Message: </strong> {$message} </p>
<p>This message was sent from the IP Address: {$ipaddress} on {$date} at {$time}</p>";

mail("enquiries@example.com","New Enquiry",$emailbody,$headers);

}

To send the message, we are going to be using the mail() function. We will need to pass this function four parameters: to, subject, message and headers.

  • to: This will be the email address that you want to send the form details to.
  • subject: This will be the email’s subject.
  • message: This will be the email’s content. We are storing this in the variable $emailbody. This is a HTML string containing the results of our form. Where you see the curly braces with our variable names in them, these will be changed into the variables value when this script is run. This is called variable substitution. This sort of substitution only works if the string is encapsulated in DOUBLE quotes, not SINGLE.
  • headers: This is used to pass additional information to the email client so it knows how to interpet the email. We are storing our headers in the $headers variable and supplying extra information on who the email is from, and what type of content it contains.

Note: Remember to change the from email address in the headers and the to email address in the mail function.

This should produce a nice email like so:


Email Screenshot

If you are on a Windows server, you may need to put this line of code in (before you declare the $headers variable) to get the mail function to work:

ini_set('sendmail_from','info@example.com');

Whether the user’s form submission was valid or not, we want to return them back to the form. If the form was valid and the message was sent, we need to provide the user with the success message. If it’s not valid, we want to display the error messages stored in the $errors array as well as populate the form fields with the data that was originally sent. We will store some variables we have been using in this script in an array and send them along with the redirect back to the form.

//what we need to return back to our form
$returndata = array(
'posted_form_data' => array(
'name' => $name,
'email' => $email,
'telephone' => $telephone,
'enquiry' => $enquiry,
'message' => $message
),
'form_ok' => $formok,
'errors' => $errors
);

We will be storing our data in an associative array. This array has three members:

  • posted_form_data: This will be an array containing the form data that was posted to the script.
  • form_ok: We will store the $formok variable in this, and this variable will be checked back on the form page to update the user with the appropriate message.
  • errors: We will store the $errors variable in this. This variable will be used if the $formok variable is equal to false.

The final thing for us to do is to redirect the user back to the form page, along with our $returndata array. Once we are redirected back to the form page, we will lose our $returndata variable; so, to make this data persistant, we will temporarily store it in the session.

Another thing we need to bear in mind is, ultimately, if the user’s browser has JavaScript enabled, we want to submit the form via AJAX. That will mean we will want our AJAX request to be posted to the same place as the form submission when the JavaScript is disabled. Because the form would have already been validated on the client-side, it will pass through all the server-side validation, and the details will be emailed to us. If the form is not valid, it will never be submitted (as the browser validation / JavaScript will prevent it). This means that, with the AJAX request, there is no reason for us to redirect or set any session variables. In the final part of this script, we will check to see if the current request to process.php was an AJAX request or not, and if it was, set our session variables and redirect.

//if this is not an ajax request
if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest'){

//set session variables
session_start();
$_SESSION['cf_returndata'] = $returndata;

//redirect back to form
header('location: ' . $_SERVER['HTTP_REFERER']);

}

To check if this was an AJAX request, we search for the variable, $_SERVER['HTTP_X_REQUESTED_WITH'] . Like the the super global $_POST array, there is also one called $_SERVER. This array contains server and execution environment information. Refer here for more detailed info.

We then call session_start() to give us access to the session and the set the variable $_SESSION['cf_returndata'] to mirror $returndata. On the form page, we will now be able to access this variable.

To redirect back to the form, we are using the header() function. We are telling it to redirect us to the last page we came from using the variable: $_SERVER['HTTP_REFERER'].

Altogether you should have ended up with this:

<?php
if( isset($_POST) ){

//form validation vars
$formok = true;
$errors = array();

//submission data
$ipaddress = $_SERVER['REMOTE_ADDR'];
$date = date('d/m/Y');
$time = date('H:i:s');

//form data
$name = $_POST['name'];
$email = $_POST['email'];
$telephone = $_POST['telephone'];
$enquiry = $_POST['enquiry'];
$message = $_POST['message'];

//validate form data

//validate name is not empty
if(empty($name)){
$formok = false;
$errors[] = "You have not entered a name";
}

//validate email address is not empty
if(empty($email)){
$formok = false;
$errors[] = "You have not entered an email address";
//validate email address is valid
}elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)){
$formok = false;
$errors[] = "You have not entered a valid email address";
}

//validate message is not empty
if(empty($message)){
$formok = false;
$errors[] = "You have not entered a message";
}
//validate message is greater than 20 characters
elseif(strlen($message) < 20){
$formok = false;
$errors[] = "Your message must be greater than 20 characters";
}

//send email if all is ok
if($formok){
$headers = "From: info@example.com" . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";

$emailbody = "<p>You have received a new message from the enquiries form on your website.</p>
<p><strong>Name: </strong> {$name} </p>
<p><strong>Email Address: </strong> {$email} </p>
<p><strong>Telephone: </strong> {$telephone} </p>
<p><strong>Enquiry: </strong> {$enquiry} </p>
<p><strong>Message: </strong> {$message} </p>
<p>This message was sent from the IP Address: {$ipaddress} on {$date} at {$time}</p>";

mail("enquiries@example.com","New Enquiry",$emailbody,$headers);

}

//what we need to return back to our form
$returndata = array(
'posted_form_data' => array(
'name' => $name,
'email' => $email,
'telephone' => $telephone,
'enquiry' => $enquiry,
'message' => $message
),
'form_ok' => $formok,
'errors' => $errors
);

//if this is not an ajax request
if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest'){
//set session variables
session_start();
$_SESSION['cf_returndata'] = $returndata;

//redirect back to form
header('location: ' . $_SERVER['HTTP_REFERER']);
}
}

That’s all for processing our form submission — done and dusted in under 90 lines of PHP! All we need to do now is update the user and provide either a success message or an error message. You can save process.php now.




Step 7: Update the UI


Now that we have processed the form data and have been returned to the page, we need to update the user on what has happened. This means accessing the session variable we set on process.php and working out what response to give. Because this page now needs to use PHP, we are going to need to change the file extension of index.html to .php (index.html = index.php). Don’t worry, this should not break anything we have already done.

The first thing we need to do is get our variables out of the session. To do this, we need access to the session. Right at the top of the page before any markup (above doctype) paste the following code in:

<?php session_start() ?>

Starting the session before any content is sent to the browser should prevent any ‘cannot send session cookie – headers already sent by…’ errors you may receive. Below the H2 of the form add in this PHP snippet:

<?php
//init variables
$cf = array();
$sr = false;

if(isset($_SESSION['cf_returndata'])){
$cf = $_SESSION['cf_returndata'];
$sr = true;
}
?>

We are setting two variables to default values. More on these later… We are then checking to see if $_SESSION['cf_returndata'] is set. We then set $cf (short for contact form) to equal our session variable. This is just so we don’t have to type $_SESSION… every time we want to access this data. The last variable $sr (short of server response), is set to true. This is a variable we are going to be checking to see if we have previously posted our form. The next thing we want to do is display an error message or success at the top of the form. Replace this:

<ul id="errors" class="">
<li id="info">There were some problems with your form submission:</li>
</ul>
<p id="success">Thanks for your message! We will get back to you ASAP!</p>

With this:

<ul id="errors" class="<?php echo ($sr && !$cf['form_ok']) ? 'visible' : ''; ?>">
<li id="info">There were some problems with your form submission:</li>
<?php
if(isset($cf['errors']) && count($cf['errors']) > 0) :
foreach($cf['errors'] as $error) :
?>
<li><?php echo $error ?></li>
<?php
endforeach;
endif;
?>
</ul>
<p id="success" class="<?php echo ($sr && $cf['form_ok']) ? 'visible' : ''; ?>">Thanks for your message! We will get back to you ASAP!</p>

By default, the messages do not appear at all because, in the CSS, we’ve set 'display:none‘. Inside the class attribute of the messages, we are using PHP to add a 'visible' class to them if they are to be shown. This class sets 'display' to 'block'.

<?php echo ($sr && !$cf['form_ok']) ? 'visible' : ''; ?>

We are using the ternary operator here to check that…

  • a) the server response is equal to true and
  • b) that the form was not ok
  • .

Essentially, if we have submitted the form, $sr will equal true, and if the form was invalid $cf['form_ok'] will equal false. So the class visible will be outputted, but the PHP and message will show, and vice versa for the success message. Inside the parenthesis, we are checking the values of two variables. We are checking that $sr is equal to true and (&&) $cf['fomr_ok'] is equal to false. We are using shorthand to check these values. You could also write it this way if you wanted:

<?php echo ($sr === true && $cf['form_ok'] === false) ? 'visible' : ''; ?>

Once we have decided which message to display, we need to populate the container with the relevant data. The success message does not change, so we can leave that as it is. The error message will need populating with the validation errors. To write these out, we are simply looping through our errors array stored in the session and populating a li element inside of the ul:

<ul id="errors" class="<?php echo ($sr && !$cf['form_ok']) ? 'visible' : ''; ?>">
<li id="info">There were some problems with your form submission:</li>
<?php
if(isset($cf['errors']) && count($cf['errors']) > 0) :
foreach($cf['errors'] as $error) :
?>
<li><?php echo $error ?></li>
<?php
endforeach;
endif;
?>
</ul>

We are first checking that we have our errors array in $cf and that it contains at least one error. The if and foreach statement may look a little different to how you have seen them before. This is called Alternative Syntax. We have used alternative syntax here just to make it a little more readable with it being mixed with the HTML. You can use the normal syntax though if you like, it’s down to preference.

That’s all we need for showing the user the response of the form submission. To test this out, disable JavaScript, and submit the form. Remember that the browser will validate the form as we are using the new HTML5 elements. So to be super sure my PHP is working, I’m testing in IE8. Yes, that’s right, IE does come in handy sometimes…

If you submit the invalid form, you should get this:


Error Message

And if you fill the form in correctly, you should get:


Success Message

You should also have received an email from the code we wrote earlier (if you filled the form in correctly). Now that the form is working, the last thing we need to do is populate the form fields again with the user’s data if the submission was invalid. Swap the HTML inside of the form tags for this:

<label for="name">Name: <span class="required">*</span></label>
<input type="text" id="name" name="name" value="<?php echo ($sr && !$cf['form_ok']) ? $cf['posted_form_data']['name'] : '' ?>" placeholder="John Doe" required="required" autofocus="autofocus" />

<label for="email">Email Address: <span class="required">*</span></label>
<input type="email" id="email" name="email" value="<?php echo ($sr && !$cf['form_ok']) ? $cf['posted_form_data']['email'] : '' ?>" placeholder="johndoe@example.com" required="required" />

<label for="telephone">Telephone: </label>
<input type="tel" id="telephone" name="telephone" value="<?php echo ($sr && !$cf['form_ok']) ? $cf['posted_form_data']['telephone'] : '' ?>" />

<label for="enquiry">Enquiry: </label>
<select id="enquiry" name="enquiry">
<option value="General" <?php echo ($sr && !$cf['form_ok'] && $cf['posted_form_data']['enquiry'] == 'General') ? "selected='selected'" : '' ?>>General</option>
<option value="Sales" <?php echo ($sr && !$cf['form_ok'] && $cf['posted_form_data']['enquiry'] == 'Sales') ? "selected='selected'" : '' ?>>Sales</option>
<option value="Support" <?php echo ($sr && !$cf['form_ok'] && $cf['posted_form_data']['enquiry'] == 'Support') ? "selected='selected'" : '' ?>>Support</option>
</select>

<label for="message">Message: <span class="required">*</span></label>
<textarea id="message" name="message" placeholder="Your message must be greater than 20 charcters" required="required" data-minlength="20"><?php echo ($sr && !$cf['form_ok']) ? $cf['posted_form_data']['message'] : '' ?></textarea>

<span id="loading"></span>
<input type="submit" value="Holla!" id="submit-button" />
<p id="req-field-desc"><span class="required">*</span> indicates a required field</p>

The only difference here is that we are using PHP to populate the value attribute of the inputs.

<?php echo ($sr && !$cf['form_ok']) ? $cf['posted_form_data']['name'] : '' ?>

Like we did with the success and error messages, we are checking to see if $sr is equal to true and $cf['form_ok'] is equal to false, and if they are, we write out the saved value in the session for this form field. This is done using the ternary operator.

On the select, we are doing the same, except, instead of writing out the saved value, we need to check each option value to see if it matches the one saved in the session. If it matches, we write out the selected attribute for that option.

Finally, one last thing we are going to do is unset this session variable after we’ve gotten our data from it. You don’t have to do this, though; it comes down to preference. By unsetting it now, when the page is refreshed via the refresh button (not form post), an error / success message will not be shown. If you did not unset it, a user could fill in the contact form, go potter about on the internet, come back to the form and the error / success message will still be shown. I don’t like this so I’m going to prevent it by putting this line of PHP just after the closing form tags:

<?php unset($_SESSION['cf_returndata']); ?>

If you submit an invalid form, you should notice now that your form input values are retained, and if you referesh the page, the message and data should be cleared. That’s it for the PHP side of things! You should have ended up with your form looking like so:

<div id="contact-form" class="clearfix">
<h1>Get In Touch!</h1>
<h2>Fill out our super swanky HTML5 contact form below to get in touch with us! Please provide as much information as possible for us to help you with your enquiry :) </h2>
<?php
//init variables
$cf = array();
$sr = false;

if(isset($_SESSION['cf_returndata'])){
$cf = $_SESSION['cf_returndata'];
$sr = true;
}
<ul id="errors" class="<?php echo ($sr && !$cf['form_ok']) ? 'visible' : ''; ?>">
<li id="info">There were some problems with your form submission:</li>
<?php
if(isset($cf['errors']) && count($cf['errors']) > 0) :
foreach($cf['errors'] as $error) :
?>
<li><?php echo $error ?></li>
<?php
endforeach;
endif;
?>
</ul>
<form method="post" action="process.php">
<label for="name">Name: <span class="required">*</span></label>
<input type="text" id="name" name="name" value="<?php echo ($sr && !$cf['form_ok']) ? $cf['posted_form_data']['name'] : '' ?>" placeholder="John Doe" required autofocus />

<label for="email">Email Address: <span class="required">*</span></label>
<input type="email" id="email" name="email" value="<?php echo ($sr && !$cf['form_ok']) ? $cf['posted_form_data']['email'] : '' ?>" placeholder="johndoe@example.com" required />

<label for="telephone">Telephone: </label>
<input type="tel" id="telephone" name="telephone" value="<?php echo ($sr && !$cf['form_ok']) ? $cf['posted_form_data']['telephone'] : '' ?>" />

<label for="enquiry">Enquiry: </label>
<select id="enquiry" name="enquiry">
<option value="General" <?php echo ($sr && !$cf['form_ok'] && $cf['posted_form_data']['enquiry'] == 'General') ? "selected='selected'" : '' ?>>General</option>
<option value="Sales" <?php echo ($sr && !$cf['form_ok'] && $cf['posted_form_data']['enquiry'] == 'Sales') ? "selected='selected'" : '' ?>>Sales</option>
<option value="Support" <?php echo ($sr && !$cf['form_ok'] && $cf['posted_form_data']['enquiry'] == 'Support') ? "selected='selected'" : '' ?>>Support</option>
</select>

<label for="message">Message: <span class="required">*</span></label>
<textarea id="message" name="message" placeholder="Your message must be greater than 20 charcters" required data-minlength="20"><?php echo ($sr && !$cf['form_ok']) ? $cf['posted_form_data']['message'] : '' ?></textarea>

<span id="loading"></span>
<input type="submit" value="Holla!" id="submit-button" />
<p id="req-field-desc"><span class="required">*</span> indicates a required field</p>
</form>
<?php unset($_SESSION['cf_returndata']); ?>
</div>

Don’t forget the session_start() right at the top of the page! We now have a fully functional contact form.

The data is validated, and, if successful, we are emailed the form results. Further, we update the UI with the results for each submission. The newer browsers will even validate the form before it is submitted using the new HTML5 input types and attributes we have used.

This is all fine and dandy, but we can take things one step further. We can use JavaScript to polyfill the features that the browser does not have (built in validation, support for HTML5 attributes etc.) . We can even use JavaScript to display our error / success messages and submit the form using AJAX.

But why do this when the form already works? Well, it’s simple. We want to provide as much consistency accross all browsers as possible, even if it is a really naff browser. Also, if we get the client’s browser to handle all of the validation work, it saves our server’s resources as we’re not posting to it when the form is not valid. These things are super browny points, and really are not that difficult to do.




Step 8: What is a Polyfill?



“A polyfill, or polyfiller, is a piece of code that provides the technology that you, the developer, expect the browser to provide natively.”


In our case we expect the browser to support the new HTML5 input types and attributes we have used. Firefox, Chrome, Opera and Safari have pretty good native support for these. IE6 – 9 has no support for them at all. Typical. To be honest, it’s quite shocking IE9 does not have support for these things, it was only just released earlier this year. Anyhow, putting IE bashing aside (I could go on forever), the first two things we are going to polyfill are the autofocus and the placeholder attribute.

We’ll be using jQuery to help us out with our JavaScript. We’ll use it primarily to handle our AJAX request, animation and DOM traversal & manipulation. You could get away with not using it, but you would have to write a significant amount of code. Its footprint isn’t too big, so I can live with the file size. I, probably like you, would rather write less code.

We’ll also be using a JavaScript library called Modernizr to help us with feature detection. This is already included as part of our HTML5 boilerplate, so we don’t have to do anything here to get Modernizr up and running!

Navigate to the js directory and crack open script.js. We don’t have to worry about hooking up this file, jQuery or Modernizr, to index.php as this was already provided for us by the HTML5 boilerplate we used. Delete everything in this file and paste in the following:

$(function(){

//set global variables and cache DOM elements for reuse later
var form = $('#contact-form').find('form'),
formElements = form.find('input[type!='submit'],textarea'),
formSubmitButton = form.find('[type='submit']'),
errorNotice = $('#errors'),
successNotice = $('#success'),
loading = $('#loading'),
errorMessages = {
required: ' is a required field',
email: 'You have not entered a valid email address for the field: ',
minlength: ' must be greater than '
}

//feature detection + polyfills
formElements.each(function(){

//do feature detection + polyfills here

});
});

All our code is going to live inside the $(function(){ }) block. This will mean our code will be executed as soon as the page is loaded. Also any variables or functions we declare inside this block will not interfere with any other code outside. We are then caching some DOM elements, as we will be accessing these quite a bit. It’s more efficient to cache them in this way than to request them each time you want to use them. Here is a breakdown of what each variable is:

  • form: The contact form element.
  • formElements: All input elements and textareas in the form except the submit button. This will just be an array of elements.
  • formSubmitButton: The form’s submit button.
  • errorNotice: The error notice — unordered list element.
  • successNotice: The success message — paragraph element.
  • loading: The loading span element. This will display a loading gif when the form is submitted once validated.
  • errorMessages: This is an object containing some text for our error messages. These are used more than once so we are instantiating them here. You will notice some of the messages don’t read correctly. We will dynamically add to these later when we move on to validating the form.

After this, we are using a jQuery function, called each() to iterate over the formElements array. Whilst we are iterating over the form elements, we want to do our feature detection for the placeholder attribute, and if an element has this attribute but is not supported by the browser, apply our polyfill. Here is the polyfill for the placeholder attribute:

//if HTML5 input placeholder attribute is not supported
if(!Modernizr.input.placeholder){
var placeholderText = this.getAttribute('placeholder');
if(placeholderText){
$(this)
.addClass('placeholder-text')
.val(placeholderText)
.bind('focus',function(){
if(this.value == placeholderText){
$(this)
.val('')
.removeClass('placeholder-text');
}
})
.bind('blur',function(){
if(this.value == ''){
$(this)
.val(placeholderText)
.addClass('placeholder-text');
}
});
}
}

Here we are using Modernizr to determine if we have support for the placeholder attribute on an input. Modernizer is an object, input is a property of that object, and placeholder is a property of input (hence all the dots). This value will either be true or false. We are checking to see if it is false (the browser does not support the placeholder attribute); if so, we implement our polyfill. The first thing we do is declare a variable that will hold the placeholder text assigned to the element. Even though the browser does not support the placeholder attribute, we can still access this attribute. We use a function, called getAttribute() for this. The keyword 'this' refers to the current DOM element we are iterating over in the loop.

Once we have the placeholder text, we can do a check to ensure that it isn’t empty. This is so we only apply our polyfill to inputs that have the placeholder attribute. We are then chaining some really useful jQuery functions together to create our polyfill. Here’s a breakdown of what we are doing:

  1. We are wrapping the ‘this’ keyword in the jQuery function ( $() ) so we have access to some of jQuery’s handy DOM functions
  2. We are adding the class 'placeholder-text‘ to the element. This will make the elements placeholder text that we are going to polyfill look like the rest of the browsers. We have set a rule for this up already in the CSS.
  3. We are setting the input’s default value to the value of the placeholder attribute. This will show the placeholder text in the input field when the page has loaded.
  4. We are binding a focus event that will check if the placeholder attribute text is the same as the inputs value. If it is, then the input’s value is set to nothing, which clears the input and we remove the ‘placeholder-text‘ class so that the text is the default input styled text.
  5. We are binding a blur event that will check if the input’s value is equal to nothing. If it is, we populate the input with the placeholder text, and re-apply the ‘placeholder-text

This will make any browser that does not support the placeholder attribute act as if it does convincingly. See the image below from IE8:


Place Holder States

We’ll next polyfill the autofocus attribute. This one is dead simple:

//if HTML5 input autofocus attribute is not supported
if(!Modernizr.input.autofocus){
if(this.getAttribute('autofocus')) this.focus();
}

We use Modernizer to determine if the autofocus attribute is supported. If not, then we check if this element has the autofocus attribute set on it, and if it does, we focus it. Simple. In any browser that does not support this attribute, this will provide a fix.

The only other things we need to polyfill are the required attribute, the email input type, and the built in form validation. We also want to add in validation for the message length, and show the error message with details of problems with the form.




Step 9: Form Validation, Polyfill Style


//to ensure compatibility with HTML5 forms, we have to validate the form on submit button click event rather than form submit event.
//An invalid html5 form element will not trigger a form submit.
formSubmitButton.bind('click',function(){
var formok = true,
errors = [];

formElements.each(function(){

//validate form elements here

});

//if form is not valid
if(!formok){

//show error message here

}
//if form is valid
else {

//ajax request + show success message here

}

return false; //this stops submission off the form and also stops browsers showing default error message
});

We are binding a click event to the form submit button (stored in the formSubmitButton variable). When this event is triggered, we will validate the form. Normally in JavaScript we would actually do this on the submit event of the form, but as the newer browsers are using their own built in validation, the form submit event is never triggered. The browser will display its own error messages, but this is highly inconsistent accross all of the browsers, and there is currently no way of styling these. Displaying our own error message will provide consistency, and also show for browsers that do not support the new validation methods. To stop the browsers showing their default error messages we return false at the end of this function. Here is a breakdown of what the variables set at the top are for:

  • formok: This will keep track of the validity of the form.
  • errors: This is an array and will hold the error messages.

It’s similar to the PHP validation we wrote earlier!

We will start inside the loop where we are going to be validating the form elements. Inside this loop, we want to start by declaring some useful variables that we will use in our validation.

var name = this.name,
nameUC = name.ucfirst(),
value = this.value,
placeholderText = this.getAttribute('placeholder'),
type = this.getAttribute('type'), //get type old school way
isRequired = this.getAttribute('required'),
minLength = this.getAttribute('data-minlength');

  • name: The name of the current element.
  • nameUC: The name of the current element with the first letter uppercased. ucfirst() is a custom method of the string object that we will be writing later.
  • value: The value of the current element.
  • placeholderText: The placeholder text of the current element.
  • type: The type of current element.
  • isRequired: Whether the current element has the required attribute set on it or not.
  • minLength: The data-minlength value of current element (if applicable).

Now that we have our variables set, we can start with our validation. For the elements that are using the HTML5 input types and attributes, we can use the new validation JavaScript API to check their validity.

In HTML5, form elements have a new property called validity. This is where all the validation data for this element is stored. In Firebug, this looks like so:


Firebug Screenshot

As you can see, there are numerous properties in this object which give us a bit more of a clue as to what the problem is. The values of the properties are either false or false. In this screenshot, I tried to submit the form with no name, and I logged the validity property for the name input in the console ( console.log(this.validity) ). This shows me that a value was missing (valueMissing = true).

Our code for checking the HTML5 elements:

//if HTML5 formfields are supported
if( (this.validity) && !this.validity.valid ){
formok = false;

//if there is a value missing
if(this.validity.valueMissing){
errors.push(nameUC + errorMessages.required);
}
//if this is an email input and it is not valid
else if(this.validity.typeMismatch && type == 'email'){
errors.push(errorMessages.email + nameUC);
}

this.focus(); //safari does not focus element an invalid element
return false;
}

We are checking whether this form element has the validity property, and if it does, we are then checking the valid property of the validity object to see if this field is ok. If it is not valid (I’m using the shorthand, !, to check for false), we set formok to false, and perform some tests to see what the problem is.

If the value is missing (triggered by required fields), we add an error message to the errors array we set earlier. We use the push() method of the array object for this. The error message will consist of the element’s name (first letter uppercased) concatenated with the required error message that we set earlier in our script.

If this form fields value is not missing, we then want to determine if the correct data was input. The only input in our form that needs validation is the email field. With this in mind, in the elseif part of our code, we are checking if the typeMismatch property of the validity object is equal to true and if this input’s type is actually email. If so, we add the email error message to our errors array.

When the browser validates a field and is deemed invalid, it is automatically focused. Safari does not support this, so for the sake of consistency, we manually focus the input. We then return false at the end of our HTML5 input validation to break out of the loop, as we know that we have an invalid element (we don’t need to waste our time validating the rest of the elements in the form).

This will cover our HTML5 inputs nicely, but we now need to cater to the browsers which do not support the JavaScript form validation API. If the JavaScript form validation API is not supported by the browser the above code will never be exectued and skipped.

The first thing we will check for is if the field was required. Our polyfill for this will look like:

//if this is a required element
if(isRequired){
//if HTML5 input required attribute is not supported
if(!Modernizr.input.required){
if(value == placeholderText){
this.focus();
formok = false;
errors.push(nameUC + errorMessages.required);
return false;
}
}
}

Firstly, we check if this field is a required field (dictated by the required attribute). We are then using Modernizr to check if the required attribute is supported by the browser. If not, we need to manually check the value of the element and compare it to the element’s placeholder attribute. If they are the same, then obviously this form field has not been filled out so we do four things:

  1. We focus the input (as this what the browser does when using its native validation)
  2. We set the formok variable to false, as the form is invalid
  3. We add an error message to our errors array.
  4. We return false, which breaks out of the loop, and will go straight to the next bit of the code outside of the loop.

We are next going to check if this is an email input, and, if it is, whether a valid email has been entered.

//if HTML5 input email input is not supported
if(type == 'email'){
if(!Modernizr.inputtypes.email){
var emailRegEx = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if( !emailRegEx.test(value) ){
this.focus();
formok = false;
errors.push(errorMessages.email + nameUC);
return false;
}
}
}

It’s pretty much the same as before. We see if this is actually an email field, and then use Modernizr to check if the email input is supported. If it’s not, we write our code that checks if it is valid or not. For this polyfill, we are using regular expressions to test if the email is valid or not. We create a regular expression in the variable emailRegEx, then use the test() method of the regular expression object to test if the value of the input is valid against the regular expression.

You can learn more on using JavaScript regular expressions here.


If the email address is not valid, we do the same four things we did on the required input check.

The last thing we need to validate in our form is the message length. The required validation has already been taken care of above, so all we need to do is check the message’s length:

//check minimum lengths
if(minLength){
if( value.length < parseInt(minLength) ){
this.focus();
formok = false;
errors.push(nameUC + errorMessages.minlength + minLength + ' charcters');
return false;
}
}

We don't need to use Modernizr here. Instead, all we need to do is check that this element has a minimum length set, and if it does, make sure its length is greater than its set minimum length. Length is a property of all string objects in JavaScript and returns the number of characters in the string. We use parseInt() to convert minLength to an integer to compare it against value.length. minLength was retrieved from the data-minlength attribute. This is retrieved as a string, so to prevent any potential errors down the line (comparing strings to numbers etc.), we convert this to an integer.

Our polyfills and validation are now finished and sorted. You should have ended up with the following code:

//to ensure compatibility with HTML5 forms, we have to validate the form on submit button click event rather than form submit event.
//An invalid html5 form element will not trigger a form submit.
formSubmitButton.bind('click',function(){
var formok = true,
errors = [];

formElements.each(function(){
var name = this.name,
nameUC = name.ucfirst(),
value = this.value,
placeholderText = this.getAttribute('placeholder'),
type = this.getAttribute('type'), //get type old school way
isRequired = this.getAttribute('required'),
minLength = this.getAttribute('data-minlength');

//if HTML5 formfields are supported
if( (this.validity) && !this.validity.valid ){
formok = false;

//if there is a value missing
if(this.validity.valueMissing){
errors.push(nameUC + errorMessages.required);
}
//if this is an email input and it is not valid
else if(this.validity.typeMismatch && type == 'email'){
errors.push(errorMessages.email + nameUC);
}

this.focus(); //safari does not focus element an invalid element
return false;
}

//if this is a required element
if(isRequired){
//if HTML5 input required attribute is not supported
if(!Modernizr.input.required){
if(value == placeholderText){
this.focus();
formok = false;
errors.push(nameUC + errorMessages.required);
return false;
}
}
}

//if HTML5 input email input is not supported
if(type == 'email'){
if(!Modernizr.inputtypes.email){
var emailRegEx = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if( !emailRegEx.test(value) ){
this.focus();
formok = false;
errors.push(errorMessages.email + nameUC);
return false;
}
}
}

//check minimum lengths
if(minLength){
if( value.length < parseInt(minLength) ){
this.focus();
formok = false;
errors.push(nameUC + errorMessages.minlength + minLength + ' charcters');
return false;
}
}
});

//if form is not valid
if(!formok){

//show error message here

}
//if form is valid
else {

//ajax request + show success message here

}

return false; //this stops submission off the form and also stops browsers showing default error message
});

Awesome! We're nearly there now. At this point, all we need to do is write the code that handles the logic to check if the form is to be submitted or not. We will need to display our error messages that we have stored, and stop the form submitting if there is an error. If, on the other hand, there isn't an error, we submit the form via AJAX and reveal the success message. We also need to cover the ucfirst() function we have used to uppercase the first letter of each field name.




Step 11: Nearly There...


The first thing we are going to do is write a function for handling the messages, and also our ucfirst() function. Paste the following code outside the formSubmitButton.bind... logic we have been writing.

//other misc functions
function showNotice(type,data)
{
if(type == 'error'){
successNotice.hide();
errorNotice.find("li[id!='info']").remove();
for(x in data){
errorNotice.append('<li>'+data[x]+'</li>');
}
errorNotice.show();
}
else {
errorNotice.hide();
successNotice.show();
}
}

String.prototype.ucfirst = function() {
return this.charAt(0).toUpperCase() + this.slice(1);
}

The showNotice function will take two arguments.

  • The type of message to show
  • The data to show in the message.

If the type is 'error', we hide the success message, loop through the data (which should be an array), and append the list elements to the error notices UL. We then show the error notice using the jQuery function show(). Because all of our code is contained in the same block, we have access to variables set outside this function (successNotice and errorNotice). If we want to show the success message, we simply hide the error message and display the success message.

With the ucfirst() function, I am adding this function to the prototype of the string object.



'A prototype is an object from which other objects inherit properties.'



This means that all string objects will inherit our ucfirst() function. This is why, earlier, we used name.ucfirst(). name is a string, and because our method is in the prototype, it is available for us to use.

We get the first character ( charAt(0) ), make it uppercase ( toUpperCase() ), then return it with the rest of the string minus the first character ( slice(1) ). charAt, toUpperCase and slice are all methods of the string object. You can read more about the prototype object here or here.

Now that we have our miscellaneous functions sorted out, we can concentrate on the logic for the form's outcome. We are back to working inside the formSubmitButton.bind logic.

//if form is not valid
if(!formok){

//show error message here

}
//if form is valid
else {

//ajax request + show success message here

}

We will start with the logic if the form is not valid. The following code should be placed inside the if statement:

//animate required field notice
$('#req-field-desc')
.stop()
.animate({
marginLeft: '+=' + 5
},150,function(){
$(this).animate({
marginLeft: '-=' + 5
},150);
});

//show error message
showNotice('error',errors);

The first chunk of code simply animates the '* indicates a required field'. This is not essential; it's just a nicety that gives the user a bit more feedback -- that a problem has, in fact, occurred. We are using the jQuery function animate() to animate the margin-left CSS value of the element. After this, we are going to call our showNotice() function. We want to show the error message so we pass 'error' as the first argument, then for the data we pass it the errors array we have been storing our form validation error messages in.

If the form is valid, we need to submit it via AJAX.

loading.show();
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
data: form.serialize(),
success: function(){
showNotice('success');
form.get(0).reset();
loading.hide();
}
});

Firstly, we reveal our loading gif to indicate that the form is doing something. We then use the jQuery function ajax() to submit the form to process.php. For the url and type, we are using the jQuery function attr() to get these attributes. For the data, we use the jQuery function serialize(). If the AJAX request was successful, we call our showNotice() function and pass it 'success' as the first argument. This displays our success message. The last thing we do is reset the form (clear the form fields) and hide the loading gif. All of the JavaScript is now taken care of! Congrats1 You should have ended with your script.js file looking like so:

$(function(){

//set global variables and cache DOM elements for reuse later
var form = $('#contact-form').find('form'),
formElements = form.find('input[type!="submit"],textarea'),
formSubmitButton = form.find('[type="submit"]'),
errorNotice = $('#errors'),
successNotice = $('#success'),
loading = $('#loading'),
errorMessages = {
required: ' is a required field',
email: 'You have not entered a valid email address for the field: ',
minlength: ' must be greater than '
}

//feature detection + polyfills
formElements.each(function(){

//if HTML5 input placeholder attribute is not supported
if(!Modernizr.input.placeholder){
var placeholderText = this.getAttribute('placeholder');
if(placeholderText){
$(this)
.addClass('placeholder-text')
.val(placeholderText)
.bind('focus',function(){
if(this.value == placeholderText){
$(this)
.val('')
.removeClass('placeholder-text');
}
})
.bind('blur',function(){
if(this.value == ''){
$(this)
.val(placeholderText)
.addClass('placeholder-text');
}
});
}
}

//if HTML5 input autofocus attribute is not supported
if(!Modernizr.input.autofocus){
if(this.getAttribute('autofocus')) this.focus();
}

});

//to ensure compatibility with HTML5 forms, we have to validate the form on submit button click event rather than form submit event.
//An invalid html5 form element will not trigger a form submit.
formSubmitButton.bind('click',function(){
var formok = true,
errors = [];

formElements.each(function(){
var name = this.name,
nameUC = name.ucfirst(),
value = this.value,
placeholderText = this.getAttribute('placeholder'),
type = this.getAttribute('type'), //get type old school way
isRequired = this.getAttribute('required'),
minLength = this.getAttribute('data-minlength');

//if HTML5 formfields are supported
if( (this.validity) && !this.validity.valid ){
formok = false;

//if there is a value missing
if(this.validity.valueMissing){
errors.push(nameUC + errorMessages.required);
}
//if this is an email input and it is not valid
else if(this.validity.typeMismatch && type == 'email'){
errors.push(errorMessages.email + nameUC);
}

this.focus(); //safari does not focus element an invalid element
return false;
}

//if this is a required element
if(isRequired){
//if HTML5 input required attribute is not supported
if(!Modernizr.input.required){
if(value == placeholderText){
this.focus();
formok = false;
errors.push(nameUC + errorMessages.required);
return false;
}
}
}

//if HTML5 input email input is not supported
if(type == 'email'){
if(!Modernizr.inputtypes.email){
var emailRegEx = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if( !emailRegEx.test(value) ){
this.focus();
formok = false;
errors.push(errorMessages.email + nameUC);
return false;
}
}
}

//check minimum lengths
if(minLength){
if( value.length < parseInt(minLength) ){
this.focus();
formok = false;
errors.push(nameUC + errorMessages.minlength + minLength + ' charcters');
return false;
}
}
});

//if form is not valid
if(!formok){

//animate required field notice
$('#req-field-desc')
.stop()
.animate({
marginLeft: '+=' + 5
},150,function(){
$(this).animate({
marginLeft: '-=' + 5
},150);
});

//show error message
showNotice('error',errors);

}
//if form is valid
else {
loading.show();
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
data: form.serialize(),
success: function(){
showNotice('success');
form.get(0).reset();
loading.hide();
}
});
}

return false; //this stops submission off the form and also stops browsers showing default error messages

});

//other misc functions
function showNotice(type,data)
{
if(type == 'error'){
successNotice.hide();
errorNotice.find("li[id!='info']").remove();
for(x in data){
errorNotice.append('<li>'+data[x]+'</li>');
}
errorNotice.show();
}
else {
errorNotice.hide();
successNotice.show();
}
}

String.prototype.ucfirst = function() {
return this.charAt(0).toUpperCase() + this.slice(1);
}

});



Conclusion


Congratulations! You've made it. It's been a long ride, and we've covered a lot of ground in this tutorial.

So, where do you go from here? This could be expanded to a much larger form, and all the code you've written will still work flawlessly. You could even add in your own validation for things like the telephone input field or the maxlength attribute!

Thanks for reading, and I hope you have enjoyed this tutorial!
"
read more