Last active
July 13, 2024 17:32
-
-
Save balupton/854622 to your computer and use it in GitHub Desktop.
Ajaxify a Website with the HTML5 History API using History.js, jQuery and ScrollTo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// History.js It! | |
// v1.0.1 - 30 September, 2012 | |
// https://gist.github.com/854622 | |
(function(window,undefined){ | |
// Prepare our Variables | |
var | |
History = window.History, | |
$ = window.jQuery, | |
document = window.document; | |
// Check to see if History.js is enabled for our Browser | |
if ( !History.enabled ) { | |
return false; | |
} | |
// Wait for Document | |
$(function(){ | |
// Prepare Variables | |
var | |
/* Application Specific Variables */ | |
contentSelector = '#content,article:first,.article:first,.post:first', | |
$content = $(contentSelector).filter(':first'), | |
contentNode = $content.get(0), | |
$menu = $('#menu,#nav,nav:first,.nav:first').filter(':first'), | |
activeClass = 'active selected current youarehere', | |
activeSelector = '.active,.selected,.current,.youarehere', | |
menuChildrenSelector = '> li,> ul > li', | |
completedEventName = 'statechangecomplete', | |
/* Application Generic Variables */ | |
$window = $(window), | |
$body = $(document.body), | |
rootUrl = History.getRootUrl(), | |
scrollOptions = { | |
duration: 800, | |
easing:'swing' | |
}; | |
// Ensure Content | |
if ( $content.length === 0 ) { | |
$content = $body; | |
} | |
// Internal Helper | |
$.expr[':'].internal = function(obj, index, meta, stack){ | |
// Prepare | |
var | |
$this = $(obj), | |
url = $this.attr('href')||'', | |
isInternalLink; | |
// Check link | |
isInternalLink = url.substring(0,rootUrl.length) === rootUrl || url.indexOf(':') === -1; | |
// Ignore or Keep | |
return isInternalLink; | |
}; | |
// HTML Helper | |
var documentHtml = function(html){ | |
// Prepare | |
var result = String(html) | |
.replace(/<\!DOCTYPE[^>]*>/i, '') | |
.replace(/<(html|head|body|title|meta|script)([\s\>])/gi,'<div class="document-$1"$2') | |
.replace(/<\/(html|head|body|title|meta|script)\>/gi,'</div>') | |
; | |
// Return | |
return result; | |
}; | |
// Ajaxify Helper | |
$.fn.ajaxify = function(){ | |
// Prepare | |
var $this = $(this); | |
// Ajaxify | |
$this.find('a:internal:not(.no-ajaxy)').click(function(event){ | |
// Prepare | |
var | |
$this = $(this), | |
url = $this.attr('href'), | |
title = $this.attr('title')||null; | |
// Continue as normal for cmd clicks etc | |
if ( event.which == 2 || event.metaKey ) { return true; } | |
// Ajaxify this link | |
History.pushState(null,title,url); | |
event.preventDefault(); | |
return false; | |
}); | |
// Chain | |
return $this; | |
}; | |
// Ajaxify our Internal Links | |
$body.ajaxify(); | |
// Hook into State Changes | |
$window.bind('statechange',function(){ | |
// Prepare Variables | |
var | |
State = History.getState(), | |
url = State.url, | |
relativeUrl = url.replace(rootUrl,''); | |
// Set Loading | |
$body.addClass('loading'); | |
// Start Fade Out | |
// Animating to opacity to 0 still keeps the element's height intact | |
// Which prevents that annoying pop bang issue when loading in new content | |
$content.animate({opacity:0},800); | |
// Ajax Request the Traditional Page | |
$.ajax({ | |
url: url, | |
success: function(data, textStatus, jqXHR){ | |
// Prepare | |
var | |
$data = $(documentHtml(data)), | |
$dataBody = $data.find('.document-body:first'), | |
$dataContent = $dataBody.find(contentSelector).filter(':first'), | |
$menuChildren, contentHtml, $scripts; | |
// Fetch the scripts | |
$scripts = $dataContent.find('.document-script'); | |
if ( $scripts.length ) { | |
$scripts.detach(); | |
} | |
// Fetch the content | |
contentHtml = $dataContent.html()||$data.html(); | |
if ( !contentHtml ) { | |
document.location.href = url; | |
return false; | |
} | |
// Update the menu | |
$menuChildren = $menu.find(menuChildrenSelector); | |
$menuChildren.filter(activeSelector).removeClass(activeClass); | |
$menuChildren = $menuChildren.has('a[href^="'+relativeUrl+'"],a[href^="/'+relativeUrl+'"],a[href^="'+url+'"]'); | |
if ( $menuChildren.length === 1 ) { $menuChildren.addClass(activeClass); } | |
// Update the content | |
$content.stop(true,true); | |
$content.html(contentHtml).ajaxify().css('opacity',100).show(); /* you could fade in here if you'd like */ | |
// Update the title | |
document.title = $data.find('.document-title:first').text(); | |
try { | |
document.getElementsByTagName('title')[0].innerHTML = document.title.replace('<','<').replace('>','>').replace(' & ',' & '); | |
} | |
catch ( Exception ) { } | |
// Add the scripts | |
$scripts.each(function(){ | |
var $script = $(this), scriptText = $script.text(), scriptNode = document.createElement('script'); | |
scriptNode.appendChild(document.createTextNode(scriptText)); | |
contentNode.appendChild(scriptNode); | |
}); | |
// Complete the change | |
if ( $body.ScrollTo||false ) { $body.ScrollTo(scrollOptions); } /* http://balupton.com/projects/jquery-scrollto */ | |
$body.removeClass('loading'); | |
$window.trigger(completedEventName); | |
// Inform Google Analytics of the change | |
if ( typeof window._gaq !== 'undefined' ) { | |
window._gaq.push(['_trackPageview', relativeUrl]); | |
} | |
// Inform ReInvigorate of a state change | |
if ( typeof window.reinvigorate !== 'undefined' && typeof window.reinvigorate.ajax_track !== 'undefined' ) { | |
reinvigorate.ajax_track(url); | |
// ^ we use the full url here as that is what reinvigorate supports | |
} | |
}, | |
error: function(jqXHR, textStatus, errorThrown){ | |
document.location.href = url; | |
return false; | |
} | |
}); // end ajax | |
}); // end onStateChange | |
}); // end onDomLoad | |
})(window); // end closure |
Why already loaded javascript is not applied to new content in content div?
Zeokat you saved my day! thanks. Nice piece of code.
I am facing an issue. I want to run jaquery on the loaded page but it not working because the page is not loaded and jquery not hit i want to show an alert when the page is loaded but not work:
jQuery(document).ready(function() { alert("hello world"); )};
i put this code in footer file but not working
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The fix from genereddick works but ScrollTo is still broken with new versions of jQuery, since$.browser has been deprecated. I've tried including the old code for $ .browser but it only seems to be working in Firefox.