@glitchr/transparent 1.0.71 → 1.0.80

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glitchr/transparent",
3
- "version": "1.0.71",
3
+ "version": "1.0.80",
4
4
  "description": "Transparent SPA Application",
5
5
  "main": "src/index.js",
6
6
  "access": "public",
@@ -228,6 +228,29 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
228
228
  return false;
229
229
  }
230
230
 
231
+ // ─── NAVIGATION TRACE LOG ───────────────────────────────────────
232
+ // Gated on Settings.debug. Set 'debug': true in Transparent.ready({...})
233
+ // to surface a per-step trace prefixed with "[TX]" in the console.
234
+ // Cheap when disabled — single boolean check, no allocation.
235
+ function _tx(tag, extra) {
236
+ if (!Settings || !Settings.debug) return;
237
+ try {
238
+ var cls = document.documentElement.className;
239
+ var t = performance.now().toFixed(1);
240
+ var here = (document.querySelector("#page") || document.documentElement);
241
+ var lay = here.getAttribute && (here.getAttribute("data-layout") || "?");
242
+ var path = location.pathname;
243
+ console.log("%c[TX]", "color:#0a0;font-weight:bold",
244
+ "+" + t + "ms", tag,
245
+ "path=" + path,
246
+ "layout=" + lay,
247
+ "ajaxSem=" + (typeof ajaxSemaphore === "undefined" ? "?" : ajaxSemaphore),
248
+ "classes=[" + cls + "]",
249
+ extra || "");
250
+ } catch(e) {}
251
+ }
252
+ // ────────────────────────────────────────────────────────────────
253
+
231
254
  const State = Transparent.state = {
232
255
 
233
256
  ROOT : "transparent",
@@ -246,9 +269,9 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
246
269
  CLICK : "click",
247
270
 
248
271
  PREACTIVE : "pre-active",
249
- FADEIN : "fade-in",
272
+ FADEIN : "fade-in",
250
273
  ACTIVE : "active",
251
- FADEOUT : "fade-out",
274
+ FADEOUT : "fade-out",
252
275
  POSTACTIVE : "post-active",
253
276
 
254
277
  NOTIFICATION: "notification"
@@ -836,11 +859,10 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
836
859
 
837
860
  return {delay:delay, duration:duration};
838
861
  }
839
-
840
862
  var fadeInTime = 0;
841
863
  var fadeInRemainingTime = 0;
842
864
  Transparent.fadeIn = function(activeCallback = function() {}) {
843
-
865
+ _tx("fadeIn ENTRY");
844
866
  if(!Transparent.html.hasClass(Transparent.state.PREACTIVE)) {
845
867
  Transparent.html.addClass(Transparent.state.PREACTIVE);
846
868
  dispatchEvent(new Event('transparent:'+Transparent.state.PREACTIVE));
@@ -876,7 +898,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
876
898
  }
877
899
 
878
900
  Transparent.fadeOut = function(activeCallback = function() {}) {
879
-
901
+ _tx("fadeOut ENTRY");
880
902
  if(!Transparent.html.hasClass(Transparent.state.ACTIVE)) {
881
903
  Transparent.html.addClass(Transparent.state.ACTIVE);
882
904
  dispatchEvent(new Event('transparent:'+Transparent.state.ACTIVE));
@@ -897,8 +919,6 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
897
919
  Transparent.callback(function() {
898
920
 
899
921
  Transparent.html.removeClass(Transparent.state.FADEOUT);
900
- ajaxSemaphore = false;
901
-
902
922
  if(Transparent.html.hasClass(Transparent.state.LOADING)) {
903
923
 
904
924
  dispatchEvent(new Event('transparent:'+Transparent.state.LOADING));
@@ -906,7 +926,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
906
926
  Object.values(Transparent.state).forEach(e => Transparent.html.removeClass(e));
907
927
  Transparent.html.addClass(Transparent.state.ROOT + " " + Transparent.state.READY);
908
928
  }
909
-
929
+
910
930
  Transparent.html.addClass(Transparent.state.POSTACTIVE);
911
931
 
912
932
  var active = Transparent.activeTime();
@@ -1272,6 +1292,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1272
1292
 
1273
1293
  setTimeout(function() {
1274
1294
 
1295
+ _tx("onLoad BODY (after 1ms)");
1275
1296
  // Transfert attributes
1276
1297
  Transparent.transferAttributes(dom);
1277
1298
 
@@ -1295,8 +1316,8 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1295
1316
 
1296
1317
  found = this.isEqualNode(el);
1297
1318
  // Also match identical <style> tags by content
1298
- if(!found && el.tagName === 'STYLE' && this.tagName === 'STYLE' &&
1299
- el.textContent && this.textContent &&
1319
+ if(!found && el.tagName === 'STYLE' && this.tagName === 'STYLE' &&
1320
+ el.textContent && this.textContent &&
1300
1321
  el.textContent.length > 100 && this.textContent.length === el.textContent.length) {
1301
1322
  found = this.textContent === el.textContent;
1302
1323
  }
@@ -1318,7 +1339,8 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1318
1339
 
1319
1340
  if(this.tagName == "SCRIPT" && Settings["global_code"] != true) {
1320
1341
 
1321
- // For inline scripts (without src), create and execute
1342
+ // For inline scripts (without src), recreate so the browser will execute.
1343
+ // Simply re-appending the same <script> node doesn't execute it.
1322
1344
  if(!this.src || this.src === '') {
1323
1345
  var script = document.createElement("script");
1324
1346
  script.text = this.innerHTML;
@@ -1348,13 +1370,6 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1348
1370
  }
1349
1371
  });
1350
1372
 
1351
- // Collect link[rel="stylesheet"] elements inserted by the head merge above
1352
- var _newStyleLinks = [];
1353
- $("head").children("link[rel='stylesheet']").each(function() {
1354
- var h = this.getAttribute("href");
1355
- if(h && !_existingStyleHrefs[h]) _newStyleLinks.push(this);
1356
- });
1357
-
1358
1373
  var bodyScript = $(dom).find("body > script");
1359
1374
  bodyScript.each(function() {
1360
1375
 
@@ -1366,7 +1381,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1366
1381
 
1367
1382
  if(this.tagName == "SCRIPT" && Settings["global_code"] != true) {
1368
1383
 
1369
- // For inline scripts (without src), create and execute
1384
+ // Same inline-script recreation as for <head>.
1370
1385
  if(!this.src || this.src === '') {
1371
1386
  var script = document.createElement("script");
1372
1387
  script.text = this.innerHTML;
@@ -1401,7 +1416,13 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1401
1416
  // Make sure name/layout keep the same after a page change (tolerance for POST or GET requests)
1402
1417
  if(oldPage.attr("data-layout") != undefined && page.attr("data-layout") != undefined) {
1403
1418
 
1404
- var switchLayout = Transparent.state.SWITCH.replace("X", page.attr("data-layout")).replace("Y", oldPage.attr("data-layout"));
1419
+ // X = prevLayout, Y = newLayout — must match the formula in handleResponse
1420
+ // (line ~1852: SWITCH.replace("X", prevLayout).replace("Y", newLayout)).
1421
+ // If these disagreed, the cleanup filter below would not recognize the
1422
+ // switchLayout class that handleResponse added to <html> and would strip
1423
+ // it before its CSS transition could play — visible as a race only in
1424
+ // whichever direction the project's CSS actually styles.
1425
+ var switchLayout = Transparent.state.SWITCH.replace("X", oldPage.attr("data-layout")).replace("Y", page.attr("data-layout"));
1405
1426
  page.attr("data-layout-prev", oldPage.attr("data-layout"));
1406
1427
  }
1407
1428
 
@@ -1410,10 +1431,13 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1410
1431
  var oldHtmlClass = Array.from(($(Transparent.html).attr("class") || "").split(" "));
1411
1432
  var removeHtmlClass = oldHtmlClass.filter(x => !htmlClass.includes(x) && switchLayout != x && !states.includes(x));
1412
1433
 
1434
+ _tx("onLoad classMgmt", "switchLayout=" + switchLayout + " remove=[" + removeHtmlClass.join(",") + "] add=[" + htmlClass.join(",") + "]");
1413
1435
  Transparent.html.removeClass(removeHtmlClass).addClass(htmlClass);
1436
+ _tx("onLoad PAGE_SWAP_BEGIN", "oldLayout=" + (oldPage.attr("data-layout")||"?") + " newLayout=" + (page.attr("data-layout")||"?"));
1414
1437
  $(page).insertBefore(oldPage);
1415
1438
 
1416
1439
  oldPage.remove();
1440
+ _tx("onLoad PAGE_SWAP_DONE");
1417
1441
 
1418
1442
  if(Settings["global_code"] == true) Transparent.evalScript($(page)[0]);
1419
1443
  document.dispatchEvent(new Event('DOMContentLoaded'));
@@ -1449,11 +1473,19 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1449
1473
  }
1450
1474
  }
1451
1475
 
1476
+ // Collect link[rel="stylesheet"] elements inserted by the head merge above
1477
+ var _newStyleLinks = [];
1478
+ $("head").children("link[rel='stylesheet']").each(function() {
1479
+ var h = this.getAttribute("href");
1480
+ if(h && !_existingStyleHrefs[h]) _newStyleLinks.push(this);
1481
+ });
1482
+
1452
1483
  // Wait for any newly added layout stylesheets to finish loading before
1453
1484
  // calling callback() / fadeOut() — otherwise #page becomes visible while
1454
1485
  // the new CSS is still being parsed, causing a flash of unstyled content.
1455
1486
  (function() {
1456
1487
  function doCallback() {
1488
+ _tx("doCallback FIRES → callback() (which starts fadeOut)");
1457
1489
  $('head').append(function() {
1458
1490
  $(Settings.identifier).append(function() {
1459
1491
  callback();
@@ -1462,20 +1494,38 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1462
1494
  });
1463
1495
  });
1464
1496
  }
1465
- if(_newStyleLinks.length === 0) {
1497
+ // For cached stylesheets, the browser may fire `load` synchronously on
1498
+ // DOM insertion — BEFORE we can attach a listener — so listener-only
1499
+ // waits get stuck on the 3 s guard. `.sheet !== null` indicates the
1500
+ // CSSStyleSheet is already parsed and ready, which is the right
1501
+ // condition to count it as "done." Cross-origin sheets still expose
1502
+ // `.sheet` even though `.cssRules` throws — `.sheet !== null` is
1503
+ // portable.
1504
+ function isStyleLoaded(link) {
1505
+ try { return link.sheet !== null; } catch(e) { return true; }
1506
+ }
1507
+ var pending = _newStyleLinks.filter(function(l) { return !isStyleLoaded(l); });
1508
+ _tx("stylesheet-wait BEGIN", "newLinks=" + _newStyleLinks.length + " cachedSkipped=" + (_newStyleLinks.length - pending.length) + " pending=" + pending.length);
1509
+ if(pending.length === 0) {
1510
+ _tx("stylesheet-wait IMMEDIATE → doCallback");
1466
1511
  doCallback();
1467
1512
  } else {
1468
- var remaining = _newStyleLinks.length;
1513
+ var remaining = pending.length;
1469
1514
  var fired = false;
1470
1515
  // Safety valve: if a stylesheet fails or stalls, don't block forever.
1471
1516
  var guard = setTimeout(function() {
1472
- if(!fired) { fired = true; doCallback(); }
1517
+ if(!fired) {
1518
+ _tx("stylesheet-wait GUARD fired (3s)", "remaining=" + remaining);
1519
+ fired = true; doCallback();
1520
+ }
1473
1521
  }, 3000);
1474
- _newStyleLinks.forEach(function(link) {
1475
- function onDone() {
1522
+ pending.forEach(function(link) {
1523
+ function onDone(e) {
1524
+ _tx("stylesheet-wait link.load", "remaining=" + (remaining-1) + " href=" + link.getAttribute("href"));
1476
1525
  if(--remaining <= 0 && !fired) {
1477
1526
  fired = true;
1478
1527
  clearTimeout(guard);
1528
+ _tx("stylesheet-wait ALL_LOADED → doCallback");
1479
1529
  doCallback();
1480
1530
  }
1481
1531
  }
@@ -1597,7 +1647,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1597
1647
  var ajaxSemaphore = false;
1598
1648
  var formSubmission = false;
1599
1649
  function __main__(e) {
1600
-
1650
+ _tx("__main__ ENTRY", "event=" + e.type + (e.target && e.target.tagName ? " target=" + e.target.tagName : ""));
1601
1651
  // Disable transparent JS (e.g. during development..)
1602
1652
  if(Settings.disable) return;
1603
1653
 
@@ -1714,25 +1764,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1714
1764
  $(Transparent.html).stop();
1715
1765
 
1716
1766
  Transparent.html.addClass(Transparent.state.LOADING);
1717
-
1718
- var fadeInDone = false;
1719
- var pendingResponseArgs = null;
1720
-
1721
- function tryDispatch(args) {
1722
- if (args !== undefined) pendingResponseArgs = args;
1723
- if (fadeInDone && pendingResponseArgs !== null)
1724
- handleResponse(...pendingResponseArgs);
1725
- }
1726
-
1727
- // Lock navigation for the full transition (fadeIn + page swap + fadeOut).
1728
- // Released inside Transparent.fadeOut's final cleanup, covering both the
1729
- // AJAX path and the popstate/cached-response path.
1730
- ajaxSemaphore = true;
1731
-
1732
- Transparent.fadeIn(function() {
1733
- fadeInDone = true;
1734
- tryDispatch();
1735
- });
1767
+ Transparent.fadeIn();
1736
1768
 
1737
1769
  function isJsonResponse(str) {
1738
1770
  try { JSON.parse(str); return true; }
@@ -1740,8 +1772,10 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1740
1772
  }
1741
1773
 
1742
1774
  function handleResponse(uuid, status = 200, method = null, data = null, xhr = null, request = null) {
1775
+ _tx("handleResponse ENTRY", "status=" + status + " method=" + method);
1743
1776
 
1744
-
1777
+ ajaxSemaphore = false;
1778
+
1745
1779
  var responseURL;
1746
1780
  responseURL = xhr !== null ? xhr.responseURL : url.href;
1747
1781
 
@@ -1797,7 +1831,6 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1797
1831
  else location.reload();
1798
1832
  }
1799
1833
 
1800
- ajaxSemaphore = false;
1801
1834
  return dispatchEvent(new Event('load'));
1802
1835
  }
1803
1836
 
@@ -1858,6 +1891,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1858
1891
  Transparent.html.addClass(Transparent.state.SAME);
1859
1892
 
1860
1893
  var switchLayout = Transparent.state.SWITCH.replace("X", prevLayout).replace("Y", newLayout);
1894
+ _tx("handleResponse switchLayout", "prev=" + prevLayout + " new=" + newLayout + " adds=." + switchLayout);
1861
1895
  Transparent.html.addClass(switchLayout);
1862
1896
 
1863
1897
  dispatchEvent(new Event('transparent:'+switchLayout));
@@ -1915,6 +1949,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1915
1949
  if(form) form.dispatchEvent(new SubmitEvent("submit", { submitter: formTrigger }));
1916
1950
  var xhr = new XMLHttpRequest();
1917
1951
 
1952
+ ajaxSemaphore = true;
1918
1953
  return jQuery.ajax({
1919
1954
  url: url.href,
1920
1955
  type: type,
@@ -1923,12 +1958,12 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1923
1958
  processData: false,
1924
1959
  headers: Settings["headers"] || {},
1925
1960
  xhr: function () { return xhr; },
1926
- success: function (html, status, request) { return tryDispatch([uuid, request.status, type, data, xhr, request]); },
1927
- error: function (request, ajaxOptions, thrownError) { return tryDispatch([uuid, request.status, type, data, xhr, request]); }
1961
+ success: function (html, status, request) { _tx("ajax SUCCESS", "status=" + request.status); return handleResponse(uuid, request.status, type, data, xhr, request); },
1962
+ error: function (request, ajaxOptions, thrownError) { _tx("ajax ERROR", "status=" + request.status); return handleResponse(uuid, request.status, type, data, xhr, request); }
1928
1963
  });
1929
1964
  }
1930
1965
 
1931
- return tryDispatch([history.state.uuid, history.state.status, history.state.method, history.state.data]);
1966
+ return handleResponse(history.state.uuid, history.state.status, history.state.method, history.state.data);
1932
1967
  }
1933
1968
 
1934
1969
  // Update history if not refreshing page or different page (avoid double pushState)