Wednesday, October 31, 2007

Building a Web Site Poll Using Ajax


Paul Hudson reveals how to add a poll to your pages using AJAX power


Just when you thought it was safe to open your web browser, JavaScript is back with a vengeance. Admit it: when you moved from clientside to serverside programming, you breathed a sigh of relief at leaving cross-browser problems, broken scripting implementations and technology acronyms behind. But now that web site back-ends have been revolutionised through powerful new scripting languages, it’s time to focus on the front end.


AJAX – in case you didn’t see our feature last issue, is an acronym for Asynchronous JavaScript and XML – is about eliminating the lack of interactivity that we’ve all grown used to on the web. If you have a document that may change while a user is viewing it (an email inbox, for example), then you would normally have had to set a HTML meta tag to refresh every minute, or force users to click Refresh by hand. With AJAX, we can program the page to ping a server to check for updates, download any new information and insert it into the page.



Nothing about AJAX is new: XML has been around for several years and JavaScript for longer. The difference is that a special JavaScript object, known as XMLHttpRequest, is being bound by JavaScript and used to send and receive XML. This object isn’t new either, but has only started to see proper use with AJAX.


To check whether a page has changed, our HTML page calls a JavaScript function that sends off an XML request to our server. This is processed and a response is sent back in XML saying what has changed. PHP fits into the AJAX equation as the serverside parsing mechanism: it accepts the client XML, runs the necessary database checks, and sends the results back down to the client. This close interrelationship of languages means you need to be up to scratch not only on PHP, but also on JavaScript and XML.


Copy the code:

We are going to take you through a very basic example of AJAX code with the aim of creating a web poll that will enable your site users to vote on an issue:


Our mission this issue is to produce an AJAX web poll using PHP, MySQL, JavaScript and good old HTML. Once you’re more proficient with AJAX you’ll see there are many ways of doing the same thing, including lots of shortcuts. Take your time: learn the standard way of doing things first, then cut corners later! For this code to work, you need to choose a relatively modern web browser: Safari 1.2, Firefox 1.5, IE 6 and other browsers of that level are all AJAX-ready.


1. The first thing we’re going to look at is how to create an instance of the XMLHttpRequest (XMLHR) object. Surprisingly enough, this was invented by Microsoft back in the IE5 days, and was implemented as an ActiveX object. Most other web browsers don’t use the ActiveX system for embedding objects into pages, so they have their own method of creating an XMLHR object. Fortunately, IE7 (due out in Windows Vista) will drop the ActiveX method and switch to the de facto standard used by other browsers. Until then, we need to write a function that detects the browser and creates the object in the correct way. Save this in ajax.js:


function createAjax() {

var ajax = false;

if(window.XMLHttpRequest) {

ajax = new XMLHttpRequest

();

} else if(window.ActiveX

Object) {

ajax = new ActiveXObject

(“Microsoft.XMLHTTP”);

}

return ajax;

}


This will create an XMLHttpRequest on any modern browser, as long as the IE browser has ActiveX enabled.


2. We can now go ahead and write a script that creates a new XMLHR object with the createAjax() function, then requests content from our server and loads it into the page. The full code to do this is in the index. php files in directory 2 of the PHP tutorial file on the CD, but we want to explain what these important lines do:


var http = createAjax();

if (http) {

http.open( get , check.

php );

http.onreadystatechange =

handleResponse;

}

function handleResponse() {

if (isAjaxReady(http)) {

response = http.response

Text;

document.getElementById

( mycontent ).innerHTML

= response;

}

}


When we’ve created our object and made sure it’s working, then call its open() function. This tells our XMLHR object what HTTP method it should use (get, rather than post or head) and what file it should request (check.php). We also set its ‘onreadystatechanged’ property to be ‘handleResponse’, which means that when the ready state (the current state of our XMLHR object) is changed, the handleResponse() function will be called. The ready state changes when the object is doing something, such as sending data or receiving data. By attaching ourselves to this state change, it’s possible for us to monitor what it’s up to and catch when it’s received some data.


The handleResponse() function gets called whenever the state of our XMLHR object changes. The first thing that happens is a call to the isAjaxReady() function, which we’ve added to your ajax.js file. The XMLHR object has several states: zero is uninitialised, one is loading, two is loaded, and so on. What we care about is state four, which means finished, and is used when the XMLHR object has sent its data and received a response back from the server. The isAjaxReady() function is just a quick one-liner to check whether the XMLHR object is in state four, and returns true if that’s the case.


If we’re in state four, then we’re able to read the response we got back from the server and print it out. In index.php you’ll see there’s a DIV with the ID ‘mycontent’. This is where the output from the XMLHR object gets stored. The request itself just loads check.php, which, if you look on your CD, you’ll see that it contains a call to phpinfo() to send back a lot of HTML. If everything has worked as it should, you’ll be able to see it embedded inside index.php thanks to AJAX.


3.Receiving some text and printing it out is hardly interesting and not at all useful, but AJAX can do so much more. If you look in the directory 3 on this issue’s CD you’ll see the file sql.txt. Take the SQL from there and insert it into a database server, because we’re now going to have our PHP script read that data, convert it into XML, send it across the web to our XMLHR object, then parse and display it using JavaScript. There are two interesting code sections to examine here. The first is check.php, which is now useful:


<?php

header(“Content-type: text/

xml”);

mysql_connect(“localhost”,

“dotnet”, “blabla69”);

mysql_select_db(“dotnet”);

$result = mysql_query

(“SELECT Question, Answer1,

Answer2, Answer3, Votes1,

Votes2, Votes3 FROM poll

ORDER BY ID DESC LIMIT

1;”);

extract(mysql_fetch_assoc

($result), EXTR_PREFIX_ALL,

“vote”);

echo “<vote>”;

echo “<question>$vote_

Question</question>”;

echo “<answer><value>$vote_

Answer1</value><votes>$vote

_Votes1</votes></answer>”;

echo “<answer><value>$vote_

Answer2</value><votes>$vote

_Votes2</votes></answer>”;

echo “<answer><value>$vote_

Answer3</value><votes>$vote

_Votes3</votes></answer>”;

echo “</vote>”;

?>


4. You’ll need to edit the MySQL connection data to work on your local system. The call to mysql_query() loads the most recent poll in your database, which is extracted and set inside some basic XML. There’s no DTD, which means there’s little point trying to reference elements by IDs because XML has, as yet, no innate knowledge of what an ID is, unlike HTML and XHTML. The second piece of interesting code is in index.php, which has now been upgraded to handle XML rather than plain text:


var response = http.response

XML;

pollQuestion = response.get

ElementsByTagName( question )

[0];

pollAnswers = response.get

ElementsByTagName( answer );

pollAnswerText = “”;

for (i = 0; i < pollAnswers.

length; ++i) {

pollAnswerValue = pollAnsw

ers[i].getElementsByTagName

( value )[0].firstChild.

data;

pollAnswerVotes = poll

Answers[i].getElementsByTag

Name( votes )[0].firstChild

.data;

pollAnswerText += <input

type=”radio” name=”vote”

value=” + (i + 1) + ” />

+ pollAnswerValue + “ (“ +

pollAnswerVotes + “)<br

/>”;

}

new_html = <form method=

”post” action=”vote.php”

><strong>Question: ;

new_html += pollQuestion.

firstChild.data + :</strong>

<br /> + pollAnswerText;

new_html += <input type=

”submit” value=”Vote!” /></

form> ;

document.getElementById( mycon

tent ).innerHTML = new_html;


The first line contains a subtle but important difference: we’re not using http.response any more, but http.responseXML instead, which gives us an object to work with rather than a text string. This object is quite difficult to use, precisely because the lack of IDs for direct reference mean we have to pull out tags by name using getElementsByTagName(), then refer to the first item in that array (the [0] part), even if there’s only one such element in the XML.


Most of the code is there to pull values from the XML (specifically the question and answer tags) and convert them into an HTML form where users can submit their answer. This form is set up to be sent to vote.php, which means that we’re using AJAX to read the data but plain old HTML forms to submit the data.


Of course, if we’re going to do an AJAX web poll we ought to go the whole hog and send and receive data. The code for this is in directory 4 on your CD, and you’ll see that check.php is still there to read the vote data, but there’s now also vote.php, which saves votes back to the database. There’s a minor change in check.php: the <vote> element now has an ID attribute so we know which poll people were voting in. As mentioned already, this isn’t the same as the HTML/XHTML ID attribute that can be used to identify elements uniquely; instead, this is just a data field, like anything else.


The index.php file has also been upgraded somewhat, because we now need to make two calls through XMLHR: one to read the poll, and another to write our vote. It’s not tricky to re-use XMLHR objects for multiple requests, but when you’re learning it’s easiest just to keep a clear separation between XML requests. As a result, in the code you’ll see that loadVote() creates an XMLHR object, doPollRead() retrieves the data, handlePollRead() parses the XML and displays it, and doVoteWrite() creates a fresh XMLHR object and submits the vote. It also re-calls loadVote() and doPollRead() so that the poll updates once you’ve voted.


The only other part of the code that needs any explanation in the new index.php is the following section:


for (i = 0; i < vote_options.

length; ++i) {

if (vote_options[i].checked

) item_selected = i + 1;

}

if (http) {

http.open( get , vote.

php?Vote= + pollID + &

Answer= + item_selected);

}


The first part loops through our vote radio buttons and finds the one that’s selected. Note that we add one because JavaScript arrays are zero-based whereas out database fields are Votes1, Votes2 and Votes3. The second part is where we send our selection over to vote.php using the HTTP GET method. This requires us to separate our URL from our data with a question mark, and also to separate each field with ampersands, as per normal.


We’ve only had space to cover the absolute core parts of the AJAX code here – to learn more, read the code on your CD.

0 comments:

Post a Comment

Followers

 

Pablo Emmanuel Otaola. Copyright 2008 All Rights Reserved Revolution Two Church theme by Brian Gardner Converted into Blogger Template by Bloganol dot com