The AJAX tutorial: Part 2
Prologue: We meet again
I am always in a habit of writing prologues to all the tutorials/works I ever make. This is another one. We have till now, covered the very basics of AJAX. Today, we will get a bit into details. In our previous examples, we learnt how to get data from the server. But, is it enough? Just getting some data from a server file/script gives you zero points on interactivity. To make your application interactive, you need to send some data to the server and then get the results based on the data sent. This is what we'll be covering in the 2nd Part of our AJAX tutorial. We all know that example isn't the best way to teach, it is the only way. Hence, in this section I've included a complete AJAX powered phonebook demo to explain how to use AJAX for practical purposes. That's all for the prologue, let's do some AJAX.
Note: This tutorial uses the 1st part as a reference throughout the tutorial. If possible keep open another window which is displaying the 1st part of the tutorial as it will be highlyt beneficial to you.
Download the complete source code(also includes source code for 1st part) used in this tutorial: .zip format .rar format
Chapter 1. Sending data to the Server
Look at our first example. We just recieved some data from the server. The server would output the same data always. But to make our AJAX project interactive, we need to send data to the server and then create the server side script in such a way that the output is based on the data recieved.
1.1: The HTTP GET method
If you script in any server-side language, you must be knowing of the 'GET' method. It is an HTTP method to send data to the server. Data is sent in the variable-value format. Multiple variables are appended in a single string known as a 'query string'. For example, if there are two variables, 'username' and 'password' and their values are 'myname' and 'mykey', then the query string would be: 'username=myname&password=mykey'. Yes, you guessed it right(and even if you didn't), variable=value for multiple variables is joined with an ampersand sign i.e an '&' sign. This query string is then appended to the address of the file/script the query is sent to. For example, if we send this data to a script called as '
http://www.mysite.com/process.php', then the adress with the data would be: '
http://www.mysite.com/process.php?usern ... word=mykey'. It is as simple as that.
1.2: Accessing the HTTP GET variables on the server script
I don't know about other languages like asp, jsp etc., but in php, all the variables sent through the 'GET' method, are stored in a pre-defined variable array called $_GET (in versions earlier to 4.10, the array was $HTTP_GET_VARS). In our example the two pieces of dat would be stored as:
$_GET['username'] = 'myname'; //A hypothetical example. In actuality, it is just
$_GET['password'] = 'mykey'; //a pre-defined variable array defined by php.
The following script would print the data we got from the client:
Code: Select all
<?php
if(isset($_GET['username']) && isset($_GET['password'])) {
printf("Username: ".$_GET['username']);
printf("
");
printf("Password: ".$_GET['password']);
}
?>
Save it as printget.php and check for yourself. You can also try with your own server-scripting language with the help of the respective ****. Now, how does this thing work? Let's check it out, line-by-line:
1. the isset($varname) function checks whether '$varname' as a variable has been initialized or not. In our case, if a GET query is sent with a variable called 'username', $_GET['username'] must be initialized and hence isset($_GET['username']) will return true. Same for $_GET['password']. In the first line, we check if both these variables are initiated or not.
2. If both these variables, are initiated, the script prints the username and the password to the output stream. And that's what we recieve from within the XMLHttpRequest() object.
Now look at the function fetchData() in Chapter 4.1: Doing some AJAX. Take a look at the first line:
Code: Select all
httpr.open('GET', 'returndata.php');
If you change it to this:
Code: Select all
httpr.open('GET', 'printget.php?username=myname&password=mykey');
Then you will notice a change in the string that is returned when you **** on the button. But still the question remains, what was the interactive nature of this script. Wait till we get going.
1.3: Adding interactivity
Go back to the HTML code in section 4.1. In place of this:
Code: Select all
<body>
<p id="fields">Text here will be changed</p>
<input type="button" value="**** to change text" ****="javascript:fetchData()" />
</body>
put this:
Code: Select all
<body>
<p id="fields">Text here will be changed</p>
<p>Username: <input id="username" type="text" /></p>
<p>Password: <input id="password" type="text" /></p>
<input id="submit" type="button" value="Send to server" ****="javascript:fetchData()" />
</body>
Basically, in this method we have created two text-fields, one is for the username and one is for the password and a button after **** which the fetchData() method is called as in the 1st part.
Also, modify the fetchData() function in JavaScript like this:
Code: Select all
function fetchData() {
var querystring = "";
querystring += "username=";
querystring += username.value;
querystring += "&password=";
querystring += password.value;
httpr.open('GET', 'printget.php?' + querystring);
httpr.onreadystatechange = processData;
httpr.send(null);
}
Please download the source code from the link in the Prologue and open the source code from 'ajax-tutorial/part2-1.3'. Complete source code has not been put here for space considerations.
Now this is what we'll observe:
http://tritium.frihost.net/tutorials/aj ... image1.gif
I've shown two 'After ****' images with two different cases of usernames/passwords. Now, how does this work. Let's get to it, line-by-line:
1. We create a string called 'querystring' which shall be the data we send to the server. We initialize it as a string. Though it is not necessary, it is always a good habit to do so.
2. We add the string 'username=' to the existing string.
3. We add the text in the username field to the querystring. Supposing the username entered was 'rohan', the querystring would now be: 'username=rohan'.
4. Now, we add the ampersand symbol to it and also the variable name of the next variable. Know the query string is: 'username=rohan&password='.
5. Finally, we add the text in the password field to the querystring. The querystring now: 'username=rohan&password=mykey'.
6. We did in so many steps just to make things clear to you. Actually, you could have done that in a much smaller way too:
Code: Select all
httpr.open('GET', 'printget.php?username=' + username.value + '&password=' + password.value);
This is what it appears to the JavaScript interpretor:
Code: Select all
httpr.open('GET', 'printget.php?username=rohan&password=mykey');
As it is appended in the address itself, it is easily interpreted by the server and the variables are passed on to the CGI-app (which in our case is php) and it creates the usable variables for us. GET is a simple way to send data, but not very secure. In the next chapter, I'll explain the usage of the much more secure POST method which is also much more reliable for large data strings.
You can also add authentication to this by modifying the php script a bit:
Code: Select all
<?php
if(isset($_GET['username']) && isset($_GET['password'])) {
if($_GET['username'] == "rohan" && $_GET['password'] == "mykey") {
printf("Login succeeded");
} else {
printf("Wrong username/password");
}
}
?>
Try this code yourself. I've not provided with a screenshot or any other post-test material.
1.4: The POST method
The POST method is much more secure and reliable than the GET method. The querystring remains the same, with the only two differences: 1. GET is sent as normal text(ASCII), while you have to send POST strings with a MIME-type which specifies the type of content you are sending. 2. POST is not appended to the file address. and on the server side, with php, the pre-defined array-variable is $_POST rather than $_GET
The reasons you should use POST are:
1. Security.
2. POST supports longer strings than GET.
3. You can send even files with POSt. However, it is not possible to send files via XMLHttpRequest (as of now).
Using POST is as simple as using GET. Let us look at the modified fetchData() example:
Code: Select all
function fetchData() {
var querystring = "";
querystring += "username=";
querystring += username.value;
querystring += "&password=";
querystring += password.value;
httpr.open('POST', 'printpost.php');
httpr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
httpr.onreadystatechange = processData;
httpr.send(querystring);
}
The changes are:
1. We have set a request header using the setRequestHeader() method of XMLHttpRequest. As I said, this is necessary as the POST method requires the MIME encoding for the data to be sent. I won't get much into MIME. Basically, it is a method of telling the type of a file for internet purposes. For now, our Content-type would be 'application/x-www-form-urlencoded' Get more on MIME here:
http://en.wikipedia.org/wiki/MIME . The header is actually an HTTP header which is extremely a crucial part of the server-client interchange on all server development platforms. HTTP headers basically, is a data transfer among the data-sender to the data-reciever on what to do with the data sent to it, what is the type of data sent to it and the rest.
2. Then, we have changed the params of the send() method from 'null' to the query string. There was a reason why we did this. In the GET method, the query is appended to the URL, but in the POST method it is not so. It is sent more like a file transfer among two networked computers. Hence, we send the data using the 'send()' method with the query string as the parameter.
Also, you need to modify your printget.php file a bit. Change it's name to printpost.php and here is the code to it:
Code: Select all
<?php
if(isset($_POST['username']) && isset($_POST['password'])) {
printf("Username: ".$_POST['username']);
printf("
");
printf("Password: ".$_POST['password']);
}
?>
Now try this out. It will work same as the previous example, but with an internal difference that it uses a different method altogether.
1.5: The thing till now
You might now have understood how you can add interactivity to your AJAX pages. You can then further play with the values you recieve and then create complex systems. It is not easy to do this directly into the practical world, but don't worry, I'll guide you through that also. In the next section, I'll present you a phonebook example which is completely AJAX powered for viewing and editing the phonebook. It is followed my some excercises so you can sharpen your AJAX skills. All this and more, in the sections to come... keep reading.
Chapter 2: The phonebook example
2.1: Introduction
This is not going to be a very big example. We are going to create a small phonebook, in which anyone can add and view the contacts. I am not going into stuff like authentication and all that. That requires another tutorial by itself. We are going to use MySQL to store the names, email addresses, phone numbers and postal addresses. So.. let's get down to some PRACTICAL AJAX...
2.2: The MySQL database
Firstly, we need to create a MySQL table which will store the data of the various people we enter in the phonebook. I've created a basic MySQL table for that and added some dummy entries in it. Here is the table:
Code: Select all
+----+------------+-----------+--------------+--------------------------+--------------------------------------+
| id | first_name | last_name | phone | email | postal_add |
+----+------------+-----------+--------------+--------------------------+--------------------------------------+
| 1 | Rohan | Prabhu | 0265-2236082 | rohan2kool@gmail.com | Some home, some street, some city |
| 2 | Some | Person | 2342356754 | somepersron@somemail.com | 343-45, This street, Delhi |
| 3 | Nikhil | Verma | 32452356 | nikhil@nikhil.com | 3456, A good place, Lucknow |
| 4 | Pallab | Sonai | 435436546 | pallab@pallab.com | The big palace, Asansol, West-Bengal |
+----+------------+-----------+--------------+--------------------------+--------------------------------------+
Create this table in a database called 'general'. If you have downloaded the source code for this tutorial, the SQL file is already provided in it to create a table like this in a database called 'general'. It is located in 'ajaxtutorials/part2-2.2/table.sql'.
2.3: The interface
The interface is going to be very simple. There is going to be a searchbox and you can type in the name of the person whose contact info you want to view. There won't be any button... The results will be displayed as you type!!! This is the power of what AJAX can do. However, this should not be practised. I've given it in this tutorial only and only to explain what AJAX is most used for. Actually, it is better if you create a button and then query the server when the button is **** because that will save you bandwidth and will help avert many problems. This is the basic interface:
http://tritium.frihost.net/tutorials/aj ... e-init.gif
We won't be going much into this. The source code is available in the download. We won't be going much into this because it is only HTML and CSS and that is not what this tutorial is about.
2.3.1: The hidden interfaces
There will be two hidden interfaces which we shall be using, first one for the editing box and second one for displaying the phonebook entry. As we just won't be moving from the page once it is loaded, we will create these interfaces in the very first page and hide them. This is the page with the hidden interfaces:
http://tritium.frihost.net/tutorials/aj ... hidden.gif
We will be hiding those two interfaces with a simple CSS piece of code. In the top level <div>, or the complete HTML slab which we want to hide, we will add an HTML attrib. The code(the body section onle) as of now is:
Code: Select all
<body>
<div id="header"><span>MyAJAX phonebook</span></div>
<div id="topbar"><p> <a href="javascript:createNew()">Create new contact</a> | <i>Search for a contact:</i> Name: <input id="sname" type="text" /></p></div>
<div id="newentry"><div id="ne_head"><span>Add a new contact</span></div>
<div id="ne_content">
<span><b> First Name: </b><input id="name" type="text" /> | <b>Last Name: </b><input id="name" type="text" />
<b> email address: </b><input id="mail" type="text" />
<b> Phone no.: </b><input id="phone" type="text" />
<b> Postal Address: </b><input id="address" type="text" />
<input type="button" value="Add contact" id="addcontact" style="margin: 2px"/></div></div>
<div id="viewentry"><div id="ve_head"><span>fName lName</span></div>
<div id="ve_content">
<span><b>email adress: </span></b><span id="mview">email@email.com</span>
<b>Phone number: </b><span id="phone">2236082</span>
<b>Postal Address: </b><span id="address">My house</span>
</div></div>
</body>
For the the two <div>s with the id as "newentry" and "viewentry", we will add an HTML attrib in this way:
Code: Select all
<body>
.....
<div id="newentry" style="display: none">
....</div>
......
<div id="viewentry" style="display: none">
....</div>
...
</body>
The altered code is present in the folder 'ajaxtutorials/phonebook-complete/main.php'. The HTML attrib 'style' is used to add CSS rules to the element. The 'display: none' CSS rule will hide the interface. We will call it using JavaScript whenever needed.
2.4: Creating the php scripts
From now on, all the sources will be available in the folder 'ajaxtutorials/phonebook-complete'. We need to create 3 php scripts: One to search for the contacts, one to return the data of a given contact and one to add new contact.
2.4.1: Creating the 'searchcontacts.php' php script
This is the code for the searchcontacts.php script:
Code: Select all
<?php
if(isset($_GET['sfor']) && if($_GET['sfor'] != '') {
$conn = @ mysql_connect("localhost", "root", "")
or die("-1");
$rs = @ mysql_select_db("general", $conn)
or die("-1");
$rs = @ mysql_query("select * from phonebook")
or die("-1");
$matches = array();
while($row = mysql_fetch_array($rs)) {
$fname = $row['first_name'];
$lname = $row['last_name'];
$id = $row['id'];
if(stristr($fname, $_GET['sfor']) || stristr($lname, $_GET['sfor'])) {
$matches[] = $id.'|'.$fname.$lname;
}
}
}
foreach($matches as $value) {
printf($value);
printf('|');
}
?>
Firstly this script checks if a GET varialbe called 'sfor' is initialized. If it is, then it connects to the MySQL database and selects a database called 'general'. Then all the contents of a table called 'phonebook' in that database are called with the MySQL query 'select * from database'. An array called matches is declared which will contain all the results relevant to the search. Finally, using a while loop, we examine all the values of the result resource which we got from running the MySQL query and check if in any cases the first name OR the last name returns a part of the search query. In this case even 'ha' would return 'Rohan' as a relevant result. If that is feeling wrong to you, you can change the stristr() function to: $fname == $_GET['sfor']. But you then need to type the complete name or parse it into first name and last name at some point(in php, or JavaScript).
For this example, this will server our purpose. Then if any search result is found relevant, it is added to the array called 'matches'. Finally, using a foreach() loop, all the variables are outputted seperated by a '|'. At the same, time we append the 'id' of these contacts too, which will be useful for use for further querying. For example, if the results are 'Rohan Prabhu' and 'Nikhil Verma' and 'Some Person' for the search string 'n', the output will be: '1|Rohan Prabhu|2|Nikhil Verma|3|Some Person'.
You can try out this script by using your browser. For example, you want to test it to search for 'rohan', you can search it this way:
http://localhost/tutorials/ajax/phonebook-complete/searchcontacts.php?sfor=rohan
For the search script, that's it.
2.4.2: The 'returndata.php' PHP script
The code for the 'returndata.php' PHP script is:
Code: Select all
<?php
if(isset($_GET['qid']) && $_GET['qid'] != '') {
$conn = @ mysql_connect("localhost", "root", "")
or die("-1");
$rs = @ mysql_select_db("general")
or die("-1");
$rs = @ mysql_query("select * from phonebook where id=".$_GET['qid'])
or die("-1");
while($row = mysql_fetch_array($rs)) {
$fname = $row['first_name'];
$lname = $row['last_name'];
$phone = $row['phone'];
$email = $row['email'];
$postal = $row['postal_add'];
printf($fname.' '.$lname.'|'.$phone.'|'.$email.'|'.$postal);
}
}
?>
Most of things here are same as in 'searchcontacts.php' script. The key difference is the query. Here, we have supplied a 'where' condition. The query 'select * from phonebook where id='.$qid. Here '$qid' is the id of the contact whose info we want. In our phonebook, we will get this 'id' from 'searchcontacts.php'. This MySQL query tells the database to give all the results from the table 'phonebook', where the id of the fields is equal to $qid. We need not provide the database with the id while adding new contacts as the 'id' field is 'auto_increment' i.e it is incremented automatically when a new field is added. Check table.sql for more info.
You can check this script also by appending the GET variable 'qid=' followed by the 'id' to your address, similarly as you tested 'searchcontacts.php'.
2.4.3: The 'addcontact.php' PHP script
The code for the 'addcontact.php' PHP script:
Code: Select all
<?php
if(isset($_POST['fname']) && isset($_POST['lname']) && isset($_POST['email']) && isset($_POST['phone']) && isset($_POST['postal'])) {
if($_POST['fname'] == "" || $_POST['lname'] == "") {
printf("Please enter the First Name or the Last Name of the contact");
die();
} else {
$fname = $_POST['fname'];
$lname = $_POST['lname'];
$email = $_POST['email'];
$phone = $_POST['phone'];
$postal = $_POST['postal'];
$conn = @ mysql_connect("localhost", "root", "")
or die("There was an error adding your contact");
$rs = @ mysql_select_db("general")
or die("There was an error adding your contact");
$sql = "insert into phonebook(first_name, last_name, email, phone, postal_add) values(\"".$fname."\", \"".$lname."\", \"".$email."\", \"".$phone."\", \"".$postal."\")";
$rs = mysql_query($sql, $conn)
or die("There was an error adding your contact");
die("New contact succesfully added");
}
}
?>
In this example, first it is checked whether the variables are properly initialized or not and then it is checked whether either of the First Name and the Last Name is filled or not. If not, the program terminates, but if filled, it first assigns some php variables from the POST variable and then connects to the MySQL database, selects a database and then creates a MySQL query which instructs to add a field to the table called 'phonebook'.
This script as others can't be tested by appending the params to the address as this script checks for POST variables. I did this just for example not for any specific reason.
Note: You must have noticed, that in case of errors, we are ending the execution of the php script and outputting "-1". We are doing this so as to catch errors. If the XMLHttpRequest gets a "-1" as the return, we can understand that an error has been caused.
Chapter 3: Making the phonebook
Now we have created the server side modules for the phonebook. Now we will bundle it all on the client site to make an AJAX powered phonebook. This work will be split in 3 parts: 1. To send the search string and then get all the relevant things and to display them as links. 2. After the user **** on one of them, contact the server and get more info for the contact. 3. Creating a new contact
3.1: The search script
Firstly, we'll create the search script. The idea is, whenver the user types anything in the search textbox, the query is sent to the server. Even if after the query is sent and a key is pressed within the search textbox, the older connection to the server is aborted if not completed already and a new connection will be esablished. Firstly, we need to tell it to execute a function every time a key is pressed when in the searchbox. View the code for the search box:
We will change it to:
Code: Select all
<input id="sname" type="text" onkeyup="javascript:execSearch()" />
It will cause it to execute a function called 'execSearch()' whenver a key is pressed in the search textbox. Now, let's look at the execSearch() function:
Code: Select all
var pendingQuery = 0;
function execSearch() {
if(pendingQuery) {
httpr.abort();
}
var query = sname.value;
httpr.open('GET', 'searchcontacts.php?sfor=' + query);
httpr.onreadystatechange = handleReturns;
httpr.send(null);
pendingQuery = 1;
}
As you know most of it by now, we won't do it on a line-by-line basis. Basically, a variable called 'pendingQuery' is constantly updated to tell whether a query is running or not. If it is true(i.e 1), the XMLHttpRequest is aborted. In any case, a new request is made and is sent. Once the new request is made, the variable 'pendingQuery' is set to 'true' i.e '1' to tell that a query is in progress. The new request, when recieved calls the handleReturns function. We will check that function now:
Code: Select all
function handleReturns() {
if(httpr.readyState == 4) {
if(httpr.status == 200) {
var data = httpr.responseText;
if(data == "-1") {
alert("Unknown error has occured while getting data from the server. Reload the page to try again");
pendingQuery = 1;
} else {
var contacts = new Array();
var contids = new Array();
var ids = new Array();
contids = data.split('|');
var idindex = 0;
var cindex = 0;
for(var i=0; i<=contids.length; i++) {
if(contids[i] == '') {
continue;
}
if(i%2 != 0) {
contacts[cindex] = contids[i];
cindex++;
} else {
ids[idindex] = contids[i];
idindex++;
}
}
var inserts = "";
for(var i=0; i<=(ids.length-1); i++) {
inserts += '<a href="javascript:getInfo(\'' + ids[i] + '\')">' + contacts[i] + '</a>' + '\n';
}
****.getElementById('display').innerHTML = "
<i>Search Results: </i>" + inserts;
}
}
}
}
Note: This is just a code snippet which shall not work individually.
Phew.. that's a big function. For the first parts, let's leave that out. Let's move on to the part which says: if(data == "-1") . Here, we first check if any errors are occured. Remember, our php scripts output -1, if there are any errors. If there isn't any error, we first create an array called 'contacts' and an array called 'ids'. Both of these are parallel arrays i.e if one contains the name of the person, other will contain the id relating to the name. Now, focus your attention towards the way we output our strings. It is seperated by a '|'. Then, the complete data returned is split and is assigned to an array called 'contids'. What happens actually: Supposing the output is: 1|Rohan|2|Nikhil|, then contids[0] will be '1', contids[1] will be 'Rohan', contids[2] will be '2', contids [3] will be 'Nikhil' and so on.
Then, it is distributed in a way such that the array ids[] contains the even elements and the array contacts[] the odd elements. Also, notice that we say
if(contids == '') {continue;}. This is important as php sometimes outputs some whitespaces which are actually a truncated null character(in fact whitespaces are returns, tabs, spaces etc.) i.e ''. We need to remove those characters as they hinder the process of parsing. When a '' whitespace is encountered we 'continue' the loop. What 'continue' does is to quit the current loop at the very instant it is called but continue from the next iteration of the loop. So, a '' whitespace is never considered to be a part of any array, ids or contacts.
The variables, cindex and idindex are incremented whenever a variable is filled in that array, so as to fill the succesive elements of the array. These are all JavaScript techniques and we won't go into much detail there.
Next, we cycle through all the elements of the contacts[] and ids[] array to create a hyperlink, which when **** shall execute a JavaScript function called getInfo(contact_id), which gives more info of the contact with the id as 'contact_id'. For example, if the name is 'Nikhil Verma' and the id is '2', the link formed will be:
<a href="javascript:getInfo('2')">Nikhil Verma</a>
All the search results are thus created into links and finally, they are shown in the page, by inserting them in a <span> field which has the id="display". This is how things look:
3.2: Viewing the complete contact info
We need two JavaScript functions for this:
Code: Select all
var getc = createRequestObject();
function getInfo(contact_id) {
getc = createRequestObject();
getc.open('GET', 'returndata.php?qid=' + contact_id);
getc.onreadystatechange = fillInfo;
getc.send(null);
}
function fillInfo() {
if(getc.readyState == 4) {
if(getc.status == 200) {
var data = getc.responseText;
var data = data.split('|');
****.getElementById('dis_name').innerHTML = data[0];
****.getElementById('dis_phone').innerHTML = data[1];
****.getElementById('dis_mail').innerHTML = data[2];
****.getElementById('dis_add').innerHTML = data[3];
****.getElementById('viewentry').style.display = "";
}
}
}
What we do here, is create another XMLHttpRequest object so that the user can also make searches side-by-side while the pages are loading. Remember, we created the hyperlinks in such a way that they call a javascript function called 'getInfo(contact_id)', in which contact_id is the 'id'. This function then calls the page 'returndata.php?qid=' + contact_id. In this case, the 'qid' is the id of the contact we are requestin information about.
fillInfo() is the javascript function which is executed when the request is completed. Here, we get the response text and you must be remembering the output of this script(section 2.4.2). This is also seperated by '|' in such a way that the first part is the name, 2nd part is the phone no., 3rd part is the email and 4th part is the postal address. This data is then added to specific fields inside the hidden interfaces. Please note that the data in the 'hidden interfaces' chapter varies from the page used in this part. Please refer to the source code in the folder 'ajaxtutorial/phonebook-complete' and not in the hidden interfaces part. Finally, we tell the page to display the <div> layer which is holding the information. That's all. Now, you can search side-by-side, **** like frenzy for your contact infos and do whatever you want. This is how it looks:
3.3: Adding new contacts
Firstly, please check the complete HTML code from your source download. It is very important that you notice how the functions are called. When you **** on 'Create New Contact', a function called createNew() is called which displays a box in which you have to enter the details for a new contact. The box has a button called 'Add contact' **** on which calls a function 'newContact()'. Here is the code"
Code: Select all
function newContact() {
****.getElementById('newentry').style.display = "none";
var fname = ****.getElementById('add_fname').value;
var lname = ****.getElementById('add_lname').value;
var phone = ****.getElementById('add_phone').value;
var email = ****.getElementById('add_mail').value;
var add = ****.getElementById('add_address').value;
newc = createRequestObject();
newc.open('POST', 'addcontact.php');
newc.onreadystatechange = verifyNew;
newc.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
newc.send('fname=' + fname + '&lname='+ lname + '&email=' + email +'&phone=' + phone + '&postal=' + add);
}
function createNew() {
****.getElementById('newentry').style.display = "";
}
function verifyNew() {
if(newc.readyState == 4) {
if(newc.status == 200) {
var data = newc.responseText;
alert(newc.responseText);
}
}
}
When the createNew() function is called, it displays the box to you, by changing the CSS attrib. You can now fill out the form and when you **** on the button 'Add contact', a function called 'newContact()' is called. This function at the first go hides the box and after taking the data from the box, it clears the contents so that more users can be added easily, and then contacts the server with the POST variables. Please checkout section 2.1.4 for understanding how to send POST data through AJAX.
The server handles out the request and returns the status which is then conveyed by the JS to the user within the verifyNew() function. Here is a screenshot of that in action:
Appendix: Problems of caching
It is a problem in some browsers that the php returns are cached and repeated requests to the script will give you the same result, despite your expectations for other content as the browser might have cached it and it is returning the same data again. To overcome this, put this piece of code on top of every php script from where you intend to recieve data via AJAX:
Code: Select all
<?php
header("Cache-control: no-cache");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
?>
Appendix 2: The complete client-side code
Here is the complete code for the main.php file with the CSS, JavaScript and the complete XML in the phonebook example:
Code: Select all
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>MyAJAX phonebook<title>
<script type="text/javascript">
<!--
var httpr = createRequestObject();
var getc;
var newc;
function createRequestObject() {
var xhr;
var browser = navigator.appName;
if(!window.XMLHttpRequest){
if(browser == "Microsoft Internet Explorer") {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
} else {
alert("Sorry, this page cannot be viewed on your browser i.e " + browser);
return false;
}
} else {
xhr = new XMLHttpRequest();
}
return xhr;
}
function getInfo(contact_id) {
getc = createRequestObject();
getc.open('GET', 'returndata.php?qid=' + contact_id);
getc.onreadystatechange = fillInfo;
getc.send(null);
}
function newContact() {
****.getElementById('newentry').style.display = "none";
var fname = ****.getElementById('add_fname').value;
var lname = ****.getElementById('add_lname').value;
var phone = ****.getElementById('add_phone').value;
var email = ****.getElementById('add_mail').value;
var add = ****.getElementById('add_address').value;
****.getElementById('add_address').value = "";
****.getElementById('add_mail').value = "";
****.getElementById('add_phone').value = "";
****.getElementById('add_fname').value = "";
****.getElementById('add_lname').value = "";
newc = createRequestObject();
newc.open('POST', 'addcontact.php');
newc.onreadystatechange = verifyNew;
newc.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
newc.send('fname=' + fname + '&lname='+ lname + '&email=' + email +'&phone=' + phone + '&postal=' + add);
}
function createNew() {
****.getElementById('newentry').style.display = "";
}
function verifyNew() {
if(newc.readyState == 4) {
if(newc.status == 200) {
var data = newc.responseText;
alert(newc.responseText);
}
}
}
function fillInfo() {
if(getc.readyState == 4) {
if(getc.status == 200) {
var data = getc.responseText;
var data = data.split('|');
var starting = 0;
****.getElementById('dis_name').innerHTML = data[0];
****.getElementById('dis_phone').innerHTML = data[1];
****.getElementById('dis_mail').innerHTML = data[2];
****.getElementById('dis_add').innerHTML = data[3];
****.getElementById('viewentry').style.display = "";
}
}
}
var pendingQuery = 0;
function execSearch() {
if(pendingQuery) {
httpr.abort();
}
var query = ****.getElementById('sname').value;
httpr.open('GET', 'searchcontacts.php?sfor=' + query);
httpr.onreadystatechange = handleReturns;
httpr.send(null);
pendingQuery = 1;
}
function handleReturns() {
if(httpr.readyState == 4) {
if(httpr.status == 200) {
var data = httpr.responseText;
if(data == "-1") {
alert("Unknown error has occured while getting data from the server. Reload the page to try again");
pendingQuery = 1;
} else {
var contacts = new Array();
var contids = new Array();
var ids = new Array();
contids = data.split('|');
var idindex = 0;
var cindex = 0;
for(var i=0; i<=contids.length; i++) {
if(contids[i] == '') {
continue;
}
if(i%2 != 0) {
contacts[cindex] = contids[i];
cindex++;
} else {
ids[idindex] = contids[i];
idindex++;
}
}
var inserts = "";
for(var i=0; i<=(ids.length-1); i++) {
inserts += '<a href="javascript:getInfo(\'' + ids[i] + '\')">' + contacts[i] + '</a>' + '\n';
}
****.getElementById('display').innerHTML = "
<i>Search Results: </i>" + inserts;
}
}
}
}
//-->
</script>
<style type="text/css">
<!--
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10px;
}
#header {
border: 1px solid #000000;
font-family: Verdana, Arial, Helvetica, sans-serif;
background: #FFC832;
font-size: 25px;
border-bottom: none;
}
#topbar {
border: 1px solid #000000;
font-family: Verdana, Arial, Helvetica, sans-serif;
background: #FCFCC8;
font-size: 10px;
}
input {
border: 1px solid #000000;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10px;
}
#newentry {
margin-top: 5px;
border: 1px solid #000000;
}
#ne_head {
background: #0080FF;
border-bottom: 1px solid #000000;
font-size: 18px;
color: #FFFFFF;
}
#viewentry {
margin-top: 5px;
border: 1px solid #000000;
}
#ve_head {
background: #0080FF;
border-bottom: 1px solid #000000;
font-size: 28px;
color: #FFFFFF;
}
#ve_content {
font-size: 14px;
}
-->
</style>
</head>
<body>
<div id="header"><span>MyAJAX phonebook</span></div>
<div id="topbar"><p> <a href="javascript:createNew()">Create new contact</a> | <i>Search for a contact:</i> Name: <input id="sname" type="text" onkeyup="javascript:execSearch()" />
<span id="display"></span></p></div>
<div id="newentry" style="display: none"><div id="ne_head"><span>Add a new contact</span></div>
<div id="ne_content">
<span><b> First Name: </b><input id="add_fname" type="text" /> | <b>Last Name: </b><input id="add_lname" type="text" />
<b> email address: </b><input id="add_mail" type="text" />
<b> Phone no.: </b><input id="add_phone" type="text" />
<b> Postal Address: </b><input id="add_address" type="text" />
<input ****="javascript:newContact()" type="button" value="Add contact" id="addcontact" style="margin: 2px"/></div></div>
<div id="viewentry" style="display: none"><div id="ve_head"><span id="dis_name">fName lName</span></div>
<div id="ve_content">
<span><b>email adress: </span></b><span id="dis_mail">email@email.com</span>
<b>Phone number: </b><span id="dis_phone">2236082</span>
<b>Postal Address: </b><span id="dis_add">My house</span>
</div></div>
</body>
</html>
Conclusion
That brings us to the end of the 2nd part of my AJAX tutorial. I hope you enjoyed it and could learn from it. It had been a wonderfull experience from my side too, because it is the first time I am being so descriptive and writing such a long tutorial. Any doubts, queries and suggestions are welcome. It took me 11.30 hours in total to finish both the parts, so please please reply to the post to make this tutorial worth the effort. That's all for now. Meet you soon in some other tutorial, where I promise to introduce you further in the wonderfull world of programmming.
©Rohan Prabhu. All images, text and content is (copyright) ©Rohan Prabhu. Source code provided here maybe re-distributed, but should accompany the copyright notice. Duplication of the article without prior permission is not allowed. mailto:
rohan2kool@gmail.com