Skip to content

Instantly share code, notes, and snippets.

@mookman288
Forked from balupton/README.md
Last active October 13, 2015 14:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mookman288/4207054 to your computer and use it in GitHub Desktop.
Save mookman288/4207054 to your computer and use it in GitHub Desktop.
Ajaxify a Website with the HTML5 History API using History.js, jQuery, Possible Sliding, and Bug Fixes!

This modified gist will ajaxify your website with the HTML5 History API using History.js, Fading or Sliding, and Bug Fixes!

Installation

<!-- jQuery CDN --> 
<script src="http://code.jquery.com/jquery.min.js"></script> 

<!-- History.js --> 
<script defer src="http://balupton.github.com/history.js/scripts/bundled/html4+html5/jquery.history.js"></script>

<!-- This Gist -->
<script defer src="http://gist.github.com/raw/4207054/ajaxify-html5.js"></script>  

Explanation

This is a fork, yes?

You should read the original gist, here.

What does this gist do, that the original doesn't?

  1. It requires you to identify the content you want to swap, by setting the global variable, gContentSelector to whatever ID or class it is:
var gContentSelector = '#main';
  1. Check if the browser is less than IE 9, if it is, disable History.js (because it's a mess otherwise.) Ripped from James Padolsey without permission.

  2. Optional choice to use sliding, which is included, sort of.

  3. Enable inline scripts being loaded with src.

  4. Add spot where you can launch scripts that need to be launched on load.

Need development done?

Shameless Plug

Further Reading

History

  • v1.0.2 - 4 December, 2012

    • Forked, and modified: first revision.
  • v1.0.1 - 30 September, 2012

    • Added completion event (customisable via completedEventName defaults to statechangecomplete)
    • Updated for new Google Analytics code - credits to aspiziri
//http://james.padolsey.com/javascript/detect-ie-in-js-using-conditional-comments/
var ie = (function(){
var undef,
v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i');
while (
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
);
return v > 4 ? v : undef;
}());
// History.js It!
// v1.0.2
(function(window,undefined){
//Bypass IE5, 6, 7, 8.
if (ie && ie < 9) return;
// 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 = gContentSelector,
$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').click(function(event){
//Ignore things like anchor links, javascript code, and blank targets.
if (jQuery(this).attr('href').charAt(0) != '#' && !jQuery(this).attr('href').match(/javascript:/g) && jQuery(this).attr('target') != '_blank') {
// 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,'');
// 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({
// right: Math.round(jQuery('body > div').width() - jQuery('body > div > section').width())
//}, 500, function() {
$content.animate({opacity: 0}, 1000);
// 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('right', -1 * Math.round(jQuery('body > div').width() - jQuery('body > div > section').width())).show().animate({right: 0}, 500); /* you could fade in here if you'd like */
$content.html(contentHtml).ajaxify().animate({opacity: 100}, 1000);
// Update the title
document.title = $data.find('.document-title:first').text();
try {
document.getElementsByTagName('title')[0].innerHTML = document.title.replace('<','&lt;').replace('>','&gt;').replace(' & ',' &amp; ');
}
catch ( Exception ) { }
// Add the scripts
$scripts.each(function(){
var $script = $(this), scriptText = $script.text(), scriptSrc = $script.attr('src'), scriptNode = document.createElement('script');
scriptNode.appendChild(document.createTextNode(scriptText));
if (scriptSrc) { scriptNode.src = scriptSrc; }
contentNode.appendChild(scriptNode);
console.log(scriptNode);
});
// Complete the change
if ( $body.ScrollTo||false ) { $body.ScrollTo(scrollOptions); } /* http://balupton.com/projects/jquery-scrollto */
$window.trigger(completedEventName);
//Add in functions that need to be parsed after a load.
jQuery(document).ready(function() {
if (window.mslide) mslide();
});
// 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
}
//Launch scripts here.
},
error: function(jqXHR, textStatus, errorThrown){
document.location.href = url;
return false;
}
}); // end ajax
}); // end onStateChange
}); // end onDomLoad
})(window); // end closure
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment