This is placeholder text. To change this content, double-click on the element and click Change Content. To manage all your collections, click on the Content Manager button in the Add panel on the left.
bottom of page
Add to: All pages
Place in: Body - end
Then, in the Editor, give your existing Quick Exit button the ID
"quickExit" (Wix: select element -> Properties panel -> ID), or simply
leave it as a link — the script intercepts any link whose text contains
"quick exit".
INSTALL ANYWHERE ELSE
Vanilla JS, no dependencies, ~2KB. MIT-style: use and modify freely.
========================================================================== */
(function () {
'use strict';
/* --- Configuration ------------------------------------------------------ */
// Where the visitor is sent. Weather is the strongest choice: it is the most
// plausible thing to have been looking at, it is not a search engine (a blank
// Google page invites "what were you searching for?"), and it loads fast.
var EXIT_URL = 'https://www.bbc.co.uk/weather';
// Opened in a second tab so the browser lands on something with real content.
var DECOY_URL = 'https://www.bbc.co.uk/news';
// Set this once the page exists. Leave null to skip the link.
var COVER_YOUR_TRACKS_URL = null; // e.g. '/support/cover-your-tracks'
// The title left in the session before leaving.
var NEUTRAL_TITLE = 'Weather';
var DOUBLE_TAP_WINDOW = 1000; // ms, for the Escape shortcut
var SHIFT_TAPS = 3;
/* --- The exit ----------------------------------------------------------- */
var exiting = false;
function quickExit() {
if (exiting) return;
exiting = true;
// 1. Blank the screen immediately. This is the part that matters on a slow
// connection: navigation may take a second, but the content is gone now.
try {
var veil = document.createElement('div');
veil.setAttribute('role', 'presentation');
veil.style.cssText =
'position:fixed;inset:0;background:#fff;z-index:2147483647;';
document.documentElement.appendChild(veil);
} catch (e) {}
// 2. Clear anything typed into a form.
try {
var fields = document.querySelectorAll('input, textarea, select');
for (var i = 0; i < fields.length; i++) {
var f = fields[i];
if (f.type === 'checkbox' || f.type === 'radio') f.checked = false;
else f.value = '';
}
if (window.sessionStorage) sessionStorage.clear();
} catch (e) {}
// 3. Make the entry we are about to overwrite unidentifiable.
try {
document.title = NEUTRAL_TITLE;
history.replaceState(null, NEUTRAL_TITLE, '/');
} catch (e) {}
// 4. Open the decoy tab. Must happen inside the user gesture or popup
// blockers will stop it. If blocked, the replace below still runs.
try {
var decoy = window.open(DECOY_URL, '_blank');
if (decoy) decoy.focus();
} catch (e) {}
// 5. Replace — not assign. assign() pushes a new history entry and leaves
// this page reachable via Back. replace() overwrites it.
try {
window.location.replace(EXIT_URL);
} catch (e) {
window.location.href = EXIT_URL;
}
}
/* --- Wiring ------------------------------------------------------------- */
function isExitTrigger(el) {
while (el && el !== document.body) {
if (el.nodeType === 1) {
if (
el.hasAttribute('data-quick-exit') ||
el.id === 'quickExit' ||
(el.className &&
typeof el.className === 'string' &&
el.className.indexOf('quick-exit') !== -1)
) {
return true;
}
// Catches the existing Wix link by its text, so it works before you
// have edited anything in the Editor.
if (
el.tagName === 'A' &&
(el.textContent || '').toLowerCase().indexOf('quick exit') !== -1
) {
return true;
}
}
el = el.parentNode;
}
return false;
}
document.addEventListener(
'click',
function (e) {
if (isExitTrigger(e.target)) {
e.preventDefault();
e.stopPropagation();
quickExit();
}
},
true // capture phase, so Wix's own handlers cannot swallow it first
);
var lastEscape = 0;
var shiftTaps = 0;
var shiftTimer = null;
document.addEventListener(
'keydown',
function (e) {
// Escape twice within the window. Two presses rather than one, so an
// accidental Escape while closing a menu does not throw the visitor out.
if (e.key === 'Escape' || e.keyCode === 27) {
var now = Date.now();
if (now - lastEscape < DOUBLE_TAP_WINDOW) {
quickExit();
return;
}
lastEscape = now;
}
// Shift, three times. A fallback for when something else has taken
// Escape, and quieter to press than Escape on a shared keyboard.
if (e.key === 'Shift' || e.keyCode === 16) {
shiftTaps++;
clearTimeout(shiftTimer);
if (shiftTaps >= SHIFT_TAPS) {
shiftTaps = 0;
quickExit();
return;
}
shiftTimer = setTimeout(function () {
shiftTaps = 0;
}, DOUBLE_TAP_WINDOW);
}
},
true
);
/* --- Make sure an exit control always exists ----------------------------- */
/* If no Quick Exit element is found on a page, this injects one. Belt and
braces: a page that is missing the button is the page someone lands on. */
function ensureButton() {
if (
document.querySelector(
'[data-quick-exit], #quickExit, .quick-exit'
)
) {
return;
}
var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
if ((links[i].textContent || '').toLowerCase().indexOf('quick exit') !== -1) {
return;
}
}
var btn = document.createElement('button');
btn.type = 'button';
btn.setAttribute('data-quick-exit', '');
btn.setAttribute(
'aria-label',
'Quick exit. Leaves this site immediately. Also press Escape twice.'
);
btn.textContent = 'Quick exit';
btn.style.cssText = [
'position:fixed', 'top:0', 'right:0', 'z-index:2147483646',
'margin:.5rem', 'padding:.6rem 1rem',
'font:600 14px/1 system-ui,-apple-system,Segoe UI,Roboto,sans-serif',
'color:#fff', 'background:#B3242B', 'border:0', 'border-radius:4px',
'cursor:pointer', 'box-shadow:0 2px 8px rgba(0,0,0,.25)'
].join(';');
document.body.appendChild(btn);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', ensureButton);
} else {
ensureButton();
}
// Exposed so you can trigger it from anywhere, e.g. a Wix Velo onClick:
// $w('#myButton').onClick(() => window.quickExit());
window.quickExit = quickExit;
window.QUICK_EXIT_COVER_TRACKS_URL = COVER_YOUR_TRACKS_URL;
})();