1252 lines
34 KiB
JavaScript
1252 lines
34 KiB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Pjax = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||||
|
|
var executeScripts = require("./lib/execute-scripts");
|
|||
|
|
var forEachEls = require("./lib/foreach-els");
|
|||
|
|
var parseOptions = require("./lib/parse-options");
|
|||
|
|
var switches = require("./lib/switches");
|
|||
|
|
var newUid = require("./lib/uniqueid");
|
|||
|
|
|
|||
|
|
var on = require("./lib/events/on");
|
|||
|
|
var trigger = require("./lib/events/trigger");
|
|||
|
|
|
|||
|
|
var clone = require("./lib/util/clone");
|
|||
|
|
var contains = require("./lib/util/contains");
|
|||
|
|
var extend = require("./lib/util/extend");
|
|||
|
|
var noop = require("./lib/util/noop");
|
|||
|
|
|
|||
|
|
var Pjax = function(options) {
|
|||
|
|
this.state = {
|
|||
|
|
numPendingSwitches: 0,
|
|||
|
|
href: null,
|
|||
|
|
options: null
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
this.options = parseOptions(options);
|
|||
|
|
this.log("Pjax options", this.options);
|
|||
|
|
|
|||
|
|
if (this.options.scrollRestoration && "scrollRestoration" in history) {
|
|||
|
|
history.scrollRestoration = "manual";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.maxUid = this.lastUid = newUid();
|
|||
|
|
|
|||
|
|
this.parseDOM(document);
|
|||
|
|
|
|||
|
|
on(
|
|||
|
|
window,
|
|||
|
|
"popstate",
|
|||
|
|
function(st) {
|
|||
|
|
if (st.state) {
|
|||
|
|
var opt = clone(this.options);
|
|||
|
|
opt.url = st.state.url;
|
|||
|
|
opt.title = st.state.title;
|
|||
|
|
// Since state already exists, prevent it from being pushed again
|
|||
|
|
opt.history = false;
|
|||
|
|
opt.scrollPos = st.state.scrollPos;
|
|||
|
|
if (st.state.uid < this.lastUid) {
|
|||
|
|
opt.backward = true;
|
|||
|
|
} else {
|
|||
|
|
opt.forward = true;
|
|||
|
|
}
|
|||
|
|
this.lastUid = st.state.uid;
|
|||
|
|
|
|||
|
|
// @todo implement history cache here, based on uid
|
|||
|
|
this.loadUrl(st.state.url, opt);
|
|||
|
|
}
|
|||
|
|
}.bind(this)
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
Pjax.switches = switches;
|
|||
|
|
|
|||
|
|
Pjax.prototype = {
|
|||
|
|
log: require("./lib/proto/log"),
|
|||
|
|
|
|||
|
|
getElements: function(el) {
|
|||
|
|
return el.querySelectorAll(this.options.elements);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
parseDOM: function(el) {
|
|||
|
|
var parseElement = require("./lib/proto/parse-element");
|
|||
|
|
forEachEls(this.getElements(el), parseElement, this);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
refresh: function(el) {
|
|||
|
|
this.parseDOM(el || document);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
reload: function() {
|
|||
|
|
window.location.reload();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
attachLink: require("./lib/proto/attach-link"),
|
|||
|
|
|
|||
|
|
attachForm: require("./lib/proto/attach-form"),
|
|||
|
|
|
|||
|
|
forEachSelectors: function(cb, context, DOMcontext) {
|
|||
|
|
return require("./lib/foreach-selectors").bind(this)(
|
|||
|
|
this.options.selectors,
|
|||
|
|
cb,
|
|||
|
|
context,
|
|||
|
|
DOMcontext
|
|||
|
|
);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
switchSelectors: function(selectors, fromEl, toEl, options) {
|
|||
|
|
return require("./lib/switches-selectors").bind(this)(
|
|||
|
|
this.options.switches,
|
|||
|
|
this.options.switchesOptions,
|
|||
|
|
selectors,
|
|||
|
|
fromEl,
|
|||
|
|
toEl,
|
|||
|
|
options
|
|||
|
|
);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
latestChance: function(href) {
|
|||
|
|
window.location = href;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onSwitch: function() {
|
|||
|
|
trigger(window, "resize scroll");
|
|||
|
|
|
|||
|
|
this.state.numPendingSwitches--;
|
|||
|
|
|
|||
|
|
// debounce calls, so we only run this once after all switches are finished.
|
|||
|
|
if (this.state.numPendingSwitches === 0) {
|
|||
|
|
this.afterAllSwitches();
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
loadContent: function(html, options) {
|
|||
|
|
if (typeof html !== "string") {
|
|||
|
|
trigger(document, "pjax:complete pjax:error", options);
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var tmpEl = document.implementation.createHTMLDocument("pjax");
|
|||
|
|
|
|||
|
|
// parse HTML attributes to copy them
|
|||
|
|
// since we are forced to use documentElement.innerHTML (outerHTML can't be used for <html>)
|
|||
|
|
var htmlRegex = /<html[^>]+>/gi;
|
|||
|
|
var htmlAttribsRegex = /\s?[a-z:]+(?:=['"][^'">]+['"])*/gi;
|
|||
|
|
var matches = html.match(htmlRegex);
|
|||
|
|
if (matches && matches.length) {
|
|||
|
|
matches = matches[0].match(htmlAttribsRegex);
|
|||
|
|
if (matches.length) {
|
|||
|
|
matches.shift();
|
|||
|
|
matches.forEach(function(htmlAttrib) {
|
|||
|
|
var attr = htmlAttrib.trim().split("=");
|
|||
|
|
if (attr.length === 1) {
|
|||
|
|
tmpEl.documentElement.setAttribute(attr[0], true);
|
|||
|
|
} else {
|
|||
|
|
tmpEl.documentElement.setAttribute(attr[0], attr[1].slice(1, -1));
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tmpEl.documentElement.innerHTML = html;
|
|||
|
|
this.log(
|
|||
|
|
"load content",
|
|||
|
|
tmpEl.documentElement.attributes,
|
|||
|
|
tmpEl.documentElement.innerHTML.length
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// Clear out any focused controls before inserting new page contents.
|
|||
|
|
if (
|
|||
|
|
document.activeElement &&
|
|||
|
|
contains(document, this.options.selectors, document.activeElement)
|
|||
|
|
) {
|
|||
|
|
try {
|
|||
|
|
document.activeElement.blur();
|
|||
|
|
} catch (e) {} // eslint-disable-line no-empty
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.switchSelectors(this.options.selectors, tmpEl, document, options);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
abortRequest: require("./lib/abort-request"),
|
|||
|
|
|
|||
|
|
doRequest: require("./lib/send-request"),
|
|||
|
|
|
|||
|
|
handleResponse: require("./lib/proto/handle-response"),
|
|||
|
|
|
|||
|
|
loadUrl: function(href, options) {
|
|||
|
|
options =
|
|||
|
|
typeof options === "object"
|
|||
|
|
? extend({}, this.options, options)
|
|||
|
|
: clone(this.options);
|
|||
|
|
|
|||
|
|
this.log("load href", href, options);
|
|||
|
|
|
|||
|
|
// Abort any previous request
|
|||
|
|
this.abortRequest(this.request);
|
|||
|
|
|
|||
|
|
trigger(document, "pjax:send", options);
|
|||
|
|
|
|||
|
|
// Do the request
|
|||
|
|
this.request = this.doRequest(
|
|||
|
|
href,
|
|||
|
|
options,
|
|||
|
|
this.handleResponse.bind(this)
|
|||
|
|
);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
afterAllSwitches: function() {
|
|||
|
|
// FF bug: Won’t autofocus fields that are inserted via JS.
|
|||
|
|
// This behavior is incorrect. So if theres no current focus, autofocus
|
|||
|
|
// the last field.
|
|||
|
|
//
|
|||
|
|
// http://www.w3.org/html/wg/drafts/html/master/forms.html
|
|||
|
|
var autofocusEl = Array.prototype.slice
|
|||
|
|
.call(document.querySelectorAll("[autofocus]"))
|
|||
|
|
.pop();
|
|||
|
|
if (autofocusEl && document.activeElement !== autofocusEl) {
|
|||
|
|
autofocusEl.focus();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// execute scripts when DOM have been completely updated
|
|||
|
|
this.options.selectors.forEach(function(selector) {
|
|||
|
|
forEachEls(document.querySelectorAll(selector), function(el) {
|
|||
|
|
executeScripts(el);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
var state = this.state;
|
|||
|
|
|
|||
|
|
if (state.options.history) {
|
|||
|
|
if (!window.history.state) {
|
|||
|
|
this.lastUid = this.maxUid = newUid();
|
|||
|
|
window.history.replaceState(
|
|||
|
|
{
|
|||
|
|
url: window.location.href,
|
|||
|
|
title: document.title,
|
|||
|
|
uid: this.maxUid,
|
|||
|
|
scrollPos: [0, 0]
|
|||
|
|
},
|
|||
|
|
document.title
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Update browser history
|
|||
|
|
this.lastUid = this.maxUid = newUid();
|
|||
|
|
|
|||
|
|
window.history.pushState(
|
|||
|
|
{
|
|||
|
|
url: state.href,
|
|||
|
|
title: state.options.title,
|
|||
|
|
uid: this.maxUid,
|
|||
|
|
scrollPos: [0, 0]
|
|||
|
|
},
|
|||
|
|
state.options.title,
|
|||
|
|
state.href
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.forEachSelectors(function(el) {
|
|||
|
|
this.parseDOM(el);
|
|||
|
|
}, this);
|
|||
|
|
|
|||
|
|
// Fire Events
|
|||
|
|
trigger(document, "pjax:complete pjax:success", state.options);
|
|||
|
|
|
|||
|
|
if (typeof state.options.analytics === "function") {
|
|||
|
|
state.options.analytics();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (state.options.history) {
|
|||
|
|
// First parse url and check for hash to override scroll
|
|||
|
|
var a = document.createElement("a");
|
|||
|
|
a.href = this.state.href;
|
|||
|
|
if (a.hash) {
|
|||
|
|
var name = a.hash.slice(1);
|
|||
|
|
name = decodeURIComponent(name);
|
|||
|
|
|
|||
|
|
var curtop = 0;
|
|||
|
|
var target =
|
|||
|
|
document.getElementById(name) || document.getElementsByName(name)[0];
|
|||
|
|
if (target) {
|
|||
|
|
// http://stackoverflow.com/questions/8111094/cross-browser-javascript-function-to-find-actual-position-of-an-element-in-page
|
|||
|
|
if (target.offsetParent) {
|
|||
|
|
do {
|
|||
|
|
curtop += target.offsetTop;
|
|||
|
|
|
|||
|
|
target = target.offsetParent;
|
|||
|
|
} while (target);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
window.scrollTo(0, curtop);
|
|||
|
|
} else if (state.options.scrollTo !== false) {
|
|||
|
|
// Scroll page to top on new page load
|
|||
|
|
if (state.options.scrollTo.length > 1) {
|
|||
|
|
window.scrollTo(state.options.scrollTo[0], state.options.scrollTo[1]);
|
|||
|
|
} else {
|
|||
|
|
window.scrollTo(0, state.options.scrollTo);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else if (state.options.scrollRestoration && state.options.scrollPos) {
|
|||
|
|
window.scrollTo(state.options.scrollPos[0], state.options.scrollPos[1]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.state = {
|
|||
|
|
numPendingSwitches: 0,
|
|||
|
|
href: null,
|
|||
|
|
options: null
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
Pjax.isSupported = require("./lib/is-supported");
|
|||
|
|
|
|||
|
|
// arguably could do `if( require("./lib/is-supported")()) {` but that might be a little to simple
|
|||
|
|
if (Pjax.isSupported()) {
|
|||
|
|
module.exports = Pjax;
|
|||
|
|
}
|
|||
|
|
// if there isn’t required browser functions, returning stupid api
|
|||
|
|
else {
|
|||
|
|
var stupidPjax = noop;
|
|||
|
|
for (var key in Pjax.prototype) {
|
|||
|
|
if (
|
|||
|
|
Pjax.prototype.hasOwnProperty(key) &&
|
|||
|
|
typeof Pjax.prototype[key] === "function"
|
|||
|
|
) {
|
|||
|
|
stupidPjax[key] = noop;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = stupidPjax;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
},{"./lib/abort-request":2,"./lib/events/on":4,"./lib/events/trigger":5,"./lib/execute-scripts":6,"./lib/foreach-els":7,"./lib/foreach-selectors":8,"./lib/is-supported":9,"./lib/parse-options":10,"./lib/proto/attach-form":11,"./lib/proto/attach-link":12,"./lib/proto/handle-response":13,"./lib/proto/log":14,"./lib/proto/parse-element":15,"./lib/send-request":16,"./lib/switches":18,"./lib/switches-selectors":17,"./lib/uniqueid":19,"./lib/util/clone":20,"./lib/util/contains":21,"./lib/util/extend":22,"./lib/util/noop":23}],2:[function(require,module,exports){
|
|||
|
|
var noop = require("./util/noop");
|
|||
|
|
|
|||
|
|
module.exports = function(request) {
|
|||
|
|
if (request && request.readyState < 4) {
|
|||
|
|
request.onreadystatechange = noop;
|
|||
|
|
request.abort();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"./util/noop":23}],3:[function(require,module,exports){
|
|||
|
|
module.exports = function(el) {
|
|||
|
|
var code = el.text || el.textContent || el.innerHTML || "";
|
|||
|
|
var src = el.src || "";
|
|||
|
|
var parent =
|
|||
|
|
el.parentNode || document.querySelector("head") || document.documentElement;
|
|||
|
|
var script = document.createElement("script");
|
|||
|
|
|
|||
|
|
if (code.match("document.write")) {
|
|||
|
|
if (console && console.log) {
|
|||
|
|
console.log(
|
|||
|
|
"Script contains document.write. Can’t be executed correctly. Code skipped ",
|
|||
|
|
el
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
script.type = "text/javascript";
|
|||
|
|
script.id = el.id;
|
|||
|
|
|
|||
|
|
/* istanbul ignore if */
|
|||
|
|
if (src !== "") {
|
|||
|
|
script.src = src;
|
|||
|
|
script.async = false; // force synchronous loading of peripheral JS
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (code !== "") {
|
|||
|
|
try {
|
|||
|
|
script.appendChild(document.createTextNode(code));
|
|||
|
|
} catch (e) {
|
|||
|
|
/* istanbul ignore next */
|
|||
|
|
// old IEs have funky script nodes
|
|||
|
|
script.text = code;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// execute
|
|||
|
|
parent.appendChild(script);
|
|||
|
|
// avoid pollution only in head or body tags
|
|||
|
|
if (
|
|||
|
|
(parent instanceof HTMLHeadElement || parent instanceof HTMLBodyElement) &&
|
|||
|
|
parent.contains(script)
|
|||
|
|
) {
|
|||
|
|
parent.removeChild(script);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{}],4:[function(require,module,exports){
|
|||
|
|
var forEachEls = require("../foreach-els");
|
|||
|
|
|
|||
|
|
module.exports = function(els, events, listener, useCapture) {
|
|||
|
|
events = typeof events === "string" ? events.split(" ") : events;
|
|||
|
|
|
|||
|
|
events.forEach(function(e) {
|
|||
|
|
forEachEls(els, function(el) {
|
|||
|
|
el.addEventListener(e, listener, useCapture);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"../foreach-els":7}],5:[function(require,module,exports){
|
|||
|
|
var forEachEls = require("../foreach-els");
|
|||
|
|
|
|||
|
|
module.exports = function(els, events, opts) {
|
|||
|
|
events = typeof events === "string" ? events.split(" ") : events;
|
|||
|
|
|
|||
|
|
events.forEach(function(e) {
|
|||
|
|
var event;
|
|||
|
|
event = document.createEvent("HTMLEvents");
|
|||
|
|
event.initEvent(e, true, true);
|
|||
|
|
event.eventName = e;
|
|||
|
|
if (opts) {
|
|||
|
|
Object.keys(opts).forEach(function(key) {
|
|||
|
|
event[key] = opts[key];
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
forEachEls(els, function(el) {
|
|||
|
|
var domFix = false;
|
|||
|
|
if (!el.parentNode && el !== document && el !== window) {
|
|||
|
|
// THANK YOU IE (9/10/11)
|
|||
|
|
// dispatchEvent doesn't work if the element is not in the DOM
|
|||
|
|
domFix = true;
|
|||
|
|
document.body.appendChild(el);
|
|||
|
|
}
|
|||
|
|
el.dispatchEvent(event);
|
|||
|
|
if (domFix) {
|
|||
|
|
el.parentNode.removeChild(el);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"../foreach-els":7}],6:[function(require,module,exports){
|
|||
|
|
var forEachEls = require("./foreach-els");
|
|||
|
|
var evalScript = require("./eval-script");
|
|||
|
|
// Finds and executes scripts (used for newly added elements)
|
|||
|
|
// Needed since innerHTML does not run scripts
|
|||
|
|
module.exports = function(el) {
|
|||
|
|
if (el.tagName.toLowerCase() === "script") {
|
|||
|
|
evalScript(el);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
forEachEls(el.querySelectorAll("script"), function(script) {
|
|||
|
|
if (!script.type || script.type.toLowerCase() === "text/javascript") {
|
|||
|
|
if (script.parentNode) {
|
|||
|
|
script.parentNode.removeChild(script);
|
|||
|
|
}
|
|||
|
|
evalScript(script);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"./eval-script":3,"./foreach-els":7}],7:[function(require,module,exports){
|
|||
|
|
/* global HTMLCollection: true */
|
|||
|
|
|
|||
|
|
module.exports = function(els, fn, context) {
|
|||
|
|
if (
|
|||
|
|
els instanceof HTMLCollection ||
|
|||
|
|
els instanceof NodeList ||
|
|||
|
|
els instanceof Array
|
|||
|
|
) {
|
|||
|
|
return Array.prototype.forEach.call(els, fn, context);
|
|||
|
|
}
|
|||
|
|
// assume simple DOM element
|
|||
|
|
return fn.call(context, els);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{}],8:[function(require,module,exports){
|
|||
|
|
var forEachEls = require("./foreach-els");
|
|||
|
|
|
|||
|
|
module.exports = function(selectors, cb, context, DOMcontext) {
|
|||
|
|
DOMcontext = DOMcontext || document;
|
|||
|
|
selectors.forEach(function(selector) {
|
|||
|
|
forEachEls(DOMcontext.querySelectorAll(selector), cb, context);
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"./foreach-els":7}],9:[function(require,module,exports){
|
|||
|
|
module.exports = function() {
|
|||
|
|
// Borrowed wholesale from https://github.com/defunkt/jquery-pjax
|
|||
|
|
return (
|
|||
|
|
window.history &&
|
|||
|
|
window.history.pushState &&
|
|||
|
|
window.history.replaceState &&
|
|||
|
|
// pushState isn’t reliable on iOS until 5.
|
|||
|
|
!navigator.userAgent.match(
|
|||
|
|
/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/
|
|||
|
|
)
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{}],10:[function(require,module,exports){
|
|||
|
|
/* global _gaq: true, ga: true */
|
|||
|
|
|
|||
|
|
var defaultSwitches = require("./switches");
|
|||
|
|
|
|||
|
|
module.exports = function(options) {
|
|||
|
|
options = options || {};
|
|||
|
|
options.elements = options.elements || "a[href], form[action]";
|
|||
|
|
options.selectors = options.selectors || ["title", ".js-Pjax"];
|
|||
|
|
options.switches = options.switches || {};
|
|||
|
|
options.switchesOptions = options.switchesOptions || {};
|
|||
|
|
options.history =
|
|||
|
|
typeof options.history === "undefined" ? true : options.history;
|
|||
|
|
options.analytics =
|
|||
|
|
typeof options.analytics === "function" || options.analytics === false
|
|||
|
|
? options.analytics
|
|||
|
|
: defaultAnalytics;
|
|||
|
|
options.scrollTo =
|
|||
|
|
typeof options.scrollTo === "undefined" ? 0 : options.scrollTo;
|
|||
|
|
options.scrollRestoration =
|
|||
|
|
typeof options.scrollRestoration !== "undefined"
|
|||
|
|
? options.scrollRestoration
|
|||
|
|
: true;
|
|||
|
|
options.cacheBust =
|
|||
|
|
typeof options.cacheBust === "undefined" ? true : options.cacheBust;
|
|||
|
|
options.debug = options.debug || false;
|
|||
|
|
options.timeout = options.timeout || 0;
|
|||
|
|
options.currentUrlFullReload =
|
|||
|
|
typeof options.currentUrlFullReload === "undefined"
|
|||
|
|
? false
|
|||
|
|
: options.currentUrlFullReload;
|
|||
|
|
|
|||
|
|
// We can’t replace body.outerHTML or head.outerHTML.
|
|||
|
|
// It creates a bug where a new body or head are created in the DOM.
|
|||
|
|
// If you set head.outerHTML, a new body tag is appended, so the DOM has 2 body nodes, and vice versa
|
|||
|
|
if (!options.switches.head) {
|
|||
|
|
options.switches.head = defaultSwitches.switchElementsAlt;
|
|||
|
|
}
|
|||
|
|
if (!options.switches.body) {
|
|||
|
|
options.switches.body = defaultSwitches.switchElementsAlt;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return options;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/* istanbul ignore next */
|
|||
|
|
function defaultAnalytics() {
|
|||
|
|
if (window._gaq) {
|
|||
|
|
_gaq.push(["_trackPageview"]);
|
|||
|
|
}
|
|||
|
|
if (window.ga) {
|
|||
|
|
ga("send", "pageview", { page: location.pathname, title: document.title });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
},{"./switches":18}],11:[function(require,module,exports){
|
|||
|
|
var on = require("../events/on");
|
|||
|
|
var clone = require("../util/clone");
|
|||
|
|
|
|||
|
|
var attrState = "data-pjax-state";
|
|||
|
|
|
|||
|
|
var formAction = function(el, event) {
|
|||
|
|
if (isDefaultPrevented(event)) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Since loadUrl modifies options and we may add our own modifications below,
|
|||
|
|
// clone it so the changes don't persist
|
|||
|
|
var options = clone(this.options);
|
|||
|
|
|
|||
|
|
// Initialize requestOptions
|
|||
|
|
options.requestOptions = {
|
|||
|
|
requestUrl: el.getAttribute("action") || window.location.href,
|
|||
|
|
requestMethod: el.getAttribute("method") || "GET"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// create a testable virtual link of the form action
|
|||
|
|
var virtLinkElement = document.createElement("a");
|
|||
|
|
virtLinkElement.setAttribute("href", options.requestOptions.requestUrl);
|
|||
|
|
|
|||
|
|
var attrValue = checkIfShouldAbort(virtLinkElement, options);
|
|||
|
|
if (attrValue) {
|
|||
|
|
el.setAttribute(attrState, attrValue);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
event.preventDefault();
|
|||
|
|
|
|||
|
|
if (el.enctype === "multipart/form-data") {
|
|||
|
|
options.requestOptions.formData = new FormData(el);
|
|||
|
|
} else {
|
|||
|
|
options.requestOptions.requestParams = parseFormElements(el);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
el.setAttribute(attrState, "submit");
|
|||
|
|
|
|||
|
|
options.triggerElement = el;
|
|||
|
|
this.loadUrl(virtLinkElement.href, options);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
function parseFormElements(el) {
|
|||
|
|
var requestParams = [];
|
|||
|
|
var formElements = el.elements;
|
|||
|
|
|
|||
|
|
for (var i = 0; i < formElements.length; i++) {
|
|||
|
|
var element = formElements[i];
|
|||
|
|
var tagName = element.tagName.toLowerCase();
|
|||
|
|
// jscs:disable disallowImplicitTypeConversion
|
|||
|
|
if (
|
|||
|
|
!!element.name &&
|
|||
|
|
element.attributes !== undefined &&
|
|||
|
|
tagName !== "button"
|
|||
|
|
) {
|
|||
|
|
// jscs:enable disallowImplicitTypeConversion
|
|||
|
|
var type = element.attributes.type;
|
|||
|
|
|
|||
|
|
if (
|
|||
|
|
!type ||
|
|||
|
|
(type.value !== "checkbox" && type.value !== "radio") ||
|
|||
|
|
element.checked
|
|||
|
|
) {
|
|||
|
|
// Build array of values to submit
|
|||
|
|
var values = [];
|
|||
|
|
|
|||
|
|
if (tagName === "select") {
|
|||
|
|
var opt;
|
|||
|
|
|
|||
|
|
for (var j = 0; j < element.options.length; j++) {
|
|||
|
|
opt = element.options[j];
|
|||
|
|
if (opt.selected && !opt.disabled) {
|
|||
|
|
values.push(opt.hasAttribute("value") ? opt.value : opt.text);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
values.push(element.value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (var k = 0; k < values.length; k++) {
|
|||
|
|
requestParams.push({
|
|||
|
|
name: encodeURIComponent(element.name),
|
|||
|
|
value: encodeURIComponent(values[k])
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return requestParams;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function checkIfShouldAbort(virtLinkElement, options) {
|
|||
|
|
// Ignore external links.
|
|||
|
|
if (
|
|||
|
|
virtLinkElement.protocol !== window.location.protocol ||
|
|||
|
|
virtLinkElement.host !== window.location.host
|
|||
|
|
) {
|
|||
|
|
return "external";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Ignore click if we are on an anchor on the same page
|
|||
|
|
if (
|
|||
|
|
virtLinkElement.hash &&
|
|||
|
|
virtLinkElement.href.replace(virtLinkElement.hash, "") ===
|
|||
|
|
window.location.href.replace(location.hash, "")
|
|||
|
|
) {
|
|||
|
|
return "anchor";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Ignore empty anchor "foo.html#"
|
|||
|
|
if (virtLinkElement.href === window.location.href.split("#")[0] + "#") {
|
|||
|
|
return "anchor-empty";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// if declared as a full reload, just normally submit the form
|
|||
|
|
if (
|
|||
|
|
options.currentUrlFullReload &&
|
|||
|
|
virtLinkElement.href === window.location.href.split("#")[0]
|
|||
|
|
) {
|
|||
|
|
return "reload";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var isDefaultPrevented = function(event) {
|
|||
|
|
return event.defaultPrevented || event.returnValue === false;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
module.exports = function(el) {
|
|||
|
|
var that = this;
|
|||
|
|
|
|||
|
|
el.setAttribute(attrState, "");
|
|||
|
|
|
|||
|
|
on(el, "submit", function(event) {
|
|||
|
|
formAction.call(that, el, event);
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"../events/on":4,"../util/clone":20}],12:[function(require,module,exports){
|
|||
|
|
var on = require("../events/on");
|
|||
|
|
var clone = require("../util/clone");
|
|||
|
|
|
|||
|
|
var attrState = "data-pjax-state";
|
|||
|
|
|
|||
|
|
var linkAction = function(el, event) {
|
|||
|
|
if (isDefaultPrevented(event)) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Since loadUrl modifies options and we may add our own modifications below,
|
|||
|
|
// clone it so the changes don't persist
|
|||
|
|
var options = clone(this.options);
|
|||
|
|
|
|||
|
|
// create a testable virtual link of the form action
|
|||
|
|
var virtLinkElement = document.createElement("a");
|
|||
|
|
if (el.tagName === "A") {
|
|||
|
|
virtLinkElement.setAttribute("href", el.getAttribute("href"));
|
|||
|
|
} else {
|
|||
|
|
// not an anchor element
|
|||
|
|
if (el.tagName !== "AREA") {
|
|||
|
|
// not an area element
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
virtLinkElement.setAttribute("href", el.getAttribute("href"));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var attrValue = checkIfShouldAbort(virtLinkElement, options);
|
|||
|
|
if (attrValue) {
|
|||
|
|
el.setAttribute(attrState, attrValue);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
event.preventDefault();
|
|||
|
|
|
|||
|
|
el.setAttribute(attrState, "load");
|
|||
|
|
|
|||
|
|
options.triggerElement = el;
|
|||
|
|
this.loadUrl(virtLinkElement.href, options);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
function checkIfShouldAbort(virtLinkElement, options) {
|
|||
|
|
// Ignore external links.
|
|||
|
|
if (
|
|||
|
|
virtLinkElement.protocol !== window.location.protocol ||
|
|||
|
|
virtLinkElement.host !== window.location.host
|
|||
|
|
) {
|
|||
|
|
return "external";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Ignore click if we are on an anchor on the same page
|
|||
|
|
if (
|
|||
|
|
virtLinkElement.hash &&
|
|||
|
|
virtLinkElement.href.replace(virtLinkElement.hash, "") ===
|
|||
|
|
window.location.href.replace(location.hash, "")
|
|||
|
|
) {
|
|||
|
|
return "anchor";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Ignore empty anchor "foo.html#"
|
|||
|
|
if (virtLinkElement.href === window.location.href.split("#")[0] + "#") {
|
|||
|
|
return "anchor-empty";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// if declared as a full reload, just normally submit the form
|
|||
|
|
if (
|
|||
|
|
options.currentUrlFullReload &&
|
|||
|
|
virtLinkElement.href === window.location.href.split("#")[0]
|
|||
|
|
) {
|
|||
|
|
return "reload";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var isDefaultPrevented = function(event) {
|
|||
|
|
return event.defaultPrevented || event.returnValue === false;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
module.exports = function(el) {
|
|||
|
|
var that = this;
|
|||
|
|
|
|||
|
|
el.setAttribute(attrState, "");
|
|||
|
|
|
|||
|
|
on(el, "click", function(event) {
|
|||
|
|
if (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Ignore click if we are not on the main button
|
|||
|
|
if (event.which > 1 || event.button > 0) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
linkAction.call(that, el, event);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
on(el, "keyup", function(event) {
|
|||
|
|
if (event.which === 13 || event.keyCode === 13) {
|
|||
|
|
linkAction.call(that, el, event);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"../events/on":4,"../util/clone":20}],13:[function(require,module,exports){
|
|||
|
|
var clone = require("../util/clone");
|
|||
|
|
var newUid = require("../uniqueid");
|
|||
|
|
var trigger = require("../events/trigger");
|
|||
|
|
|
|||
|
|
module.exports = function(responseText, request, href, options) {
|
|||
|
|
options = clone(options || this.options);
|
|||
|
|
options.request = request;
|
|||
|
|
|
|||
|
|
// Fail if unable to load HTML via AJAX
|
|||
|
|
if (responseText === false) {
|
|||
|
|
trigger(document, "pjax:complete pjax:error", options);
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// push scroll position to history
|
|||
|
|
var currentState = window.history.state || {};
|
|||
|
|
window.history.replaceState(
|
|||
|
|
{
|
|||
|
|
url: currentState.url || window.location.href,
|
|||
|
|
title: currentState.title || document.title,
|
|||
|
|
uid: currentState.uid || newUid(),
|
|||
|
|
scrollPos: [
|
|||
|
|
document.documentElement.scrollTop || document.body.scrollTop,
|
|||
|
|
document.documentElement.scrollLeft || document.body.scrollLeft
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
document.title,
|
|||
|
|
window.location.href
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// Check for redirects
|
|||
|
|
var oldHref = href;
|
|||
|
|
if (request.responseURL) {
|
|||
|
|
if (href !== request.responseURL) {
|
|||
|
|
href = request.responseURL;
|
|||
|
|
}
|
|||
|
|
} else if (request.getResponseHeader("X-PJAX-URL")) {
|
|||
|
|
href = request.getResponseHeader("X-PJAX-URL");
|
|||
|
|
} else if (request.getResponseHeader("X-XHR-Redirected-To")) {
|
|||
|
|
href = request.getResponseHeader("X-XHR-Redirected-To");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Add back the hash if it was stripped off because we stripped it off in `send-request.js`
|
|||
|
|
var a = document.createElement("a");
|
|||
|
|
a.href = oldHref;
|
|||
|
|
var oldHash = a.hash;
|
|||
|
|
a.href = href;
|
|||
|
|
if (oldHash && !a.hash) {
|
|||
|
|
a.hash = oldHash;
|
|||
|
|
href = a.href;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.state.href = href;
|
|||
|
|
this.state.options = options;
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
this.loadContent(responseText, options);
|
|||
|
|
} catch (e) {
|
|||
|
|
trigger(document, "pjax:error", options);
|
|||
|
|
|
|||
|
|
if (!this.options.debug) {
|
|||
|
|
if (console && console.error) {
|
|||
|
|
console.error("Pjax switch fail: ", e);
|
|||
|
|
}
|
|||
|
|
return this.latestChance(href);
|
|||
|
|
} else {
|
|||
|
|
throw e;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"../events/trigger":5,"../uniqueid":19,"../util/clone":20}],14:[function(require,module,exports){
|
|||
|
|
module.exports = function() {
|
|||
|
|
if (this.options.debug && console) {
|
|||
|
|
if (typeof console.log === "function") {
|
|||
|
|
console.log.apply(console, arguments);
|
|||
|
|
}
|
|||
|
|
// IE is weird
|
|||
|
|
else if (console.log) {
|
|||
|
|
console.log(arguments);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{}],15:[function(require,module,exports){
|
|||
|
|
module.exports = function(el) {
|
|||
|
|
switch (el.tagName.toLowerCase()) {
|
|||
|
|
case "a":
|
|||
|
|
// only attach link if el has an href
|
|||
|
|
if (!el.hasAttribute("href")) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (
|
|||
|
|
el.href.indexOf(window.location.protocol + "//" + window.location.host) !==
|
|||
|
|
0
|
|||
|
|
) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (el.target.toLowerCase() === "_blank") {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (el.getAttribute("download") !== null) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.attachLink(el);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case "form":
|
|||
|
|
this.attachForm(el);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
throw "Pjax can only be applied on <a> or <form> submit";
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{}],16:[function(require,module,exports){
|
|||
|
|
var updateQueryString = require("./util/update-query-string");
|
|||
|
|
|
|||
|
|
module.exports = function(location, options, callback) {
|
|||
|
|
options = options || {};
|
|||
|
|
var queryString;
|
|||
|
|
var requestOptions = options.requestOptions || {};
|
|||
|
|
var requestMethod = (requestOptions.requestMethod || "GET").toUpperCase();
|
|||
|
|
var requestParams = requestOptions.requestParams || null;
|
|||
|
|
var formData = requestOptions.formData || null;
|
|||
|
|
var requestPayload = null;
|
|||
|
|
var request = new XMLHttpRequest();
|
|||
|
|
var timeout = options.timeout || 0;
|
|||
|
|
|
|||
|
|
request.onreadystatechange = function() {
|
|||
|
|
if (request.readyState === 4) {
|
|||
|
|
if (request.status === 200) {
|
|||
|
|
callback(request.responseText, request, location, options);
|
|||
|
|
} else if (request.status !== 0) {
|
|||
|
|
callback(null, request, location, options);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
request.onerror = function(e) {
|
|||
|
|
console.log(e);
|
|||
|
|
callback(null, request, location, options);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
request.ontimeout = function() {
|
|||
|
|
callback(null, request, location, options);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// Prepare the request payload for forms, if available
|
|||
|
|
if (requestParams && requestParams.length) {
|
|||
|
|
queryString = requestParams
|
|||
|
|
.map(function(param) {
|
|||
|
|
return param.name + "=" + param.value;
|
|||
|
|
})
|
|||
|
|
.join("&");
|
|||
|
|
|
|||
|
|
switch (requestMethod) {
|
|||
|
|
case "GET":
|
|||
|
|
location = location.split("?")[0];
|
|||
|
|
location += "?";
|
|||
|
|
location += queryString;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case "POST":
|
|||
|
|
requestPayload = queryString;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
} else if (formData) {
|
|||
|
|
requestPayload = formData;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Add a timestamp as part of the query string if cache busting is enabled
|
|||
|
|
if (options.cacheBust) {
|
|||
|
|
location = updateQueryString(location, "t", Date.now());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
request.open(requestMethod, location, true);
|
|||
|
|
request.timeout = timeout;
|
|||
|
|
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
|||
|
|
request.setRequestHeader("X-PJAX", "true");
|
|||
|
|
request.setRequestHeader(
|
|||
|
|
"X-PJAX-Selectors",
|
|||
|
|
JSON.stringify(options.selectors)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// Send the proper header information for POST forms
|
|||
|
|
if (requestPayload && requestMethod === "POST" && !formData) {
|
|||
|
|
request.setRequestHeader(
|
|||
|
|
"Content-Type",
|
|||
|
|
"application/x-www-form-urlencoded"
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
request.send(requestPayload);
|
|||
|
|
|
|||
|
|
return request;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"./util/update-query-string":24}],17:[function(require,module,exports){
|
|||
|
|
var forEachEls = require("./foreach-els");
|
|||
|
|
|
|||
|
|
var defaultSwitches = require("./switches");
|
|||
|
|
|
|||
|
|
module.exports = function(
|
|||
|
|
switches,
|
|||
|
|
switchesOptions,
|
|||
|
|
selectors,
|
|||
|
|
fromEl,
|
|||
|
|
toEl,
|
|||
|
|
options
|
|||
|
|
) {
|
|||
|
|
var switchesQueue = [];
|
|||
|
|
|
|||
|
|
selectors.forEach(function(selector) {
|
|||
|
|
var newEls = fromEl.querySelectorAll(selector);
|
|||
|
|
var oldEls = toEl.querySelectorAll(selector);
|
|||
|
|
if (this.options.debug) {
|
|||
|
|
this.log("Pjax switch", selector, newEls, oldEls);
|
|||
|
|
}
|
|||
|
|
if (newEls.length !== oldEls.length) {
|
|||
|
|
// forEachEls(newEls, function(el) {
|
|||
|
|
// console.log("newEl", el.outerHTML)
|
|||
|
|
// })
|
|||
|
|
// forEachEls(oldEls, function(el) {
|
|||
|
|
// console.log("oldEl", el.outerHTML)
|
|||
|
|
// })
|
|||
|
|
if (this.options.debug) {
|
|||
|
|
this.log("DOM doesn’t look the same on new loaded page: " + selector);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
forEachEls(
|
|||
|
|
newEls,
|
|||
|
|
function(newEl, i) {
|
|||
|
|
var oldEl = oldEls[i];
|
|||
|
|
if (this.options.debug) {
|
|||
|
|
this.log("newEl", newEl, "oldEl", oldEl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var callback = switches[selector]
|
|||
|
|
? switches[selector].bind(this, oldEl, newEl, options, switchesOptions)
|
|||
|
|
: defaultSwitches.outerHTML.bind(
|
|||
|
|
this,
|
|||
|
|
oldEl,
|
|||
|
|
newEl,
|
|||
|
|
options,
|
|||
|
|
switchesOptions
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
switchesQueue.push(callback);
|
|||
|
|
},
|
|||
|
|
this
|
|||
|
|
);
|
|||
|
|
}, this);
|
|||
|
|
|
|||
|
|
this.state.numPendingSwitches = switchesQueue.length;
|
|||
|
|
|
|||
|
|
switchesQueue.forEach(function(queuedSwitch) {
|
|||
|
|
queuedSwitch();
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"./foreach-els":7,"./switches":18}],18:[function(require,module,exports){
|
|||
|
|
var on = require("./events/on");
|
|||
|
|
|
|||
|
|
module.exports = {
|
|||
|
|
outerHTML: function(oldEl, newEl) {
|
|||
|
|
oldEl.outerHTML = newEl.outerHTML;
|
|||
|
|
this.onSwitch();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
innerHTML: function(oldEl, newEl) {
|
|||
|
|
oldEl.innerHTML = newEl.innerHTML;
|
|||
|
|
if (newEl.className === "") {
|
|||
|
|
oldEl.removeAttribute("class");
|
|||
|
|
} else {
|
|||
|
|
oldEl.className = newEl.className;
|
|||
|
|
}
|
|||
|
|
this.onSwitch();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
switchElementsAlt: function(oldEl, newEl) {
|
|||
|
|
oldEl.innerHTML = newEl.innerHTML;
|
|||
|
|
|
|||
|
|
// Copy attributes from the new element to the old one
|
|||
|
|
if (newEl.hasAttributes()) {
|
|||
|
|
var attrs = newEl.attributes;
|
|||
|
|
for (var i = 0; i < attrs.length; i++) {
|
|||
|
|
oldEl.attributes.setNamedItem(attrs[i].cloneNode());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.onSwitch();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// Equivalent to outerHTML(), but doesn't require the new element to have the same ID
|
|||
|
|
replaceNode: function(oldEl, newEl) {
|
|||
|
|
oldEl.parentNode.replaceChild(newEl, oldEl);
|
|||
|
|
this.onSwitch();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
sideBySide: function(oldEl, newEl, options, switchOptions) {
|
|||
|
|
var forEach = Array.prototype.forEach;
|
|||
|
|
var elsToRemove = [];
|
|||
|
|
var elsToAdd = [];
|
|||
|
|
var fragToAppend = document.createDocumentFragment();
|
|||
|
|
var animationEventNames = [
|
|||
|
|
"animationend",
|
|||
|
|
"webkitAnimationEnd",
|
|||
|
|
"MSAnimationEnd",
|
|||
|
|
"oanimationend"
|
|||
|
|
];
|
|||
|
|
var animated = false;
|
|||
|
|
var dummyEnded = function() {
|
|||
|
|
if (animated) {
|
|||
|
|
this.onSwitch();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
switchOptions = switchOptions || {};
|
|||
|
|
|
|||
|
|
forEach.call(oldEl.childNodes, function(el) {
|
|||
|
|
elsToRemove.push(el);
|
|||
|
|
if (el.classList && !el.classList.contains("js-Pjax-remove")) {
|
|||
|
|
// Push existing class
|
|||
|
|
if (el.hasAttribute("data-pjax-classes")) {
|
|||
|
|
el.className = el.className
|
|||
|
|
.replace(el.getAttribute("data-pjax-classes"), "")
|
|||
|
|
.trim();
|
|||
|
|
el.removeAttribute("data-pjax-classes");
|
|||
|
|
}
|
|||
|
|
el.classList.add("js-Pjax-remove");
|
|||
|
|
if (switchOptions.callbacks && switchOptions.callbacks.removeElement) {
|
|||
|
|
switchOptions.callbacks.removeElement(el);
|
|||
|
|
}
|
|||
|
|
if (switchOptions.classNames) {
|
|||
|
|
el.className += " " + switchOptions.classNames.remove;
|
|||
|
|
animated = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
forEach.call(newEl.childNodes, function(el) {
|
|||
|
|
if (el.classList) {
|
|||
|
|
var addClass = "";
|
|||
|
|
if (switchOptions.classNames) {
|
|||
|
|
addClass = " " + switchOptions.classNames.add;
|
|||
|
|
}
|
|||
|
|
if (switchOptions.callbacks && switchOptions.callbacks.addElement) {
|
|||
|
|
switchOptions.callbacks.addElement(el);
|
|||
|
|
}
|
|||
|
|
if (el.className.length > 0) {
|
|||
|
|
el.setAttribute("data-pjax-classes", addClass);
|
|||
|
|
addClass = " " + el.className + addClass;
|
|||
|
|
}
|
|||
|
|
el.className = addClass;
|
|||
|
|
elsToAdd.push(el);
|
|||
|
|
fragToAppend.appendChild(el);
|
|||
|
|
animated = true;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// Pass all elements to be added
|
|||
|
|
oldEl.appendChild(fragToAppend);
|
|||
|
|
|
|||
|
|
// What to do when the animation ends
|
|||
|
|
var onAnimationEnd = function(e) {
|
|||
|
|
if (e.target.classList.contains("js-Pjax-remove")) {
|
|||
|
|
// Remove old elements
|
|||
|
|
if (e.target.parentNode) {
|
|||
|
|
e.target.parentNode.removeChild(e.target);
|
|||
|
|
}
|
|||
|
|
dummyEnded.apply(this);
|
|||
|
|
} else {
|
|||
|
|
// Remove class of new elements
|
|||
|
|
e.target.className = e.target.className
|
|||
|
|
.replace(switchOptions.classNames.add, "")
|
|||
|
|
.trim();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (animated) {
|
|||
|
|
on(oldEl, animationEventNames, onAnimationEnd.bind(this));
|
|||
|
|
} else {
|
|||
|
|
this.onSwitch();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{"./events/on":4}],19:[function(require,module,exports){
|
|||
|
|
module.exports = function() {
|
|||
|
|
return Date.now();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{}],20:[function(require,module,exports){
|
|||
|
|
module.exports = function(obj) {
|
|||
|
|
if (null === obj || "object" !== typeof obj) {
|
|||
|
|
return obj;
|
|||
|
|
}
|
|||
|
|
var copy = obj.constructor();
|
|||
|
|
for (var attr in obj) {
|
|||
|
|
if (obj.hasOwnProperty(attr)) {
|
|||
|
|
copy[attr] = obj[attr];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return copy;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{}],21:[function(require,module,exports){
|
|||
|
|
module.exports = function contains(doc, selectors, el) {
|
|||
|
|
for (var i = 0; i < selectors.length; i++) {
|
|||
|
|
var selectedEls = doc.querySelectorAll(selectors[i]);
|
|||
|
|
for (var j = 0; j < selectedEls.length; j++) {
|
|||
|
|
if (selectedEls[j] === el) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{}],22:[function(require,module,exports){
|
|||
|
|
module.exports = function(target) {
|
|||
|
|
if (target == null) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var to = Object(target);
|
|||
|
|
|
|||
|
|
for (var i = 1; i < arguments.length; i++) {
|
|||
|
|
var source = arguments[i];
|
|||
|
|
|
|||
|
|
if (source != null) {
|
|||
|
|
for (var key in source) {
|
|||
|
|
// Avoid bugs when hasOwnProperty is shadowed
|
|||
|
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|||
|
|
to[key] = source[key];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return to;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{}],23:[function(require,module,exports){
|
|||
|
|
module.exports = function() {};
|
|||
|
|
|
|||
|
|
},{}],24:[function(require,module,exports){
|
|||
|
|
module.exports = function(uri, key, value) {
|
|||
|
|
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
|
|||
|
|
var separator = uri.indexOf("?") !== -1 ? "&" : "?";
|
|||
|
|
if (uri.match(re)) {
|
|||
|
|
return uri.replace(re, "$1" + key + "=" + value + "$2");
|
|||
|
|
} else {
|
|||
|
|
return uri + separator + key + "=" + value;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
},{}]},{},[1])(1)
|
|||
|
|
});
|