Since the request is for an updated answer, here's my solution using HTML5's History API with jQuery. It should run easily by combining the PHP and HTML parts into one file.
My solution allows for AJAX to return the following:
- A message through AJAX, which updates a
<div>
container.
- A URL, which causes the browser to redirect to the URL
- A complete HTML page, which calls the History API's
history.pushState()
to add the current URL to the browser's history and replaces the entire HTML on the page with the HTML returned from AJAX.
PHP
This is just a sample of what the PHP script will need to return when it is invoked via AJAX. It shows how to encode flags to determine whether the AJAX call should update the container or load a new page, and how to return its result via JSON through json_encode. For completeness, I named this script test.php.
<?php
// Random messages to return
$messages = array(
'Stack Overflow',
'Error Message',
'Testing'
);
// If the page was requested via AJAX
if( isset( $_POST['ajax']))
{
$response = array(
'redirect' => // Flag to redirect
( rand() % 2 == 0) ? true : false,
'load_html' => // Flag to load HTML or do URL redirect
( rand() % 2 == 0) ? true : false,
'html' => // Returned HTML
'<html><head><title>AJAX Loaded Title</title></head><body>It works!</body></html>',
'title' => 'History API previous title',
'message' => // Random message
$messages[ (rand() % count( $messages)) ]
);
echo json_encode( $response);
exit;
}
JS
Since I am using jQuery, lets start with that. The following submits an AJAX POST to the server, to the above PHP script at URL test.php. Note that it also sets the POST parameter ajax
to be true
, enabling the PHP script to detect that it received an AJAX request. The dataType
field tells jQuery that the server's response will be in JSON, and that it should decode that JSON to a JSON object in the response callback. Finally, the success
callback, which is fired when the AJAX response is successfully received, determines what to do based on the flags sent from the server.
$.ajax({
type: 'POST',
url: "/test.php",
data: {ajax : true},
dataType: "json",
success: function( json) {
if( json.redirect) {
if( json.load_html) {
// If the History API is available
if( !(typeof history.pushState === 'undefined')) {
history.pushState(
{ url: redirect_url, title: document.title},
document.title, // Can also use json.title to set previous page title on server
redirect_url
);
}
// Output the HTML
document.open();
document.write( json.html);
document.close();
}
else {
window.location = redirect_url;
}
}
else {
$('#message').html( json.message);
}
},
});
HTML
Here is the complete HTML source of my tested file. I tested it in FF4 - FF8. Note that jQuery provides the ready
method to prevent the JS from executing until the DOM is loaded. I've also used Google's hosting of jQuery, so you do not need to upload a copy of jQuery to your server to test this.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js" type="text/javascript"></script>
<title>Default Page</title>
<script type="text/javascript"">
$( document).ready( function() {
$('#ajax_link').click( function() {
var redirect_url = "/test.php";
$.ajax({
type: 'POST',
url: "/test.php",
data: {ajax : true},
dataType: "json",
success: function( json) {
if( json.redirect) {
if( json.load_html) {
// If the History API is available
if( !(typeof history.pushState === 'undefined')) {
history.pushState(
{ url: redirect_url, title: document.title},
document.title, // Can also use json.title to set previous page title on server
redirect_url
);
}
document.open();
document.write( json.html);
document.close();
}
else {
window.location = redirect_url;
}
}
else {
$('#message').html( json.message);
}
},
});
})
});
</script>
</head>
<body>
<div id="message">The default contents of the message</div>
<a id="ajax_link" href="#">Fire AJAX</a>
</body>
</html>