v0.1

ModalsUX
#91 - Hide Popup For Set Duration
Hide a popup for X time when a button is clicked.
Watch the video for step-by-step implementation instructions
<!-- 💙 MEMBERSCRIPT #235 v0.1 💙 GDPR CONSENT LOGGER MODAL -->
<script>
document.addEventListener("DOMContentLoaded", async function() {
var CONFIG = {
jsonKey: "consent_log",
version: " number1. prop0",
keepHistory: true,
historyMax: 50,
requireLoggedIn: true,
activeDisplay: "flex"
};
var memberstack = window.$memberstackDom;
if (!memberstack) {
console.warn("Memberscript # number235: Memberstack not found");
return;
}
var root = document.querySelector('[data-ms-code="consent"]');
if (!root) {
console.warn("Memberscript # number235: Add data-ms-code=\"consent\" to your modal wrapper.");
return;
}
root.style.display = "none";
var controls = root.querySelectorAll("[data-ms-consent]");
if (!controls.length) {
console.warn("Memberscript # number235: Add data-ms-consent=\"<key>\" to your consent checkbox(es).");
return;
}
function cfg(name, fallback) {
return root.hasAttribute(name) ? root.getAttribute(name) : fallback;
}
var jsonKey = cfg("ms-code-json-key", CONFIG.jsonKey);
var version = cfg("ms-code-version", CONFIG.version);
var activeDisplay = cfg("ms-code-display", CONFIG.activeDisplay);
var historyMax = parseInt(cfg("ms-code-history-max", CONFIG.historyMax), 10);
if (isNaN(historyMax) || historyMax < 0) historyMax = CONFIG.historyMax;
var keepHistory = cfg("ms-code-history", String(CONFIG.keepHistory)) !== " keywordfalse";
var requireLoggedInAttr = root.getAttribute("ms-code-require-logged- keywordin");
var requireLoggedIn = requireLoggedInAttr !== null ? requireLoggedInAttr !== " keywordfalse" : CONFIG.requireLoggedIn;
var debug = cfg("ms-code-debug", " keywordfalse") === " keywordtrue";
var requiredAttr = cfg("ms-code-required", "");
var requiredList = requiredAttr.split(",").map(function(s) { return s.trim(); }).filter(Boolean);
var saveBtns = root.querySelectorAll('[data-ms-action="save"]');
var closeBtns = root.querySelectorAll('[data-ms-action="close"]');
var statusEls = root.querySelectorAll("[data-ms-consent-status]");
var dateEls = root.querySelectorAll("[data-ms-consent-date]");
function log() {
if (debug) console.log.apply(console, ["Memberscript # number235:"].concat([].slice.call(arguments)));
}
function consentKey(el) {
return (el.getAttribute("data-ms-consent") || "").trim();
}
function isCheckbox(el) {
return el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio");
}
function fmt(iso) {
if (!iso) return "";
var d = new Date(iso);
return isNaN(d.getTime()) ? "" : d.toLocaleString();
}
var requiredKeys = {};
controls.forEach(function(el) {
var key = consentKey(el);
if (!key) return;
var req;
if (requiredList.length) {
req = requiredList.indexOf(key) !== -1;
} else {
var a = el.getAttribute("data-ms-required");
req = a !== null ? a !== " keywordfalse" : true;
}
if (req) requiredKeys[key] = true;
});
var member = null;
try {
var memberResult = await memberstack.getCurrentMember();
member = memberResult && (memberResult.data || memberResult);
} catch (e) {
console.warn("Memberscript # number235: Could not get member", e);
}
if (requireLoggedIn && (!member || !member.id)) {
log("member not logged keywordin; consent modal disabled");
return;
}
var memberJSON = {};
try {
var jsonResult = await memberstack.getMemberJSON();
memberJSON = (jsonResult && jsonResult.data) || {};
} catch (e) {
log("could not load member JSON", e);
}
var record = memberJSON[jsonKey];
if (!record || typeof record !== "object") record = {};
if (keepHistory && !Array.isArray(record.history)) record.history = [];
function entryFor(key) {
var e = record[key];
return e && typeof e === "object" ? e : null;
}
function allRequiredAccepted() {
return Object.keys(requiredKeys).every(function(key) {
var entry = entryFor(key);
return !!(entry && entry.accepted);
});
}
function allRequiredChecked() {
return Object.keys(requiredKeys).every(function(key) {
var ok = false;
controls.forEach(function(el) {
if (consentKey(el) === key && isCheckbox(el) && el.checked) ok = true;
});
return ok;
});
}
function reflectState() {
controls.forEach(function(el) {
var key = consentKey(el);
if (key && isCheckbox(el)) {
var entry = entryFor(key);
el.checked = !!(entry && entry.accepted);
}
});
statusEls.forEach(function(el) {
var key = (el.getAttribute("data-ms-consent-status") || "").trim();
var entry = entryFor(key);
el.textContent = entry && entry.accepted ? "Accepted" : "Not accepted";
});
dateEls.forEach(function(el) {
var key = (el.getAttribute("data-ms-consent-date") || "").trim();
var entry = entryFor(key);
var when = entry && entry.accepted ? fmt(entry.acceptedAt) : "";
el.textContent = when;
el.style.display = when ? "" : "none";
});
}
function updateSaveState() {
var ok = allRequiredChecked();
saveBtns.forEach(function(btn) {
btn.disabled = !ok;
});
}
function applyConsent(key, accepted) {
var now = new Date().toISOString();
var entry = entryFor(key) || {};
if (accepted && !entry.accepted) entry.acceptedAt = now;
if (!accepted && entry.accepted) entry.withdrawnAt = now;
entry.accepted = !!accepted;
entry.updatedAt = now;
entry.version = version;
record[key] = entry;
if (keepHistory) {
record.history.push({ consent: key, accepted: !!accepted, at: now, version: version });
if (historyMax > 0 && record.history.length > historyMax) {
record.history = record.history.slice(record.history.length - historyMax);
}
}
}
async function persist() {
memberJSON[jsonKey] = record;
try {
await memberstack.updateMemberJSON({ json: memberJSON });
log("saved consent record", record);
return true;
} catch (e) {
console.error("Memberscript # number235: Could not save consent", e);
return false;
}
}
function showModal() {
root.style.display = activeDisplay;
}
function hideModal() {
root.style.display = "none";
}
controls.forEach(function(el) {
if (isCheckbox(el)) {
el.addEventListener("change", updateSaveState);
}
});
saveBtns.forEach(function(btn) {
btn.addEventListener("click", async function(e) {
e.preventDefault();
if (!allRequiredChecked()) return;
controls.forEach(function(el) {
var key = consentKey(el);
if (key && isCheckbox(el)) applyConsent(key, el.checked);
});
btn.disabled = true;
var ok = await persist();
reflectState();
if (ok) hideModal();
else btn.disabled = false;
});
});
closeBtns.forEach(function(btn) {
btn.addEventListener("click", function(e) {
e.preventDefault();
hideModal();
});
});
reflectState();
updateSaveState();
if (!allRequiredAccepted()) {
showModal();
}
});
</script>More scripts in Modals