|
|
|
@ -205,6 +205,150 @@
|
|
|
|
|
|
|
|
|
|
}()); |
|
|
|
|
|
|
|
|
|
!(function () { |
|
|
|
|
'use strict'; |
|
|
|
|
|
|
|
|
|
// Ratchet's layout includes fixed position headers & footers that should always
|
|
|
|
|
// appear before the main .content div within <body>
|
|
|
|
|
//
|
|
|
|
|
// These fixed bars will have new content swapped in, ignoring any
|
|
|
|
|
// transitions (slide-in, slide-out & fade).
|
|
|
|
|
//
|
|
|
|
|
// These following selectors define which elements are transitioned with
|
|
|
|
|
// simple DOM replacement and are always immediate children of <body>
|
|
|
|
|
var barSelectors = [ |
|
|
|
|
'.bar-tab', |
|
|
|
|
'.bar-nav', |
|
|
|
|
'.bar-footer', |
|
|
|
|
'.bar-header-secondary' |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
// Other than any fixed bars, '.content' should be the only other child of body
|
|
|
|
|
var contentSelector = '.content'; |
|
|
|
|
|
|
|
|
|
// For any bar elements in `newMarkup`, either:
|
|
|
|
|
// * replace an existing bar elements with new content
|
|
|
|
|
// * add new bar elements when an existing one isn't present
|
|
|
|
|
// * remove any bar elements not found in `newMarkup`
|
|
|
|
|
var updateBars = function (newMarkup) { |
|
|
|
|
for (var i = 0; i < barSelectors.length; i++) { |
|
|
|
|
var selector = barSelectors[i]; |
|
|
|
|
var newBar = newMarkup.querySelector(selector); |
|
|
|
|
var existingBar = document.querySelector(selector); |
|
|
|
|
|
|
|
|
|
if (newBar) { |
|
|
|
|
displayBar(newBar, existingBar); |
|
|
|
|
} else if (existingBar) { |
|
|
|
|
existingBar.parentNode.removeChild(existingBar); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
var displayBar = function (bar, container) { |
|
|
|
|
if (container) { |
|
|
|
|
container.innerHTML = ''; |
|
|
|
|
container.appendChild(bar); |
|
|
|
|
} else { |
|
|
|
|
// per Ratchet's CSS, bar elements must be the first thing in <body>
|
|
|
|
|
// here we assume `.content` is an immediate child of <body>
|
|
|
|
|
document.body.insertBefore(bar, document.querySelector(contentSelector)); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
var transitionContent = function (swap, container, transition, complete) { |
|
|
|
|
var enter; |
|
|
|
|
var containerDirection; |
|
|
|
|
var swapDirection; |
|
|
|
|
|
|
|
|
|
enter = /in$/.test(transition); |
|
|
|
|
|
|
|
|
|
if (transition === 'fade') { |
|
|
|
|
container.classList.add('in'); |
|
|
|
|
container.classList.add('fade'); |
|
|
|
|
swap.classList.add('fade'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (/slide/.test(transition)) { |
|
|
|
|
swap.classList.add('sliding-in', enter ? 'right' : 'left'); |
|
|
|
|
swap.classList.add('sliding'); |
|
|
|
|
container.classList.add('sliding'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
container.parentNode.insertBefore(swap, container); |
|
|
|
|
|
|
|
|
|
if (transition === 'fade') { |
|
|
|
|
container.offsetWidth; // force reflow
|
|
|
|
|
container.classList.remove('in'); |
|
|
|
|
var fadeContainerEnd = function () { |
|
|
|
|
container.removeEventListener(window.RATCHET.getTransitionEnd, fadeContainerEnd); |
|
|
|
|
swap.classList.add('in'); |
|
|
|
|
swap.addEventListener(window.RATCHET.getTransitionEnd, fadeSwapEnd); |
|
|
|
|
}; |
|
|
|
|
var fadeSwapEnd = function () { |
|
|
|
|
swap.removeEventListener(window.RATCHET.getTransitionEnd, fadeSwapEnd); |
|
|
|
|
container.parentNode.removeChild(container); |
|
|
|
|
swap.classList.remove('fade'); |
|
|
|
|
swap.classList.remove('in'); |
|
|
|
|
complete && complete(); |
|
|
|
|
}; |
|
|
|
|
container.addEventListener(window.RATCHET.getTransitionEnd, fadeContainerEnd); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (/slide/.test(transition)) { |
|
|
|
|
var slideEnd = function () { |
|
|
|
|
swap.removeEventListener(window.RATCHET.getTransitionEnd, slideEnd); |
|
|
|
|
swap.classList.remove('sliding', 'sliding-in'); |
|
|
|
|
swap.classList.remove(swapDirection); |
|
|
|
|
container.parentNode.removeChild(container); |
|
|
|
|
complete && complete(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
container.offsetWidth; // force reflow
|
|
|
|
|
swapDirection = enter ? 'right' : 'left'; |
|
|
|
|
containerDirection = enter ? 'left' : 'right'; |
|
|
|
|
container.classList.add(containerDirection); |
|
|
|
|
swap.classList.remove(swapDirection); |
|
|
|
|
swap.addEventListener('webkitTransitionEnd', slideEnd); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// `contents` can either be a string of HTML or a DOM object.
|
|
|
|
|
// Either way, `contents` must include:
|
|
|
|
|
// * bar elements (optional -- see `barSelectors`)
|
|
|
|
|
// * a single content element
|
|
|
|
|
// All as children of a single parent.
|
|
|
|
|
//
|
|
|
|
|
// For example:
|
|
|
|
|
// <div>
|
|
|
|
|
// <div class="bar-tab"></div>
|
|
|
|
|
// <div class="bar-nav"></div>
|
|
|
|
|
// <div class="contents"></div>
|
|
|
|
|
// </div>
|
|
|
|
|
var TRANSITION = function (contents, transition, complete) { |
|
|
|
|
|
|
|
|
|
if(typeof(contents) === 'string' || contents instanceof String) { |
|
|
|
|
var div = document.createElement('div'); |
|
|
|
|
div.innerHTML = contents; |
|
|
|
|
contents = div.childNodes[0]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (transition) { |
|
|
|
|
updateBars(contents); |
|
|
|
|
|
|
|
|
|
var existingContentDiv = document.querySelector(contentSelector); |
|
|
|
|
var newContentDiv = contents.querySelector(contentSelector); |
|
|
|
|
transitionContent(newContentDiv, existingContentDiv, |
|
|
|
|
transition, complete); |
|
|
|
|
} else { |
|
|
|
|
document.body.innerHTML = ''; |
|
|
|
|
document.body.appendChild(contents); |
|
|
|
|
complete && complete(); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
window.TRANSITION = TRANSITION; |
|
|
|
|
}()); |
|
|
|
|
|
|
|
|
|
/* ======================================================================== |
|
|
|
|
* Ratchet: push.js v2.0.2 |
|
|
|
|
* http://goratchet.com/components#push
|
|
|
|
@ -214,7 +358,7 @@
|
|
|
|
|
* Licensed under MIT (https://github.com/twbs/ratchet/blob/master/LICENSE)
|
|
|
|
|
* ======================================================================== */ |
|
|
|
|
|
|
|
|
|
/* global _gaq: true */ |
|
|
|
|
/* global _gaq, TRANSITION */ |
|
|
|
|
|
|
|
|
|
!(function () { |
|
|
|
|
'use strict'; |
|
|
|
@ -236,13 +380,6 @@
|
|
|
|
|
fade : 'fade' |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
var bars = { |
|
|
|
|
bartab : '.bar-tab', |
|
|
|
|
barnav : '.bar-nav', |
|
|
|
|
barfooter : '.bar-footer', |
|
|
|
|
barheadersecondary : '.bar-header-secondary' |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
var cacheReplace = function (data, updates) { |
|
|
|
|
PUSH.id = data.id; |
|
|
|
|
if (updates) { |
|
|
|
@ -334,8 +471,6 @@
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
var popstate = function (e) { |
|
|
|
|
var key; |
|
|
|
|
var barElement; |
|
|
|
|
var activeObj; |
|
|
|
|
var activeDom; |
|
|
|
|
var direction; |
|
|
|
@ -383,27 +518,11 @@
|
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (transitionFromObj.transition) { |
|
|
|
|
activeObj = extendWithDom(activeObj, '.content', activeDom.cloneNode(true)); |
|
|
|
|
for (key in bars) { |
|
|
|
|
if (bars.hasOwnProperty(key)) { |
|
|
|
|
barElement = document.querySelector(bars[key]); |
|
|
|
|
if (activeObj[key]) { |
|
|
|
|
swapContent(activeObj[key], barElement); |
|
|
|
|
} else if (barElement) { |
|
|
|
|
barElement.parentNode.removeChild(barElement); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
swapContent( |
|
|
|
|
(activeObj.contents || activeDom).cloneNode(true), |
|
|
|
|
document.querySelector('.content'), |
|
|
|
|
transition, function () { |
|
|
|
|
triggerStateChange(); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
TRANSITION(activeDom.cloneNode(true), |
|
|
|
|
transitionFromObj.transition, |
|
|
|
|
function() { |
|
|
|
|
triggerStateChange(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
PUSH.id = id; |
|
|
|
|
|
|
|
|
@ -415,17 +534,8 @@
|
|
|
|
|
// =======================
|
|
|
|
|
|
|
|
|
|
var PUSH = function (options) { |
|
|
|
|
var key; |
|
|
|
|
var xhr = PUSH.xhr; |
|
|
|
|
|
|
|
|
|
options.container = options.container || options.transition ? document.querySelector('.content') : document.body; |
|
|
|
|
|
|
|
|
|
for (key in bars) { |
|
|
|
|
if (bars.hasOwnProperty(key)) { |
|
|
|
|
options[key] = options[key] || document.querySelector(bars[key]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (xhr && xhr.readyState < 4) { |
|
|
|
|
xhr.onreadystatechange = noop; |
|
|
|
|
xhr.abort(); |
|
|
|
@ -480,8 +590,6 @@
|
|
|
|
|
// =================
|
|
|
|
|
|
|
|
|
|
var success = function (xhr, options) { |
|
|
|
|
var key; |
|
|
|
|
var barElement; |
|
|
|
|
var data = parseXHR(xhr, options); |
|
|
|
|
|
|
|
|
|
if (!data.contents) { |
|
|
|
@ -492,20 +600,7 @@
|
|
|
|
|
document.title = data.title; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (options.transition) { |
|
|
|
|
for (key in bars) { |
|
|
|
|
if (bars.hasOwnProperty(key)) { |
|
|
|
|
barElement = document.querySelector(bars[key]); |
|
|
|
|
if (data[key]) { |
|
|
|
|
swapContent(data[key], barElement); |
|
|
|
|
} else if (barElement) { |
|
|
|
|
barElement.parentNode.removeChild(barElement); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
swapContent(data.contents, options.container, options.transition, function () { |
|
|
|
|
TRANSITION(data.contents, options.transition, function () { |
|
|
|
|
cacheReplace({ |
|
|
|
|
id : options.id || +new Date(), |
|
|
|
|
url : data.url, |
|
|
|
@ -516,6 +611,7 @@
|
|
|
|
|
triggerStateChange(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!options.ignorePush && window._gaq) { |
|
|
|
|
_gaq.push(['_trackPageview']); // google analytics
|
|
|
|
|
} |
|
|
|
@ -532,84 +628,6 @@
|
|
|
|
|
// PUSH helpers
|
|
|
|
|
// ============
|
|
|
|
|
|
|
|
|
|
var swapContent = function (swap, container, transition, complete) { |
|
|
|
|
var enter; |
|
|
|
|
var containerDirection; |
|
|
|
|
var swapDirection; |
|
|
|
|
|
|
|
|
|
if (!transition) { |
|
|
|
|
if (container) { |
|
|
|
|
container.innerHTML = swap.innerHTML; |
|
|
|
|
} else if (swap.classList.contains('content')) { |
|
|
|
|
document.body.appendChild(swap); |
|
|
|
|
} else { |
|
|
|
|
document.body.insertBefore(swap, document.querySelector('.content')); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
enter = /in$/.test(transition); |
|
|
|
|
|
|
|
|
|
if (transition === 'fade') { |
|
|
|
|
container.classList.add('in'); |
|
|
|
|
container.classList.add('fade'); |
|
|
|
|
swap.classList.add('fade'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (/slide/.test(transition)) { |
|
|
|
|
swap.classList.add('sliding-in', enter ? 'right' : 'left'); |
|
|
|
|
swap.classList.add('sliding'); |
|
|
|
|
container.classList.add('sliding'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
container.parentNode.insertBefore(swap, container); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!transition) { |
|
|
|
|
if (complete) { |
|
|
|
|
complete(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (transition === 'fade') { |
|
|
|
|
container.offsetWidth; // force reflow
|
|
|
|
|
container.classList.remove('in'); |
|
|
|
|
var fadeContainerEnd = function () { |
|
|
|
|
container.removeEventListener(window.RATCHET.getTransitionEnd, fadeContainerEnd); |
|
|
|
|
swap.classList.add('in'); |
|
|
|
|
swap.addEventListener(window.RATCHET.getTransitionEnd, fadeSwapEnd); |
|
|
|
|
}; |
|
|
|
|
var fadeSwapEnd = function () { |
|
|
|
|
swap.removeEventListener(window.RATCHET.getTransitionEnd, fadeSwapEnd); |
|
|
|
|
container.parentNode.removeChild(container); |
|
|
|
|
swap.classList.remove('fade'); |
|
|
|
|
swap.classList.remove('in'); |
|
|
|
|
if (complete) { |
|
|
|
|
complete(); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
container.addEventListener(window.RATCHET.getTransitionEnd, fadeContainerEnd); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (/slide/.test(transition)) { |
|
|
|
|
var slideEnd = function () { |
|
|
|
|
swap.removeEventListener(window.RATCHET.getTransitionEnd, slideEnd); |
|
|
|
|
swap.classList.remove('sliding', 'sliding-in'); |
|
|
|
|
swap.classList.remove(swapDirection); |
|
|
|
|
container.parentNode.removeChild(container); |
|
|
|
|
if (complete) { |
|
|
|
|
complete(); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
container.offsetWidth; // force reflow
|
|
|
|
|
swapDirection = enter ? 'right' : 'left'; |
|
|
|
|
containerDirection = enter ? 'left' : 'right'; |
|
|
|
|
container.classList.add(containerDirection); |
|
|
|
|
swap.classList.remove(swapDirection); |
|
|
|
|
swap.addEventListener(window.RATCHET.getTransitionEnd, slideEnd); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
var triggerStateChange = function () { |
|
|
|
|
var e = new CustomEvent('push', { |
|
|
|
|
detail: { state: getCached(PUSH.id) }, |
|
|
|
@ -638,29 +656,6 @@
|
|
|
|
|
window.location.replace(url); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
var extendWithDom = function (obj, fragment, dom) { |
|
|
|
|
var i; |
|
|
|
|
var result = {}; |
|
|
|
|
|
|
|
|
|
for (i in obj) { |
|
|
|
|
if (obj.hasOwnProperty(i)) { |
|
|
|
|
result[i] = obj[i]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Object.keys(bars).forEach(function (key) { |
|
|
|
|
var el = dom.querySelector(bars[key]); |
|
|
|
|
if (el) { |
|
|
|
|
el.parentNode.removeChild(el); |
|
|
|
|
} |
|
|
|
|
result[key] = el; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
result.contents = dom.querySelector(fragment); |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
var parseXHR = function (xhr, options) { |
|
|
|
|
var head; |
|
|
|
|
var body; |
|
|
|
@ -687,11 +682,7 @@
|
|
|
|
|
var text = 'innerText' in data.title ? 'innerText' : 'textContent'; |
|
|
|
|
data.title = data.title && data.title[text].trim(); |
|
|
|
|
|
|
|
|
|
if (options.transition) { |
|
|
|
|
data = extendWithDom(data, '.content', body); |
|
|
|
|
} else { |
|
|
|
|
data.contents = body; |
|
|
|
|
} |
|
|
|
|
data.contents = body; |
|
|
|
|
|
|
|
|
|
return data; |
|
|
|
|
}; |
|
|
|
|