Skip to content

Commit

Permalink
Update to latest jquery.pjax.js - tweak site-pjax a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewsimo committed Jun 20, 2013
1 parent 9603165 commit a0545f4
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 43 deletions.
144 changes: 111 additions & 33 deletions assets/js/jquery.pjax.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function handleClick(event, container, options) {
return

// Ignore cross origin links
if ( location.protocol !== link.protocol || location.host !== link.host )
if ( location.protocol !== link.protocol || location.hostname !== link.hostname )
return

// Ignore anchors on the same page
Expand All @@ -89,9 +89,14 @@ function handleClick(event, container, options) {
fragment: null
}

pjax($.extend({}, defaults, options))
var opts = $.extend({}, defaults, options)
var clickEvent = $.Event('pjax:click')
$(link).trigger(clickEvent, [opts])

event.preventDefault()
if (!clickEvent.isDefaultPrevented()) {
pjax(opts)
event.preventDefault()
}
}

// Public: pjax on form submit handler
Expand All @@ -118,13 +123,12 @@ function handleSubmit(event, container, options) {
throw "$.pjax.submit requires a form element"

var defaults = {
type: form.method,
type: form.method.toUpperCase(),
url: form.action,
data: $(form).serializeArray(),
container: $(form).attr('data-pjax'),
target: form,
fragment: null,
timeout: 0
fragment: null
}

pjax($.extend({}, defaults, options))
Expand Down Expand Up @@ -186,6 +190,12 @@ function pjax(options) {
settings.timeout = 0
}

xhr.setRequestHeader('X-PJAX', 'true')
xhr.setRequestHeader('X-PJAX-Container', context.selector)

if (!fire('pjax:beforeSend', [xhr, settings]))
return false

if (settings.timeout > 0) {
timeoutTimer = setTimeout(function() {
if (fire('pjax:timeout', [xhr, options]))
Expand All @@ -196,14 +206,6 @@ function pjax(options) {
settings.timeout = 0
}

xhr.setRequestHeader('X-PJAX', 'true')
xhr.setRequestHeader('X-PJAX-Container', context.selector)

var result

if (!fire('pjax:beforeSend', [xhr, settings]))
return false

options.requestUrl = parseURL(settings.url).href
}

Expand All @@ -226,8 +228,23 @@ function pjax(options) {
}

options.success = function(data, status, xhr) {
// If $.pjax.defaults.version is a function, invoke it first.
// Otherwise it can be a static string.
var currentVersion = (typeof $.pjax.defaults.version === 'function') ?
$.pjax.defaults.version() :
$.pjax.defaults.version

var latestVersion = xhr.getResponseHeader('X-PJAX-Version')

var container = extractContainer(data, xhr, options)

// If there is a layout version mismatch, hard load the new url
if (currentVersion && latestVersion && currentVersion !== latestVersion) {
locationReplace(container.url)
return
}

// If the new response is missing a body, hard load the page
if (!container.contents) {
locationReplace(container.url)
return
Expand All @@ -248,15 +265,12 @@ function pjax(options) {

if (container.title) document.title = container.title
context.html(container.contents)
executeScriptTags(container.scripts)

// Scroll to top by default
if (typeof options.scrollTo === 'number')
$(window).scrollTop(options.scrollTo)

// Google Analytics support
if ( (options.replace || options.push) && window._gaq )
_gaq.push(['_trackPageview'])

// If the URL has a hash in it, make sure the browser
// knows to navigate to the hash.
if ( hash !== '' ) {
Expand Down Expand Up @@ -345,6 +359,23 @@ function locationReplace(url) {
window.location.replace(url)
}


var initialPop = true
var initialURL = window.location.href
var initialState = window.history.state

// Initialize $.pjax.state if possible
// Happens when reloading a page and coming forward from a different
// session history.
if (initialState && initialState.container) {
pjax.state = initialState
}

// Non-webkit browsers don't fire an initial popstate event
if ('state' in window.history) {
initialPop = false
}

// popstate handler takes care of the back and forward buttons
//
// You probably shouldn't use pjax on pages with other pushState
Expand All @@ -353,23 +384,23 @@ function onPjaxPopstate(event) {
var state = event.state

if (state && state.container) {
// When coming forward from a separate history session, will get an
// initial pop with a state we are already at. Skip reloading the current
// page.
if (initialPop && initialURL == state.url) return

var container = $(state.container)
if (container.length) {
var contents = cacheMapping[state.id]
var direction, contents = cacheMapping[state.id]

if (pjax.state) {
// Since state ids always increase, we can deduce the history
// direction from the previous state.
var direction = pjax.state.id < state.id ? 'forward' : 'back'
direction = pjax.state.id < state.id ? 'forward' : 'back'

// Cache current container before replacement and inform the
// cache which direction the history shifted.
cachePop(direction, pjax.state.id, container.clone().contents())
} else {
// Page was reloaded but we have an existing history entry.
// Set it to our initial state.
pjax.state = state;
return;
}

var popstateEvent = $.Event('pjax:popstate', {
Expand Down Expand Up @@ -407,6 +438,7 @@ function onPjaxPopstate(event) {
locationReplace(location.href)
}
}
initialPop = false
}

// Fallback version of main pjax function for browsers that don't
Expand Down Expand Up @@ -551,6 +583,10 @@ function findAll(elems, selector) {
return elems.filter(selector).add(elems.find(selector));
}

function parseHTML(html) {
return $.parseHTML(html, document, true)
}

// Internal: Extracts container and metadata from response.
//
// 1. Extracts X-PJAX-URL header if set
Expand All @@ -571,10 +607,10 @@ function extractContainer(data, xhr, options) {

// Attempt to parse response html into elements
if (/<html/i.test(data)) {
var $head = $(data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0])
var $body = $(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0])
var $head = $(parseHTML(data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0]))
var $body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]))
} else {
var $head = $body = $(data)
var $head = $body = $(parseHTML(data))
}

// If response data is empty, return fast
Expand Down Expand Up @@ -610,10 +646,14 @@ function extractContainer(data, xhr, options) {
// Clean up any <title> tags
if (obj.contents) {
// Remove any parent title elements
obj.contents = obj.contents.not('title')
obj.contents = obj.contents.not(function() { return $(this).is('title') })

// Then scrub any titles from their descendents
// Then scrub any titles from their descendants
obj.contents.find('title').remove()

// Gather all script[src] elements
obj.scripts = findAll(obj.contents, 'script[src]').remove()
obj.contents = obj.contents.not(obj.scripts)
}

// Trim any whitespace off the title
Expand All @@ -622,6 +662,33 @@ function extractContainer(data, xhr, options) {
return obj
}

// Load an execute scripts using standard script request.
//
// Avoids jQuery's traditional $.getScript which does a XHR request and
// globalEval.
//
// scripts - jQuery object of script Elements
//
// Returns nothing.
function executeScriptTags(scripts) {
if (!scripts) return

var existingScripts = $('script[src]')

scripts.each(function() {
var src = this.src
var matchedScripts = existingScripts.filter(function() {
return this.src === src
})
if (matchedScripts.length) return

var script = document.createElement('script')
script.type = $(this).attr('type')
script.src = $(this).attr('src')
document.head.appendChild(script)
})
}

// Internal: History DOM caching class.
var cacheMapping = {}
var cacheForwardStack = []
Expand Down Expand Up @@ -675,6 +742,16 @@ function cachePop(direction, id, value) {
delete cacheMapping[id]
}

// Public: Find version identifier for the initial page load.
//
// Returns String version or undefined.
function findVersion() {
return $('meta').filter(function() {
var name = $(this).attr('http-equiv')
return name && name.toUpperCase() === 'X-PJAX-VERSION'
}).attr('content')
}

// Install pjax functions on $.pjax to enable pushState behavior.
//
// Does nothing if already enabled.
Expand All @@ -699,9 +776,10 @@ function enable() {
type: 'GET',
dataType: 'html',
scrollTo: 0,
maxCacheLength: 20
maxCacheLength: 20,
version: findVersion
}
$(window).bind('popstate.pjax', onPjaxPopstate)
$(window).on('popstate.pjax', onPjaxPopstate)
}

// Disable pushState behavior.
Expand All @@ -724,7 +802,7 @@ function disable() {
$.pjax.submit = $.noop
$.pjax.reload = function() { window.location.reload() }

$(window).unbind('popstate.pjax', onPjaxPopstate)
$(window).off('popstate.pjax', onPjaxPopstate)
}


Expand Down
21 changes: 11 additions & 10 deletions assets/js/site-pjax.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
// console.log(typeof pjaxData.pjaxTarget + " : " + pjaxData.pjaxTarget);

// Uncomment for pjax event testing
// $(document).on('pjax:start', function() { console.log("starting pjax") });
// $(document).on('pjax:end', function() {console.log("ending pjax") });
// $(document).on('pjax:start', function() { console.log("starting pjax") });
// $(document).on('pjax:end', function() {console.log("ending pjax") });
// $(document).on('pjax:error', function(e, data, type) { return false; });
$(document).on('pjax:timeout', function(e) { return false; });


// requests ending with these strings will NOT trigger a pjax request.
Expand Down Expand Up @@ -44,17 +46,16 @@

$(document).on('click', pjaxData.pjaxTarget, function(e) {

if($(e.srcElement).attr('href'))
clickTarget = $(e.srcElement).attr('href');
if($(e.target).attr('href'))
clickTarget = $(e.target).attr('href');
else
clickTarget = $(e.srcElement).parents('a').attr('href');
clickTarget = $(e.target).parents('a').attr('href');

if(matchesTypes(clickTarget)){
// Business as usual
if( matchesTypes(clickTarget) ){
// Bad match - business as usual
} else {
if($.support.pjax) {
$.pjax({ url: clickTarget, container: $(pjaxData.pjaxContainer) });
}
if($.support.pjax)
$.pjax.click(e, { container: pjaxData.pjaxContainer });
}

});
Expand Down

0 comments on commit a0545f4

Please sign in to comment.