Created
July 20, 2013 13:53
-
-
Save Hadryan/6045111 to your computer and use it in GitHub Desktop.
a class of no-djax added to the original djax to have non-updatable internal links/elements. modification to have inline scripts at the end of updatable zone.
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
/* | |
* jQuery djax | |
* | |
* @version v0.122 | |
* | |
* Copyright 2012, Brian Zeligson | |
* Released under the MIT license. | |
* http://www.opensource.org/licenses/mit-license.php | |
* | |
* Homepage: | |
* http://beezee.github.com/djax.html | |
* | |
* Authors: | |
* Brian Zeligson | |
* | |
* Contributors: | |
* Gary Jones @GaryJones | |
* | |
* Maintainer: | |
* Brian Zeligson github @beezee | |
* | |
*/ | |
/*jslint browser: true, indent: 4, maxerr: 50, sub: true */ | |
/*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true, latedef:true, noarg:true, noempty:true, nomen:true, nonew:true, onevar:true, plusplus:true, regexp:true, smarttabs:true, strict:true, trailing:true, undef:true, white:true, browser:true, jquery:true, indent:4, maxerr:50, */ | |
/*global jQuery */ | |
// ==ClosureCompiler== | |
// @compilation_level ADVANCED_OPTIMIZATIONS | |
// @output_file_name jquery.djax.js | |
// @externs_url http://closure-compiler.googlecode.com/svn/trunk/contrib/externs/jquery-1.7.js | |
// ==/ClosureCompiler== | |
// http://closure-compiler.appspot.com/home | |
(function ($, exports) { | |
'use strict'; | |
$.fn.djax = function (selector, exceptions, replaceBlockWithFunc) { | |
// If browser doesn't support pushState, abort now | |
if (!history.pushState) { | |
return $(this); | |
} | |
var self = this, | |
blockSelector = selector, | |
excludes = (exceptions && exceptions.length) ? exceptions : [], | |
replaceBlockWith = (replaceBlockWithFunc) ? replaceBlockWithFunc : $.fn.replaceWith, | |
djaxing = false; | |
// Ensure that the history is correct when going from 2nd page to 1st | |
window.history.replaceState( | |
{ | |
'url' : window.location.href, | |
'title' : $('title').text() | |
}, | |
$('title').text(), | |
window.location.href | |
); | |
self.clearDjaxing = function() { | |
self.djaxing = false; | |
} | |
// Exclude the link exceptions | |
self.attachClick = function (element, event) { | |
var link = $(element), | |
exception = false; | |
$.each(excludes, function (index, exclusion) { | |
if (link.attr('href').indexOf(exclusion) !== -1) { | |
exception = true; | |
} | |
if (window.location.href.indexOf(exclusion) !== -1) { | |
exception = true; | |
} | |
}); | |
// If the link is one of the exceptions, return early so that | |
// the link can be clicked and a full page load as normal | |
if (exception) { | |
return $(element); | |
} | |
// From this point on, we handle the behaviour | |
event.preventDefault(); | |
// If we're already doing djaxing, return now and silently fail | |
if (self.djaxing) { | |
setTimeout(self.clearDjaxing, 1000); | |
return $(element); | |
} | |
$(window).trigger('djaxClick', [element]); | |
self.reqUrl = link.attr('href'); | |
self.triggered = false; | |
self.navigate(link.attr('href'), true); | |
}; | |
// Handle the navigation | |
self.navigate = function (url, add) { | |
var blocks = $(blockSelector); | |
self.djaxing = true; | |
// Get the new page | |
$(window).trigger( | |
'djaxLoading', | |
[{ | |
'url' : url | |
}] | |
); | |
var replaceBlocks = function (response) { | |
if (url !== self.reqUrl) { | |
self.navigate(self.reqUrl, false); | |
return true; | |
} | |
var result = $(response), | |
newBlocks = $(result).find(blockSelector); | |
if (add) { | |
window.history.pushState( | |
{ | |
'url' : url, | |
'title' : $(result).filter('title').text() | |
}, | |
$(result).filter('title').text(), | |
url | |
); | |
} | |
// Set page title as new page title | |
$('title').text($(result).filter('title').text()); | |
//Remove element not done by other removes | |
$('.datepicker').remove(); | |
var newStyle = $(result).filter('style'+blockSelector).text(); | |
if($('style'+blockSelector).length) | |
{ | |
$('style'+blockSelector).remove(); | |
} | |
//Get all styles to add to the new page | |
var head = document.getElementsByTagName('head')[0]; | |
var newStyles = $(result).filter('style'+blockSelector); | |
$.each(newStyles, function () { | |
var newStyle = $(this).text(); | |
var style = document.createElement('style'); | |
style.type = 'text/css'; | |
style.className = blockSelector.replace('.', ''); | |
if (style.styleSheet){ | |
style.styleSheet.cssText = newStyle; | |
} else { | |
style.appendChild(document.createTextNode(newStyle)); | |
} | |
head.appendChild(style); | |
}); | |
// Loop through each block and find new page equivalent | |
blocks.each(function () { | |
var id = '#' + $(this).attr('id'), | |
newBlock = newBlocks.filter(id), | |
block = $(this); | |
//console.log(newBlock.html()); | |
//console.log(block.html()); | |
$('a', newBlock).not('.no-djax').filter(function () { | |
return this.hostname === location.hostname; | |
}).addClass('dJAX_internal').on('click', function (event) { | |
return self.attachClick(this, event); | |
}); | |
if (newBlock.length) { | |
if (block.html() !== newBlock.html()) { | |
replaceBlockWith.call(block, newBlock); | |
} | |
} else { | |
block.remove(); | |
} | |
}); | |
// Loop through new page blocks and add in as needed | |
$.each(newBlocks, function () { | |
var newBlock = $(this), | |
id = '#' + $(this).attr('id'), | |
$previousSibling; | |
//console.log(newBlocks.html()); | |
//console.log(newBlock.html()); | |
// If there is a new page block without an equivalent block | |
// in the old page, we need to find out where to insert it | |
if (!$(id).length) { | |
// Find the previous sibling | |
$previousSibling = $(result).find(id).prev(); | |
if ($previousSibling.length) { | |
// Insert after the previous element | |
newBlock.insertAfter('#' + $previousSibling.attr('id')); | |
} else { | |
// There's no previous sibling, so prepend to parent instead | |
newBlock.prependTo('#' + newBlock.parent().attr('id')); | |
} | |
} | |
// Only add a class to internal links | |
$('a', newBlock).not('.no-djax').filter(function () { | |
return this.hostname === location.hostname; | |
}).addClass('dJAX_internal').on('click', function (event) { | |
return self.attachClick(this, event); | |
}); | |
}); | |
var oldScripts = $('script.no-djax'); | |
$.each(oldScripts, function () { | |
$(this).remove(); | |
}); | |
//Get all scripts to add to the new page | |
var newScripts = $(result).filter('script.no-djax'); | |
$.each(newScripts, function () { | |
var newScript = $(this).text(); | |
//console.log('error', newScript); //Debugging yo | |
//Create new script element and add it to the DOM corrently, that way it is executed :D | |
var script = document.createElement("script"); | |
script.type = "text/javascript"; | |
script.text = newScript; // use this for inline script | |
script.className = "no-djax"; | |
var updateId = blockSelector.replace('#', ''); | |
document.getElementById(updateId).appendChild(script); | |
}); | |
// Trigger djaxLoad event as a pseudo ready() | |
if (!self.triggered) { | |
$(window).trigger( | |
'djaxLoad', | |
[{ | |
'url' : url, | |
'title' : $(result).filter('title').text(), | |
'response' : response | |
}] | |
); | |
self.triggered = true; | |
self.djaxing = false; | |
} | |
}; | |
$.get(url, function (response) { | |
replaceBlocks(response); | |
}).error(function (response) { | |
// handle error | |
console.log('error', response); | |
replaceBlocks(response['responseText']); | |
}); | |
}; /* End self.navigate */ | |
// Only add a class to internal links | |
$(this).find('a').not('.no-djax').filter(function () { | |
return this.hostname === location.hostname; | |
}).addClass('dJAX_internal').on('click', function (event) { | |
return self.attachClick(this, event); | |
}); | |
// On new page load | |
$(window).bind('popstate', function (event) { | |
self.triggered = false; | |
if (event.originalEvent.state) { | |
self.reqUrl = event.originalEvent.state.url; | |
self.navigate(event.originalEvent.state.url, false); | |
} | |
}); | |
}; | |
}(jQuery, window)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment