Creating a Dynamic Poll with jQuery and PHP

When you combine some neat functionality courtesy of PHP with the cleverness of jQuery you can produce some pretty cool results. In this tutorial we'll create a poll using PHP and XHTML, then make use of some jQuery Ajax effects to eliminate the need for a page refresh, and to give it a nice little bit of animation.

This form will be processed by the PHP for now, and when we get the Javascript running, by jQuery. The PHP and Javascript are designed to pull the option ID from the value tag. &nbsp; is just a HTML entity encoded space, and &rarr; is an arrow: →.

PHP

Introduction

If Javascript is disabled, the PHP will:

Take GET/POST requests from the form

Set/check a cookie

Make sure the request is from a unique IP

Store the vote in a flat file DB

Return the results included with a HTML file

If Javascript is enabled, the PHP will:

Take GET/POST requests from the Javascript

Make sure the request is from a unique IP

Store the vote in a flat file DB

Return the results as JSON

For the flat file DB we will be using a package written by Luke Plant.

.graph styles the container for the bars, titles and percentages. The width will be different for each site.

.bar-title styles the titles for the bar graphs.

.bar-container styles the individual bar and percentage containers

.bar-container div styles the div that the bar is applied to. To create the bars, a percentage width is set with PHP or Javascript.

.bar-container strong styles the percentage.

#poll-results p styles the total votes.

Javascript

Introduction

The Javascript will intercept the submit button, send the vote with Ajax, and animate the results.

First, some global variables. You should recognize the first three from the PHP. votedID stores the ID of the option the client voted for.

var OPT_ID = 0;
var OPT_TITLE = 1;
var OPT_VOTES = 2;
var votedID;

Now we need a jQuery ready function which runs when the page loads:

$(document).ready(function(){

Inside that function we register the handler for the vote button which will run formProcess when it is triggered:

$("#poll").submit(formProcess);

We also need to check if the results <div> exists, and animate the results if it does:

if ($("#poll-results").length > 0 ) {
animateResults();
}

If we have a cookie we should jump straight to generating the results because the user has already voted. To do that we need to get rid of the poll form, get the id from the cookie, grab the results from the PHP and pass them to loadResults().

formProcess() is called by the submit event which passes it an event object. It prevents the form from doing a normal submit, checks/sets the cookies, runs an Ajax submit instead, then calls loadResults() to convert the results to HTML.

input[@name='poll']:checked is a jQuery selector that selects a <input> with an attribute of name='poll' that is checked. attr("value") gets the value of the object which in our case is optn where n is the ID of the option.

Now that we have the ID, we can process it. To start, we fade out the poll form, and setup an anonymous function as a callback that is run when the fade is complete. Animations don’t pause the script, so weird things happen if you don’t do it this way.

$("#poll-container").fadeOut("slow",function(){

After it has faded out we can delete the form from the DOM using empty():

$(this).empty();

In this case, $(this) is jQuery shorthand for the DOM element that the fade was applied to.

jQuery has some other shortcut functions, including $.getJSON() which does GET request for a JSON object. When we have the object, we call loadResults() with it:

loadResults() is called by $.getJSON() and is passed a JSON object containing the results DB. It is pretty much the same as it’s PHP counterpart poll_return_results() with a few exceptions. The first difference is that we set the width on all the bars to 0% because we will be animating them. The other difference is that we are using a jQuery append() instead of regex to show the results. After the results fade in, the function calls animateResults().