Skip to content

Instantly share code, notes, and snippets.

@0b10011
Created October 14, 2014 16:10
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 0b10011/dfd74cb0aed4b144b3c7 to your computer and use it in GitHub Desktop.
Save 0b10011/dfd74cb0aed4b144b3c7 to your computer and use it in GitHub Desktop.
/*jslint nomen: true */
/*global $, ga, findAll, FB, HTMLFormElement */
/*jslint nomen: false */
(function () {
"use strict";
if (!$.support.pjax) {
// If PJAX isn't supported, there is no need to run this code
return;
}
$.pjax.cancel = function () {
var xhr = $.pjax.xhr;
if (xhr && xhr.readyState < 4) {
xhr.onreadystatechange = $.noop;
xhr.abort();
}
};
// Use PJAX to load regular links
$(document).pjax('a:not([download]):not([data-ignore-pjax])', '#pjax-container', {
timeout: 2000 // A bit of a cushion for long-loading pages
});
$(document).on('pjax:click', function (event, options) {
// Blur focused element asap to avoid header position flickering
$(':focus').blur();
var target = $(event.target);
options.append = target.data("pjax-append");
if (target.data("pjax-remove")) {
target.remove();
}
});
// Use PJAX to submit forms
$(document).on('submit', 'form', function (event) {
// Blur focused element asap to avoid header position flickering
// (Isn't always the event target. Sometimes it's an input.)
$(':focus').blur();
$.pjax.submit(event, '#pjax-container', {
xhr: function () {
var progressBar = $('#pjax-loading-progress'),
progressHeader = $('#pjax-loading-progress-header'),
xhr = $.ajaxSettings.xhr(),
downloading = false;
progressBar.removeAttr("value");
function updateProgress(type, progress) {
progressHeader.text(type + "...");
if (progress === null || progress >= 100) {
progressBar.removeAttr("value");
return;
}
progressBar.attr("value", progress);
progressBar.text(progress + "%");
}
// Load progress
xhr.onprogress = function (event) {
downloading = true;
var progress = null;
if (event.lengthComputable) {
progress = event.loaded / event.total * 100;
}
updateProgress("Loading", progress);
};
xhr.onloadend = function () {
downloading = true;
updateProgress("Loading", null);
};
// Upload progress
xhr.upload.onprogress = function (event) {
if (downloading) {
return;
}
var progress = null;
if (event.lengthComputable) {
progress = event.loaded / event.total * 100;
}
updateProgress("Uploading", progress);
};
xhr.upload.onloadend = function () {
if (downloading) {
return;
}
updateProgress("Uploading", null);
};
// Return the customized object
return xhr;
}
});
});
// Request sent
$(document).on('pjax:send', function (event, xhr, options) {
// Add loading class
$('body').addClass('pjax-loading');
// Set href for retry link
$('#pjax-loading-timeout-retry').attr('href', options.url);
});
// Request complete (error or success)
$(document).on('pjax:complete', function () {
// Remove loading and timeout classes
$('body').removeClass('pjax-loading pjax-timeout');
// Remove href from retry link
$('#pjax-loading-timeout-retry').attr('href', '#');
});
function extractNodes(container, updateBodyClass) {
var selector, nav, navCurrentText;
// Update account menu
selector = '#primary-nav-account';
// Update existing
$(selector).html(findAll(container.contents, selector).last().html());
// Remove node (should be top level)
container.contents = container.contents.not(selector);
// Update existing
nav = container.contents.filter('#primary-nav');
navCurrentText = nav.find('.primary-nav-current').text();
$('#primary-nav, #primary-nav-mobile').find('ul > li > a').each(function () {
if ($(this).text() === navCurrentText) {
$(this).addClass('primary-nav-current');
} else {
$(this).removeClass('primary-nav-current');
}
});
// Remove node (should be top level)
container.contents = container.contents.not('#primary-nav');
// Update body-inner class
if (updateBodyClass !== false) {
$('#body-inner').attr("class", findAll(container.contents, '#body-inner').last().attr("class"));
}
// Remove node (should be top level)
container.contents = container.contents.not('#body-inner');
}
// Request successful - Alter response
$(document).on('pjax:beforeSuccess', function (event, container, status, xhr, options) {
extractNodes(container, !options.append);
});
// Request successful (before inline scripts are inserted, after title is set)
$(document).on('pjax:beforeHtml', function () {
// Track pageview for Google Analytics
ga('send', 'pageview', "/" + window.location.pathname);
});
// Request successful
$(document).on('pjax:success', function () {
// Parse Facebook comments box
if (typeof FB !== 'undefined') {
FB.XFBML.parse();
}
});
// Request timeout
$(document).on('pjax:timeout', function (event) {
// Add timeout class
$('body').addClass('pjax-timeout');
// Prevent default timeout handling
event.preventDefault();
});
// Request error
$(document).on('pjax:error', function (event, xhr, textStatus, errorThrown, options) {
// Links and forms
switch (xhr.status) {
case 404: // Not found
case 410: // Gone
// Not 200, but should still display response as if it were
//
// Fake a successful request
options.success(xhr.responseText, textStatus, xhr);
// Cancel default behavior
return false;
}
// If a normal link, try loading it without PJAX
if (!$(event.relatedTarget).is("form")) {
return;
}
// Forms only
switch (xhr.status) {
case 412:
// Outdated code on client, submit request again normally
//
// Disable pjax
$.pjax.disable();
// Turn off event handlers
$(document).off('submit', 'form');
// Don't double submit "../"
$(event.relatedTarget).attr("action", window.location.href);
// Submit form
// This is an ugly hack to workaround submit buttons without a name that
// automatically take the name 'submit', thereby breaking form.submit().
HTMLFormElement.prototype.submit.call(event.relatedTarget);
// Cancel default behavior
return false;
case 500:
// Server error, probably too large of an upload
//
// Alert the user so they can try submitting the form again manually
window.alert("Our server couldn't fully handle your request. If you " +
"are trying to upload a file, please make sure it is within " +
"the size requirements listed. If you continue to run into " +
"issues, give us a call at 231.933.3699 and we'll help you " +
"out.");
return;
}
});
function findAll(elems, selector) {
return elems.filter(selector).add(elems.find(selector));
}
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment