src/helpers/bodyTrap.js
import portalOpenInstances from "./portalOpenInstances";
// Body focus trap see Issue #742
let before,
after,
instances = [];
/* eslint-disable no-console */
/* istanbul ignore next */
export function resetState() {
for (let item of [before, after]) {
if (!item) continue;
item.parentNode && item.parentNode.removeChild(item);
}
before = after = null;
instances = [];
}
/* istanbul ignore next */
export function log() {
console.log("bodyTrap ----------");
console.log(instances.length);
for (let item of [before, after]) {
let check = item || {};
console.log(check.nodeName, check.className, check.id);
}
console.log("edn bodyTrap ----------");
}
/* eslint-enable no-console */
function focusContent() {
if (instances.length === 0) {
if (process.env.NODE_ENV !== "production") {
// eslint-disable-next-line no-console
console.warn(`React-Modal: Open instances > 0 expected`);
}
return;
}
instances[instances.length - 1].focusContent();
}
function bodyTrap(eventType, openInstances) {
if (!before && !after) {
before = document.createElement("div");
before.setAttribute("data-react-modal-body-trap", "");
before.style.position = "absolute";
before.style.opacity = "0";
before.setAttribute("tabindex", "0");
before.addEventListener("focus", focusContent);
after = before.cloneNode();
after.addEventListener("focus", focusContent);
}
instances = openInstances;
if (instances.length > 0) {
// Add focus trap
if (document.body.firstChild !== before) {
document.body.insertBefore(before, document.body.firstChild);
}
if (document.body.lastChild !== after) {
document.body.appendChild(after);
}
} else {
// Remove focus trap
if (before.parentElement) {
before.parentElement.removeChild(before);
}
if (after.parentElement) {
after.parentElement.removeChild(after);
}
}
}
portalOpenInstances.subscribe(bodyTrap);