500 lines
16 KiB
JavaScript
500 lines
16 KiB
JavaScript
/* Maple GDPR Cookies - Script Blocker (GDPR Compliant) */
|
|
(function () {
|
|
"use strict";
|
|
|
|
// Check consent status immediately
|
|
const consentCookie = getCookie("mgc_consent");
|
|
const consentCategories = getCookie("mgc_consent_categories");
|
|
|
|
// If user has given consent, enable scripts
|
|
if (consentCookie === "accept" && consentCategories) {
|
|
const categories = JSON.parse(consentCategories || "[]");
|
|
enableScripts(categories);
|
|
}
|
|
|
|
// Block scripts on initial load (GDPR compliance - prior consent)
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
blockScripts();
|
|
|
|
// Show notice if no consent given
|
|
if (!consentCookie) {
|
|
createNotice();
|
|
} else {
|
|
// Add persistent cookie settings button or footer text
|
|
addPersistentPreferenceLink();
|
|
}
|
|
|
|
// Handle clicks on shortcode preference links
|
|
document.addEventListener("click", function (e) {
|
|
if (
|
|
e.target.matches("[data-mgc-preferences-trigger]") ||
|
|
e.target.closest("[data-mgc-preferences-trigger]")
|
|
) {
|
|
e.preventDefault();
|
|
showSettingsModal();
|
|
}
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Block all non-essential scripts until consent is given
|
|
* CRITICAL for GDPR compliance
|
|
*/
|
|
function blockScripts() {
|
|
// Find all scripts with data-category attribute
|
|
const scripts = document.querySelectorAll("script[data-cookie-category]");
|
|
|
|
scripts.forEach(function (script) {
|
|
const category = script.getAttribute("data-cookie-category");
|
|
|
|
// Check if this category is allowed
|
|
if (!isCategoryAllowed(category)) {
|
|
// Block the script by changing type
|
|
if (script.type !== "text/plain") {
|
|
script.type = "text/plain";
|
|
script.setAttribute("data-original-type", "text/javascript");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Enable scripts for allowed categories
|
|
*/
|
|
function enableScripts(allowedCategories) {
|
|
// Always allow functional
|
|
if (!allowedCategories.includes("functional")) {
|
|
allowedCategories.push("functional");
|
|
}
|
|
|
|
// Find all blocked scripts
|
|
const scripts = document.querySelectorAll(
|
|
'script[data-cookie-category][type="text/plain"]',
|
|
);
|
|
|
|
scripts.forEach(function (script) {
|
|
const category = script.getAttribute("data-cookie-category");
|
|
|
|
// If category is allowed, re-enable script
|
|
if (allowedCategories.includes(category)) {
|
|
const originalType =
|
|
script.getAttribute("data-original-type") || "text/javascript";
|
|
|
|
// Create new script element (changing type on existing doesn't execute)
|
|
const newScript = document.createElement("script");
|
|
newScript.type = originalType;
|
|
|
|
// Copy attributes
|
|
Array.from(script.attributes).forEach(function (attr) {
|
|
if (attr.name !== "type" && attr.name !== "data-original-type") {
|
|
newScript.setAttribute(attr.name, attr.value);
|
|
}
|
|
});
|
|
|
|
// Copy content
|
|
if (script.src) {
|
|
newScript.src = script.src;
|
|
} else {
|
|
newScript.textContent = script.textContent;
|
|
}
|
|
|
|
// Replace old script with new one
|
|
script.parentNode.replaceChild(newScript, script);
|
|
}
|
|
});
|
|
|
|
// Trigger event for other integrations
|
|
document.dispatchEvent(
|
|
new CustomEvent("mgc_scripts_loaded", {
|
|
detail: { categories: allowedCategories },
|
|
}),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check if a category is currently allowed
|
|
*/
|
|
function isCategoryAllowed(category) {
|
|
const consentCookie = getCookie("mgc_consent");
|
|
if (consentCookie !== "accept") {
|
|
return false;
|
|
}
|
|
|
|
const categories = JSON.parse(getCookie("mgc_consent_categories") || "[]");
|
|
return categories.includes(category) || category === "functional";
|
|
}
|
|
|
|
/**
|
|
* Add persistent cookie preference link (GDPR requirement - easy withdrawal)
|
|
* Can be either a floating icon button or footer text link based on settings
|
|
*/
|
|
function addPersistentPreferenceLink() {
|
|
// Check what type of display is preferred
|
|
const displayType = window.mgcSettings?.preferenceDisplayType || "icon";
|
|
|
|
// If 'neither', don't add anything - user will use shortcode
|
|
if (displayType === "neither") {
|
|
return;
|
|
}
|
|
|
|
// Check if element already exists
|
|
if (
|
|
document.querySelector(".mgc-floating-button") ||
|
|
document.querySelector(".mgc-footer-preference-link")
|
|
) {
|
|
return;
|
|
}
|
|
|
|
if (displayType === "footer") {
|
|
// Create footer text link
|
|
const footerLink = document.createElement("a");
|
|
footerLink.className = "mgc-footer-preference-link";
|
|
footerLink.href = "#";
|
|
footerLink.textContent = "Cookie Preferences";
|
|
footerLink.setAttribute("aria-label", "Cookie Preferences");
|
|
footerLink.onclick = function (e) {
|
|
e.preventDefault();
|
|
showSettingsModal();
|
|
};
|
|
|
|
document.body.appendChild(footerLink);
|
|
} else {
|
|
// Create floating icon button (default)
|
|
const button = document.createElement("button");
|
|
button.className = "mgc-floating-button";
|
|
button.setAttribute("aria-label", "Cookie Settings");
|
|
button.innerHTML =
|
|
'<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z"/></svg>';
|
|
button.title = "Cookie Settings";
|
|
button.onclick = function () {
|
|
showSettingsModal();
|
|
};
|
|
|
|
document.body.appendChild(button);
|
|
}
|
|
}
|
|
|
|
function createNotice() {
|
|
const settings = window.mgcSettings || {};
|
|
|
|
// Create notice container
|
|
const notice = document.createElement("div");
|
|
notice.className =
|
|
"mgc-notice mgc-position-" +
|
|
(settings.position || "bottom") +
|
|
" mgc-theme-" +
|
|
(settings.theme || "light") +
|
|
" mgc-animation-" +
|
|
(settings.animation || "slide");
|
|
|
|
// Create content
|
|
const content = document.createElement("div");
|
|
content.className = "mgc-notice-content";
|
|
const noticeText = (
|
|
settings.noticeText ||
|
|
"We use cookies to enhance your browsing experience."
|
|
)
|
|
.replace(/\\"/g, '"')
|
|
.replace(/\\\\/g, "\\")
|
|
.replace(/"/g, '"')
|
|
.replace(/"Accept All"/g, "<strong>Accept All</strong>")
|
|
.replace(/"Reject All"/g, "<strong>Reject All</strong>");
|
|
content.innerHTML = noticeText;
|
|
|
|
// Add privacy policy link if provided
|
|
if (settings.privacyPolicyUrl) {
|
|
content.innerHTML +=
|
|
' <a href="' +
|
|
settings.privacyPolicyUrl +
|
|
'" class="mgc-privacy-link" target="_blank">' +
|
|
(settings.privacyPolicyText || "Privacy Policy") +
|
|
"</a>";
|
|
}
|
|
|
|
// Create buttons container
|
|
const buttons = document.createElement("div");
|
|
buttons.className = "mgc-notice-buttons";
|
|
|
|
// Accept button
|
|
const acceptBtn = document.createElement("button");
|
|
acceptBtn.className =
|
|
"mgc-button mgc-button-accept mgc-button-color-" +
|
|
(settings.buttonColor || "blue");
|
|
acceptBtn.textContent = settings.acceptButtonText || "Accept All";
|
|
acceptBtn.onclick = function () {
|
|
handleConsent("accept", ["analytics", "marketing", "functional"]);
|
|
};
|
|
buttons.appendChild(acceptBtn);
|
|
|
|
// Reject button (optional)
|
|
if (settings.showRejectButton) {
|
|
const rejectBtn = document.createElement("button");
|
|
rejectBtn.className =
|
|
"mgc-button mgc-button-reject mgc-button-color-" +
|
|
(settings.buttonColor || "blue");
|
|
rejectBtn.textContent = settings.rejectButtonText || "Reject All";
|
|
rejectBtn.onclick = function () {
|
|
handleConsent("reject", ["functional"]); // Only functional cookies
|
|
};
|
|
buttons.appendChild(rejectBtn);
|
|
}
|
|
|
|
// Settings button (optional)
|
|
if (settings.showSettingsButton) {
|
|
const settingsBtn = document.createElement("button");
|
|
settingsBtn.className =
|
|
"mgc-button mgc-button-settings mgc-button-color-" +
|
|
(settings.buttonColor || "blue");
|
|
settingsBtn.textContent =
|
|
settings.settingsButtonText || "Cookie Settings";
|
|
settingsBtn.onclick = function () {
|
|
showSettingsModal();
|
|
};
|
|
buttons.appendChild(settingsBtn);
|
|
}
|
|
|
|
// Append elements
|
|
notice.appendChild(content);
|
|
notice.appendChild(buttons);
|
|
document.body.appendChild(notice);
|
|
}
|
|
|
|
function showSettingsModal() {
|
|
// Remove initial notice if present
|
|
const initialNotice = document.querySelector(".mgc-notice");
|
|
if (initialNotice) {
|
|
initialNotice.classList.add("mgc-hidden");
|
|
}
|
|
|
|
// Create settings modal
|
|
const modal = document.createElement("div");
|
|
modal.className = "mgc-settings-modal";
|
|
|
|
const modalContent = document.createElement("div");
|
|
modalContent.className = "mgc-settings-content";
|
|
|
|
// Modal title
|
|
const title = document.createElement("h3");
|
|
title.textContent = "Cookie Settings";
|
|
title.style.marginTop = "0";
|
|
modalContent.appendChild(title);
|
|
|
|
// Description
|
|
const desc = document.createElement("p");
|
|
desc.textContent = "Choose which types of cookies you want to allow:";
|
|
modalContent.appendChild(desc);
|
|
|
|
// Get current consent
|
|
const currentCategories = JSON.parse(
|
|
getCookie("mgc_consent_categories") || '["functional"]',
|
|
);
|
|
|
|
// Cookie categories
|
|
const categories = [
|
|
{
|
|
id: "functional",
|
|
label: "Functional Cookies",
|
|
description:
|
|
"These cookies are essential for the website to function properly. They enable basic features like page navigation, security, and access to secure areas. The website cannot function properly without these cookies.",
|
|
required: true,
|
|
},
|
|
{
|
|
id: "analytics",
|
|
label: "Analytics Cookies",
|
|
description:
|
|
"These cookies help us understand how visitors interact with our website by collecting and reporting information anonymously. They help us improve our website performance.",
|
|
required: false,
|
|
},
|
|
{
|
|
id: "marketing",
|
|
label: "Marketing Cookies",
|
|
description:
|
|
"These cookies are used to track visitors across websites and display personalized advertisements. They may be set by third-party advertising networks.",
|
|
required: false,
|
|
},
|
|
];
|
|
|
|
const checkboxes = [];
|
|
categories.forEach(function (cat) {
|
|
const categoryDiv = document.createElement("div");
|
|
categoryDiv.className = "mgc-category";
|
|
categoryDiv.style.marginBottom = "15px";
|
|
categoryDiv.style.padding = "10px";
|
|
categoryDiv.style.border = "1px solid #ddd";
|
|
categoryDiv.style.borderRadius = "4px";
|
|
|
|
const label = document.createElement("label");
|
|
label.style.display = "flex";
|
|
label.style.alignItems = "flex-start";
|
|
label.style.cursor = cat.required ? "not-allowed" : "pointer";
|
|
|
|
const checkbox = document.createElement("input");
|
|
checkbox.type = "checkbox";
|
|
checkbox.id = "mgc-cat-" + cat.id;
|
|
checkbox.value = cat.id;
|
|
checkbox.checked = currentCategories.includes(cat.id);
|
|
checkbox.disabled = cat.required;
|
|
checkbox.style.marginRight = "10px";
|
|
checkbox.style.marginTop = "3px";
|
|
|
|
if (!cat.required) {
|
|
checkboxes.push(checkbox);
|
|
}
|
|
|
|
const textDiv = document.createElement("div");
|
|
|
|
const labelText = document.createElement("strong");
|
|
labelText.textContent = cat.label;
|
|
if (cat.required) {
|
|
labelText.textContent += " (Always Active)";
|
|
}
|
|
|
|
const descText = document.createElement("div");
|
|
descText.textContent = cat.description;
|
|
descText.style.fontSize = "13px";
|
|
descText.style.color = "#666";
|
|
descText.style.marginTop = "3px";
|
|
|
|
textDiv.appendChild(labelText);
|
|
textDiv.appendChild(descText);
|
|
|
|
label.appendChild(checkbox);
|
|
label.appendChild(textDiv);
|
|
categoryDiv.appendChild(label);
|
|
modalContent.appendChild(categoryDiv);
|
|
});
|
|
|
|
// Buttons
|
|
const buttonRow = document.createElement("div");
|
|
buttonRow.className = "mgc-notice-buttons";
|
|
buttonRow.style.marginTop = "20px";
|
|
|
|
// Save Preferences button
|
|
const saveBtn = document.createElement("button");
|
|
saveBtn.className =
|
|
"mgc-button mgc-button-accept mgc-button-color-" +
|
|
(window.mgcSettings?.buttonColor || "blue");
|
|
saveBtn.textContent = "Save Preferences";
|
|
saveBtn.onclick = function () {
|
|
const selectedCategories = ["functional"];
|
|
checkboxes.forEach(function (cb) {
|
|
if (cb.checked) {
|
|
selectedCategories.push(cb.value);
|
|
}
|
|
});
|
|
handleConsent("accept", selectedCategories);
|
|
modal.remove();
|
|
};
|
|
buttonRow.appendChild(saveBtn);
|
|
|
|
// Accept All button
|
|
const acceptAll = document.createElement("button");
|
|
acceptAll.className =
|
|
"mgc-button mgc-button-accept mgc-button-color-" +
|
|
(window.mgcSettings?.buttonColor || "blue");
|
|
acceptAll.textContent = "Accept All";
|
|
acceptAll.onclick = function () {
|
|
handleConsent("accept", ["functional", "analytics", "marketing"]);
|
|
modal.remove();
|
|
};
|
|
buttonRow.appendChild(acceptAll);
|
|
|
|
// Reject Optional button
|
|
const rejectOptional = document.createElement("button");
|
|
rejectOptional.className =
|
|
"mgc-button mgc-button-settings mgc-button-color-" +
|
|
(window.mgcSettings?.buttonColor || "blue");
|
|
rejectOptional.textContent = "Reject Optional";
|
|
rejectOptional.onclick = function () {
|
|
handleConsent("accept", ["functional"]);
|
|
modal.remove();
|
|
};
|
|
buttonRow.appendChild(rejectOptional);
|
|
|
|
modalContent.appendChild(buttonRow);
|
|
modal.appendChild(modalContent);
|
|
document.body.appendChild(modal);
|
|
}
|
|
|
|
function handleConsent(type, categories) {
|
|
// Set cookies
|
|
const expiry = window.mgcSettings?.cookieExpiry || 365;
|
|
setCookie("mgc_consent", type, expiry);
|
|
setCookie("mgc_consent_categories", JSON.stringify(categories), expiry);
|
|
|
|
// Enable scripts for allowed categories
|
|
enableScripts(categories);
|
|
|
|
// Send to server
|
|
if (window.mgcSettings?.ajaxUrl) {
|
|
const formData = new FormData();
|
|
formData.append("action", "mgc_save_consent");
|
|
formData.append("nonce", window.mgcSettings.nonce);
|
|
formData.append("consent_type", type);
|
|
|
|
categories.forEach(function (cat) {
|
|
formData.append("categories[]", cat);
|
|
});
|
|
|
|
fetch(window.mgcSettings.ajaxUrl, {
|
|
method: "POST",
|
|
body: formData,
|
|
}).catch(function () {
|
|
// Silently fail
|
|
});
|
|
}
|
|
|
|
// Remove notice
|
|
const notice = document.querySelector(".mgc-notice");
|
|
if (notice) {
|
|
notice.classList.add("mgc-hidden");
|
|
setTimeout(function () {
|
|
notice.remove();
|
|
}, 300);
|
|
}
|
|
|
|
// Add persistent preference link
|
|
addPersistentPreferenceLink();
|
|
|
|
// Trigger event
|
|
document.dispatchEvent(
|
|
new CustomEvent("mgc_consent_saved", {
|
|
detail: { type: type, categories: categories },
|
|
}),
|
|
);
|
|
|
|
// Reload page to apply changes
|
|
if (type === "accept") {
|
|
setTimeout(function () {
|
|
window.location.reload();
|
|
}, 500);
|
|
}
|
|
}
|
|
|
|
function setCookie(name, value, days) {
|
|
const d = new Date();
|
|
d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000);
|
|
const expires = "expires=" + d.toUTCString();
|
|
const secure = window.location.protocol === "https:" ? ";Secure" : "";
|
|
document.cookie =
|
|
name +
|
|
"=" +
|
|
encodeURIComponent(value) +
|
|
";" +
|
|
expires +
|
|
";path=/;SameSite=Lax" +
|
|
secure;
|
|
}
|
|
|
|
function getCookie(name) {
|
|
const nameEQ = name + "=";
|
|
const ca = document.cookie.split(";");
|
|
for (let i = 0; i < ca.length; i++) {
|
|
let c = ca[i];
|
|
while (c.charAt(0) === " ") c = c.substring(1, c.length);
|
|
if (c.indexOf(nameEQ) === 0)
|
|
return decodeURIComponent(c.substring(nameEQ.length, c.length));
|
|
}
|
|
return null;
|
|
}
|
|
})();
|