Ajax tutorial with Prototype: Display multiple pages without refreshing

a fresh how-to guide with the help of the powerful Javascript framework named Prototype

1. About this tutorial

In this tutorial you will learn how to retrieve and display pages without refreshing the browser.

download Download all working files for this tutorial and read along (you'll need a php-enabled webserver)

2. Introduction

2.1. When can I use this technique?

2.2. What is Prototype?

2.3. Demo

For those in a hurry: watch the final result.

2.4. You will need:

  1. to download the Prototype Javascript framework
  2. Optional: a server. Most webdesigners have a local server installed with php/mysql for development/testing purposes. We'll be needing PHP for our back-end. For those who don't have a server at their disposal, install one on your computer (this is called a 'localhost' or 127.0.0.1). I can recommend an all-in package (php, mysql, apache webserver, phpmyadmin, etc...) with installer for all flavours of platforms called XAMMP
  3. A cup of coffee

2. Front-End

I'm not going to explain the HTML & CSS, because this is the absolute basis that any web developer should know. For this example I've made the class & id tags as self-explanatory as possible.

2.1. The HTML

		<!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">
		<head>
			<title>Ajax Retrieve ∓ Display multiple pages</title>
			<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
			<meta http-equiv="pragma" content="no-cache" />
			<style type="text/css" media="screen">
			<!--
			
			// our css goes here
			
			-->
			</style>
			<script type="text/javascript" src="prototype.js"></script>
			<script type="text/javascript">
			// <![CDATA[
			
			// our javascript goes here //
			
			// 
			</script>
		</head>
		<body>
			<h1>The News Today</h1>
			<div id="newsContainer">
				<div id="newsCategoriesContainer">
					<div class="newsCat" id="newsCat1">Politics</div>
					<div class="newsCat" id="newsCat2">Sports</div>
					<div class="newsCat" id="newsCat3">LifeStyle</div>
				</div>
				<div id="newsLoading">Loading <img src="loading_indicator.gif" title="Loading..." alt="Loading..." border="0" /></div>
				<div id="newsContent"></div>
			</div>
		</body>
		</html>
		

2.2. The CSS

This is not really important. I've just made a very simple design. You can copy this or make your own design.
		body {
			background-color: #efefef;
			font: 1em Verdana, Arial, Helvetica, sans-serif;		
			}
		
		h1 {
			text-align:center;
			}
		
		#newsContainer {
			background-color:white;
			width: 500px;
			height: 300px;
			margin: 0 auto; /* we center our container div */
			border: 5px solid #ccc;
			}
		
		#newsCategoriesContainer {
			float: left; 
			height: 300px;
			background-color: #fafafa;
			margin-right:10px;
		}
		
		#newsCategoriesContainer .newsCat{
			margin: 10px 0;
			padding: 4px;
			text-align:center;
			display: block;
			cursor:pointer;
			border:1px solid #ccc;
			width: 100px;
		}
		
		#newsContent {
			padding: 10px;
		}
		
		#newsLoading {
			text-align:center;
			display:none;
			margin-top: 10px;
		}
		

2.3. The Javascript

		Event.observe(document, 'dom:loaded', function() {
			var newsCat = document.getElementsByClassName('newsCat');
            
			for (var i = 0; i < newsCat.length; i++) {
				$(newsCat[i].id).onclick = function () {
					getCatPage(this.id);
				}
			}
		});
		
		function getCatPage(id) {
			var url = 'load-content.php';
			var rand = Math.random(9999);
			var pars = 'id=' + id + '&rand=' + rand; // this is in fact a query string: e.g. id=newsCat1&rand=0.781213244
			var myAjax = new Ajax.Request( url, {method: 'get', parameters: pars, onLoading: showLoad, onComplete: showResponse} );
		}
		
		function showLoad() {
			$('newsContent').style.display = 'none';
			$('newsLoading').style.display = 'block';
		}
		
		function showResponse(originalRequest) {
			var newData = originalRequest.responseText;
			$('newsLoading').style.display = 'none';
			$('newsContent').style.display = 'block';		
			$('newsContent').innerHTML = newData;
		}
		

Event.observe(document, 'dom:loaded', function() { // stuff to initialize });
is called when the document has finished loading, that way we are sure that the DOM is built and that every element is accessible. The first line of that function searches for all elements which have a class name of newsCat and stores them in a variable called newsCat, which acts as an array in which all the found elements are stored in. In our example it will find three instances; our three categories. Next, the for-loop loops through all our found elements. Since we have three categories which all have the same class, our code is confused on which it should set the onclick method.. Clever as we are, we do have assigned unique element id's to our categories. The i in our for-loop is in fact, as you might know, a number. So in the first iteration of our loop we read $(newsCat1.id).onclick. Convenient, as these are our id's... The onclick method calls an other function getCatPage(this.id) and takes as argument the id of our element.

function getCatPage()
After we declared our URL to send our request to, along with a random number which prevents the browser from caching the data, we're going to send the request. This will be done with the following code: Ajax.Request(url, options). The method of sending the data will be 'get' (as opposed to 'post'), the parameters are passed on as well. Next we can call some functions. For this example we'll opt for two additional functions. We call the showLoad() function when the data is being requested/loaded and we call the showResponse() function when the request is complete. Other examples include onFailure, onCreate, ... .

function showLoad()
This function does in fact exactly what its name implies. It searches for the element with id="newsloading" and sets it style to display: block, rendering it visible. In the meanwhile we set the diplay style to none for the element which holds the content.

function showResponse()
This function is called when the request for data has been completed. We first store the data we got back in a variable. We have finished loading, so we set the display style of the element with id="newsLoading" to none. And the display style of the element with id="newsContent" to block, making it visible. At last, we use the .innerHTML property to inject our data into the element with id="newsContent".

2.4. Putting it all together: HTML + CSS + Javascript

» Save code snippet as: news.html

If you did everything according to plan, you should see this:
		<!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">
		<head>
			<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
			<title>Ajax and Prototype: Display multiple pages without refreshing</title>
			<script type="text/javascript" src="prototype.js"></script>
			<script type="text/javascript">
			// <![CDATA[
			// Makes the DOM available to us before images are loaded. Handy when elements should be invisible 
			Event.observe(document, 'dom:loaded', function() {
				var newsCat = document.getElementsByClassName('newsCat');
				for (var i = 0; i < categories.length; i++) {
					$(categories[i].id).onclick = function () {
						getCatPage(this.id);
					}
				}
			});
			
			function getCatPage(id) {
				var url = 'load-content.php';
				var rand   = Math.random(9999);
				var pars   = 'id=' + id + '&rand=' + rand;
				var myAjax = new Ajax.Request( url, {method: 'get', parameters: pars, onLoading: showLoad, onComplete: showResponse} );
			}
			
			function showLoad () {
				$('newsContent').style.display = 'none';
				$('newsLoading').style.display = 'block';
			}
			
			function showResponse (originalRequest) {
				var newData = originalRequest.responseText;
				$('newsLoading').style.display = 'none';
				$('newsContent').style.display = 'block';		
				$('newsContent').innerHTML = newData;
			}
			// 
			</script>		
			<style type="text/css" media="screen">
			<!--
			body {
				background-color: #efefef;
				font: 1em Verdana, Arial, Helvetica, sans-serif;		
				}
			
			h1 {
				text-align:center;
				}
			
			#newsContainer {
				background-color:white;
				width: 500px;
				height: 300px;
				margin: 0 auto; /* we center our container div */
				border: 5px solid #ccc;
				}
			
			#newsCategoriesContainer {
				float: left; 
				height: 300px;
				background-color: #fafafa;
				margin-right:10px;
			}
			
			#newsCategoriesContainer .newsCat{
				margin: 10px 0;
				padding: 4px;
				text-align:center;
				display: block;
				cursor:pointer;
				border:1px solid #ccc;
				width: 100px;
			}
			
			#newsContent {
				padding: 10px;
			}
			
			#newsLoading {
				text-align:center;
				display:none;
				margin-top: 10px;
			}
			-->
			</style>
		</head>
		<body>
			<h1>The News Today</h1>
			<div id="newsContainer">
				<div id="newsCategoriesContainer">
					<div class="newsCat" id="newsCat1">Politics</div>
					<div class="newsCat" id="newsCat2">Sports</div>
					<div class="newsCat" id="newsCat3">LifeStyle</div>
				</div>
				<div id="newsLoading">Loading <img src="loading_indicator.gif" title="Loading..." alt="Loading..." border="0" /></div>
				<div id="newsContent"></div>
			</div>
		</body>
		</html>
		

3. The Back-end

3.1. The PHP

		<?php
		function stringForJavascript($in_string) {
		   $str = ereg_replace("[\r\n]", " \\n\\\n", $in_string);
		   $str = ereg_replace('"', '\\"', $str);
		   return $str;
		}
		switch($_GET['id']) {
			case 'newsCat1':
				$content = 'This is content for page Politics.';
				break;
			case 'newsCat2':
				$content = 'This is content for page Sports.';
				break;
			case 'newsCat3':
				$content = 'This is content for page Lifestyle.';
				break;
			default:
				$content = 'There was an error.';
		
		} 
		print stringForJavascript($content);
		usleep(600000);
		?>
		
In the Javascript part, we sent the id of the element to our back-end using the get-method. Too lazy to scroll:
function getCatPage(id) {
			var url = 'load-content.php';
			var rand   = Math.random(9999);
			var pars   = 'id=' + id + '&rand=' + rand;
			var myAjax = new Ajax.Request( url, {method: 'get', parameters: pars, onLoading: showLoad, onComplete: showResponse} );
		}
In our php code we use a switch statement on $_GET['id'] to see which page we have to send back to our front-end. Instead of $content = 'page Politics' we could use include('politics.html');. It's just a matter what you're up to with your app. For example's sake I have included a small delay on our response of 0.6 seconds usleep(600000), otherwise the pages would load too fast and you wouldn't see what happens.

4. Demo

5. Rate this tutorial

+147 241 votes

Bookmark and Share

Was this tutorial:

The information you were looking for?

Make a tutorial suggestion

I would like to see a tutorial about:
 Submit suggestion

More Ajax tutorials with Prototype

  • In this tutorial we will get data and do a live update on our page. You can use it as a real-time visitor counter, stock exchange ticker (boring...), live scores from a game. In fact anything that needs live updating. For this tutorial we'll make a live visitor counter. Hell yeah!
    Rating: +2591

  • In this tutorial we use Prototype with the Script.aculo.us Javascript libraries to sort images or any list of items you want. Then we, optionally, save the order automatically to a database.
    Rating: +759

  • In this short tutorial you will learn how to automatically expand or contract a textarea while typing. This is handy when you want to restrict space in your contact form layout but still give the user access to this fine piece of usability. I've added some extra functionality like highlighting a field when it's focused and sending the form with Ajax to our back-end. Enjoy!
    Rating: +704

  • In this short tutorial we use the Prototype library to send forms to our back-end for processing.
    Rating: +430

  • In this tutorial we will use the Prototype javascript framework to retrieve and display comments made on a news item without refreshing the browser. In fact you can get any data you want, but for the purpose of this tutorial we'll stick with retrieving comments.
    Rating: +260

  • In this tutorial we will toggle elements, paragraphs for example, by their selector ID and by their position in the DOM (if for some reason their ID is unknown, like dynamically inserted content).
    Rating: +253

  • Learn how to build an Ajax Star Rating System using Javascript's powerful Prototype framework.
    Rating: +180

  • In this short tutorial you will learn how to stop default link, form or any other element's behaviour when it is clicked. (like a link or a submit button)
    Rating: +45