Excellent way to learn new software and programs. Exceeded my expectations.More Testimonials »

More Ajax Applications

In this lesson, we seek to apply Ajax concepts to practical applications.

Lesson Goals

  • To apply the concepts covered thus far to practical applications:
    • Inline Editing
    • Detailed Information on Demand
    • AutoLogout
    • AutoCompletion

Inline Editing

Sometimes it is nice to be able to edit a page without displaying form elements by default. For example, if you want to allow people who are logged in as administrators to edit sections of a page, you could make it so that the administrator could click on those sections to turn them into form elements.

Our example below shows a simple table showing the presidents' first and last names:

The neat thing about this table is that the names become editable when double-clicked:

All the user has to do is type a new value and tab out or click anywhere else in the document to change the value in the table. An XMLHttpRequest is used to change the record in the database. The code is shown below:

Code Sample:

MoreAjaxApps/Demos/Presidents.php
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Inline Editing: Form Controls</title>
<script type="text/javascript" src="../../lib.js"></script>
<script type="text/javascript" src="inline-editing.js"></script>
<script type="text/javascript">
	observeEvent(window,"load",enableEditing);
</script>
<link type="text/css" rel="stylesheet" href="Presidents.css">
</head>
<body>
<?php
	try
	{
		$connect = new mysqli('localhost','root','pwdpwd','Presidents');
		$sql= "SELECT PresidentID, FirstName, LastName, Bio FROM Presidents";
		$rs = $connect->query($sql);
		
		echo "<h1>Presidents</h1>";
		echo "<p>Double click on any cell to edit the field. Click off the field to save your change.</p>";
		echo "<table>";
		while ( $row = $rs->fetch_assoc() )
    {
			echo "<tr id='" . $row["PresidentID"] . "'>";
			echo "<td class='editable' title='FirstName'>" . $row["FirstName"] . "</td>";
			echo "<td class='editable' title='LastName'>" . $row["LastName"] . "</td>";
			echo "<td class='editable' title='Bio'>" . $row["Bio"] . "</td>";
			echo "</tr>";
		}
		echo "</table>";
	}
	catch(Exception $e)
	{
		echo "failed: " . $e->getMessage();
	}
?>
</body>
</html>

The code queries the database for the presidents' first and last names and biographies (taken from the Whitehouse website) and then iterates through the result set creating a table row for each president. Notice the td elements have the "editable" class.

Code Sample:

MoreAjaxApps/Demos/inline-editing.js
function enableEditing() {
	var editableElems = getElementsByClassName(document,"editable");
	var numElems = editableElems.length;
	for (var i=0; i<numElems; i++) {
		observeEvent(editableElems[i],"dblclick",editElem);
	}
}

function editElem(e) {
	var target = getTarget(e);
	var input;
	var textLen = target.innerHTML.length;
	if (textLen > 30) {
		target.innerHTML = "<textarea cols='120' rows='6'>" + target.innerHTML + "</textarea>";
	} else {
		target.innerHTML = "<input value='" + target.innerHTML + "'>";
	}
	var input = target.firstChild;
	input.select();
	observeEvent(input,"change",saveCell);
}

function saveCell(e) {
	var target = getTarget(e);
	var td = target.parentNode;
	var tr = td.parentNode;
	var field = td.title;
	var value = target.value;
	var pid = tr.id;	
	
	var xmlhttp = new XMLHttpRequest();
	xmlhttp.open("POST", "SaveCell.php", true);
	xmlhttp.onreadystatechange=function() {
		if (xmlhttp.readyState==4 && xmlhttp.status==200) {
			td.innerHTML = target.value;
			blinkText(td,1000,"Saved","Normal");
		}
	}
	xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;");
	xmlhttp.send("field=" + field + "&value=" + value + "&pid=" + pid);
}

function blinkText(elem,time,on,off,timePast) {
	var timePast = timePast + 100 || 0;
	elem.className = (elem.className == on) ? off : on;

	if (timePast < time) {
		setTimeout(function () { blinkText(elem,time,on,off,timePast) },100);
	} else {
		elem.className = "editable";
	}
}

This is the JavaScript library. It has the following functions:

  • enableEditing()
    1. Gets all the elements with the "editable" class using the getElementsByClassName() function from lib.js and attaches the editElem() function to their double-click events.
  • editElem()
    1. Changes the innerHTML of the double-clicked td to an input or textarea tag (depending on the length of the innerHTML) and attaches the saveCell() function to its change event.
  • saveCell()
    1. Uses Ajax to send the field, value, and president id to SaveCell.php, which updates the record.
    2. The inline callback function changes the innerHTML of the td to the new value and calls blinkText().
  • blinkText()
    1. Toggles the class name of the passed-in element (elem) between the passed-in on and off values for timePast milliseconds. This creates a blinking effect.

The contenteditable Attribute

HTML5 includes a contenteditable attribute that can be applied to almost any element, though Internet Explorer does not allow it on elements that make up tables (e.g., table, tr, td, etc.). Editing contenteditable content in the browser can be tricky/quirky when nested tags are involved, but it is pretty simple (and cool) when you are dealing with straight text. The code is simple:

Code Sample:

MoreAjaxApps/Demos/contenteditable.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Content Editable</title>
</head>
<body>
<p contenteditable="true" style="font-size:xx-large">I am editable.</p>
</body>
</html>

All you have to do to make an element editable is add contenteditable="true" to the tag. The screenshot below shows the page after the user has clicked in the paragraph and entered the word "truly."

Although contenteditable wasn't added to the specification until HTML5, it is well supported by browsers in use today - even Internet Explorer 6.

Of course, when the user changes content on the page it doesn't have any permanent effect. You, as the developer, have to catch that change and do something about it. When an editable element loses focus, a blur event is triggered (there is no change event). You can use the blur event to trigger Ajax code that saves any changes the user made. Run the following example to see how it works:

Code Sample:

MoreAjaxApps/Demos/contenteditable-blur.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Content Editable</title>
<script type="text/javascript" src="../../lib.js"></script>
<script type="text/javascript">
observeEvent(window,"load",function() {
	var p1 = document.getElementById("p1");
	observeEvent(p1,"blur",function(e) {
		var target = getTarget(e);
		alert(target.innerHTML);
	});
});
</script>
</head>
<body>
<p id="p1" style="font-size:xx-large" contenteditable="true">I am editable.</p>
</body>
</html>

Using ContentEditable for Inline Editing

Duration: 20 to 30 minutes.

In this exercise, you will improve the inline editing page to make use of the ContentEditable attribute instead of form elements.

  1. Open MoreAjaxApps/Exercises/inline-editing.js for editing. This file currently contains the same code we saw in the demo earlier.
  2. Delete the editElem() function. You won't need it.
  3. Modify the enableEditing() function so that the text of the editable elements gets surrounded with a span tag that has the ContentEditable attribute set to "true." Attach the saveCell() function to blur events on the new span tag. We no longer need to observe double clicks.
  4. Modify the saveCell() function so that it gets the correct value. Remember, we are now using a span rather than a form element. Also, in the callback function, we no longer need to change the form field back to text.
  5. Test your solution by opening MoreAjaxApps/Exercises/Presidents.php in your browser and modifying a field. The text should blink. Refresh the page to see if your change stuck.

Solution:

MoreAjaxApps/Solutions/inline-editing.js
function enableEditing() {
	var editableElems = getElementsByClassName(document,"editable");
	var numElems = editableElems.length;
	var elem;
	for (var i=0; i<numElems; i++) {
		elem = editableElems[i];
		elem.innerHTML = "<span contenteditable='true'>" + elem.innerHTML + "</span>";
		observeEvent(elem.firstChild,"blur",saveCell);
	}
}

function saveCell(e) {
	var target = getTarget(e);
	var td = target.parentNode;
	var tr = td.parentNode;
	var field = td.title;
	var value = target.innerHTML;
	var pid = tr.id;	
	
	var xmlhttp = new XMLHttpRequest();
	xmlhttp.open("POST", "SaveCell.php", true);
	xmlhttp.onreadystatechange=function() {
		if (xmlhttp.readyState==4 && xmlhttp.status==200) {
			//DELETED: td.innerHTML = target.value;
			blinkText(td,1000,"Saved","Normal");
		}
	}
	xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;");
	xmlhttp.send("field=" + field + "&value=" + value + "&pid=" + pid);
}

function blinkText(elem,time,on,off,timePast) {
	var timePast = timePast + 100 || 0;
	elem.className = (elem.className == on) ? off : on;

	if (timePast < time) {
		setTimeout(function () { blinkText(elem,time,on,off,timePast) },100);
	} else {
		elem.className = "editable";
	}
}

observeEvent(window,"load",enableEditing);

Detailed Information on Demand

Netflix, the online movie rental company, has a cool feature on their website (http://www.netflix.com) that allows users to hover over a picture of a movie to get more detailed information about that movie. This makes it possible to give users the detailed information they want without downloading detailed information about every movie shown on the page. A screenshot is shown below:

We've done something similar (though not as fancy) with our Presidents page:

The JavaScript code is shown below:

Code Sample:

MoreAjaxApps/Demos/more-info.js
function getBio(e) {
	var bioDiv=document.getElementById("Bio");
	var target = getTarget(e);
	var presID = target.parentNode.parentNode.id;
	var xmlhttp = new XMLHttpRequest();
	xmlhttp.open("GET", "Bio.php?id=" + presID, true);
	xmlhttp.onreadystatechange=function() {
		if (xmlhttp.readyState==4 && xmlhttp.status==200) {
			showBio(xmlhttp);
		}
	}
	xmlhttp.send(null);
	
	function showBio(xmlhttp) {
		bioDiv.innerHTML = xmlhttp.responseText;
		bioDiv.style.marginTop = (presID * 50) + "px"; //position element (hack)
		bioDiv.style.visibility="visible";
	}
}

function hideBio() {
	var bioDiv=document.getElementById("Bio");
	bioDiv.style.visibility="hidden";
	bioDiv.innerHTML="";
}

observeEvent(window,"load",function() {
	var table = document.getElementById("Table");
	var imgs = table.getElementsByTagName("img");
	var numImages = imgs.length;
	for (var i=0; i<numImages; i++) {
		observeEvent(imgs[i],"mouseover",getBio);
		observeEvent(imgs[i],"mouseout",hideBio);
	}
});

The TableRowsMoreInfo.php file creates the presidents HTML table and includes the more-info.js file. When the page loads, we attach mouseover and mouseout events to the images to call showBio() and hideBio(), respectively. The getBio() function calls Bio.php to get the biography of the associated president. Its nested showBio() callback function shows the biography.

When the user mouses out, hideBio() hides the div containing biography.

AutoLogout

If a user is idle for a certain amount of time, it is often a good idea to force a logout, especially if there might be sensitive data on the screen. This is normally handled on the server side; however, if we want to hide the data on the screen and alert the user that the session has ended, we'll need to handle the session on the client as well. One way to handle this is described below:

  1. When the user logs in, create a JavaScript timer with the window.setTimeout() method. The timer will call a function that ends the session after n minutes.
  2. Whenever there is user activity, the timer must be restarted.
  3. When the user explicitly logs out (e.g., clicks on a logout button), the timer must be killed.

To illustrate, we will be forcing the presidents to log in to our inline editing application. The logins are all first initial - lastname (e.g., "gwashington") and the passwords are all the word "password". First, let's look at the application. It starts with a simple login form:

When the user logs in, the editable table appears. We also provide a Logout button so the user can log himself out:

When the session times out, the page goes blank and an alert appears informing the user that the session has timed out:

After the user clicks the OK button, the login form reappears.

Let's look at the code. There are quite a few files involved. The main file is shown below:

Code Sample:

MoreAjaxApps/Demos/PresidentsLogin.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Authentication</title>
<link href="Presidents.css" type="text/css" rel="stylesheet">
<link href="Login.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="../../lib.js"></script>
<script type="text/javascript" src="inline-editing.js"></script>
<script type="text/javascript">
	var presConfig = {
		userName : null,
		autoLogoutTimer: null
	}
	
	function startApp() {	
		var loggedInDiv = document.getElementById("LoggedInDiv");
		var logOutDiv = document.getElementById("LogoutDiv");
		loggedInDiv.innerHTML = "Logged in as " + presConfig.userName;
		loggedInDiv.style.display="block";
		logOutDiv.style.display="block";
		showPresidents();
		startAutoLogoutTimer();
		observeEvent(document.body,"click",startAutoLogoutTimer);
	}
	
	function endApp() {
		var loggedInDiv = document.getElementById("LoggedInDiv");
		var logOutDiv = document.getElementById("LogoutDiv");
		clearTimeout(presConfig.autoLogoutTimer);
		presConfig.userName=null;
		loggedInDiv.innerHTML = "";
		loggedInDiv.style.display="none";
		logOutDiv.style.display="none";
		loginForm();
		unObserveEvent(document.body,"click",startAutoLogoutTimer);
	}
	
	function showPresidents() {
		var xmlhttp = new XMLHttpRequest();
		xmlhttp.open("GET","Controller.php?req=Table",true);
		xmlhttp.onreadystatechange = function() {
			if (xmlhttp.readyState==4 && xmlhttp.status==200) {
				results(xmlhttp);	
			}
		}
		xmlhttp.send(null);
		
		function results(xmlhttp) {
			var output = document.getElementById("Output");
			output.innerHTML = xmlhttp.responseText;
			enableEditing();
		}
	}
	
	function loginForm() {
		var xmlhttp = new XMLHttpRequest();
		xmlhttp.open("GET","Controller.php?req=LoginForm",true);
		xmlhttp.onreadystatechange = function() {
			if (xmlhttp.readyState==4 && xmlhttp.status==200) {
				results(xmlhttp);	
			}
		}
		xmlhttp.send(null);
	
		function results(xmlhttp) {
			var output = document.getElementById("Output");
			var loginForm;
			output.innerHTML = xmlhttp.responseText;
			loginForm = document.getElementById("LoginForm");
			loginForm.onsubmit = function() {
				login(loginForm.Username.value,loginForm.Password.value);
				return false;
			}
		}
	}

	function login(un,pw) {
		var params="username=" + un + "&password=" + pw;
		var xmlhttp = new XMLHttpRequest();
		xmlhttp.open("POST","Controller.php?req=Login",true);
		xmlhttp.onreadystatechange = function() {
			if (xmlhttp.readyState==4 && xmlhttp.status==200) {
				results(xmlhttp);	
			}
		}
		xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;");
		xmlhttp.send(params);
	
		function results(xmlhttp) {
			if (xmlhttp.responseText.indexOf("failed") == -1) {
				presConfig.userName = xmlhttp.responseText;
				startApp();
			} else {
				var badLogin = document.getElementById("BadLogin"); 
				var userName = document.getElementById("Username"); 
				badLogin.style.display="block";
				userName.select();
				userName.className="Highlighted";
				setTimeout(function() {document.getElementById('BadLogin').style.display='none'; },5000);
			}
		}
	}

	function startAutoLogoutTimer() {
		var sessionTime = 15 * 1000; //15 seconds
		clearTimeout(presConfig.autoLogoutTimer);
		presConfig.autoLogoutTimer = setTimeout(function() { logout(true); }, sessionTime);
	}


	function logout(auto) {
		var xmlhttp = new XMLHttpRequest();
		document.getElementById("Output").innerHTML = "";
		xmlhttp.open("GET","Controller.php?req=Logout",true);
		xmlhttp.onreadystatechange = function() {
			if (xmlhttp.readyState==4 && xmlhttp.status==200) {
				results(xmlhttp);	
			}
		}
		xmlhttp.send(null);
	
		function results(xmlhttp) {
			endApp();
			if (auto) {
				alert("You have been logged out due to inactivity.");
			}
		}
	}
	
	function checkLogin() {
		var xmlhttp = new XMLHttpRequest();
		xmlhttp.open("GET","Controller.php?req=LoggedIn",true);
		xmlhttp.onreadystatechange = function() {
			if (xmlhttp.readyState==4 && xmlhttp.status==200) {
				results(xmlhttp);	
			}
		}
		xmlhttp.send(null);
	
		function results(xmlhttp) {
			if (xmlhttp.responseText.indexOf("failed") == -1) {
				presConfig.userName = xmlhttp.responseText;
				startApp();
			} else {
				loginForm();
			}
		}
	}

	observeEvent(window,"load",function() {
		var btnLogout = document.getElementById("logout");
		observeEvent(btnLogout,"click",function() {
			logout(false);
		});
		checkLogin();
	});
</script>
</head>
<body>
<div id="LogoutDiv">
	<button id="logout">Logout</button>
</div>
<div id="LoggedInDiv"></div>
<div id="Output">One moment please...</div>
</body>
</html>

This page contains the basic HTML elements that will hold data returned from the server:

<div id="LogoutDiv">
	<button id="logout">Logout</button>
</div>
<div id="LoggedInDiv"></div>
<div id="Output">One moment please...</div>

The "Output" div will hold the login form or the table data, depending on whether or not the user is logged in. This page also controls the flow of the application:

When the page loads, the checkLogin() function is called, which looks like this:

function checkLogin() {
	var xmlhttp = new XMLHttpRequest();
	xmlhttp.open("GET","Controller.php?req=LoggedIn",true);
	xmlhttp.onreadystatechange = function() {
		if (xmlhttp.readyState==4 && xmlhttp.status==200) {
			results(xmlhttp);	
		}
	}
	xmlhttp.send(null);

	function results(xmlhttp) {
		if (xmlhttp.responseText.indexOf("failed") == -1) {
			presConfig.userName = xmlhttp.responseText;
			startApp();
		} else {
			loginForm();
		}
	}
}

It makes an Ajax request to Controller.php, which handles the assignment of tasks based on the req parameter. In this case, it will redirect to Helpers/LoggedIn.php, which returns the user's name if he's logged in and the text "failed" if he is not. The results() callback function then calls startApp() (if the user is logged in) to start the application or loginForm() (if the user is NOT logged in) to show the login form. Let's first see what happens when the user is NOT logged in:

function loginForm() {
	var xmlhttp = new XMLHttpRequest();
	xmlhttp.open("GET","Controller.php?req=LoginForm",true);
	xmlhttp.onreadystatechange = function() {
		if (xmlhttp.readyState==4 && xmlhttp.status==200) {
			results(xmlhttp);	
		}
	}
	xmlhttp.send(null);

	function results(xmlhttp) {
		var output = document.getElementById("Output");
		var loginForm;
		output.innerHTML = xmlhttp.responseText;
		loginForm = document.getElementById("LoginForm");
		observeEvent(loginForm,"submit",function() {
			login(loginForm.Username.value,loginForm.Password.value);
			return false;
		});
	}
}

The loginForm() function uses Ajax to get an HTML login form and then, in the results() callback function, displays the form and attaches the login() function to its submit event.

When the user logs in, the login() function is called:

function login(un,pw) {
	var params="username=" + un + "&password=" + pw;
	var xmlhttp = new XMLHttpRequest();
	xmlhttp.open("POST","Controller.php?req=Login",true);
	xmlhttp.onreadystatechange = function() {
		if (xmlhttp.readyState==4 && xmlhttp.status==200) {
			results(xmlhttp);	
		}
	}
	xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;");
	xmlhttp.send(params);

	function results(xmlhttp) {
		if (xmlhttp.responseText.indexOf("failed") == -1) {
			presConfig.userName = xmlhttp.responseText;
			startApp();
		} else {
			var badLogin = document.getElementById("BadLogin"); 
			var userName = document.getElementById("Username"); 
			badLogin.style.display="block";
			userName.select();
			userName.className="Highlighted";
			setTimeout(function() {document.getElementById('BadLogin').style.display='none'; },5000);
		}
	}
}

The login() function sends the passed-in username and password to Controller.php using Ajax to try to log the user in. If the login succeeds, the server returns the user's full name (e.g., George Washington). If the login fails, the server returns "failed". The results() callback function either starts the application or displays a bad login message and leaves the form in place for the user to try again.

When the user does successfully log in, the startApp() function is called:

function startApp() {	
	var loggedInDiv = document.getElementById("LoggedInDiv");
	var logOutDiv = document.getElementById("LogoutDiv");
	loggedInDiv.innerHTML = "Logged in as " + presConfig.userName;
	loggedInDiv.style.display="block";
	logOutDiv.style.display="block";
	showPresidents();
	startAutoLogoutTimer();
	observeEvent(document.body,"click",startAutoLogoutTimer);
}

The startApp() function does the following:

  1. Shows the logged-in message and the Logout button.
  2. Calls showPresidents(), which gets the editable Presidents table we saw in earlier demos.
  3. Calls startAutoLogoutTimer(), which starts the inactivity timer. This function is recalled every time the user clicks the mouse. It is shown below:
function startAutoLogoutTimer() {
	var sessionTime = 15 * 1000; //15 seconds
	clearTimeout(presConfig.autoLogoutTimer);
	presConfig.autoLogoutTimer = setTimeout(function() { logout(true); }, sessionTime);
}

The startAutoLogoutTimer() function simply sets a timer to call logout() after 15 seconds and passing in true to indicate that it is an auto logout vs. a user-initiated logout. The function is recalled (and the timer restarted) each time the user clicks the mouse. We set the timer at 15 seconds so that you wouldn't have to wait too long to see it work. Normally, it would be much longer. The logout() function is shown below:

function logout(auto) {
	var xmlhttp = new XMLHttpRequest();
	var loggedInDiv = document.getElementById("LoggedInDiv");
	var logOutDiv = document.getElementById("LogoutDiv");
	var output = document.getElementById("Output");
	
	xmlhttp.open("HEAD","Controller.php?req=Logout",true);
	xmlhttp.send(null);
	
	clearTimeout(presConfig.autoLogoutTimer);
	
	output.innerHTML = "";
	loggedInDiv.innerHTML = "";
	loggedInDiv.style.display="none";
	logOutDiv.style.display="none";
	loginForm();
	
	unObserveEvent(document.body,"click",startAutoLogoutTimer);
	
	if (auto) {
		alert("You have been logged out due to inactivity.");
	}
}

As we don't need a response from the server to log the user out, we use the "HEAD" method to send the request. The rest of the function sets the page back as it was when it first loaded.

You may also be interested in the Controller.php file, which handles the flow on the server-side:

Code Sample:

MoreAjaxApps/Demos/Controller.php
<?php
try
{
	if ($_GET["req"]=="Table")
	{
		header("Location: Helpers/PresidentsTable.php");
	}
	elseif ($_GET["req"]=="Login")
	{
		header("Location: Helpers/Login.php?username=" . $_POST['username'] . "&password=" . $_POST['password']);
	}
	elseif ($_GET["req"]=="LoggedIn")
	{
		header("Location: Helpers/LoggedIn.php");
	}
	elseif ($_GET["req"]=="Logout")
	{
		header("Location: Helpers/Logout.php");
	}
	else //LoginForm
	{
		header("Location: Helpers/LoginForm.html");
	}
}
catch(Exception $e)
{
	echo "failed: " . $e->getMessage();
}
?>

As you can see, this page simply checks the value of the URL parameter, req, and dishes out the work to helper files. This makes the flow of the application easier to follow and maintain.

AutoCompletion

Developers have become very excited about "autocomplete" dropdowns since Google Suggest beta came out. A screenshot is shown below:

Writing your own autocompletion scripts would be a difficult undertaking. And it's unlikely to be worth your while, as there are many such scripts available for free. The script.aculo.us library makes creating autocompleting text fields very easy and our demo below makes use of it:

The code is shown below:

Code Sample:

MoreAjaxApps/Demos/AutoComplete.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>AutoComplete</title>
<link rel="stylesheet" type="text/css" href="AutoComplete.css">
<script type="text/javascript" src="../../lib.js"></script>
<script type="text/javascript" src="../../prototype.js"></script>
<script type="text/javascript" src="scriptaculous/src/scriptaculous.js"></script>
<script type="text/javascript">
	function init() {
		new Ajax.Autocompleter("President","PresidentOptions","AutoComplete.php");
	}
	
	observeEvent(window,"load",init);
</script>
</head>
<body>
<form>
	<input autocomplete="off" type="text" size="40" name="President" id="President">
	<div class="auto_complete" id="PresidentOptions" style="display: none;"></div>
</form>
</body>
</html>

Code Sample:

MoreAjaxApps/Demos/AutoComplete.php
<?php
try
{
	$connect = new mysqli('localhost','root','pwdpwd','Presidents');
	$sql= "SELECT PresidentID, FirstName, LastName FROM Presidents
			WHERE FirstName LIKE '%" .$_POST['President'] . "%'
			OR LastName LIKE '%" .$_POST['President'] . "%'";
	$rs = $connect->query($sql);
	
	echo "<ul>";
	
	while ( $row = $rs->fetch_assoc() )
	{
		echo "<li>";
		echo $row["FirstName"] . " " . $row["LastName"];
		echo "</li>";
	}
	
	echo "</ul>";
}
catch(Exception $e)
{
	echo "failed: " . $e->getMessage();
}
?>

The HTML file simply has an input element and a div for outputting the dropdown options. We create the autocomplete with script.aculo.us's Ajax.Autocompleter() method, which requires three arguments: the name of the input field, the name of the output div, and the file to get the results from.

The server-side script simply returns the results as an unordered list. We format this list with CSS, which is in the associated AutoComplete.css file.

Many JavaScript frameworks, including jQuery, YUI and GWT, provide similar built-in autocompleters.

← Ajax/JavaScript Frameworks

Client Success
  1. Compare Us
  2. Client List
  3. Testimonials
Join The Team
  1. Learn how you can become a Webucator Trainer
  2. Career Opportunities
Locations
© Webucator, Inc. All rights reserved. |Toll Free: 1-877-932-8228Toll Free: 1-877-932-8228 |Outside the USA: 315-849-2724|Fax: 315-849-2723