A matter of <form>
When I redesigned iandevlin.com as a business-card style website, I was a bit lazy when it came to the contact form. Other than making it snazzily slide down when the @ symbol graphic is clicked on, I didn’t do much else with it, leaving it the way it was – using a CGI script to send the email (I know! Seriously!)
I always had the intention of changing it but never actually got around to doing it for various reasons that range from just not being bothered to being lazy. But after reading a form of madness over at Dive Into HTML5, I decided that the time had come to actually get on with it, and to make use some of the new elements within html5. And so I have.
Decisions, decisions
To begin with, since I had already converted the site to HTML5, I wanted to take advantage of the new tags that HTML5 offered. Granted most browsers will simply ignore them, but it’s nice to have them in place and to get used to using them.
Since the site itself is contained within the one HTML page, I also wanted to use AJAX to provide some on page feedback if the form was filled out incorrectly, if the sending failed or of course, if it succeeded. I’m aware that there are plenty of existing JavaScript plugins out there that already do all this, and since the site already uses JQuery for the sliding effect, I still wanted to write my own AJAX routine, since I had been using it recently whilst writing the chat feature for the Wildlifefocus website (which is nearing completion).
HTML5 form
I won’t go into all the new form elements that HTML5 offers, you can read about them in a form of madness and/or in the HTML5 specification itself. Here I will just mention the items that I have used which are as follows:
- the
placeholder
attribute — which is used to display default text in a field, e.g. “enter your name”. I have used this in each of the input fields that are part of my form. Currently only Safari 4 and Chrome support this. - the
autofocus
attribute — is used to automatically focus on a field, e.g. on the name field in my form. Safari 4, Chrome and Opera currently support this feature. <input type="email">
element — which is used to define an element containing an email address. It’s important to note in this case that if a browser doesn’t support one of these new HTML5<input>
types, it simply treats it as atext
type and doesn’t have any adverse affects. Opera currently styles this field with a small email icon alongside it, but the spec itself doesn’t define what to do with it. Perhaps some browsers will build in some automatic data checking in the future?
Note, that for HTML5 compliancy, the <input>
elements do not have closing tags.
AJAX and PHP
With the form markup out of the way, it was time to tackle the validation and submitting of the email itself, which isn’t actually that difficult at all and I’ll simply show you here what I’ve done.
The form action itself calls a JavaScript function which collects the parameters, and calls the sendmail.php
page (described below) to send the email. The sendEmail
JavaScript function looks like this:
function sendEmail(obj) { var params = ""; if (obj.elements.name != "") { params += (params=='')?'?':'&'; params += "name=" + escape(obj.elements.name.value); } if (obj.elements.emailaddr != "") { params += (params=='')?'?':'&'; params += "emailaddr=" + escape(obj.elements.emailaddr.value); } if (obj.elements.subject != "") { params += (params=='')?'?':'&'; params += "subject=" + escape(obj.elements.subject.value); } if (obj.elements.message != "") { params += (params=='')?'?':'&'; params += "message=" + escape(obj.elements.message.value); } if (params != "") { xmlhttp = GetXmlHttpObj(); if (xmlhttp == null) { alert ("Your browser does not support XMLHTTP!"); return; } var url = "sendemail.php" + params; xmlhttp.onreadystatechange = sendEmailStateChanged; xmlhttp.open("POST", url, true); xmlhttp.send(null); } }
GetXmlHttpObj()
returns the appropriate Xml Http object for the browser as follows:
function GetXmlHttpObj() { if (window.XMLHttpRequest) return new XMLHttpRequest(); if (window.ActiveXObject) return new ActiveXObject("Microsoft.XMLHTTP"); else return null; }
The function sendEmailStateChanged()
which displays the result of the email sending once the state has changed is:
function sendEmailStateChanged() { if (xmlhttp.readyState == 4) { var response = xmlhttp.responseText; if (response == "ok") { document.getElementById("emailcontainer").innerHTML = "Thanks"; } else { document.getElementById("formerror").style.display = "block"; document.getElementById("formerror").innerHTML = response; } } }
To replace the old CGI script, I created a simple PHP page that handles the actual sending of the email. It parses the incoming arguments and validates them, adding to an error string if anything is amiss (missing fields, invalid email address) and either sends the email or returns the error string for AJAX to display above the form:
<?php
require("lib/lib_email.php");
$temp_name = $_GET["name"];
$temp_email = $_GET["emailaddr"];
$temp_subject = $_GET["subject"];
$temp_message = $_GET["message"];
$name = trim($temp_name);
$email = trim($temp_email);
$subject = trim($temp_subject);
$message = trim($temp_message);
$return_msg = "";
if ($name == "") $return_msg .= "enter your name";
if ($email == "") $return_msg .= "enter your email";
else if (!is_email_address_valid($email)) {
$return_msg .= "enter a valid email address";
}
if ($subject == "") $return_msg .= "enter a subject";
if ($message == "") $return_msg .= "enter a message";
if ($return_msg == "") {
$headers = "From: " . $email . "\r\n";
$to = "name@emailaddress.com";
$message = str_replace("\n.", "\n..", $message);
if (!mail($to, $subject, $message, $headers)) [
print "error sending mail";
}
else print "ok";
}
else print $return_msg;
?>
Note that lib_email.php
contains the is_email_address_valid()
function that validates the email address using regular expressions. Also, there’s not much sanitisation performed on the parameters since they’re not being added to a database so it’s not that important here.
And there you have it. A simple HTML5 compatible contact form that uses AJAX and PHP to send an email.