@glitchr/transparent 1.0.70 → 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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/js/transparent.js +109 -58
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glitchr/transparent",
3
- "version": "1.0.70",
3
+ "version": "1.0.80",
4
4
  "description": "Transparent SPA Application",
5
5
  "main": "src/index.js",
6
6
  "access": "public",
@@ -181,18 +181,14 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
181
181
  "smoothscroll_easing" : "swing",
182
182
  "exceptions": [],
183
183
  // headlock: list of url substrings/regex to preserve in <head> across page transitions
184
- // (e.g. third-party widgets like Brevo that inject <style>/<link> dynamically).
184
+ // (e.g. third-party widgets that inject <style>/<link> dynamically).
185
185
  // In addition, head nodes injected dynamically AFTER initial DOMContentLoaded are
186
186
  // preserved automatically. Use data-headlock="false" on a head element to opt-out.
187
- "headlock": [
188
- "brevo",
189
- "conversations-widget",
190
- /brevo/i
191
- ]
187
+ "headlock": []
192
188
  };
193
189
 
194
190
  // Set of <head> children present on initial load. Anything added after is treated
195
- // as dynamically injected (e.g. Brevo widget) and preserved across transitions.
191
+ // as dynamically injected and preserved across transitions.
196
192
  var originalHeadNodes = new WeakSet();
197
193
  function snapshotHeadNodes() {
198
194
  var head = document.head;
@@ -201,7 +197,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
201
197
  originalHeadNodes.add(head.children[i]);
202
198
  }
203
199
  // Snapshot synchronously at module-eval time (scripts at end of <body> run before any
204
- // async script — e.g. Brevo — can inject <style> tags, so the snapshot is clean).
200
+ // async script can inject <style> tags, so the snapshot is clean).
205
201
  // A DOMContentLoaded fallback is kept for the rare case where document.head is null
206
202
  // (e.g. script loaded inside <head> before it finishes parsing).
207
203
  snapshotHeadNodes();
@@ -232,6 +228,29 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
232
228
  return false;
233
229
  }
234
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
+
235
254
  const State = Transparent.state = {
236
255
 
237
256
  ROOT : "transparent",
@@ -250,9 +269,9 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
250
269
  CLICK : "click",
251
270
 
252
271
  PREACTIVE : "pre-active",
253
- ACTIVEIN : "active-in",
272
+ FADEIN : "fade-in",
254
273
  ACTIVE : "active",
255
- ACTIVEOUT : "active-out",
274
+ FADEOUT : "fade-out",
256
275
  POSTACTIVE : "post-active",
257
276
 
258
277
  NOTIFICATION: "notification"
@@ -499,7 +518,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
499
518
 
500
519
  if($(Transparent.html).hasClass(Transparent.state.FIRST)) {
501
520
  Transparent.scrollToHash(location.hash, {}, function() {
502
- Transparent.activeOut(() => Transparent.html.removeClass(Transparent.state.FIRST));
521
+ Transparent.fadeOut(() => Transparent.html.removeClass(Transparent.state.FIRST));
503
522
  });
504
523
  }
505
524
 
@@ -840,28 +859,28 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
840
859
 
841
860
  return {delay:delay, duration:duration};
842
861
  }
843
- var activeInTime = 0;
844
- var activeInRemainingTime = 0;
845
- Transparent.activeIn = function(activeCallback = function() {}) {
846
-
862
+ var fadeInTime = 0;
863
+ var fadeInRemainingTime = 0;
864
+ Transparent.fadeIn = function(activeCallback = function() {}) {
865
+ _tx("fadeIn ENTRY");
847
866
  if(!Transparent.html.hasClass(Transparent.state.PREACTIVE)) {
848
867
  Transparent.html.addClass(Transparent.state.PREACTIVE);
849
868
  dispatchEvent(new Event('transparent:'+Transparent.state.PREACTIVE));
850
869
  }
851
870
 
852
871
  var active = Transparent.activeTime();
853
- activeInTime = Date.now();
854
- activeInRemainingTime = active.delay+active.duration;
872
+ fadeInTime = Date.now();
873
+ fadeInRemainingTime = active.delay+active.duration;
855
874
 
856
875
  Transparent.html.removeClass(Transparent.state.PREACTIVE);
857
- if(!Transparent.html.hasClass(Transparent.state.ACTIVEIN)) {
858
- Transparent.html.addClass(Transparent.state.ACTIVEIN);
859
- dispatchEvent(new Event('transparent:'+Transparent.state.ACTIVEIN));
876
+ if(!Transparent.html.hasClass(Transparent.state.FADEIN)) {
877
+ Transparent.html.addClass(Transparent.state.FADEIN);
878
+ dispatchEvent(new Event('transparent:'+Transparent.state.FADEIN));
860
879
  }
861
880
 
862
881
  Transparent.callback(function() {
863
882
 
864
- Transparent.html.removeClass(Transparent.state.ACTIVEIN);
883
+ Transparent.html.removeClass(Transparent.state.FADEIN);
865
884
  if(!Transparent.html.hasClass(Transparent.state.ACTIVE)) {
866
885
  Transparent.html.addClass(Transparent.state.ACTIVE);
867
886
  dispatchEvent(new Event('transparent:'+Transparent.state.ACTIVE));
@@ -871,23 +890,23 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
871
890
  Transparent.callback(function() {
872
891
 
873
892
  activeCallback();
874
- activeInRemainingTime = 0;
893
+ fadeInRemainingTime = 0;
875
894
 
876
895
  }.bind(this), active.duration);
877
896
 
878
897
  }.bind(this), active.delay);
879
898
  }
880
899
 
881
- Transparent.activeOut = function(activeCallback = function() {}) {
882
-
900
+ Transparent.fadeOut = function(activeCallback = function() {}) {
901
+ _tx("fadeOut ENTRY");
883
902
  if(!Transparent.html.hasClass(Transparent.state.ACTIVE)) {
884
903
  Transparent.html.addClass(Transparent.state.ACTIVE);
885
904
  dispatchEvent(new Event('transparent:'+Transparent.state.ACTIVE));
886
905
  }
887
906
 
888
- if(!Transparent.html.hasClass(Transparent.state.ACTIVEOUT)) {
889
- Transparent.html.addClass(Transparent.state.ACTIVEOUT);
890
- dispatchEvent(new Event('transparent:'+Transparent.state.ACTIVEOUT));
907
+ if(!Transparent.html.hasClass(Transparent.state.FADEOUT)) {
908
+ Transparent.html.addClass(Transparent.state.FADEOUT);
909
+ dispatchEvent(new Event('transparent:'+Transparent.state.FADEOUT));
891
910
  }
892
911
 
893
912
  var active = Transparent.activeTime();
@@ -899,7 +918,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
899
918
  var active = Transparent.activeTime();
900
919
  Transparent.callback(function() {
901
920
 
902
- Transparent.html.removeClass(Transparent.state.ACTIVEOUT);
921
+ Transparent.html.removeClass(Transparent.state.FADEOUT);
903
922
  if(Transparent.html.hasClass(Transparent.state.LOADING)) {
904
923
 
905
924
  dispatchEvent(new Event('transparent:'+Transparent.state.LOADING));
@@ -1004,7 +1023,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1004
1023
  Transparent.evalScript($("body")[0]);
1005
1024
  }
1006
1025
 
1007
- Transparent.activeOut();
1026
+ Transparent.fadeOut();
1008
1027
  }
1009
1028
 
1010
1029
  Transparent.userScroll = function(el = undefined) { return $(el === undefined ? document.documentElement : el).closestScrollable().prop("user-scroll") ?? true; }
@@ -1271,9 +1290,9 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1271
1290
  $(this).stop();
1272
1291
  });
1273
1292
 
1274
- activeInRemainingTime = activeInRemainingTime - (Date.now() - activeInTime);
1275
1293
  setTimeout(function() {
1276
1294
 
1295
+ _tx("onLoad BODY (after 1ms)");
1277
1296
  // Transfert attributes
1278
1297
  Transparent.transferAttributes(dom);
1279
1298
 
@@ -1296,9 +1315,9 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1296
1315
  head.children().each(function() {
1297
1316
 
1298
1317
  found = this.isEqualNode(el);
1299
- // Also match identical <style> tags by content (Brevo styles are identical across pages)
1300
- if(!found && el.tagName === 'STYLE' && this.tagName === 'STYLE' &&
1301
- el.textContent && this.textContent &&
1318
+ // Also match identical <style> tags by content
1319
+ if(!found && el.tagName === 'STYLE' && this.tagName === 'STYLE' &&
1320
+ el.textContent && this.textContent &&
1302
1321
  el.textContent.length > 100 && this.textContent.length === el.textContent.length) {
1303
1322
  found = this.textContent === el.textContent;
1304
1323
  }
@@ -1320,7 +1339,8 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1320
1339
 
1321
1340
  if(this.tagName == "SCRIPT" && Settings["global_code"] != true) {
1322
1341
 
1323
- // 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.
1324
1344
  if(!this.src || this.src === '') {
1325
1345
  var script = document.createElement("script");
1326
1346
  script.text = this.innerHTML;
@@ -1350,13 +1370,6 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1350
1370
  }
1351
1371
  });
1352
1372
 
1353
- // Collect link[rel="stylesheet"] elements inserted by the head merge above
1354
- var _newStyleLinks = [];
1355
- $("head").children("link[rel='stylesheet']").each(function() {
1356
- var h = this.getAttribute("href");
1357
- if(h && !_existingStyleHrefs[h]) _newStyleLinks.push(this);
1358
- });
1359
-
1360
1373
  var bodyScript = $(dom).find("body > script");
1361
1374
  bodyScript.each(function() {
1362
1375
 
@@ -1368,7 +1381,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1368
1381
 
1369
1382
  if(this.tagName == "SCRIPT" && Settings["global_code"] != true) {
1370
1383
 
1371
- // For inline scripts (without src), create and execute
1384
+ // Same inline-script recreation as for <head>.
1372
1385
  if(!this.src || this.src === '') {
1373
1386
  var script = document.createElement("script");
1374
1387
  script.text = this.innerHTML;
@@ -1403,7 +1416,13 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1403
1416
  // Make sure name/layout keep the same after a page change (tolerance for POST or GET requests)
1404
1417
  if(oldPage.attr("data-layout") != undefined && page.attr("data-layout") != undefined) {
1405
1418
 
1406
- 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"));
1407
1426
  page.attr("data-layout-prev", oldPage.attr("data-layout"));
1408
1427
  }
1409
1428
 
@@ -1412,10 +1431,13 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1412
1431
  var oldHtmlClass = Array.from(($(Transparent.html).attr("class") || "").split(" "));
1413
1432
  var removeHtmlClass = oldHtmlClass.filter(x => !htmlClass.includes(x) && switchLayout != x && !states.includes(x));
1414
1433
 
1434
+ _tx("onLoad classMgmt", "switchLayout=" + switchLayout + " remove=[" + removeHtmlClass.join(",") + "] add=[" + htmlClass.join(",") + "]");
1415
1435
  Transparent.html.removeClass(removeHtmlClass).addClass(htmlClass);
1436
+ _tx("onLoad PAGE_SWAP_BEGIN", "oldLayout=" + (oldPage.attr("data-layout")||"?") + " newLayout=" + (page.attr("data-layout")||"?"));
1416
1437
  $(page).insertBefore(oldPage);
1417
1438
 
1418
1439
  oldPage.remove();
1440
+ _tx("onLoad PAGE_SWAP_DONE");
1419
1441
 
1420
1442
  if(Settings["global_code"] == true) Transparent.evalScript($(page)[0]);
1421
1443
  document.dispatchEvent(new Event('DOMContentLoaded'));
@@ -1451,11 +1473,19 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1451
1473
  }
1452
1474
  }
1453
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
+
1454
1483
  // Wait for any newly added layout stylesheets to finish loading before
1455
- // calling callback() / activeOut() — otherwise #page becomes visible while
1484
+ // calling callback() / fadeOut() — otherwise #page becomes visible while
1456
1485
  // the new CSS is still being parsed, causing a flash of unstyled content.
1457
1486
  (function() {
1458
1487
  function doCallback() {
1488
+ _tx("doCallback FIRES → callback() (which starts fadeOut)");
1459
1489
  $('head').append(function() {
1460
1490
  $(Settings.identifier).append(function() {
1461
1491
  callback();
@@ -1464,20 +1494,38 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1464
1494
  });
1465
1495
  });
1466
1496
  }
1467
- 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");
1468
1511
  doCallback();
1469
1512
  } else {
1470
- var remaining = _newStyleLinks.length;
1513
+ var remaining = pending.length;
1471
1514
  var fired = false;
1472
1515
  // Safety valve: if a stylesheet fails or stalls, don't block forever.
1473
1516
  var guard = setTimeout(function() {
1474
- if(!fired) { fired = true; doCallback(); }
1517
+ if(!fired) {
1518
+ _tx("stylesheet-wait GUARD fired (3s)", "remaining=" + remaining);
1519
+ fired = true; doCallback();
1520
+ }
1475
1521
  }, 3000);
1476
- _newStyleLinks.forEach(function(link) {
1477
- function onDone() {
1522
+ pending.forEach(function(link) {
1523
+ function onDone(e) {
1524
+ _tx("stylesheet-wait link.load", "remaining=" + (remaining-1) + " href=" + link.getAttribute("href"));
1478
1525
  if(--remaining <= 0 && !fired) {
1479
1526
  fired = true;
1480
1527
  clearTimeout(guard);
1528
+ _tx("stylesheet-wait ALL_LOADED → doCallback");
1481
1529
  doCallback();
1482
1530
  }
1483
1531
  }
@@ -1487,7 +1535,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1487
1535
  }
1488
1536
  })();
1489
1537
 
1490
- }.bind(this), activeInRemainingTime > 0 ? activeInRemainingTime : 1);
1538
+ }.bind(this), 1);
1491
1539
  }
1492
1540
 
1493
1541
  function uuidv4() {
@@ -1599,7 +1647,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1599
1647
  var ajaxSemaphore = false;
1600
1648
  var formSubmission = false;
1601
1649
  function __main__(e) {
1602
-
1650
+ _tx("__main__ ENTRY", "event=" + e.type + (e.target && e.target.tagName ? " target=" + e.target.tagName : ""));
1603
1651
  // Disable transparent JS (e.g. during development..)
1604
1652
  if(Settings.disable) return;
1605
1653
 
@@ -1716,7 +1764,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1716
1764
  $(Transparent.html).stop();
1717
1765
 
1718
1766
  Transparent.html.addClass(Transparent.state.LOADING);
1719
- Transparent.activeIn();
1767
+ Transparent.fadeIn();
1720
1768
 
1721
1769
  function isJsonResponse(str) {
1722
1770
  try { JSON.parse(str); return true; }
@@ -1724,6 +1772,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1724
1772
  }
1725
1773
 
1726
1774
  function handleResponse(uuid, status = 200, method = null, data = null, xhr = null, request = null) {
1775
+ _tx("handleResponse ENTRY", "status=" + status + " method=" + method);
1727
1776
 
1728
1777
  ajaxSemaphore = false;
1729
1778
 
@@ -1842,6 +1891,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1842
1891
  Transparent.html.addClass(Transparent.state.SAME);
1843
1892
 
1844
1893
  var switchLayout = Transparent.state.SWITCH.replace("X", prevLayout).replace("Y", newLayout);
1894
+ _tx("handleResponse switchLayout", "prev=" + prevLayout + " new=" + newLayout + " adds=." + switchLayout);
1845
1895
  Transparent.html.addClass(switchLayout);
1846
1896
 
1847
1897
  dispatchEvent(new Event('transparent:'+switchLayout));
@@ -1850,13 +1900,14 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1850
1900
  return window.location.reload();
1851
1901
 
1852
1902
  // Kick off preloads for stylesheets the new page needs but aren't yet in <head>.
1853
- // They download in parallel during the activeIn animation so onLoad() finds them
1903
+ // They download in parallel during the fadeIn animation so onLoad() finds them
1854
1904
  // already cached — eliminating FOUC on cold-cache layout transitions.
1855
1905
  (function() {
1856
1906
  var loaded = {};
1857
1907
  $("head").children("link[rel='stylesheet']").each(function() {
1858
1908
  var h = this.getAttribute("href"); if(h) loaded[h] = true;
1859
1909
  });
1910
+
1860
1911
  $(dom).find("head").children("link[rel='stylesheet']").each(function() {
1861
1912
  var h = this.getAttribute("href");
1862
1913
  if(!h || loaded[h]) return;
@@ -1869,7 +1920,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1869
1920
 
1870
1921
  return Transparent.onLoad(uuid, dom, function() {
1871
1922
 
1872
- Transparent.activeOut(function() {
1923
+ Transparent.fadeOut(function() {
1873
1924
 
1874
1925
  Transparent.html
1875
1926
  .removeClass(switchLayout)
@@ -1892,7 +1943,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1892
1943
  if(history.state)
1893
1944
  Transparent.setResponse(history.state.uuid, Transparent.html[0], Transparent.getScrollableElementXY());
1894
1945
 
1895
- $(Transparent.html).prop("user-scroll", false); // make sure to avoid page jump during transition (cancelled in activeIn callback)
1946
+ $(Transparent.html).prop("user-scroll", false); // make sure to avoid page jump during transition (cancelled in fadeIn callback)
1896
1947
 
1897
1948
  // Submit ajax request..
1898
1949
  if(form) form.dispatchEvent(new SubmitEvent("submit", { submitter: formTrigger }));
@@ -1907,8 +1958,8 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
1907
1958
  processData: false,
1908
1959
  headers: Settings["headers"] || {},
1909
1960
  xhr: function () { return xhr; },
1910
- success: function (html, status, request) { return handleResponse(uuid, request.status, type, data, xhr, request); },
1911
- error: function (request, ajaxOptions, thrownError) { return handleResponse(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); }
1912
1963
  });
1913
1964
  }
1914
1965
 
@@ -2027,7 +2078,7 @@ jQuery.event.special.mousewheel = { setup: function( _, ns, handle ) { this.addE
2027
2078
  if(Settings.debug || preventDefault) {
2028
2079
 
2029
2080
  if(preventDefault) Transparent.html.addClass(Transparent.state.READY);
2030
- if(preventDefault) Transparent.activeOut();
2081
+ if(preventDefault) Transparent.fadeOut();
2031
2082
  if(preventDefault) dispatchEvent(new Event('load'));
2032
2083
 
2033
2084
  return "Dude, are you sure you want to leave? Think of the kittens!";