- // Ajaxify
- // v1.0.1 - 30 September, 2012
- // https://github.com/browserstate/ajaxify
- (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 $.trim(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');
- if ( $script.attr('src') ) {
- if ( !$script[0].async ) { scriptNode.async = false; }
- scriptNode.src = $script.attr('src');
- }
- 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