Create a bullet-proof contact form

Note: This article has been marked for a quality review and will soon be updated.

Contact pages are usually one of the basic building blocks of any website, and while many simple feature an email address for spam bots to pick up and use, or even a handy 'mailto' link, the best ones feature a proper contact form. To make a bulletproof one we're going to need some thick glass and a riot shield PHP and JavaScript. Having those bad-boys on our side will ensure we can create a beautiful AJAX-enabled means of contact for our users. We also need to ensure our form will work on the rare occasion that a user has JavaScript turned-off *gasp* - I know, it's a scary thought, but I'm sure we'll figure something out!

So we'll start with some simple HTML to set out our fields, the following code is what we'll be working with:

<form id="contact" class="right" method="post" action="mail.php">
	<h3 class="hidden success"><br/>Message sent!</h3>
	
	<label>Name: <span class="warning right"></span>
		<input type="text" name="name" />
	</label>
	
	<label>Email: <span class="warning right"></span>
		<input type="text" name="email" />
	</label>

	<label>Message: <span class="warning right"></span>
		<textarea name="message"></textarea>
	</label>
	<input class="right" type="submit" value="Send" />
</form>

Aside from the obvious, the form features a few extra elements - namely the .warning elements - we'll see what they're for in a moment. I also assume that you have the class of .right set up to float elements to the right; if now, then you'll need to float the affected elements individually in your CSS. Right, that's the HTML sorted, lets take a look at the JavaScript for this puppy.

function validateEmail(email){ 
	 var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ 
	 return email.match(re); 
}

$('#contact').submit(function(){
	var name, email, message, errors;
	
	errors = 0;
	name = $('input[name=name]').val();
	email = $('input[name=email]').val();
	message = $('textarea[name=message]').val();
	
	$('.warning').text('');
	
	if(name==''){ $('input[name=name]').siblings('.warning').text('This field is required!'); errors++; }
	if(email==''){ $('input[name=email]').siblings('.warning').text('This field is required!'); errors++; }
	if(message==''){ $('textarea[name=message]').siblings('.warning').text('This field is required!'); errors++; }
	if(!validateEmail(email)){ $('input[name=email]').siblings('.warning').text('Please enter a valid email!'); errors++; }
	
	if(errors==0){
		var dataString = $(this).serialize() + '&js=true';
	
		$.ajax({
			url: 'contact-post.php',
			data: dataString,
			type: 'POST',
			success: function(data){
				$('form label, form input[type=submit]').slideUp(500, function(){
					$('form .success').hide().removeClass('hidden').slideDown(500);
				});
			}
		});
	}
	
	return false;
});

Now for the moment we'll ignore the validateEmail() function, and take a look at the form submission code. First off we set up some variables for the values in our form, this prevents us having to use longer code snippets and querying the DOM too much. Once we've got them set up we give the user the benefit of the doubt and remove any warning that may have previously been set by removing any text from the elements with the class of .warning. And then we validate the fields. The first three 'if' statements simply check that the user has entered a value in each field - if they haven't we tell them so, and increment our errors variable by 1. The last 'if' statement uses the validateEmail() function that we set earlier. There's no reason to worry if you don't understand how that function works, Regular Expressions are a world of their own. All we need to know, is that it tells us if the user has entered a valid email address.

Following our rather basic validation checks we then test to see if the form has passed - because we've been using our errors variable all along, if it's set to '0' we can rest assured nothing has gone wrong. If that's the case we serialise the form, and use a simple AJAX request to submit the data to our server. If our server is happy, we show our users a success message. Now all we need to do is set up our contact-post.php file, like so:

function redirect($hash){
	if($hash!='success'){
		echo 'Invalid ' . $hash;
	}else {
		echo 'Message sent!';
		echo '<meta http-equiv="refresh" content="0;url=http://example.com/">';
	}
	die();
}

if($_POST){
	if(empty($_POST['js'])){
		// Validate info here
		if(empty($_POST['name'])){ redirect('name'); }
		if(empty($_POST['email'])){ redirect('email'); }
		if(empty($_POST['message'])){ redirect('message');  }
		if(filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)){ redirect('email'); }
	}
	
	$sendto = 'you@example.com';

	$name = $_POST['name'];
	$email = $_POST['email'];
	$phone = $_POST['phone'];
	$message = $_POST['message'];
	
	$to = $sendto;
	$subject = "[MySiteName] Message";
	
	$message = "
	<html>
	<head>
	<title>Contact form Submission</title>
	</head>
	<body>
	<p style='font-family:Arial, Helvetica, sans-serif; color:black;'>The following was sent by <strong>".$name." (Email: ".$email."):</strong></p>
	<p style='font-family:Arial, Helvetica, sans-serif; color:black; font-size:16px;'>".nl2br(stripslashes($message))."</p>
	
	<p style='font-family:Arial, Helvetica, sans-serif; color:black;'>(Sent on: ".gmdate('d\/m\/y').")</p>
	</body>
	</html>
	";
	
	$headers = "MIME-Version: 1.0" . "\r\n";
	$headers .= "Content-type:text/html;charset=iso-8859-1" . "\r\n";
	$headers .= 'From: ' . $name;
	
	mail($to,$subject,$message,$headers);
	
	redirect('success');
}else {
        redirect('submission - no data entered!');
}

The function at the top will be used when we want to give the user some feedback - if they entered all the correct info, they'll be given a success message, and then redirected to your site in a timely fashion, otherwise they will be told what is wrong with their submission. Then we get to the guts of the script - we first make sure there is some data to play with - if there isn't we tell the user off, and if there is we go on to see if the user has JavaScript running. You may have noticed the little variable 'js' that we added to the serialised form back in our JavaScript - that is our way of finding out if the form is being submitted via an AJAX request in JavaScript - if the variable is empty, we let PHP validate our form's content - this is essentially identical to the JS code we used previously.

We then set up a really basic email, and send it to the address in the $sendto variable. Finally we redirect the user to the site. As a side note, do remember that this page will only be seen by users without JavaScript turned on.

And that's it! You now have a swanky contact form that, for all intents and purposes, is bullet-proof, but having said that, I wouldn't actually test that theory with a gun of any kind...

WordPress: Load more posts on page scroll

Note: This article has been marked for a quality review and will soon be updated.

Although I don't visit archive pages very often, when I do I like it when I don't have to trawl through pages and pages of 10 posts using tiny navigation buttons at the bottom of the page. A great way to prevent this annoyance for your users is to use AJAX to dynamically append posts to the end of your archive list. To do this in WordPress we need to abstract the process of getting the list of posts and then use some Javascript (in out case jQuery aided) magic to load in our content. So lets get started.

First off we need to create a function that we can call to spit out a list of posts. Usually on an archive page we would use the normal WordPress loop to accomplish this, but in our case we need to abstract the loop into a separate function so that we can access it from any file - more specifically our Javascript file. We also need to be able to pass an offset value to this function to make sure we don't load the same posts every time it is called. This function is going to differ slightly depending on your markup for your archive page, but this is how it would look for Tom's Big Box:

function getArchives($count,$offset){
	query_posts('posts_per_page='.$count.'&offset='.$offset);
	
	$posts = array();

	if(have_posts()) : while(have_posts()) : the_post(); 	
		$img = post_image($post->ID);
		$commentsNo = get_comments_number();
		if($commentsNo==0){
			$comments = 'No Responses';
		}else if($commentsNo==1){
			$comments = '1 Response';
		}else {
			$comments = $commentsNo . ' Responses';
		}
		
		$item = '<li id="'. get_the_ID() .'">
			<figure class="vignette left">
				<img src="'. get_bloginfo('template_url') .'/scripts/timthumb.php?src='. $img->src .'&w=180&h=120" alt="'. $img->alt .'" />
			</figure>
			<h3><a href="'. get_permalink() .'">'. get_the_title() .'
			<p class="article-meta left">'. get_the_time('jS M Y',$post->ID) .' ~ '. $comments .'

<p class="extract"> '. get_the_excerpt() .' </p> </li>'; array_push($posts,$item); endwhile; endif; return $posts; }*/

Stick this in your functions.php file, and we can walk through what this code is doing. Firstly the two parameters that we it accepts are $count - which tells our functions how many posts we want, and $offset - to ensure that we don't load the same posts every time our function is called. We then send these parameters to WordPress's query_posts() function which will give us a list of posts. We then set up the $posts array to sold our data and begin iterating through the posts. I created a separate image variable to hold information about each post's image because I don't use WordPress's inbuilt image resizing, this is something which may not apply to you. After that an if statement creates a nice string based on the number of comments per post - this is because the inbuilt functions return only the number of comments or directly outputs to the document - something we don;t want. Then we load our content into the $item variable using whatever markup we need, and finally use array_push() to add our $item variable to the $posts variable, before returning the final $posts variable in its entirety.

Phew! Well that's most of the server-side stuff done, but before we can say goodbye to PHP, we need to do one more thing. We need to create a file to which we will pass our parameters, and that will execute the function we just created, and return the code we need. Don't worry, this is far simpler than the function above, let's take a look at the code:

require( '../../../../wp-load.php' );
$posts = getArchives(20,$_GET['offset'],false); 
foreach($posts as $p){
	echo str_replace("'","'",$p);
}

So, ignoring the first line for a moment, this file simply passes the $_GET['offset'] variable to our newly created function, and then iterates over the output, making sure to replace any single quotation marks to stop it from breaking. "But hang on Tom, what does that first line do?!" I hear you cry, well the first line makes sure we can access the function we just created, and for that matter all the inbuilt WordPress functions, so it is vital that you keep it. You will also need to change the path in the require() statement to ensure it matches the root directory of your WordPress install. Pop the above code in a file called get-posts.php and stick it in your theme's directory. And with that, we can say hasta la vista to PHP, and buongiorno to jQuery (that's right, I'm cultured).

Now, having made sure jQuery is included on your page, paste in the following code:

var halfWay = ($(document).height()/2);
var offset = 20;
var inAction = false;
var reachedEnd = false;

$(document).scroll(function(){
   if($(document).scrollTop() > halfWay && inAction == false){
       inAction = true;
		
       $('.article-list').append($('
').load('http://example.com/wp-content/themes/myTheme/get-posts.php?offset='+offset, function(){ offset = offset + 20; halfWay = halfWay + 1775; inAction = false; })); } });

Lets go through what this does. We have a function that fires whenever the page scrolls, and within that we compare the current scroll amount to half the overall document height, if it is greater (meaning that the user has scrolled more than half way down the page), and the variable inAction (I'll get to that in a moment) is true, it executes the following code. If the conditions are satisfied we then use AJAX to load in some more posts. Now it may appear a rather convoluted way to be doing so, but in my experience this way of handling an AJAX request of this type is the best. So for this method we send a request to our file that we just created in our theme's directory, and pass it the variable offset, when the content is loaded we run the embedded function which increments our offset variable by 20, adds a suitable amount to our halfWay variable. We then reset the inAction variable. This variable is used to prevent a massive build up of requests because of page scrolling, we use it because every time the page scrolls even a pixel, the function is called, so we don't want it to be called 3 times before we have a chance to offset the next post, otherwise we will end up with a huge amount of duplicate posts being loaded in. The conditions in the if statement will stop being satisfied after the last posts are loaded in because our inAction will stay in it's true state forever after one request for no posts means the success() function isn't executed.

And that's it! It might be a good idea to have a loading graphic at the bottom of you page when doing this to give some user feedback, and I would suggest also adding pagination just incase your server stops responding and leaves your users hanging. But aside from that, I think I covered the basics of how to implement the AJAx loading in of content. Oh and by the way, you will now also be able to generate archives anywhere on your site using the function getArchives(), meaning you will write less code in the long run - two birds with one stone!