@glitchr/transparent 1.0.81 → 1.0.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/js/transparent.js +127 -11
package/package.json
CHANGED
package/src/js/transparent.js
CHANGED
|
@@ -274,12 +274,48 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
|
|
|
274
274
|
FADEOUT : "fade-out",
|
|
275
275
|
POSTACTIVE : "post-active",
|
|
276
276
|
|
|
277
|
-
NOTIFICATION: "notification"
|
|
277
|
+
NOTIFICATION: "notification",
|
|
278
|
+
OFFLINE : "offline"
|
|
278
279
|
};
|
|
279
280
|
|
|
280
281
|
var isReady = false;
|
|
281
282
|
var rescueMode = false;
|
|
282
283
|
|
|
284
|
+
// ─── OFFLINE DETECTION ──────────────────────────────────────────
|
|
285
|
+
// Two-source signal:
|
|
286
|
+
// 1. window 'online'/'offline' events fired by the browser when the
|
|
287
|
+
// OS-level connectivity changes (Wi-Fi off, airplane mode, etc.)
|
|
288
|
+
// 2. AJAX network errors during navigation — if a request fails with
|
|
289
|
+
// status 0 (and wasn't aborted), the device probably can't reach
|
|
290
|
+
// the server even though navigator.onLine may still be true.
|
|
291
|
+
// The `html.offline` class is the public surface — the project's CSS
|
|
292
|
+
// styles the YouTube-style "Offline" banner from there. Custom events
|
|
293
|
+
// `transparent:offline` and `transparent:online` give JS hooks too.
|
|
294
|
+
var isOnline = (typeof navigator !== "undefined") ? navigator.onLine !== false : true;
|
|
295
|
+
Transparent.isOnline = function() { return isOnline; }
|
|
296
|
+
function setOnlineStatus(online) {
|
|
297
|
+
if (online === isOnline) return; // no change
|
|
298
|
+
isOnline = online;
|
|
299
|
+
if (online) {
|
|
300
|
+
$($(document).find("html")[0]).removeClass(State.OFFLINE);
|
|
301
|
+
dispatchEvent(new Event("transparent:online"));
|
|
302
|
+
} else {
|
|
303
|
+
$($(document).find("html")[0]).addClass(State.OFFLINE);
|
|
304
|
+
dispatchEvent(new Event("transparent:offline"));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (typeof window !== "undefined") {
|
|
308
|
+
window.addEventListener("online", function() { setOnlineStatus(true); });
|
|
309
|
+
window.addEventListener("offline", function() { setOnlineStatus(false); });
|
|
310
|
+
}
|
|
311
|
+
// Apply initial state synchronously so first-paint reflects offline if applicable.
|
|
312
|
+
if (!isOnline) {
|
|
313
|
+
// Use the document element directly here — Transparent.html isn't initialized yet at module-eval time.
|
|
314
|
+
var _htmlEl = document.documentElement;
|
|
315
|
+
if (_htmlEl && _htmlEl.classList) _htmlEl.classList.add(State.OFFLINE);
|
|
316
|
+
}
|
|
317
|
+
// ────────────────────────────────────────────────────────────────
|
|
318
|
+
|
|
283
319
|
Transparent.html = $($(document).find("html")[0]);
|
|
284
320
|
Transparent.html.addClass(Transparent.state.ROOT+ " " + Transparent.state.LOADING + " " + Transparent.state.FIRST);
|
|
285
321
|
|
|
@@ -861,6 +897,15 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
|
|
|
861
897
|
}
|
|
862
898
|
var fadeInTime = 0;
|
|
863
899
|
var fadeInRemainingTime = 0;
|
|
900
|
+
// Schedule fn for after the currently in-flight fadeIn animation has
|
|
901
|
+
// finished. Used by handleResponse's three reload/redirect paths to
|
|
902
|
+
// ensure the loader is at full opacity before the browser unloads.
|
|
903
|
+
function _waitForFadeIn(fn) {
|
|
904
|
+
var elapsed = Date.now() - fadeInTime;
|
|
905
|
+
var remaining = fadeInRemainingTime - elapsed;
|
|
906
|
+
if (remaining > 0) setTimeout(fn, remaining + 30);
|
|
907
|
+
else fn();
|
|
908
|
+
}
|
|
864
909
|
Transparent.fadeIn = function(activeCallback = function() {}) {
|
|
865
910
|
_tx("fadeIn ENTRY");
|
|
866
911
|
if(!Transparent.html.hasClass(Transparent.state.PREACTIVE)) {
|
|
@@ -1026,7 +1071,22 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
|
|
|
1026
1071
|
Transparent.fadeOut();
|
|
1027
1072
|
}
|
|
1028
1073
|
|
|
1029
|
-
Transparent.userScroll = function(el = undefined) {
|
|
1074
|
+
Transparent.userScroll = function(el = undefined) {
|
|
1075
|
+
// Defensive: closestScrollable() can return a value without .prop
|
|
1076
|
+
// when called from event handlers on transient DOM (e.g. ajaxer
|
|
1077
|
+
// result containers, sticky-scrollpercent triggers fired during
|
|
1078
|
+
// infinite-scroll while the page is transitioning). The app-defer.js
|
|
1079
|
+
// wrapper around $.fn.closestScrollable is supposed to enforce the
|
|
1080
|
+
// jQuery return, but races with timing-sensitive callers can still
|
|
1081
|
+
// hit this. Default to true ("user is scrolling, don't autoscroll").
|
|
1082
|
+
try {
|
|
1083
|
+
var $target = $(el === undefined ? document.documentElement : el);
|
|
1084
|
+
if (!$target || !$target.length) return true;
|
|
1085
|
+
var $scroll = $target.closestScrollable && $target.closestScrollable();
|
|
1086
|
+
if (!$scroll || typeof $scroll.prop !== "function") return true;
|
|
1087
|
+
return $scroll.prop("user-scroll") ?? true;
|
|
1088
|
+
} catch (e) { return true; }
|
|
1089
|
+
}
|
|
1030
1090
|
Transparent.scrollTo = function(dict, el = window, callback = function() {})
|
|
1031
1091
|
{
|
|
1032
1092
|
setTimeout(function() {
|
|
@@ -1290,9 +1350,28 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
|
|
|
1290
1350
|
$(this).stop();
|
|
1291
1351
|
});
|
|
1292
1352
|
|
|
1353
|
+
// Defer the DOM swap until #page's opacity transition has had a
|
|
1354
|
+
// chance to finish. Read the transition-duration from getComputedStyle
|
|
1355
|
+
// (closure-local — no module state shared between navigations) so
|
|
1356
|
+
// this stays in sync with whatever the project's CSS uses. Without
|
|
1357
|
+
// this delay, a fast/cached AJAX response can land the swap while
|
|
1358
|
+
// #page is still partway through the LOADING-induced fade-out,
|
|
1359
|
+
// making the content change visible to the user (the original
|
|
1360
|
+
// flicker).
|
|
1361
|
+
var _swapDelay = 1;
|
|
1362
|
+
try {
|
|
1363
|
+
var _pageEl = $(Settings.identifier)[0];
|
|
1364
|
+
if (_pageEl) {
|
|
1365
|
+
var _dur = 1000 * Transparent.parseDuration(
|
|
1366
|
+
window.getComputedStyle(_pageEl).transitionDuration || "0"
|
|
1367
|
+
);
|
|
1368
|
+
if (_dur > 1) _swapDelay = _dur;
|
|
1369
|
+
}
|
|
1370
|
+
} catch(e) {}
|
|
1371
|
+
|
|
1293
1372
|
setTimeout(function() {
|
|
1294
1373
|
|
|
1295
|
-
_tx("onLoad BODY (after
|
|
1374
|
+
_tx("onLoad BODY (after " + _swapDelay + "ms)");
|
|
1296
1375
|
// Transfert attributes
|
|
1297
1376
|
Transparent.transferAttributes(dom);
|
|
1298
1377
|
|
|
@@ -1543,7 +1622,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
|
|
|
1543
1622
|
}
|
|
1544
1623
|
})();
|
|
1545
1624
|
|
|
1546
|
-
}.bind(this),
|
|
1625
|
+
}.bind(this), _swapDelay);
|
|
1547
1626
|
}
|
|
1548
1627
|
|
|
1549
1628
|
function uuidv4() {
|
|
@@ -1747,6 +1826,17 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
|
|
|
1747
1826
|
if (ajaxSemaphore) return;
|
|
1748
1827
|
if (url == location) return;
|
|
1749
1828
|
|
|
1829
|
+
// Block navigation when offline. Project CSS / JS can react to
|
|
1830
|
+
// html.offline + the transparent:offline event to surface a banner.
|
|
1831
|
+
// The event is re-dispatched here on each attempted navigation so a
|
|
1832
|
+
// listener can briefly flash/highlight the banner to acknowledge the
|
|
1833
|
+
// click instead of doing nothing silently.
|
|
1834
|
+
if (!isOnline || (typeof navigator !== "undefined" && navigator.onLine === false)) {
|
|
1835
|
+
setOnlineStatus(false);
|
|
1836
|
+
dispatchEvent(new Event("transparent:offline"));
|
|
1837
|
+
return;
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1750
1840
|
if((e.type == Transparent.state.CLICK || e.type == Transparent.state.HASHCHANGE) && url.pathname == location.pathname && url.search == location.search && type != "POST") {
|
|
1751
1841
|
|
|
1752
1842
|
if(!url.hash) return;
|
|
@@ -1866,12 +1956,18 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
|
|
|
1866
1956
|
history.pushState({uuid: uuid, status:status, method: method, data: {}, href: responseURL}, '', responseURL);
|
|
1867
1957
|
|
|
1868
1958
|
// Page not recognized.. just go fetch by yourself.. no POST information transmitted..
|
|
1869
|
-
|
|
1870
|
-
|
|
1959
|
+
// Defer the redirect until fadeIn settles, same reasoning as the
|
|
1960
|
+
// html.reload path above.
|
|
1961
|
+
if(!Transparent.isPage(dom)) {
|
|
1962
|
+
_waitForFadeIn(function() { window.location.href = url; });
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1871
1965
|
|
|
1872
1966
|
// Layout not compatible.. needs to be reloaded (exception when POST is detected..)
|
|
1873
|
-
if(!Transparent.isCompatiblePage(dom, method, data))
|
|
1874
|
-
|
|
1967
|
+
if(!Transparent.isCompatiblePage(dom, method, data)) {
|
|
1968
|
+
_waitForFadeIn(function() { window.location.href = url; });
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1875
1971
|
|
|
1876
1972
|
// Mark layout as known
|
|
1877
1973
|
if(!Transparent.isKnownLayout(dom)) {
|
|
@@ -1904,8 +2000,18 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
|
|
|
1904
2000
|
|
|
1905
2001
|
dispatchEvent(new Event('transparent:'+switchLayout));
|
|
1906
2002
|
|
|
1907
|
-
if($(dom).find("html").hasClass(Transparent.state.RELOAD) || $(dom).find("html").hasClass(Transparent.state.DISABLE))
|
|
1908
|
-
|
|
2003
|
+
if($(dom).find("html").hasClass(Transparent.state.RELOAD) || $(dom).find("html").hasClass(Transparent.state.DISABLE)) {
|
|
2004
|
+
// Defer the reload until fadeIn has finished, so the loader is
|
|
2005
|
+
// at full opacity when the browser unloads. Without this, a
|
|
2006
|
+
// fast AJAX response can fire reload() while fadeIn is still
|
|
2007
|
+
// mid-animation: the browser swaps to a page that starts with
|
|
2008
|
+
// .active (loader at 100%), and the user perceives a snap
|
|
2009
|
+
// from in-progress opacity to full. Reading as "fade-out then
|
|
2010
|
+
// fade-in" because the partial loader receded as the browser
|
|
2011
|
+
// swapped frames.
|
|
2012
|
+
_waitForFadeIn(function() { window.location.reload(); });
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
1909
2015
|
|
|
1910
2016
|
// Kick off preloads for stylesheets the new page needs but aren't yet in <head>.
|
|
1911
2017
|
// They download in parallel during the fadeIn animation so onLoad() finds them
|
|
@@ -1967,7 +2073,17 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
|
|
|
1967
2073
|
headers: Settings["headers"] || {},
|
|
1968
2074
|
xhr: function () { return xhr; },
|
|
1969
2075
|
success: function (html, status, request) { _tx("ajax SUCCESS", "status=" + request.status); return handleResponse(uuid, request.status, type, data, xhr, request); },
|
|
1970
|
-
error: function (request, ajaxOptions, thrownError) {
|
|
2076
|
+
error: function (request, ajaxOptions, thrownError) {
|
|
2077
|
+
_tx("ajax ERROR", "status=" + request.status + " textStatus=" + ajaxOptions);
|
|
2078
|
+
// status=0 with non-abort textStatus typically means the device
|
|
2079
|
+
// couldn't reach the server: dropped connection, DNS failure,
|
|
2080
|
+
// captive portal, etc. Flip to offline so the project's banner
|
|
2081
|
+
// surfaces even if navigator.onLine still reports true.
|
|
2082
|
+
if (request.status === 0 && ajaxOptions !== "abort") {
|
|
2083
|
+
setOnlineStatus(false);
|
|
2084
|
+
}
|
|
2085
|
+
return handleResponse(uuid, request.status, type, data, xhr, request);
|
|
2086
|
+
}
|
|
1971
2087
|
});
|
|
1972
2088
|
}
|
|
1973
2089
|
|