Update intercooler.js

This commit is contained in:
Jason McBrayer 2020-07-08 13:24:00 -04:00
parent adc65f8d5a
commit 012c0b74c1
1 changed files with 244 additions and 115 deletions

View File

@ -4,7 +4,7 @@
define(["jquery"], function (a0) {
return (root['Intercooler'] = factory(a0));
});
} else if (typeof exports === 'object') {
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
@ -24,7 +24,7 @@ var Intercooler = Intercooler || (function() {
// work around zepto build issue TODO - fix me
if((typeof Zepto !== "undefined") && ($ == null)) {
$ = Zepto
window["$"] = Zepto
}
//--------------------------------------------------
@ -68,7 +68,7 @@ var Intercooler = Intercooler || (function() {
return false;
}
return adest.slice(0, asrc.length).join("/") == asrc.join("/") ||
asrc.slice(0, adest.length).join("/") == adest.join("/");
asrc.slice(0, adest.length).join("/") == adest.join("/");
};
//============================================================
@ -88,9 +88,10 @@ var Intercooler = Intercooler || (function() {
}
function hideIndicator(elt) {
if (elt.data('ic-use-transition')) {
if (elt.data('ic-use-transition') || elt.data('ic-indicator-cleared')) {
elt.data('ic-use-transition', null);
elt.addClass('ic-use-transition');
elt.data('ic-indicator-cleared', true);
} else {
elt.hide();
}
@ -259,6 +260,11 @@ var Intercooler = Intercooler || (function() {
document.title = xhr.getResponseHeader("X-IC-Title");
}
if (xhr.getResponseHeader("X-IC-Title-Encoded")) {
var decodedTitle = decodeURIComponent((xhr.getResponseHeader("X-IC-Title-Encoded")).replace(/\+/g, '%20'));
document.title = decodedTitle;
}
if (xhr.getResponseHeader("X-IC-Refresh")) {
var pathsToRefresh = xhr.getResponseHeader("X-IC-Refresh").split(",");
log(elt, "X-IC-Refresh: refreshing " + pathsToRefresh, "DEBUG");
@ -351,14 +357,19 @@ var Intercooler = Intercooler || (function() {
function beforeRequest(elt) {
elt.addClass('disabled');
elt.addClass('ic-request-in-flight');
elt.data('ic-request-in-flight', true);
}
function requestCleanup(indicator, elt) {
function requestCleanup(indicator, globalIndicator, elt) {
if (indicator.length > 0) {
hideIndicator(indicator);
}
if (globalIndicator.length > 0) {
hideIndicator(globalIndicator);
}
elt.removeClass('disabled');
elt.removeClass('ic-request-in-flight');
elt.data('ic-request-in-flight', false);
if (elt.data('ic-next-request')) {
elt.data('ic-next-request')["req"]();
@ -404,19 +415,19 @@ var Intercooler = Intercooler || (function() {
var names = [];
var values = [];
if (args) {
for (var i = 0; i < args.length; i++) {
names.push(args[i][0]);
values.push(args[i][1]);
}
for (var i = 0; i < args.length; i++) {
names.push(args[i][0]);
values.push(args[i][1]);
}
}
if (isIdentifier(script)) {
return window[script].apply(this, values);
return window[script].apply(this, values);
} else {
var outerfunc = window["eval"].call(
window,
'(function (' + names.join(", ") + ') {' + script + '})'
);
return outerfunc.apply(this, values);
var outerfunc = window["eval"].call(
window,
'(function (' + names.join(", ") + ') {' + script + '})'
);
return outerfunc.apply(this, values);
}
}
@ -439,12 +450,35 @@ var Intercooler = Intercooler || (function() {
return msg;
}
function getLocalURL(baseURL, paramsToPush, data) {
if (paramsToPush) {
baseURL = baseURL + "?";
var vars = {};
data.replace(/([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
$(paramsToPush.split(",")).each(function(index) {
var param = $.trim(this);
var value = vars[param] || "";
baseURL += (index == 0) ? "" : "&";
baseURL += param + "=" + value;
});
}
return baseURL;
}
function handleRemoteRequest(elt, type, url, data, success) {
beforeRequest(elt);
data = replaceOrAddMethod(data, type);
// Global spinner support
var globalIndicator = findGlobalIndicator(elt);
if (globalIndicator && globalIndicator.length > 0) {
showIndicator(globalIndicator);
}
// Spinner support
var indicator = findIndicator(elt);
if (indicator.length > 0) {
@ -479,17 +513,18 @@ var Intercooler = Intercooler || (function() {
}
maybeInvokeLocalAction(elt, "-beforeSend");
},
success: function(data, textStatus, xhr) {
triggerEvent(elt, "success.ic", [elt, data, textStatus, xhr, requestId]);
success: function(responseData, textStatus, xhr) {
triggerEvent(elt, "success.ic", [elt, responseData, textStatus, xhr, requestId]);
log(elt, "AJAX request " + requestId + " was successful.", "DEBUG");
var onSuccess = closestAttrValue(elt, 'ic-on-success');
if (onSuccess) {
if (globalEval(onSuccess, [["elt", elt], ["data", data], ["textStatus", textStatus], ["xhr", xhr]]) == false) {
if (globalEval(onSuccess, [["elt", elt], ["data", responseData], ["textStatus", textStatus], ["xhr", xhr]]) == false) {
return;
}
}
var beforeHeaders = new Date();
var oldTitle = document.title;
try {
if (processHeaders(elt, xhr)) {
log(elt, "Processed headers for request " + requestId + " in " + (new Date() - beforeHeaders) + "ms", "DEBUG");
@ -497,10 +532,12 @@ var Intercooler = Intercooler || (function() {
if (xhr.getResponseHeader("X-IC-PushURL") || closestAttrValue(elt, 'ic-push-url') == "true") {
try {
requestCleanup(indicator, elt); // clean up before snap-shotting HTML
var newUrl = xhr.getResponseHeader("X-IC-PushURL") || closestAttrValue(elt, 'ic-src');
requestCleanup(indicator, globalIndicator, elt); // clean up before snap-shotting HTML
var baseURL = closestAttrValue(elt, 'ic-src');
var paramsToPush = closestAttrValue(elt, 'ic-push-params');
var newUrl = xhr.getResponseHeader("X-IC-PushURL") || getLocalURL(baseURL, paramsToPush, data);
if(_history) {
_history.snapshotForHistory(newUrl);
_history.snapshotForHistory(newUrl, oldTitle);
} else {
throw "History support not enabled";
}
@ -509,11 +546,11 @@ var Intercooler = Intercooler || (function() {
}
}
success(data, textStatus, elt, xhr);
success(responseData, textStatus, elt, xhr);
log(elt, "Process content for request " + requestId + " in " + (new Date() - beforeSuccess) + "ms", "DEBUG");
}
triggerEvent(elt, "after.success.ic", [elt, data, textStatus, xhr, requestId]);
triggerEvent(elt, "after.success.ic", [elt, responseData, textStatus, xhr, requestId]);
maybeInvokeLocalAction(elt, "-success");
} catch (e) {
log(elt, "Error processing successful request " + requestId + " : " + formatError(e), "ERROR");
@ -531,7 +568,7 @@ var Intercooler = Intercooler || (function() {
},
complete: function(xhr, status) {
log(elt, "AJAX request " + requestId + " completed in " + (new Date() - requestStart) + "ms", "DEBUG");
requestCleanup(indicator, elt);
requestCleanup(indicator, globalIndicator, elt);
try {
if ($.contains(document, elt[0])) {
triggerEvent(elt, "complete.ic", [elt, data, status, xhr, requestId]);
@ -557,14 +594,24 @@ var Intercooler = Intercooler || (function() {
triggerEvent($(document), "beforeAjaxSend.ic", [ajaxSetup, elt]);
if(ajaxSetup.cancel) {
requestCleanup(indicator, elt);
requestCleanup(indicator, globalIndicator, elt);
} else {
$.ajax(ajaxSetup)
}
}
function findGlobalIndicator(elt) {
var indicator = $([]);
elt = $(elt);
var attr = closestAttrValue(elt, 'ic-global-indicator');
if (attr && attr !== "false") {
indicator = $(attr).first();
}
return indicator;
}
function findIndicator(elt) {
var indicator = null;
var indicator = $([]);
elt = $(elt);
if (getICAttribute(elt, 'ic-indicator')) {
indicator = $(getICAttribute(elt, 'ic-indicator')).first();
@ -612,14 +659,14 @@ var Intercooler = Intercooler || (function() {
return data;
}
function appendData(data, string, value) {
function appendData(data, key, value) {
if ($.type(data) === "string") {
if($.type(value) !== "string") {
value = JSON.stringify(value);
}
return data + "&" + string + "=" + encodeURIComponent(value);
return data + "&" + key + "=" + encodeURIComponent(value);
} else {
data.append(string, value);
data.append(key, value);
return data;
}
}
@ -727,6 +774,7 @@ var Intercooler = Intercooler || (function() {
});
} else {
processMacros(elt);
processEnhancement(elt);
processSources(elt);
processPolling(elt);
processEventSources(elt);
@ -846,6 +894,18 @@ var Intercooler = Intercooler || (function() {
}
}
function processEnhancement(elt) {
if (elt.closest('.ic-ignore').length == 0) {
if(closestAttrValue(elt, 'ic-enhance') === 'true') {
enhanceDomTree(elt);
} else {
elt.find(getICAttributeSelector('ic-enhance')).each(function(){
enhanceDomTree($(this));
});
}
}
}
function processEventSources(elt) {
if (elt.closest('.ic-ignore').length == 0) {
handleEventSource(elt);
@ -1024,14 +1084,15 @@ var Intercooler = Intercooler || (function() {
elt = $(elt);
if (getICAttribute(elt, 'ic-sse-src')) {
var evtSrcUrl = getICAttribute(elt, 'ic-sse-src');
var eventSource = initEventSource(elt, evtSrcUrl);
var evtSrcWithCredentials = getICAttribute(elt, 'ic-sse-with-credentials') === 'true';
var eventSource = initEventSource(elt, evtSrcUrl, evtSrcWithCredentials);
elt.data('ic-event-sse-source', eventSource);
elt.data('ic-event-sse-map', {});
}
}
function initEventSource(elt, evtSrcUrl) {
var eventSource = Intercooler._internal.initEventSource(evtSrcUrl);
function initEventSource(elt, evtSrcUrl, evtSrcWithCredentials) {
var eventSource = Intercooler._internal.initEventSource(evtSrcUrl, evtSrcWithCredentials);
eventSource.onmessage = function(e) {
processICResponse(e.data, elt, false);
};
@ -1069,7 +1130,9 @@ var Intercooler = Intercooler || (function() {
}
function handleTriggerOn(elt) {
if (getICAttribute(elt, 'ic-trigger-on')) {
var triggerOnValue = getICAttribute(elt, 'ic-trigger-on');
if (triggerOnValue) {
// record button or submit input click info
if(elt.is('form')) {
elt.on('click focus', 'input, button, select, textarea', function(e){
@ -1080,59 +1143,65 @@ var Intercooler = Intercooler || (function() {
}
});
}
if (getICAttribute(elt, 'ic-trigger-on') == 'load') {
fireICRequest(elt);
} else if (getICAttribute(elt, 'ic-trigger-on') == 'scrolled-into-view') {
initScrollHandler();
setTimeout(function() {
triggerEvent($(window), 'scroll');
}, 100); // Trigger a scroll in case element is already viewable
} else {
var triggerOn = getICAttribute(elt, 'ic-trigger-on').split(" ");
if(triggerOn[0].indexOf("sse:") == 0) {
//Server-sent event, find closest event source and register for it
var sourceElt = elt.closest(getICAttributeSelector('ic-sse-src'));
if(sourceElt) {
registerSSE(sourceElt, triggerOn[0].substr(4))
}
var triggerOnArray = triggerOnValue.split(",");
for (var i = 0; i < triggerOnArray.length; i++) {
var triggerOn = $.trim(triggerOnArray[i]);
var splitTriggerOn = triggerOn.split(" ");
var eventString = eventFor(splitTriggerOn[0], $(elt));
var eventModifier = splitTriggerOn[1];
if (triggerOn == 'load') {
fireICRequest(elt);
} else if (triggerOn == 'scrolled-into-view') {
initScrollHandler();
setTimeout(function() {
triggerEvent($(window), 'scroll');
}, 100); // Trigger a scroll in case element is already viewable
} else {
var triggerOn = getICAttribute($(elt), 'ic-trigger-on').split(" ");
var event = eventFor(triggerOn[0], $(elt));
$(getTriggeredElement(elt)).on(event, function(e) {
var onBeforeTrigger = closestAttrValue(elt, 'ic-on-beforeTrigger');
if (onBeforeTrigger) {
if (globalEval(onBeforeTrigger, [["elt", elt], ["evt", e], ["elt", elt]]) == false) {
log(elt, "ic-trigger cancelled by ic-on-beforeTrigger", "DEBUG");
if(eventString.indexOf("sse:") == 0) {
//Server-sent event, find closest event source and register for it
var sourceElt = elt.closest(getICAttributeSelector('ic-sse-src'));
if(sourceElt.length > 0) {
registerSSE(sourceElt, splitTriggerOn[0].substr(4))
}
} else {
$(getTriggeredElement(elt)).on(eventString, function(e) {
var onBeforeTrigger = closestAttrValue(elt, 'ic-on-beforeTrigger');
if (onBeforeTrigger) {
if (globalEval(onBeforeTrigger, [["elt", elt], ["evt", e], ["elt", elt]]) == false) {
log(elt, "ic-trigger cancelled by ic-on-beforeTrigger", "DEBUG");
return false;
}
}
if (eventModifier == 'changed') {
var currentVal = elt.val();
var previousVal = elt.data('ic-previous-val');
elt.data('ic-previous-val', currentVal);
if (currentVal != previousVal) {
fireICRequest(elt);
}
} else if (eventModifier == 'once') {
var alreadyTriggered = elt.data('ic-already-triggered');
elt.data('ic-already-triggered', true);
if (alreadyTriggered !== true) {
fireICRequest(elt);
}
} else {
fireICRequest(elt);
}
if (preventDefault(elt, e)) {
e.preventDefault();
return false;
}
return true;
});
if(eventString && (eventString.indexOf("timeout:") == 0)) {
var timeout = parseInterval(eventString.split(":")[1]);
setTimeout(function () {
$(getTriggeredElement(elt)).trigger(eventString);
}, timeout);
}
if (triggerOn[1] == 'changed') {
var currentVal = elt.val();
var previousVal = elt.data('ic-previous-val');
elt.data('ic-previous-val', currentVal);
if (currentVal != previousVal) {
fireICRequest(elt);
}
} else if (triggerOn[1] == 'once') {
var alreadyTriggered = elt.data('ic-already-triggered');
elt.data('ic-already-triggered', true);
if (alreadyTriggered !== true) {
fireICRequest(elt);
}
} else {
fireICRequest(elt);
}
if (preventDefault(elt, e)) {
e.preventDefault();
return false;
}
return true;
});
if(event && (event.indexOf("timeout:") == 0)) {
setTimeout(function () {
$(getTriggeredElement(elt)).trigger(event);
}, parseInterval(event.split(":")[1]));
}
}
}
@ -1178,6 +1247,7 @@ var Intercooler = Intercooler || (function() {
setIfAbsent(elt, 'ic-trigger-on', 'default');
setIfAbsent(elt, 'ic-deps', 'ignore');
}
if (macroIs(macro, 'ic-action')) {
setIfAbsent(elt, 'ic-trigger-on', 'default');
}
@ -1209,6 +1279,51 @@ var Intercooler = Intercooler || (function() {
}
}
function isLocalLink(anchor) {
return location.hostname === anchor[0].hostname &&
anchor.attr('href') &&
!anchor.attr('href').startsWith("#")
}
function enhanceAnchor(anchor) {
if (closestAttrValue(anchor, 'ic-enhance') === "true") {
if (isLocalLink(anchor)) {
setIfAbsent(anchor, 'ic-src', anchor.attr('href'));
setIfAbsent(anchor, 'ic-trigger-on', 'default');
setIfAbsent(anchor, 'ic-deps', 'ignore');
setIfAbsent(anchor, 'ic-push-url', 'true');
}
}
}
function determineFormVerb(form) {
return form.find('input[name="_method"]').val() || form.attr('method') || form[0].method;
}
function enhanceForm(form) {
if (closestAttrValue(form, 'ic-enhance') === "true") {
setIfAbsent(form, 'ic-src', form.attr('action'));
setIfAbsent(form, 'ic-trigger-on', 'default');
setIfAbsent(form, 'ic-deps', 'ignore');
setIfAbsent(form, 'ic-verb', determineFormVerb(form));
}
}
function enhanceDomTree(elt) {
if(elt.is('a')) {
enhanceAnchor(elt);
}
elt.find('a').each(function(){
enhanceAnchor($(this));
});
if(elt.is('form')){
enhanceForm(elt);
}
elt.find('form').each(function(){
enhanceForm($(this));
});
}
function setIfAbsent(elt, attr, value) {
if (getICAttribute(elt, attr) == null) {
setICAttribute(elt, attr, value);
@ -1222,7 +1337,7 @@ var Intercooler = Intercooler || (function() {
function isScrolledIntoView(elem) {
elem = $(elem);
if (elem.height() == 0 && elem.width() == 0) {
return false;
return false;
}
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
@ -1231,13 +1346,13 @@ var Intercooler = Intercooler || (function() {
var elemBottom = elemTop + elem.height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
&& (elemBottom <= docViewBottom) && (elemTop >= docViewTop));
&& (elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
function maybeScrollToTarget(elt, target) {
if (closestAttrValue(elt, 'ic-scroll-to-target') != "false" &&
(closestAttrValue(elt, 'ic-scroll-to-target') == 'true' ||
closestAttrValue(target, 'ic-scroll-to-target') == 'true')) {
(closestAttrValue(elt, 'ic-scroll-to-target') == 'true' ||
closestAttrValue(target, 'ic-scroll-to-target') == 'true')) {
var offset = -50; // -50 px default offset padding
if (closestAttrValue(elt, 'ic-scroll-offset')) {
offset = parseInt(closestAttrValue(elt, 'ic-scroll-offset'));
@ -1352,6 +1467,19 @@ var Intercooler = Intercooler || (function() {
if (forHistory != true) {
maybeScrollToTarget(elt, target);
}
var switchClass = elt.closest(getICAttributeSelector('ic-switch-class'));
var classToSwitch = switchClass.attr(fixICAttributeName('ic-switch-class'));
if(classToSwitch) {
switchClass.children().removeClass(classToSwitch);
switchClass.children().each(function(){
if($.contains($(this)[0], $(elt)[0]) || $(this)[0] == $(elt)[0]) {
$(this).addClass(classToSwitch);
$(this).addClass(classToSwitch);
}
})
}
}
};
@ -1449,7 +1577,7 @@ var Intercooler = Intercooler || (function() {
}
}
function fireICRequest(elt, alternateHandler) {
function fireICRequest(elt, alternateHandler) {
elt = $(elt);
var triggerOrigin = elt;
@ -1628,9 +1756,9 @@ var Intercooler = Intercooler || (function() {
/* Instance Methods */
function historyConfigHasChanged(historySupportData) {
return historySupportData == null ||
historySupportData.slotLimit != slotLimit ||
historySupportData.historyVersion != historyVersion ||
historySupportData.lruList == null
historySupportData.slotLimit != slotLimit ||
historySupportData.historyVersion != historyVersion ||
historySupportData.lruList == null
}
function clearHistory() {
@ -1687,18 +1815,19 @@ var Intercooler = Intercooler || (function() {
storage.setItem(restorationData.id, content);
} catch (e) {
log(getTargetForHistory($('body')), "Unable to save intercooler history with entire history cleared, is something else eating " +
"local storage? History Limit:" + slotLimit, "ERROR");
"local storage? History Limit:" + slotLimit, "ERROR");
}
}
}
function makeHistoryEntry(html, yOffset, url) {
function makeHistoryEntry(html, yOffset, url, title) {
var restorationData = {
"url": url,
"id": HISTORY_SLOT_PREFIX + url,
"content": html,
"yOffset": yOffset,
"timestamp": new Date().getTime()
"timestamp": new Date().getTime(),
"title": title
};
updateLRUList(url);
// save to the history slot
@ -1724,18 +1853,18 @@ var Intercooler = Intercooler || (function() {
function updateHistory() {
if (_snapshot) {
pushUrl(_snapshot.newUrl, currentUrl(), _snapshot.oldHtml, _snapshot.yOffset);
pushUrl(_snapshot.newUrl, currentUrl(), _snapshot.oldHtml, _snapshot.yOffset, _snapshot.oldTitle);
_snapshot = null;
}
}
function pushUrl(newUrl, originalUrl, originalHtml, yOffset) {
function pushUrl(newUrl, originalUrl, originalHtml, yOffset, originalTitle) {
var historyEntry = makeHistoryEntry(originalHtml, yOffset, originalUrl);
var historyEntry = makeHistoryEntry(originalHtml, yOffset, originalUrl, originalTitle);
history.replaceState({"ic-id": historyEntry.id}, "", "");
var t = getTargetForHistory($('body'));
var restorationData = makeHistoryEntry(t.html(), window.pageYOffset, newUrl);
var restorationData = makeHistoryEntry(t.html(), window.pageYOffset, newUrl, document.title);
history.pushState({'ic-id': restorationData.id}, "", newUrl);
triggerEvent(t, "pushUrl.ic", [t, restorationData]);
@ -1748,7 +1877,12 @@ var Intercooler = Intercooler || (function() {
if (historyData) {
processICResponse(historyData["content"], getTargetForHistory($('body')), true);
if (historyData["yOffset"]) {
window.scrollTo(0, historyData["yOffset"])
setTimeout(function () {
window.scrollTo(0, historyData["yOffset"]);
}, 100);
}
if (historyData["title"]) {
document.title = historyData["title"];
}
return true;
} else {
@ -1771,13 +1905,14 @@ var Intercooler = Intercooler || (function() {
}
}
function snapshotForHistory(newUrl) {
function snapshotForHistory(newUrl, oldTitle) {
var t = getTargetForHistory($('body'));
triggerEvent(t, "beforeHistorySnapshot.ic", [t]);
_snapshot = {
newUrl: newUrl,
oldHtml: t.html(),
yOffset: window.pageYOffset
yOffset: window.pageYOffset,
oldTitle: oldTitle
};
}
@ -1897,12 +2032,11 @@ var Intercooler = Intercooler || (function() {
if($.zepto) {
$('body').data('zeptoDataTest', {});
if(typeof($('body').data('zeptoDataTest')) == "string") {
console.log("!!!! Please include the data module with Zepto! Intercooler requires full data support to function !!!!")
log(null,
"!!!! Please include the data module with Zepto! Intercooler requires full data support to function !!!!",
"ERROR")
}
}
if (location.search && location.search.indexOf("ic-launch-debugger=true") >= 0) {
Intercooler.debug();
}
}
$(function() {
@ -1922,27 +2056,22 @@ var Intercooler = Intercooler || (function() {
isDependent: isDependent,
getTarget: getTarget,
processHeaders: processHeaders,
startPolling: startPolling,
cancelPolling: cancelPolling,
setIsDependentFunction: function(func) {
_isDependentFunction = func;
},
ready: function(readyHandler) {
_readyHandlers.push(readyHandler);
},
debug: function() {
var debuggerUrl = closestAttrValue('body', 'ic-debugger-url') ||
"https://intercoolerreleases-leaddynocom.netdna-ssl.com/intercooler-debugger.js";
$.getScript(debuggerUrl)
.fail(function(jqxhr, settings, exception) {
log($('body'), formatError(exception), "ERROR");
});
},
_internal: {
init: init,
replaceOrAddMethod: replaceOrAddMethod,
initEventSource: function(url) {
return new EventSource(url);
initEventSource: function(url, withCredentials) {
return new EventSource(url, {withCredentials: withCredentials});
},
globalEval: globalEval
globalEval: globalEval,
getLocalURL: getLocalURL
}
};
})();