A simple AJAX website with jQuery

A simple AJAX website with jQuery

Introduction

This time we are going to create a simple AJAX website with jQuery and the right amount of PHP & CSS. It is going to have a few pages loaded by AJAX from the PHP back-end, and a complete support of the browser history – a real pain for any AJAX or Flash site .

So get the demo files and lets start rollin’.

The XHTML

First, we create the XHTML backbone of the site.

demo.html

<div id="rounded">

<img src="img/top_bg.gif" /><!-- image with rounded left and right top corners -->
<div id="main" class="container"><!-- our main container element -->

<h1>A simple AJAX driven jQuery website</h1> <!-- titles -->
<h2>Because simpler is better</h2>

<ul id="navigation"> <!-- the navigation menu -->
<li><a href="#page1">Page 1</a></li> <!-- a few navigation buttons -->
<li><a href="#page2">Page 2</a></li>
<li><a href="#page3">Page 3</a></li>
<li><a href="#page4">Page 4</a></li>
<li><img id="loading" src="img/ajax_load.gif" alt="loading" /></li> <!-- rotating gif - hidden by default -->
</ul>

<div class="clear"></div> <!-- the above links are floated - we have to use the clearfix hack -->

<div id="pageContent"> <!-- this is where our AJAX-ed content goes -->
Hello, this is the default content
</div>

</div>

<div class="clear"></div> <!-- clearing just in case -->

<img src="img/bottom_bg.gif" /> <!-- the bottom two rounded corners of the page -->

</div>

This code is positioned in the body part of our demo.html file. Its main purpose is to serve as a front-end to the php back-end, with jQuery handling all the communication in between.

Note the addresses of the navigation links – #page and a page number. This part, called a hash, is included in the current URL without a page refresh, creating an entry in the browser’s history. By monitoring this hash with javascript, we can change the loaded page by AJAX and provide a seamless browsing experience.

Our simple AJAX enabled jQuery website

Our simple AJAX enabled jQuery website

The CSS

Lets take a look at our style sheet.

demo.css

body,h1,h2,h3,p,td,quote,
small,form,input,ul,li,ol,label{	/* resetting our page elements */
	margin:0px;
	padding:0px;
	font-family:Arial, Helvetica, sans-serif;
}

body{	/* styling the body */
	margin-top:20px;
	color:#51555C;
	font-size:13px;
	background-color:#123456;
}

.clear{	/* the clearfix hack */
	clear:both;
}

a, a:visited {	/* styling the links */
	color:#007bc4;
	text-decoration:none;
	outline:none;
}

a:hover{	/* the hover effect */
	text-decoration:underline;
}

#rounded{	/* the outermost div element */
	width:800px;
	margin:20px auto;	/*center it on the page*/
}

.container{	/* this one contains our navigation, titles, and fetched content */
	background-color:#FFFFFF;
	padding:10px 20px 20px 20px;
}

h1{	/* the heading */
	font-size:28px;
	font-weight:bold;
	font-family:"Trebuchet MS",Arial, Helvetica, sans-serif;
}

h2{	/* the subheading */
	font-weight:normal;
	font-size:20px;

	color:#999999;
}

ul{	/* the unordered list used in the navigation */
	margin:30px 0px;
}

li{	/* we float the li-s, which contain our navigation links - we later apply clearfix */
	list-style:none;
	display:block;
	float:left;
	width:70px;
}

li a,li a:visited{	/* the navigation links */
	padding:5px 10px;
	text-align:center;
	background-color:#000033;
	color:white;

	-moz-border-radius:5px;	/* rounding them */
	-khtml-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius:5px;

}

li a:hover{
	background-color:#666666;
	text-decoration:none;
}

#pageContent{	/* the container that holds our AJAX loaded content */
	margin-top:20px;

	border:1px dashed #cccccc;
	padding:10px;

	-moz-border-radius: 5px;	/* rounding the element */
	-khtml-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;
}

#loading{	/* hiding the rotating gif graphic by default */
	visibility:hidden;
}

An important reminder would be to note that rounding corners with CSS is only supported in the latest versions of Firefox, Safari and Chrome.

The jQuery source

To complement the front-end, here is the script that drives the site.

script.js

$(document).ready(function(){	//executed after the page has loaded

	checkURL();	//check if the URL has a reference to a page and load it

	$('ul li a').click(function (e){	//traverse through all our navigation links..

			checkURL(this.hash);	//.. and assign them a new onclick event, using their own hash as a parameter (#page1 for example)

	});

	setInterval("checkURL()",250);	//check for a change in the URL every 250 ms to detect if the history buttons have been used

});

var lasturl="";	//here we store the current URL hash

function checkURL(hash)
{
	if(!hash) hash=window.location.hash;	//if no parameter is provided, use the hash value from the current address

	if(hash != lasturl)	// if the hash value has changed
	{
		lasturl=hash;	//update the current hash
		loadPage(hash);	// and load the new page
	}
}

function loadPage(url)	//the function that loads pages via AJAX
{
	url=url.replace('#page','');	//strip the #page part of the hash and leave only the page number

	$('#loading').css('visibility','visible');	//show the rotating gif animation

	$.ajax({	//create an ajax request to load_page.php
		type: "POST",
		url: "load_page.php",
		data: 'page='+url,	//with the page number as a parameter
		dataType: "html",	//expect html to be returned
		success: function(msg){

			if(parseInt(msg)!=0)	//if no errors
			{
				$('#pageContent').html(msg);	//load the returned html into pageContet
				$('#loading').css('visibility','hidden');	//and hide the rotating gif
			}
		}

	});

}

Note how, on line 3, we call the checkURL() function as soon as the page finishes loading – this way we insure that, if a link to an inner page on the site has been shared and a new visitor visits it, the site will fetch the required page and show it when the page is loaded.

As you can see on line 11, we setup an interval for checkURL() to check the browser’s address 4 times a second in order to detect any possible changes arising from the use of the back/forward buttons.

Now lets take a look at the back-end.

The PHP

The PHP back-end is just a few lines of code and is the place to start, if you want to customize this example.

load_file.php

if(!$_POST['page']) die("0");

$page = (int)$_POST['page'];

if(file_exists('pages/page_'.$page.'.html'))
echo file_get_contents('pages/page_'.$page.'.html');

else echo 'There is no such page!';

It basically checks whether the variable $_POST['page'] is set, and if it is, checks whether the respective page_.html file exists, and outputs it back to jQuery.

You can improve upon this by fetching data from a database, by using sessions, or displaying a folder of images – anything you might have on your mind.

Conclusion

Today we created a simple, customization-ready, AJAX enabled web site. Feel free to use the code and the techniques that were demonstrated in any of your projects.

Join our newsletter and get our PSDs!19,642 people learn about HTML5, JS and more. Join them!

by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and it still is his favorite side project.

71 Comments

  1. website says:

    This is a really interesting one i loved reading it. Yeah it is a simple one.

  2. Arvind says:

    Nice tutorial.. I m thinking to add ajax for viewing post in wordpress.

    1. sara says:

      same here :)

  3. muhammadiq says:

    Awesome...thanks for this tut...!

  4. thiago says:

    its a little messy in ie8

  5. Martin says:

    Fixed. Seem to have uploaded an older version. Enjoy.

  6. Selen says:

    Hmmm, nicely done but I have an question.

    What about changing: load_file.php >>> insted load HTML load PHP

    5.if(file_exists('pages/page_'.$page.'.html'))
    6.echo file_get_contents('pages/page_'.$page.'.html');

    When i change
    [...]_'.$page.'.html')) [...]
    into
    [...]'.$page.'.php'))[...]

    firefox just ignore and leave blank space as He just coudln't use php file.

    Thanks for help
    Selen

  7. Selen says:

    hmmm

    include ('pages/page_'.$page.'.php'); insted 6.echo file_get_contents(’pages/page_’.$page.’.html’);

    worked, so nvm.

    Thanks for great tutorial

    1. Glenn says:

      @selem: nice... got some trouble while calling php files instead of html... thanks for this... hehehehe...
      and for the author of this tut... keep it up... very useful stuff,,

  8. amnesia7 says:

    I really like this affect, great article.

    One question though. I know you've allowed for the history to work when you click the back button but when I click a few pages then click back until I get to the webpage that doesn't have a #anchor in the URL (the initial page) then it just shows the animation spinning.

    Is this an issue? And if so, does anyone know how to correct it?

  9. Martin says:

    @amnesia7 -
    Thanks for noticing. I updated the demo and the download files. You can check it out.

  10. Thanks for this cool simple demonstration, it is very useful

  11. Good tutorial, but I would make sure to have it work with javascript disabled. The method I use is to .hide the elements with jQuery instead of CSS, it has a slight flickr, but its not too bad.

    Thanks.

  12. neel says:

    Nice simple one page website created using the jquery slider techniques.

  13. David says:

    Absolutely superb!! I might bring this into the IM world for modern sales pages.

    Thanks!

  14. kelincidungu says:

    awesome tuts... i like it... ( luv u martins.) no homo !

  15. lanner says:

    Hi all , thanks for this tutorial very nice, but i don't understand how to make this work with php file with sql, echo ""; etc
    If someone can explain, i try everything and nothing appears
    Thanks :)

  16. Tom says:

    Awesome tutorial, used it to create an archives page for my blog, thanks! :D

  17. mat says:

    what do I have to modify or add, if I want to use additional anchors within a ajax loaded site? e.g. in page_1.html I want to add a anchor.

  18. Organzae says:

    Thank you. An another good tuto.

  19. Ben says:

    I noticed you are not using return false on any of your javascript and your code does not shoot the user back up to the top.

    How are you accomplishing this? I always have to do a return false; to avoid this.

  20. v3nka7 says:

    Loved the concept. Thnx for sharing the idea :)

  21. gino says:

    Hi, how can we add php search, i did a page with a link request looking like. #page5?search=my search term

    But it's doesn't work

    I changed the load_page.php to

    if(file_exists('pages/page_'.$page.'.php'))
    echo file_get_contents('pages/page_'.$page.'.php');

    elseif(file_exists('pages/page_'.$page.'.html'))
    echo file_get_contents('pages/page_'.$page.'.html');

    It's working for php normal link but how to do a search query?

  22. Reif says:

    Hey ! mine is not working. i tried to do simpler, something like just.. about page, services page and its not working. the jquery file
    is like this:

    function loadPage(url) //the function that loads pages via AJAX
    {

    $('#loading').css('visibility','visible'); //show the rotating gif animation

    $.ajax({ //create an ajax request to load_page.php
    type: "POST",
    url: "load_page.php",
    data: 'page='+url, //with the page number as a parameter
    dataType: "html", //expect html to be returned
    success: function(msg){

    if(parseInt(msg)!=0) //if no errors
    {
    $('#pageContent').html(msg); //load the returned html into pageContet
    $('#loading').css('visibility','hidden'); //and hide the rotating gif
    }
    }

    });

  23. Joakim says:

    Hey! Thanks for sharing this script. I have tried it, and it works perfectly in firefox,safari and chrome. But, in IE version 7 and lower, the anchor tags aren't treated as history, which means that the backbutton will send you to the previous website and not the previous anchor within the site.

    Do you have the same problem, or is it my IE versions that are messing with me?

  24. jimi says:

    This is really cool. I completed the tutorial. everything worked fine except loading the pages. any help will be appreciated

  25. dean says:

    you guys have done a great job at showing off your skills? I long something new every day.
    I wish jounld buying a show long list of how it is all done .
    Once at ;

  26. Levent says:

    Thanks.

  27. Fredrik says:

    I have also problem loading the pages for the demo. Any help would be appreciated :)

  28. PJ says:

    Awesome demo and tut. Is there any way of doing exactly the same thing in classic ASP (not .NET) instead of PHP? Can you point me in the right direction? Any assistance would be appreciated.

  29. Patrick H. says:

    Great tutorial! Is it possible to replace #page1 link for /page1 link? I replaced hash for slash in the script, but it doesn't work.

  30. r2 says:

    Hello.

    I'm trying to use your siple website. It work fine with content, but when i place a adsense code on page1 for example:
    - on firefox it stops working and everything goes blank...
    - on IE8 it works but doesn´t display the ad...

    is there any to correct it and make it work with google adsense?

    thanks a lot

    r2

  31. Neil says:

    great script only onee problem for me....is there anyway to stop the #page appearing as the at the top of the browser

  32. chandana says:

    Great tutorial
    very easy to understand it........
    Thanks for the great tut again... keep it up

  33. hamming says:

    Hi, I have a question:

    I want to put one of the pages loaded by default. For example page2.html

    How do I do?

    thanks

  34. This is a wonderful article, im lucky I recently found this. Ill be back down the track to check out other posts that you have on your blog.

  35. Deoxys says:

    Nice tut, but too many mistakes...

  36. Baker says:

    that's very nice, i wonder can i find the sample tutorial with asp.net?

  37. Adam says:

    Hi,

    The history doesn't work for me in IE7 and earlier. I think it has to do with the checkURL() function - for some reason IE7 (and earlier) doesn't seem to detect that the data is new after the new html files are loaded. Like IE7 isn't checking for an updated XMLHttpRequest or something.

    It works in IE8 and other browsers.

    Anyone else experiencing this?

  38. Keir says:

    Hi, if you place an internal / external javascript in the head of one of the ajax pages will it be executed when the li is clicked?

  39. Mike says:

    Great tutorial. Most tutorials get into way to many unimportant details which leaves the reader confused. This is a great way to build a foundation for using jquery to perform Ajax since I’m a jquery newb. Thanks!
    ---------------
    HD radio

  40. Shajed says:

    Nice and easy to understand! Thanks

  41. very nice ! i love it so much, thanks a lot

  42. Luke says:

    Great tutorial. Good usage of the border-radius as this is now standard on all modern browsers. Can be used to create a good effect without having to include JQuery UI and its overhead.

  43. e11world says:

    For SEO purposes, I would like to change the page1, page2, ....etc to something more useful such as the actual page-name.html but not exactly sure how you would do that? Any suggestion from anyone to give me a starting point is very appreciated as I'm intermediate in both PHP and Javascript. Thanks!

    1. e11world says:

      Also wondering if there's a way to change the Title of the pages loading in that div to effect the main title (for example your demo page right now says A simple AJAX website with jQuery) and I want to change that according to each page.

    2. Greg Formager says:

      I have the same question - I would like to use different names for the pages instead of "page_1", "page_2", etc.

      I can't figure out how to make this work..

  44. I've been using the AJAX part to be implemented on my personal site, and when I include the Prototype the AJAX part doesnt works! I've been using prototype for using lighbox gallery plugin to use in my image gallery section. Any suggestions or fixes on this issue?

  45. Timur says:

    Very nice tutorial! Thank you!

    I have one question, how to get one of the buttons to get active status to style with css?

  46. charles says:

    million thanks, martin.. this really helped me.. i tried many other, but this one worked perfectly.

  47. Ben says:

    Hey Martin, I was just wondering how I could pass a simple GET parameter to one of these pages. Any help would be great.

  48. Danny3 says:

    Simple and neat. Martin, you are amazing, it's great that you add the files for every tutorial. Thank you!

  49. DJEROCK says:

    Figured it out replace the function loadPage(url) with this: (Be sure to change out your $(".extLink").fancybox({ with what your fancybox link type is...)

    function loadPage(url)
    {
    	url=url.replace('#page','');
    	
    	$('#loading').css('visibility','visible');
    	
    	$.ajax({
    		type: "POST",
    		url: "load_page.php",
    		data: 'page='+url,
    		dataType: "html",
    		success: function(msg){
    			if(parseInt(msg)!=0)
    			{
    				$('#pageContent').html(msg);
    				$('#loading').css('visibility','hidden');
    			}
    			function(output){ 
    				setTimeout( 
    					function() { 
    						$("#pageContent") 
    						.empty() 
    						.append(output) 
    						.fadeIn('slow', function(){ 
    							$(document).ready(function(){ 
    								$(".extLink").fancybox({
    									'width' : '75%',
    									'height' : '100%',
    									'autoScale' : false,
    									'transitionIn' : 'elastic',
    									'transitionOut' : 'fade',
    									'type' : 'iframe'
    								}); 
    							}) 
    						}, 600);
    					});
    				}
    		}
    	});
    
    }
    
  50. John says:

    Hello,

    The code works perfectly, however when I use another anchor for example to send people back to the top of the page, it treats it as an ajax query and it gives me the "This page does not exist" error. Is there a way to fix this?

    Thanks.

  51. sthen says:

    hi, got a question about using jquery library

    when i change loaded script

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

    into new version f.e
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

    its collapsing, other page #page1 #page2 etc. is loading, but can't do it right. Any ideas, how to load new jquery library?

  52. Ashley says:

    Could someone please tell me is this method SEO friendly? Very nice tutorial btw.

  53. Payam says:

    tank u for usefull tutorial...
    how can i change name of fies ?!
    i want use #about , #contact Instead of #page_1 ...

    1. daniel says:

      did anyone resolve this?

      any idea much appreciated!!

  54. Joeri says:

    Great tutorial !

    Changing the kind of pages to load in is also very simple. ( You can choose to load simple html pages, or php pages, as you wish )

    But what about loading php pages with GET parameters ? It would be one thing to extract the correct filename out of the url, no problem with that as you can get the index of the ".php" string part ... and everything after that index can be seen as 'the parameters string part'

    that would mean :

    for example: products.php?category=fruits

    - Get the indexes of the ".php" string-part ( => 8-to-12 )
    - You now have the correct page beïng: from index 0 to 12 => "products.php"
    - now strip the complete string with the correct page string => "?category=fruits"
    - you check if the page exists with the correct page string => "products.php"
    - and you load in the complete url you have now : "products.php?category=fruits"

    If you have all this data, you should be able to make it work for PHP pages with GET parameters attatched.

    Or am I wrong ? - Any notes on this ?

    1. daniel says:

      Joeri,

      is there any way to change the page names so it says #contact etc instead of #page_1....

      any suggestions welcome!

      thanks in advance

  55. Sara says:

    Great tutorial. thanks a lot.

  56. Petuboy says:

    thanks for the tutorial, I want to learn about ajax. :))

  57. Implico says:

    Have you seen AjaxGetContent plugin? It allows to transform a standard, traditional website into a fully AJAX-based one. It maintains back/forward browser buttons functionality and content visibility for search engines like Google.

    Here is the link to the documentation:
    http://www.implico.pl/lang-en/ajaxgetcontent_dynamic_ajax_website,7.html

    Sample sites with plugin integrated (mainly in Polish):
    http://www.implico.pl/lang-en/ (our homepage)
    http://www.ptchprie.pl/ (Polish Plastic and Aesthetic Surgeons Society)
    http://www.finestra.pl/ (PVC windows manufacturer)
    http://www.sportolimp.pl/ (wholesaler of sport goods)

    Enjoy reading & integration!

  58. Ahmed says:

    Amazing tutorial, thank you Martin.

    In order to change the url name from page numbers to desired name.

    in function loadPage(url)

    function loadPage(url)
    {
    
    var datastring=url.replace('#','');    //strip the # and leave only the page name
    
    $('#loading').css('visibility','visible');  //show the rotating gif animation
    
    $.ajax({    //create an ajax request to load_page.php
        type: "POST",
        url: "load_file.php",
        data: 'datastring='+datastring,   //add datastring here
        dataType: "html",   //expect html to be returned
        async: false,
        success: function(msg){
    
            if(parseInt(msg)!=0)    //if no errors
            {
                $('#content').html(msg);    //load the returned html into pageContet
                $('#loading').css('visibility','hidden');   //and hide the rotating gif
            }
        }
    
    });
    
    

    in load_page.php

    <?php  
    $url = $_REQUEST['datastring'];
    echo $url;
    
    if(file_exists(''.$url.'.html'))
    echo file_get_contents(''.$url.'.html');
    
    else echo 'There is no such page!';
    
    ?>
    

    Here i have saved the html files that i have to access is stored where load_page.php is stored.

    Kind Regards

  59. Tukai says:

    You can also use the link with Ahmed's solution, to hide index.php page.-
    www.mydomain.com/#pagename

    If you want to load an inline page(iframe), just paste the code in a blank text page and then load, it will display the iframe.

  60. Pierre says:

    Hi,
    I want to display the result of the search engine of my web site in the middle.
    I can do it with this code since I have always an error wich is : "undefined index" Thanks.

  61. sally says:

    Thank you! thank you! thank you! ...a thousand times! This is just what I was looking for this morning and got it working pronto!

  62. tickleman says:

    An alternative : you can have it without need of php code or heavy javascript code.

    Consider using the jquery.xtarget plugin and replace your links with it :

    <li><a href="page1.html" target="#pageContent">Page 1</a></li> <!-- a few navigation buttons -->
    11
    <li><a href="page2.html" target="#pageContent">Page 2</a></li>
    12
    <li><a href="page3.html" target="#pageContent">Page 3</a></li>
    13
    <li><a href="page4.html" target="#pageContent">Page 4</a></li>

    And put the content of each tab into each page*.html.

    More info here : https://github.com/bapplistudio/jquery.xtarget

  63. Mutebi Roy says:

    Waiting for an Advanced Ajax Website Tutorial. Thanks guys

  64. Rodrigo says:

    I used your files and everything is ok. The only problem is that when I load a page that has some kind of jQuery banners, they stop.
    I'm using boostrap (a css framework) that has some jquery plugin: carrousel, etc...All the javascript at internal pages stoped
    Did someone find this too?

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links