GitCodeTree/libs/ondemand/turbolinks.js

424 lines
13 KiB
JavaScript

// Generated by CoffeeScript 1.6.3
(function() {
var CSRFToken, anchoredLink, browserCompatibleDocumentParser, browserIsntBuggy, browserSupportsPushState, cacheCurrentPage, cacheSize, changePage, constrainPageCacheTo, createDocument, crossOriginLink, currentState, executeScriptTags, extractLink, extractTitleAndBody, fetchHistory, fetchReplacement, handleClick, ignoreClick, initializeTurbolinks, installClickHandlerLast, loadedAssets, noTurbolink, nonHtmlLink, nonStandardClick, pageCache, pageChangePrevented, pagesCached, processResponse, recallScrollPosition, referer, reflectNewUrl, reflectRedirectedUrl, rememberCurrentState, rememberCurrentUrl, removeHash, removeNoscriptTags, requestMethod, requestMethodIsSafe, resetScrollPosition, targetLink, triggerEvent, visit, xhr, _ref,
__hasProp = {}.hasOwnProperty,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
cacheSize = 10;
currentState = null;
referer = null;
loadedAssets = null;
pageCache = {};
createDocument = null;
requestMethod = ((_ref = document.cookie.match(/request_method=(\w+)/)) != null ? _ref[1].toUpperCase() : void 0) || '';
xhr = null;
fetchReplacement = function(url) {
var safeUrl;
triggerEvent('page:fetch');
safeUrl = removeHash(url);
if (xhr != null) {
xhr.abort();
}
xhr = new XMLHttpRequest;
xhr.open('GET', safeUrl, true);
xhr.setRequestHeader('Accept', 'text/html, application/xhtml+xml, application/xml');
xhr.setRequestHeader('X-XHR-Referer', referer);
xhr.onload = function() {
var doc;
triggerEvent('page:receive');
if (doc = processResponse()) {
reflectNewUrl(url);
changePage.apply(null, extractTitleAndBody(doc));
reflectRedirectedUrl();
if (document.location.hash) {
document.location.href = document.location.href;
} else {
resetScrollPosition();
}
return triggerEvent('page:load');
} else {
return document.location.href = url;
}
};
xhr.onloadend = function() {
return xhr = null;
};
xhr.onabort = function() {
return rememberCurrentUrl();
};
xhr.onerror = function() {
return document.location.href = url;
};
return xhr.send();
};
fetchHistory = function(position) {
var page;
cacheCurrentPage();
page = pageCache[position];
if (xhr != null) {
xhr.abort();
}
changePage(page.title, page.body);
recallScrollPosition(page);
return triggerEvent('page:restore');
};
cacheCurrentPage = function() {
pageCache[currentState.position] = {
url: document.location.href,
body: document.body,
title: document.title,
positionY: window.pageYOffset,
positionX: window.pageXOffset
};
return constrainPageCacheTo(cacheSize);
};
pagesCached = function(size) {
if (size == null) {
size = cacheSize;
}
if (/^[\d]+$/.test(size)) {
return cacheSize = parseInt(size);
}
};
constrainPageCacheTo = function(limit) {
var key, value;
for (key in pageCache) {
if (!__hasProp.call(pageCache, key)) continue;
value = pageCache[key];
if (key <= currentState.position - limit) {
pageCache[key] = null;
}
}
};
changePage = function(title, body, csrfToken, runScripts) {
document.title = title;
document.documentElement.replaceChild(body, document.body);
if (csrfToken != null) {
CSRFToken.update(csrfToken);
}
removeNoscriptTags();
if (runScripts) {
executeScriptTags();
}
currentState = window.history.state;
return triggerEvent('page:change');
};
executeScriptTags = function() {
var attr, copy, nextSibling, parentNode, script, scripts, _i, _j, _len, _len1, _ref1, _ref2;
scripts = Array.prototype.slice.call(document.body.querySelectorAll('script:not([data-turbolinks-eval="false"])'));
for (_i = 0, _len = scripts.length; _i < _len; _i++) {
script = scripts[_i];
if (!((_ref1 = script.type) === '' || _ref1 === 'text/javascript')) {
continue;
}
copy = document.createElement('script');
_ref2 = script.attributes;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
attr = _ref2[_j];
copy.setAttribute(attr.name, attr.value);
}
copy.appendChild(document.createTextNode(script.innerHTML));
parentNode = script.parentNode, nextSibling = script.nextSibling;
parentNode.removeChild(script);
parentNode.insertBefore(copy, nextSibling);
}
};
removeNoscriptTags = function() {
var noscript, noscriptTags, _i, _len;
noscriptTags = Array.prototype.slice.call(document.body.getElementsByTagName('noscript'));
for (_i = 0, _len = noscriptTags.length; _i < _len; _i++) {
noscript = noscriptTags[_i];
noscript.parentNode.removeChild(noscript);
}
};
reflectNewUrl = function(url) {
if (url !== referer) {
return window.history.pushState({
turbolinks: true,
position: currentState.position + 1
}, '', url);
}
};
reflectRedirectedUrl = function() {
var location, preservedHash;
if (location = xhr.getResponseHeader('X-XHR-Redirected-To')) {
preservedHash = removeHash(location) === location ? document.location.hash : '';
return window.history.replaceState(currentState, '', location + preservedHash);
}
};
rememberCurrentUrl = function() {
return window.history.replaceState({
turbolinks: true,
position: Date.now()
}, '', document.location.href);
};
rememberCurrentState = function() {
return currentState = window.history.state;
};
recallScrollPosition = function(page) {
return window.scrollTo(page.positionX, page.positionY);
};
resetScrollPosition = function() {
return window.scrollTo(0, 0);
};
removeHash = function(url) {
var link;
link = url;
if (url.href == null) {
link = document.createElement('A');
link.href = url;
}
return link.href.replace(link.hash, '');
};
triggerEvent = function(name) {
var event;
event = document.createEvent('Events');
event.initEvent(name, true, true);
return document.dispatchEvent(event);
};
pageChangePrevented = function() {
return !triggerEvent('page:before-change');
};
processResponse = function() {
var assetsChanged, clientOrServerError, doc, extractTrackAssets, intersection, validContent;
clientOrServerError = function() {
var _ref1;
return (400 <= (_ref1 = xhr.status) && _ref1 < 600);
};
validContent = function() {
return xhr.getResponseHeader('Content-Type').match(/^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/);
};
extractTrackAssets = function(doc) {
var node, _i, _len, _ref1, _results;
_ref1 = doc.head.childNodes;
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
node = _ref1[_i];
if ((typeof node.getAttribute === "function" ? node.getAttribute('data-turbolinks-track') : void 0) != null) {
_results.push(node.src || node.href);
}
}
return _results;
};
assetsChanged = function(doc) {
var fetchedAssets;
loadedAssets || (loadedAssets = extractTrackAssets(document));
fetchedAssets = extractTrackAssets(doc);
return fetchedAssets.length !== loadedAssets.length || intersection(fetchedAssets, loadedAssets).length !== loadedAssets.length;
};
intersection = function(a, b) {
var value, _i, _len, _ref1, _results;
if (a.length > b.length) {
_ref1 = [b, a], a = _ref1[0], b = _ref1[1];
}
_results = [];
for (_i = 0, _len = a.length; _i < _len; _i++) {
value = a[_i];
if (__indexOf.call(b, value) >= 0) {
_results.push(value);
}
}
return _results;
};
if (!clientOrServerError() && validContent()) {
doc = createDocument(xhr.responseText);
if (doc && !assetsChanged(doc)) {
return doc;
}
}
};
extractTitleAndBody = function(doc) {
var title;
title = doc.querySelector('title');
return [title != null ? title.textContent : void 0, doc.body, CSRFToken.get(doc).token, 'runScripts'];
};
CSRFToken = {
get: function(doc) {
var tag;
if (doc == null) {
doc = document;
}
return {
node: tag = doc.querySelector('meta[name="csrf-token"]'),
token: tag != null ? typeof tag.getAttribute === "function" ? tag.getAttribute('content') : void 0 : void 0
};
},
update: function(latest) {
var current;
current = this.get();
if ((current.token != null) && (latest != null) && current.token !== latest) {
return current.node.setAttribute('content', latest);
}
}
};
browserCompatibleDocumentParser = function() {
var createDocumentUsingDOM, createDocumentUsingParser, createDocumentUsingWrite, e, testDoc, _ref1;
createDocumentUsingParser = function(html) {
return (new DOMParser).parseFromString(html, 'text/html');
};
createDocumentUsingDOM = function(html) {
var doc;
doc = document.implementation.createHTMLDocument('');
doc.documentElement.innerHTML = html;
return doc;
};
createDocumentUsingWrite = function(html) {
var doc;
doc = document.implementation.createHTMLDocument('');
doc.open('replace');
doc.write(html);
doc.close();
return doc;
};
try {
if (window.DOMParser) {
testDoc = createDocumentUsingParser('<html><body><p>test');
return createDocumentUsingParser;
}
} catch (_error) {
e = _error;
testDoc = createDocumentUsingDOM('<html><body><p>test');
return createDocumentUsingDOM;
} finally {
if ((testDoc != null ? (_ref1 = testDoc.body) != null ? _ref1.childNodes.length : void 0 : void 0) !== 1) {
return createDocumentUsingWrite;
}
}
};
installClickHandlerLast = function(event) {
if (!event.defaultPrevented) {
document.removeEventListener('click', handleClick, false);
return document.addEventListener('click', handleClick, false);
}
};
handleClick = function(event) {
var link;
if (!event.defaultPrevented) {
link = extractLink(event);
if (link.nodeName === 'A' && !ignoreClick(event, link)) {
if (!pageChangePrevented()) {
visit(link.href);
}
return event.preventDefault();
}
}
};
extractLink = function(event) {
var link;
link = event.target;
while (!(!link.parentNode || link.nodeName === 'A')) {
link = link.parentNode;
}
return link;
};
crossOriginLink = function(link) {
return location.protocol !== link.protocol || location.host !== link.host;
};
anchoredLink = function(link) {
return ((link.hash && removeHash(link)) === removeHash(location)) || (link.href === location.href + '#');
};
nonHtmlLink = function(link) {
var url;
url = removeHash(link);
return url.match(/\.[a-z]+(\?.*)?$/g) && !url.match(/\.html?(\?.*)?$/g);
};
noTurbolink = function(link) {
var ignore;
while (!(ignore || link === document)) {
ignore = link.getAttribute('data-no-turbolink') != null;
link = link.parentNode;
}
return ignore;
};
targetLink = function(link) {
return link.target.length !== 0;
};
nonStandardClick = function(event) {
return event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
};
ignoreClick = function(event, link) {
return crossOriginLink(link) || anchoredLink(link) || nonHtmlLink(link) || noTurbolink(link) || targetLink(link) || nonStandardClick(event);
};
initializeTurbolinks = function() {
rememberCurrentUrl();
rememberCurrentState();
createDocument = browserCompatibleDocumentParser();
document.addEventListener('click', installClickHandlerLast, true);
return window.addEventListener('popstate', function(event) {
var state;
state = event.state;
if (state != null ? state.turbolinks : void 0) {
if (pageCache[state.position]) {
return fetchHistory(state.position);
} else {
return visit(event.target.location.href);
}
}
}, false);
};
browserSupportsPushState = window.history && window.history.pushState && window.history.replaceState && window.history.state !== void 0;
browserIsntBuggy = !navigator.userAgent.match(/CriOS\//);
requestMethodIsSafe = requestMethod === 'GET' || requestMethod === '';
if (browserSupportsPushState && browserIsntBuggy && requestMethodIsSafe) {
visit = function(url) {
referer = document.location.href;
cacheCurrentPage();
return fetchReplacement(url);
};
initializeTurbolinks();
} else {
visit = function(url) {
return document.location.href = url;
};
}
this.Turbolinks = {
visit: visit,
pagesCached: pagesCached
};
}).call(this);