From 0b15fbe964bed057f2202ccdfc78c212a499d8f6 Mon Sep 17 00:00:00 2001 From: webworkerJoshua Date: Mon, 13 Apr 2026 22:03:22 +0200 Subject: [PATCH 1/3] - add configurable option to delete user consent after 1,3,6,12 month(s) --- PrivacyWire.module | 1 + PrivacyWireConfig.php | 15 ++++++++++ js/PrivacyWire.js | 2 +- js/PrivacyWire_legacy.js | 2 +- src/js/PrivacyWire.js | 63 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 80 insertions(+), 3 deletions(-) diff --git a/PrivacyWire.module b/PrivacyWire.module index cefa167..7521a83 100644 --- a/PrivacyWire.module +++ b/PrivacyWire.module @@ -191,6 +191,7 @@ class PrivacyWire extends WireData implements Module, ConfigurableModule $privacyWireSettings->bots = ($this->checkForBots) ? "1" : "0"; $privacyWireSettings->customFunction = ($this->wire('sanitizer')->text($this->trigger_custom_js_function)) ?? ""; $privacyWireSettings->messageTimeout = ($this->messageTimeout && intval($this->messageTimeout) > 1) ? intval($this->messageTimeout) : 1500; + $privacyWireSettings->consentStorageDurationMonths = intval($this->consent_storage_duration_months ?? 0); $privacyWireSettings->consentByClass = ($this->detect_consents_by_class) ? "1" : "0"; $privacyWireSettings->cookieGroups = [ 'necessary' => $this->get("cookies_necessary_label{$this->lang}|cookies_necessary_label"), diff --git a/PrivacyWireConfig.php b/PrivacyWireConfig.php index 6a706a2..31522b0 100644 --- a/PrivacyWireConfig.php +++ b/PrivacyWireConfig.php @@ -67,6 +67,20 @@ public function __construct() 'description' => $this->_("How many milliseconds should the consent saving confirmation be visible after the user makes a choice."), 'columnWidth' => 25, ], + [ // consent storage duration + 'name' => 'consent_storage_duration_months', + 'type' => 'select', + 'label' => $this->_('Consent Storage Duration'), + 'description' => $this->_("Choose how long a consent decision may remain stored in the browser before the banner is shown again."), + 'options' => [ + "0" => $this->_("Unlimited"), + "1" => $this->_("1 month"), + "3" => $this->_("3 months"), + "6" => $this->_("6 months"), + "12" => $this->_("12 months"), + ], + 'columnWidth' => 25, + ], ], ], [ // groups labels @@ -400,6 +414,7 @@ public function getDefaults() 'textformatter_choose_label' => $this->_("Show or edit my Cookie Consent"), 'trigger_custom_js_function' => "", 'messageTimeout' => 1500, + 'consent_storage_duration_months' => 0, 'add_basic_css_styling' => true, 'ask_consent_message' => $this->_("To load this element, it is required to consent to the following cookie category: {category}."), 'ask_content_button_label' => $this->_("Load {category} cookies"), diff --git a/js/PrivacyWire.js b/js/PrivacyWire.js index b250085..01911c5 100644 --- a/js/PrivacyWire.js +++ b/js/PrivacyWire.js @@ -1 +1 @@ -!function(){"use strict";String.prototype.formatUnicorn=String.prototype.formatUnicorn||function(){var e=this.toString();if(arguments.length){var t,s=typeof arguments[0],n="string"===s||"number"===s?Array.prototype.slice.call(arguments):arguments[0];for(t in n)e=e.replace(new RegExp("\\{"+t+"\\}","gi"),n[t])}return e};class PrivacyWire{constructor(e){this.name="privacywire",this.toggleToStatus=!0,this.cookieGroups=Object.freeze(["necessary","functional","statistics","marketing","external_media"]),this.settings=this.sanitizeSettings(e),this.userConsent=this.sanitizeStoredConsent(),this.elements=this.initiateElements(),this.syncConsentToCheckboxes(),this.updateBodyClasses(),this.checkForValidConsent()||this.showBanner(),this.checkElementsWithRequiredConsent(),this.handleButtons()}sanitizeSettings(e){const t={};t.version=Number.parseInt(e.version),t.dnt=Boolean(Number.parseInt(e.dnt)),t.bots=Boolean(Number.parseInt(e.bots)),t.customFunction=`${e.customFunction}`,t.messageTimeout=Number.parseInt(e.messageTimeout),t.consentByClass=Boolean(Number.parseInt(e.consentByClass)),t.cookieGroups={};for(const s of this.cookieGroups)t.cookieGroups[s]=`${e.cookieGroups[s]}`;return t}sanitizeStoredConsent(){if(!window.localStorage.getItem(this.name))return this.getDefaultConsent();const e=JSON.parse(window.localStorage.getItem(this.name));if(Number.parseInt(e.version)!==this.settings.version)return this.getDefaultConsent();if(void 0===e.cookieGroups)return this.removeStoredConsent(),this.getDefaultConsent();const t={};t.version=Number.parseInt(e.version),t.cookieGroups={};for(const s of this.cookieGroups)t.cookieGroups[s]=Boolean(e.cookieGroups[s]);return t}getDefaultConsent(){const e={version:0,cookieGroups:{}};for(const t of this.cookieGroups)e.cookieGroups[t]="necessary"===t;return e}initiateElements(){const e={banner:{}};e.banner.wrapper=document.getElementById("privacywire-wrapper"),e.banner.intro=e.banner.wrapper.getElementsByClassName("privacywire-banner"),e.banner.options=e.banner.wrapper.getElementsByClassName("privacywire-options"),e.banner.message=e.banner.wrapper.getElementsByClassName("privacywire-message"),e.buttons={},e.buttons.acceptAll=e.banner.wrapper.getElementsByClassName("allow-all"),e.buttons.acceptNecessary=e.banner.wrapper.getElementsByClassName("allow-necessary"),e.buttons.choose=e.banner.wrapper.getElementsByClassName("choose"),e.buttons.toggle=e.banner.wrapper.getElementsByClassName("toggle"),e.buttons.save=e.banner.wrapper.getElementsByClassName("save"),e.buttons.askForConsent=document.getElementsByClassName("privacywire-consent-button"),e.buttons.externalTrigger=document.getElementsByClassName("privacywire-show-options"),e.checkboxes={};for(const t of this.cookieGroups)"necessary"!==t&&(e.checkboxes[t]=document.getElementById(t));return e.blueprint=document.getElementById("privacywire-ask-consent-blueprint"),e.elementsWithRequiredConsent=!0===this.settings.consentByClass?document.getElementsByClassName("require-consent"):document.querySelectorAll("[data-category]"),e.consentWindows=document.getElementsByClassName("privacywire-ask-consent"),e}handleButtons(){this.handleButtonHelper(this.elements.buttons.acceptAll,"handleButtonAcceptAll"),this.handleButtonHelper(this.elements.buttons.acceptNecessary,"handleButtonAcceptNecessary"),this.handleButtonHelper(this.elements.buttons.choose,"handleButtonChoose"),this.handleButtonHelper(this.elements.buttons.toggle,"handleButtonToggle"),this.handleButtonHelper(this.elements.buttons.save,"handleButtonSave"),this.handleButtonHelper(this.elements.buttons.askForConsent,"handleButtonAskForConsent"),this.handleButtonHelper(this.elements.buttons.externalTrigger,"handleButtonExternalTrigger")}handleButtonHelper(e,t){if(e)for(const s of e)this[t](s)}reHandleExternalButtons(){this.elements.buttons.externalTrigger=document.getElementsByClassName("privacywire-show-options"),this.handleButtonHelper(this.elements.buttons.externalTrigger,"handleButtonExternalTrigger")}handleButtonAcceptAll(e){e.addEventListener("click",(()=>{for(const e of this.cookieGroups)this.userConsent.cookieGroups[e]=!0;this.syncConsentToCheckboxes(),this.saveConsent()}))}handleButtonAcceptNecessary(e){e.addEventListener("click",(()=>{this.userConsent=this.getDefaultConsent(),this.syncConsentToCheckboxes(),this.saveConsent()}))}handleButtonChoose(e){e.addEventListener("click",(()=>{this.showOptions()}))}handleButtonToggle(e){e.addEventListener("click",(()=>{for(const e in this.elements.checkboxes)this.elements.checkboxes[e].checked=this.toggleToStatus;this.toggleToStatus=!this.toggleToStatus}))}handleButtonSave(e){e.addEventListener("click",(()=>{for(const e of this.cookieGroups)"necessary"!==e&&(this.userConsent.cookieGroups[e]=this.elements.checkboxes[e].checked);this.saveConsent()}))}handleButtonAskForConsent(e){e.addEventListener("click",(()=>{const{dataset:t}=e;this.userConsent.cookieGroups[t.consentCategory]=!0,this.syncConsentToCheckboxes(),this.saveConsent(),e.parentElement.remove()}))}handleButtonExternalTrigger(e){e.addEventListener("click",(e=>{e.preventDefault(),this.showOptions()}))}syncConsentToCheckboxes(){for(const e of this.cookieGroups)"necessary"!==e&&(this.elements.checkboxes[e].checked=this.userConsent.cookieGroups[e])}checkForValidConsent(){return this.userConsent.version>0&&this.userConsent.version===this.settings.version||(this.settings.bots?this.checkForBots():this.settings.dnt&&!0===this.checkForUsersDNT())}checkForUsersDNT(){return!(!this.settings.dnt||"1"!==navigator.doNotTrack)&&(this.userConsent=this.getDefaultConsent(),this.saveConsent(!0),!0)}detectRobot(){return new RegExp([/bot/,/spider/,/crawl/,/APIs-Google/,/AdsBot/,/Googlebot/,/mediapartners/,/Google Favicon/,/Google Page Speed Insights/,/Chrome-Lighthouse/,/FeedFetcher/,/Google-Read-Aloud/,/DuplexWeb-Google/,/googleweblight/,/bing/,/yandex/,/baidu/,/duckduck/,/yahoo/,/ecosia/,/ia_archiver/,/facebook/,/instagram/,/pinterest/,/reddit/,/slack/,/twitter/,/whatsapp/,/youtube/,/semrush/].map((e=>e.source)).join("|"),"i").test(navigator.userAgent)}checkForBots(){return!!this.detectRobot()&&(this.userConsent=this.getDefaultConsent(),this.saveConsent(!0),!0)}updateBodyClasses(){for(const e of this.cookieGroups){const t=`consent-${e}`;this.userConsent.cookieGroups[e]?document.body.classList.add(t):document.body.classList.remove(t)}}saveConsent(e=!1){this.userConsent.version=this.settings.version,window.localStorage.removeItem(this.name),window.localStorage.setItem(this.name,JSON.stringify(this.userConsent)),this.hideBannerAndOptions(),e||this.showMessage(),this.checkElementsWithRequiredConsent(),this.updateBodyClasses(),this.triggerCustomFunction()}triggerCustomFunction(){this.settings.customFunction.length&&"function"==typeof window[this.settings.customFunction]&&window[this.settings.customFunction]()}hideBannerAndOptions(){this.elements.banner.wrapper.classList.remove("show-banner","show-options"),document.body.classList.remove("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireBannerAndOptionsClosed"))}showBanner(){this.elements.banner.wrapper.classList.add("show-banner"),document.body.classList.add("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireBannerOpened"))}showOptions(){this.elements.banner.wrapper.classList.remove("show-banner"),this.elements.banner.wrapper.classList.add("show-options"),document.body.classList.add("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireOptionsOpened"))}showMessage(){this.elements.banner.wrapper.classList.add("show-message"),setTimeout((()=>{this.elements.banner.wrapper.classList.remove("show-message")}),this.settings.messageTimeout)}checkElementsWithRequiredConsent(){if(!1===this.settings.consentByClass&&(this.elements.elementsWithRequiredConsent=document.querySelectorAll("[data-category]")),this.cleanOldConsentWindows(),this.elements.elementsWithRequiredConsent)for(const e of this.elements.elementsWithRequiredConsent){const t=e.dataset.category;if(!t)continue;let s=!1;for(const e in this.userConsent.cookieGroups)if(e===t&&!0===this.userConsent.cookieGroups[e]){s=!0;break}s?this.updateAllowedElement(e):this.updateDisallowedElement(e)}}cleanOldConsentWindows(){if(this.elements.consentWindows)for(const e of this.elements.consentWindows){const{dataset:t}=e,s=t.disallowedConsentCategory;let n=!1;for(const e in this.userConsent.cookieGroups)if(e===s&&!0===this.userConsent.cookieGroups[e]){n=!0;break}n&&e.remove()}}updateDisallowedElement(e){const{dataset:t}=e;if(!t.askConsent||"1"===t.askConsentRendered)return;const s=t.category,n=this.settings.cookieGroups[s],o=document.createElement("div");o.classList.add("privacywire-ask-consent",`consent-category-${s}`),o.dataset.disallowedConsentCategory=s,o.innerHTML=this.elements.blueprint.innerHTML.formatUnicorn({category:n,categoryname:s}),t.askConsentMessage&&(o.querySelector(".privacywire-consent-message").textContent=t.askConsentMessage),t.askConsentButtonLabel&&(o.querySelector("button").textContent=t.askConsentButtonLabel),e.insertAdjacentElement("afterend",o),e.dataset.askConsentRendered="1"}updateAllowedElement(e){"script"===e.tagName.toLowerCase()?this.updateAllowedElementScript(e):this.updateAllowedElementOther(e)}updateAllowedElementScript(e){const{dataset:t}=e;let s=document.createElement(e.tagName);for(const n of Object.keys(t))s.dataset[n]=e.dataset[n];s.type=t.type??"text/javascript",t.src&&(s.src=t.src),s.textContent=e.textContent,e.id&&(s.id=e.id),s.defer=e.defer,s.async=e.async,s=this.removeUnusedAttributesFromElement(s),e.insertAdjacentElement("afterend",s),e.remove()}updateAllowedElementOther(e){const{dataset:t}=e;e.type=t.type??"text/javascript";for(const s of["src","srcset","srcdoc","poster"])void 0!==t[s]&&(e[s]=t[s]);this.removeUnusedAttributesFromElement(e)}removeUnusedAttributesFromElement(e){return e.removeAttribute("data-ask-consent"),e.removeAttribute("data-ask-consent-rendered"),e.removeAttribute("data-category"),e.removeAttribute("data-poster"),e.removeAttribute("data-src"),e.removeAttribute("data-srcset"),e.removeAttribute("data-srcdoc"),e.removeAttribute("data-type"),e.classList.remove("require-consent"),e}refresh(){this.checkElementsWithRequiredConsent(),this.handleButtonHelper(this.elements.buttons.askForConsent,"handleButtonAskForConsent")}removeStoredConsent(){window.localStorage.getItem(this.name)&&window.localStorage.removeItem(this.name)}}document.addEventListener("DOMContentLoaded",(()=>{window.PrivacyWire=new PrivacyWire(PrivacyWireSettings)}))}(); \ No newline at end of file +!function(){"use strict";String.prototype.formatUnicorn=String.prototype.formatUnicorn||function(){var e=this.toString();if(arguments.length){var t,s=typeof arguments[0],n="string"===s||"number"===s?Array.prototype.slice.call(arguments):arguments[0];for(t in n)e=e.replace(new RegExp("\\{"+t+"\\}","gi"),n[t])}return e};class PrivacyWire{constructor(e){this.name="privacywire",this.toggleToStatus=!0,this.cookieGroups=Object.freeze(["necessary","functional","statistics","marketing","external_media"]),this.settings=this.sanitizeSettings(e),this.userConsent=this.sanitizeStoredConsent(),this.elements=this.initiateElements(),this.syncConsentToCheckboxes(),this.updateBodyClasses(),this.checkForValidConsent()||this.showBanner(),this.checkElementsWithRequiredConsent(),this.handleButtons()}sanitizeSettings(e){const t={};t.version=Number.parseInt(e.version),t.dnt=Boolean(Number.parseInt(e.dnt)),t.bots=Boolean(Number.parseInt(e.bots)),t.customFunction=`${e.customFunction}`,t.messageTimeout=Number.parseInt(e.messageTimeout),t.consentStorageDurationMonths=Number.parseInt(e.consentStorageDurationMonths)||0,t.consentByClass=Boolean(Number.parseInt(e.consentByClass)),t.cookieGroups={};for(const s of this.cookieGroups)t.cookieGroups[s]=`${e.cookieGroups[s]}`;return t}sanitizeStoredConsent(){if(!window.localStorage.getItem(this.name))return this.getDefaultConsent();let e;try{e=JSON.parse(window.localStorage.getItem(this.name))}catch{return this.removeStoredConsent(),this.getDefaultConsent()}if(Number.parseInt(e.version)!==this.settings.version)return this.getDefaultConsent();if(void 0===e.cookieGroups)return this.removeStoredConsent(),this.getDefaultConsent();if(this.hasConsentExpired(e))return this.removeStoredConsent(),this.getDefaultConsent();const t={};t.version=Number.parseInt(e.version),t.storedAt=this.getStoredAtTimestamp(e),t.cookieGroups={};for(const s of this.cookieGroups)t.cookieGroups[s]=Boolean(e.cookieGroups[s]);return t}getDefaultConsent(){const e={version:0,storedAt:null,cookieGroups:{}};for(const t of this.cookieGroups)e.cookieGroups[t]="necessary"===t;return e}getStoredAtTimestamp(e){const t=Number.parseInt(e.storedAt);return!Number.isFinite(t)||t<=0?null:t}hasConsentExpired(e){if(this.settings.consentStorageDurationMonths<=0)return!1;const t=this.getStoredAtTimestamp(e);return null===t||Date.now()>=this.getConsentExpiryTimestamp(t)}getConsentExpiryTimestamp(e){const t=new Date(e),s=t.getUTCDate();return t.setUTCDate(1),t.setUTCMonth(t.getUTCMonth()+this.settings.consentStorageDurationMonths),t.setUTCDate(Math.min(s,this.getDaysInUtcMonth(t))),t.getTime()}getDaysInUtcMonth(e){return new Date(Date.UTC(e.getUTCFullYear(),e.getUTCMonth()+1,0)).getUTCDate()}initiateElements(){const e={banner:{}};e.banner.wrapper=document.getElementById("privacywire-wrapper"),e.banner.intro=e.banner.wrapper.getElementsByClassName("privacywire-banner"),e.banner.options=e.banner.wrapper.getElementsByClassName("privacywire-options"),e.banner.message=e.banner.wrapper.getElementsByClassName("privacywire-message"),e.buttons={},e.buttons.acceptAll=e.banner.wrapper.getElementsByClassName("allow-all"),e.buttons.acceptNecessary=e.banner.wrapper.getElementsByClassName("allow-necessary"),e.buttons.choose=e.banner.wrapper.getElementsByClassName("choose"),e.buttons.toggle=e.banner.wrapper.getElementsByClassName("toggle"),e.buttons.save=e.banner.wrapper.getElementsByClassName("save"),e.buttons.askForConsent=document.getElementsByClassName("privacywire-consent-button"),e.buttons.externalTrigger=document.getElementsByClassName("privacywire-show-options"),e.checkboxes={};for(const t of this.cookieGroups)"necessary"!==t&&(e.checkboxes[t]=document.getElementById(t));return e.blueprint=document.getElementById("privacywire-ask-consent-blueprint"),e.elementsWithRequiredConsent=!0===this.settings.consentByClass?document.getElementsByClassName("require-consent"):document.querySelectorAll("[data-category]"),e.consentWindows=document.getElementsByClassName("privacywire-ask-consent"),e}handleButtons(){this.handleButtonHelper(this.elements.buttons.acceptAll,"handleButtonAcceptAll"),this.handleButtonHelper(this.elements.buttons.acceptNecessary,"handleButtonAcceptNecessary"),this.handleButtonHelper(this.elements.buttons.choose,"handleButtonChoose"),this.handleButtonHelper(this.elements.buttons.toggle,"handleButtonToggle"),this.handleButtonHelper(this.elements.buttons.save,"handleButtonSave"),this.handleButtonHelper(this.elements.buttons.askForConsent,"handleButtonAskForConsent"),this.handleButtonHelper(this.elements.buttons.externalTrigger,"handleButtonExternalTrigger")}handleButtonHelper(e,t){if(e)for(const s of e)this[t](s)}reHandleExternalButtons(){this.elements.buttons.externalTrigger=document.getElementsByClassName("privacywire-show-options"),this.handleButtonHelper(this.elements.buttons.externalTrigger,"handleButtonExternalTrigger")}handleButtonAcceptAll(e){e.addEventListener("click",(()=>{for(const e of this.cookieGroups)this.userConsent.cookieGroups[e]=!0;this.syncConsentToCheckboxes(),this.saveConsent()}))}handleButtonAcceptNecessary(e){e.addEventListener("click",(()=>{this.userConsent=this.getDefaultConsent(),this.syncConsentToCheckboxes(),this.saveConsent()}))}handleButtonChoose(e){e.addEventListener("click",(()=>{this.showOptions()}))}handleButtonToggle(e){e.addEventListener("click",(()=>{for(const e in this.elements.checkboxes)this.elements.checkboxes[e].checked=this.toggleToStatus;this.toggleToStatus=!this.toggleToStatus}))}handleButtonSave(e){e.addEventListener("click",(()=>{for(const e of this.cookieGroups)"necessary"!==e&&(this.userConsent.cookieGroups[e]=this.elements.checkboxes[e].checked);this.saveConsent()}))}handleButtonAskForConsent(e){e.addEventListener("click",(()=>{const{dataset:t}=e;this.userConsent.cookieGroups[t.consentCategory]=!0,this.syncConsentToCheckboxes(),this.saveConsent(),e.parentElement.remove()}))}handleButtonExternalTrigger(e){e.addEventListener("click",(e=>{e.preventDefault(),this.showOptions()}))}syncConsentToCheckboxes(){for(const e of this.cookieGroups)"necessary"!==e&&(this.elements.checkboxes[e].checked=this.userConsent.cookieGroups[e])}checkForValidConsent(){return this.userConsent.version>0&&this.userConsent.version===this.settings.version||(this.settings.bots?this.checkForBots():this.settings.dnt&&!0===this.checkForUsersDNT())}checkForUsersDNT(){return!(!this.settings.dnt||"1"!==navigator.doNotTrack)&&(this.userConsent=this.getDefaultConsent(),this.saveConsent(!0),!0)}detectRobot(){return new RegExp([/bot/,/spider/,/crawl/,/APIs-Google/,/AdsBot/,/Googlebot/,/mediapartners/,/Google Favicon/,/Google Page Speed Insights/,/Chrome-Lighthouse/,/FeedFetcher/,/Google-Read-Aloud/,/DuplexWeb-Google/,/googleweblight/,/bing/,/yandex/,/baidu/,/duckduck/,/yahoo/,/ecosia/,/ia_archiver/,/facebook/,/instagram/,/pinterest/,/reddit/,/slack/,/twitter/,/whatsapp/,/youtube/,/semrush/].map((e=>e.source)).join("|"),"i").test(navigator.userAgent)}checkForBots(){return!!this.detectRobot()&&(this.userConsent=this.getDefaultConsent(),this.saveConsent(!0),!0)}updateBodyClasses(){for(const e of this.cookieGroups){const t=`consent-${e}`;this.userConsent.cookieGroups[e]?document.body.classList.add(t):document.body.classList.remove(t)}}saveConsent(e=!1){this.userConsent.version=this.settings.version,this.userConsent.storedAt=Date.now(),window.localStorage.removeItem(this.name),window.localStorage.setItem(this.name,JSON.stringify(this.userConsent)),this.hideBannerAndOptions(),e||this.showMessage(),this.checkElementsWithRequiredConsent(),this.updateBodyClasses(),this.triggerCustomFunction()}triggerCustomFunction(){this.settings.customFunction.length&&"function"==typeof window[this.settings.customFunction]&&window[this.settings.customFunction]()}hideBannerAndOptions(){this.elements.banner.wrapper.classList.remove("show-banner","show-options"),document.body.classList.remove("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireBannerAndOptionsClosed"))}showBanner(){this.elements.banner.wrapper.classList.add("show-banner"),document.body.classList.add("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireBannerOpened"))}showOptions(){this.elements.banner.wrapper.classList.remove("show-banner"),this.elements.banner.wrapper.classList.add("show-options"),document.body.classList.add("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireOptionsOpened"))}showMessage(){this.elements.banner.wrapper.classList.add("show-message"),setTimeout((()=>{this.elements.banner.wrapper.classList.remove("show-message")}),this.settings.messageTimeout)}checkElementsWithRequiredConsent(){if(!1===this.settings.consentByClass&&(this.elements.elementsWithRequiredConsent=document.querySelectorAll("[data-category]")),this.cleanOldConsentWindows(),this.elements.elementsWithRequiredConsent)for(const e of this.elements.elementsWithRequiredConsent){const t=e.dataset.category;if(!t)continue;let s=!1;for(const e in this.userConsent.cookieGroups)if(e===t&&!0===this.userConsent.cookieGroups[e]){s=!0;break}s?this.updateAllowedElement(e):this.updateDisallowedElement(e)}}cleanOldConsentWindows(){if(this.elements.consentWindows)for(const e of this.elements.consentWindows){const{dataset:t}=e,s=t.disallowedConsentCategory;let n=!1;for(const e in this.userConsent.cookieGroups)if(e===s&&!0===this.userConsent.cookieGroups[e]){n=!0;break}n&&e.remove()}}updateDisallowedElement(e){const{dataset:t}=e;if(!t.askConsent||"1"===t.askConsentRendered)return;const s=t.category,n=this.settings.cookieGroups[s],o=document.createElement("div");o.classList.add("privacywire-ask-consent",`consent-category-${s}`),o.dataset.disallowedConsentCategory=s,o.innerHTML=this.elements.blueprint.innerHTML.formatUnicorn({category:n,categoryname:s}),t.askConsentMessage&&(o.querySelector(".privacywire-consent-message").textContent=t.askConsentMessage),t.askConsentButtonLabel&&(o.querySelector("button").textContent=t.askConsentButtonLabel),e.insertAdjacentElement("afterend",o),e.dataset.askConsentRendered="1"}updateAllowedElement(e){"script"===e.tagName.toLowerCase()?this.updateAllowedElementScript(e):this.updateAllowedElementOther(e)}updateAllowedElementScript(e){const{dataset:t}=e;let s=document.createElement(e.tagName);for(const n of Object.keys(t))s.dataset[n]=e.dataset[n];s.type=t.type??"text/javascript",t.src&&(s.src=t.src),s.textContent=e.textContent,e.id&&(s.id=e.id),s.defer=e.defer,s.async=e.async,s=this.removeUnusedAttributesFromElement(s),e.insertAdjacentElement("afterend",s),e.remove()}updateAllowedElementOther(e){const{dataset:t}=e;e.type=t.type??"text/javascript";for(const s of["src","srcset","srcdoc","poster"])void 0!==t[s]&&(e[s]=t[s]);this.removeUnusedAttributesFromElement(e)}removeUnusedAttributesFromElement(e){return e.removeAttribute("data-ask-consent"),e.removeAttribute("data-ask-consent-rendered"),e.removeAttribute("data-category"),e.removeAttribute("data-poster"),e.removeAttribute("data-src"),e.removeAttribute("data-srcset"),e.removeAttribute("data-srcdoc"),e.removeAttribute("data-type"),e.classList.remove("require-consent"),e}refresh(){this.checkElementsWithRequiredConsent(),this.handleButtonHelper(this.elements.buttons.askForConsent,"handleButtonAskForConsent")}removeStoredConsent(){window.localStorage.getItem(this.name)&&window.localStorage.removeItem(this.name)}}document.addEventListener("DOMContentLoaded",(()=>{window.PrivacyWire=new PrivacyWire(PrivacyWireSettings)}))}(); \ No newline at end of file diff --git a/js/PrivacyWire_legacy.js b/js/PrivacyWire_legacy.js index 996c2ec..fbdea33 100644 --- a/js/PrivacyWire_legacy.js +++ b/js/PrivacyWire_legacy.js @@ -1 +1 @@ -!function(){"use strict";function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=Array(t);n=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,r=!0,a=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return r=e.done,e},e:function(e){a=!0,s=e},f:function(){try{r||null==n.return||n.return()}finally{if(a)throw s}}}}function _toPropertyKey(e){var t=function _toPrimitive(e,t){if("object"!=typeof e||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var o=n.call(e,t);if("object"!=typeof o)return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e,"string");return"symbol"==typeof t?t:t+""}function _typeof(e){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof(e)}String.prototype.formatUnicorn=String.prototype.formatUnicorn||function(){var e=this.toString();if(arguments.length){var t,n=_typeof(arguments[0]),o="string"===n||"number"===n?Array.prototype.slice.call(arguments):arguments[0];for(t in o)e=e.replace(new RegExp("\\{"+t+"\\}","gi"),o[t])}return e};var e=function(){return _createClass((function PrivacyWire(e){!function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,PrivacyWire),this.name="privacywire",this.toggleToStatus=!0,this.cookieGroups=Object.freeze(["necessary","functional","statistics","marketing","external_media"]),this.settings=this.sanitizeSettings(e),this.userConsent=this.sanitizeStoredConsent(),this.elements=this.initiateElements(),this.syncConsentToCheckboxes(),this.updateBodyClasses(),this.checkForValidConsent()||this.showBanner(),this.checkElementsWithRequiredConsent(),this.handleButtons()}),[{key:"sanitizeSettings",value:function sanitizeSettings(e){var t={};t.version=Number.parseInt(e.version),t.dnt=Boolean(Number.parseInt(e.dnt)),t.bots=Boolean(Number.parseInt(e.bots)),t.customFunction="".concat(e.customFunction),t.messageTimeout=Number.parseInt(e.messageTimeout),t.consentByClass=Boolean(Number.parseInt(e.consentByClass)),t.cookieGroups={};var n,o=_createForOfIteratorHelper(this.cookieGroups);try{for(o.s();!(n=o.n()).done;){var s=n.value;t.cookieGroups[s]="".concat(e.cookieGroups[s])}}catch(e){o.e(e)}finally{o.f()}return t}},{key:"sanitizeStoredConsent",value:function sanitizeStoredConsent(){if(!window.localStorage.getItem(this.name))return this.getDefaultConsent();var e=JSON.parse(window.localStorage.getItem(this.name));if(Number.parseInt(e.version)!==this.settings.version)return this.getDefaultConsent();if(void 0===e.cookieGroups)return this.removeStoredConsent(),this.getDefaultConsent();var t={};t.version=Number.parseInt(e.version),t.cookieGroups={};var n,o=_createForOfIteratorHelper(this.cookieGroups);try{for(o.s();!(n=o.n()).done;){var s=n.value;t.cookieGroups[s]=Boolean(e.cookieGroups[s])}}catch(e){o.e(e)}finally{o.f()}return t}},{key:"getDefaultConsent",value:function getDefaultConsent(){var e,t={version:0,cookieGroups:{}},n=_createForOfIteratorHelper(this.cookieGroups);try{for(n.s();!(e=n.n()).done;){var o=e.value;t.cookieGroups[o]="necessary"===o}}catch(e){n.e(e)}finally{n.f()}return t}},{key:"initiateElements",value:function initiateElements(){var e={banner:{}};e.banner.wrapper=document.getElementById("privacywire-wrapper"),e.banner.intro=e.banner.wrapper.getElementsByClassName("privacywire-banner"),e.banner.options=e.banner.wrapper.getElementsByClassName("privacywire-options"),e.banner.message=e.banner.wrapper.getElementsByClassName("privacywire-message"),e.buttons={},e.buttons.acceptAll=e.banner.wrapper.getElementsByClassName("allow-all"),e.buttons.acceptNecessary=e.banner.wrapper.getElementsByClassName("allow-necessary"),e.buttons.choose=e.banner.wrapper.getElementsByClassName("choose"),e.buttons.toggle=e.banner.wrapper.getElementsByClassName("toggle"),e.buttons.save=e.banner.wrapper.getElementsByClassName("save"),e.buttons.askForConsent=document.getElementsByClassName("privacywire-consent-button"),e.buttons.externalTrigger=document.getElementsByClassName("privacywire-show-options"),e.checkboxes={};var t,n=_createForOfIteratorHelper(this.cookieGroups);try{for(n.s();!(t=n.n()).done;){var o=t.value;"necessary"!==o&&(e.checkboxes[o]=document.getElementById(o))}}catch(e){n.e(e)}finally{n.f()}return e.blueprint=document.getElementById("privacywire-ask-consent-blueprint"),e.elementsWithRequiredConsent=!0===this.settings.consentByClass?document.getElementsByClassName("require-consent"):document.querySelectorAll("[data-category]"),e.consentWindows=document.getElementsByClassName("privacywire-ask-consent"),e}},{key:"handleButtons",value:function handleButtons(){this.handleButtonHelper(this.elements.buttons.acceptAll,"handleButtonAcceptAll"),this.handleButtonHelper(this.elements.buttons.acceptNecessary,"handleButtonAcceptNecessary"),this.handleButtonHelper(this.elements.buttons.choose,"handleButtonChoose"),this.handleButtonHelper(this.elements.buttons.toggle,"handleButtonToggle"),this.handleButtonHelper(this.elements.buttons.save,"handleButtonSave"),this.handleButtonHelper(this.elements.buttons.askForConsent,"handleButtonAskForConsent"),this.handleButtonHelper(this.elements.buttons.externalTrigger,"handleButtonExternalTrigger")}},{key:"handleButtonHelper",value:function handleButtonHelper(e,t){if(e){var n,o=_createForOfIteratorHelper(e);try{for(o.s();!(n=o.n()).done;){var s=n.value;this[t](s)}}catch(e){o.e(e)}finally{o.f()}}}},{key:"reHandleExternalButtons",value:function reHandleExternalButtons(){this.elements.buttons.externalTrigger=document.getElementsByClassName("privacywire-show-options"),this.handleButtonHelper(this.elements.buttons.externalTrigger,"handleButtonExternalTrigger")}},{key:"handleButtonAcceptAll",value:function handleButtonAcceptAll(e){var t=this;e.addEventListener("click",(function(){var e,n=_createForOfIteratorHelper(t.cookieGroups);try{for(n.s();!(e=n.n()).done;){var o=e.value;t.userConsent.cookieGroups[o]=!0}}catch(e){n.e(e)}finally{n.f()}t.syncConsentToCheckboxes(),t.saveConsent()}))}},{key:"handleButtonAcceptNecessary",value:function handleButtonAcceptNecessary(e){var t=this;e.addEventListener("click",(function(){t.userConsent=t.getDefaultConsent(),t.syncConsentToCheckboxes(),t.saveConsent()}))}},{key:"handleButtonChoose",value:function handleButtonChoose(e){var t=this;e.addEventListener("click",(function(){t.showOptions()}))}},{key:"handleButtonToggle",value:function handleButtonToggle(e){var t=this;e.addEventListener("click",(function(){for(var e in t.elements.checkboxes)t.elements.checkboxes[e].checked=t.toggleToStatus;t.toggleToStatus=!t.toggleToStatus}))}},{key:"handleButtonSave",value:function handleButtonSave(e){var t=this;e.addEventListener("click",(function(){var e,n=_createForOfIteratorHelper(t.cookieGroups);try{for(n.s();!(e=n.n()).done;){var o=e.value;"necessary"!==o&&(t.userConsent.cookieGroups[o]=t.elements.checkboxes[o].checked)}}catch(e){n.e(e)}finally{n.f()}t.saveConsent()}))}},{key:"handleButtonAskForConsent",value:function handleButtonAskForConsent(e){var t=this;e.addEventListener("click",(function(){var n=e.dataset;t.userConsent.cookieGroups[n.consentCategory]=!0,t.syncConsentToCheckboxes(),t.saveConsent(),e.parentElement.remove()}))}},{key:"handleButtonExternalTrigger",value:function handleButtonExternalTrigger(e){var t=this;e.addEventListener("click",(function(e){e.preventDefault(),t.showOptions()}))}},{key:"syncConsentToCheckboxes",value:function syncConsentToCheckboxes(){var e,t=_createForOfIteratorHelper(this.cookieGroups);try{for(t.s();!(e=t.n()).done;){var n=e.value;"necessary"!==n&&(this.elements.checkboxes[n].checked=this.userConsent.cookieGroups[n])}}catch(e){t.e(e)}finally{t.f()}}},{key:"checkForValidConsent",value:function checkForValidConsent(){return this.userConsent.version>0&&this.userConsent.version===this.settings.version||(this.settings.bots?this.checkForBots():this.settings.dnt&&!0===this.checkForUsersDNT())}},{key:"checkForUsersDNT",value:function checkForUsersDNT(){return!(!this.settings.dnt||"1"!==navigator.doNotTrack)&&(this.userConsent=this.getDefaultConsent(),this.saveConsent(!0),!0)}},{key:"detectRobot",value:function detectRobot(){return new RegExp([/bot/,/spider/,/crawl/,/APIs-Google/,/AdsBot/,/Googlebot/,/mediapartners/,/Google Favicon/,/Google Page Speed Insights/,/Chrome-Lighthouse/,/FeedFetcher/,/Google-Read-Aloud/,/DuplexWeb-Google/,/googleweblight/,/bing/,/yandex/,/baidu/,/duckduck/,/yahoo/,/ecosia/,/ia_archiver/,/facebook/,/instagram/,/pinterest/,/reddit/,/slack/,/twitter/,/whatsapp/,/youtube/,/semrush/].map((function(e){return e.source})).join("|"),"i").test(navigator.userAgent)}},{key:"checkForBots",value:function checkForBots(){return!!this.detectRobot()&&(this.userConsent=this.getDefaultConsent(),this.saveConsent(!0),!0)}},{key:"updateBodyClasses",value:function updateBodyClasses(){var e,t=_createForOfIteratorHelper(this.cookieGroups);try{for(t.s();!(e=t.n()).done;){var n=e.value,o="consent-".concat(n);this.userConsent.cookieGroups[n]?document.body.classList.add(o):document.body.classList.remove(o)}}catch(e){t.e(e)}finally{t.f()}}},{key:"saveConsent",value:function saveConsent(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.userConsent.version=this.settings.version,window.localStorage.removeItem(this.name),window.localStorage.setItem(this.name,JSON.stringify(this.userConsent)),this.hideBannerAndOptions(),e||this.showMessage(),this.checkElementsWithRequiredConsent(),this.updateBodyClasses(),this.triggerCustomFunction()}},{key:"triggerCustomFunction",value:function triggerCustomFunction(){this.settings.customFunction.length&&"function"==typeof window[this.settings.customFunction]&&window[this.settings.customFunction]()}},{key:"hideBannerAndOptions",value:function hideBannerAndOptions(){this.elements.banner.wrapper.classList.remove("show-banner","show-options"),document.body.classList.remove("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireBannerAndOptionsClosed"))}},{key:"showBanner",value:function showBanner(){this.elements.banner.wrapper.classList.add("show-banner"),document.body.classList.add("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireBannerOpened"))}},{key:"showOptions",value:function showOptions(){this.elements.banner.wrapper.classList.remove("show-banner"),this.elements.banner.wrapper.classList.add("show-options"),document.body.classList.add("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireOptionsOpened"))}},{key:"showMessage",value:function showMessage(){var e=this;this.elements.banner.wrapper.classList.add("show-message"),setTimeout((function(){e.elements.banner.wrapper.classList.remove("show-message")}),this.settings.messageTimeout)}},{key:"checkElementsWithRequiredConsent",value:function checkElementsWithRequiredConsent(){if(!1===this.settings.consentByClass&&(this.elements.elementsWithRequiredConsent=document.querySelectorAll("[data-category]")),this.cleanOldConsentWindows(),this.elements.elementsWithRequiredConsent){var e,t=_createForOfIteratorHelper(this.elements.elementsWithRequiredConsent);try{for(t.s();!(e=t.n()).done;){var n=e.value,o=n.dataset.category;if(o){var s=!1;for(var r in this.userConsent.cookieGroups)if(r===o&&!0===this.userConsent.cookieGroups[r]){s=!0;break}s?this.updateAllowedElement(n):this.updateDisallowedElement(n)}}}catch(e){t.e(e)}finally{t.f()}}}},{key:"cleanOldConsentWindows",value:function cleanOldConsentWindows(){if(this.elements.consentWindows){var e,t=_createForOfIteratorHelper(this.elements.consentWindows);try{for(t.s();!(e=t.n()).done;){var n=e.value,o=n.dataset.disallowedConsentCategory,s=!1;for(var r in this.userConsent.cookieGroups)if(r===o&&!0===this.userConsent.cookieGroups[r]){s=!0;break}s&&n.remove()}}catch(e){t.e(e)}finally{t.f()}}}},{key:"updateDisallowedElement",value:function updateDisallowedElement(e){var t=e.dataset;if(t.askConsent&&"1"!==t.askConsentRendered){var n=t.category,o=this.settings.cookieGroups[n],s=document.createElement("div");s.classList.add("privacywire-ask-consent","consent-category-".concat(n)),s.dataset.disallowedConsentCategory=n,s.innerHTML=this.elements.blueprint.innerHTML.formatUnicorn({category:o,categoryname:n}),t.askConsentMessage&&(s.querySelector(".privacywire-consent-message").textContent=t.askConsentMessage),t.askConsentButtonLabel&&(s.querySelector("button").textContent=t.askConsentButtonLabel),e.insertAdjacentElement("afterend",s),e.dataset.askConsentRendered="1"}}},{key:"updateAllowedElement",value:function updateAllowedElement(e){"script"===e.tagName.toLowerCase()?this.updateAllowedElementScript(e):this.updateAllowedElementOther(e)}},{key:"updateAllowedElementScript",value:function updateAllowedElementScript(e){for(var t,n=e.dataset,o=document.createElement(e.tagName),s=0,r=Object.keys(n);se.length)&&(t=e.length);for(var n=0,o=Array(t);n=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,r=!0,a=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return r=e.done,e},e:function(e){a=!0,s=e},f:function(){try{r||null==n.return||n.return()}finally{if(a)throw s}}}}function _toPropertyKey(e){var t=function _toPrimitive(e,t){if("object"!=typeof e||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var o=n.call(e,t);if("object"!=typeof o)return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e,"string");return"symbol"==typeof t?t:t+""}function _typeof(e){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof(e)}String.prototype.formatUnicorn=String.prototype.formatUnicorn||function(){var e=this.toString();if(arguments.length){var t,n=_typeof(arguments[0]),o="string"===n||"number"===n?Array.prototype.slice.call(arguments):arguments[0];for(t in o)e=e.replace(new RegExp("\\{"+t+"\\}","gi"),o[t])}return e};var e=function(){return _createClass((function PrivacyWire(e){!function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,PrivacyWire),this.name="privacywire",this.toggleToStatus=!0,this.cookieGroups=Object.freeze(["necessary","functional","statistics","marketing","external_media"]),this.settings=this.sanitizeSettings(e),this.userConsent=this.sanitizeStoredConsent(),this.elements=this.initiateElements(),this.syncConsentToCheckboxes(),this.updateBodyClasses(),this.checkForValidConsent()||this.showBanner(),this.checkElementsWithRequiredConsent(),this.handleButtons()}),[{key:"sanitizeSettings",value:function sanitizeSettings(e){var t={};t.version=Number.parseInt(e.version),t.dnt=Boolean(Number.parseInt(e.dnt)),t.bots=Boolean(Number.parseInt(e.bots)),t.customFunction="".concat(e.customFunction),t.messageTimeout=Number.parseInt(e.messageTimeout),t.consentStorageDurationMonths=Number.parseInt(e.consentStorageDurationMonths)||0,t.consentByClass=Boolean(Number.parseInt(e.consentByClass)),t.cookieGroups={};var n,o=_createForOfIteratorHelper(this.cookieGroups);try{for(o.s();!(n=o.n()).done;){var s=n.value;t.cookieGroups[s]="".concat(e.cookieGroups[s])}}catch(e){o.e(e)}finally{o.f()}return t}},{key:"sanitizeStoredConsent",value:function sanitizeStoredConsent(){if(!window.localStorage.getItem(this.name))return this.getDefaultConsent();var e;try{e=JSON.parse(window.localStorage.getItem(this.name))}catch(e){return this.removeStoredConsent(),this.getDefaultConsent()}if(Number.parseInt(e.version)!==this.settings.version)return this.getDefaultConsent();if(void 0===e.cookieGroups)return this.removeStoredConsent(),this.getDefaultConsent();if(this.hasConsentExpired(e))return this.removeStoredConsent(),this.getDefaultConsent();var t={};t.version=Number.parseInt(e.version),t.storedAt=this.getStoredAtTimestamp(e),t.cookieGroups={};var n,o=_createForOfIteratorHelper(this.cookieGroups);try{for(o.s();!(n=o.n()).done;){var s=n.value;t.cookieGroups[s]=Boolean(e.cookieGroups[s])}}catch(e){o.e(e)}finally{o.f()}return t}},{key:"getDefaultConsent",value:function getDefaultConsent(){var e,t={version:0,storedAt:null,cookieGroups:{}},n=_createForOfIteratorHelper(this.cookieGroups);try{for(n.s();!(e=n.n()).done;){var o=e.value;t.cookieGroups[o]="necessary"===o}}catch(e){n.e(e)}finally{n.f()}return t}},{key:"getStoredAtTimestamp",value:function getStoredAtTimestamp(e){var t=Number.parseInt(e.storedAt);return!Number.isFinite(t)||t<=0?null:t}},{key:"hasConsentExpired",value:function hasConsentExpired(e){if(this.settings.consentStorageDurationMonths<=0)return!1;var t=this.getStoredAtTimestamp(e);return null===t||Date.now()>=this.getConsentExpiryTimestamp(t)}},{key:"getConsentExpiryTimestamp",value:function getConsentExpiryTimestamp(e){var t=new Date(e),n=t.getUTCDate();return t.setUTCDate(1),t.setUTCMonth(t.getUTCMonth()+this.settings.consentStorageDurationMonths),t.setUTCDate(Math.min(n,this.getDaysInUtcMonth(t))),t.getTime()}},{key:"getDaysInUtcMonth",value:function getDaysInUtcMonth(e){return new Date(Date.UTC(e.getUTCFullYear(),e.getUTCMonth()+1,0)).getUTCDate()}},{key:"initiateElements",value:function initiateElements(){var e={banner:{}};e.banner.wrapper=document.getElementById("privacywire-wrapper"),e.banner.intro=e.banner.wrapper.getElementsByClassName("privacywire-banner"),e.banner.options=e.banner.wrapper.getElementsByClassName("privacywire-options"),e.banner.message=e.banner.wrapper.getElementsByClassName("privacywire-message"),e.buttons={},e.buttons.acceptAll=e.banner.wrapper.getElementsByClassName("allow-all"),e.buttons.acceptNecessary=e.banner.wrapper.getElementsByClassName("allow-necessary"),e.buttons.choose=e.banner.wrapper.getElementsByClassName("choose"),e.buttons.toggle=e.banner.wrapper.getElementsByClassName("toggle"),e.buttons.save=e.banner.wrapper.getElementsByClassName("save"),e.buttons.askForConsent=document.getElementsByClassName("privacywire-consent-button"),e.buttons.externalTrigger=document.getElementsByClassName("privacywire-show-options"),e.checkboxes={};var t,n=_createForOfIteratorHelper(this.cookieGroups);try{for(n.s();!(t=n.n()).done;){var o=t.value;"necessary"!==o&&(e.checkboxes[o]=document.getElementById(o))}}catch(e){n.e(e)}finally{n.f()}return e.blueprint=document.getElementById("privacywire-ask-consent-blueprint"),e.elementsWithRequiredConsent=!0===this.settings.consentByClass?document.getElementsByClassName("require-consent"):document.querySelectorAll("[data-category]"),e.consentWindows=document.getElementsByClassName("privacywire-ask-consent"),e}},{key:"handleButtons",value:function handleButtons(){this.handleButtonHelper(this.elements.buttons.acceptAll,"handleButtonAcceptAll"),this.handleButtonHelper(this.elements.buttons.acceptNecessary,"handleButtonAcceptNecessary"),this.handleButtonHelper(this.elements.buttons.choose,"handleButtonChoose"),this.handleButtonHelper(this.elements.buttons.toggle,"handleButtonToggle"),this.handleButtonHelper(this.elements.buttons.save,"handleButtonSave"),this.handleButtonHelper(this.elements.buttons.askForConsent,"handleButtonAskForConsent"),this.handleButtonHelper(this.elements.buttons.externalTrigger,"handleButtonExternalTrigger")}},{key:"handleButtonHelper",value:function handleButtonHelper(e,t){if(e){var n,o=_createForOfIteratorHelper(e);try{for(o.s();!(n=o.n()).done;){var s=n.value;this[t](s)}}catch(e){o.e(e)}finally{o.f()}}}},{key:"reHandleExternalButtons",value:function reHandleExternalButtons(){this.elements.buttons.externalTrigger=document.getElementsByClassName("privacywire-show-options"),this.handleButtonHelper(this.elements.buttons.externalTrigger,"handleButtonExternalTrigger")}},{key:"handleButtonAcceptAll",value:function handleButtonAcceptAll(e){var t=this;e.addEventListener("click",(function(){var e,n=_createForOfIteratorHelper(t.cookieGroups);try{for(n.s();!(e=n.n()).done;){var o=e.value;t.userConsent.cookieGroups[o]=!0}}catch(e){n.e(e)}finally{n.f()}t.syncConsentToCheckboxes(),t.saveConsent()}))}},{key:"handleButtonAcceptNecessary",value:function handleButtonAcceptNecessary(e){var t=this;e.addEventListener("click",(function(){t.userConsent=t.getDefaultConsent(),t.syncConsentToCheckboxes(),t.saveConsent()}))}},{key:"handleButtonChoose",value:function handleButtonChoose(e){var t=this;e.addEventListener("click",(function(){t.showOptions()}))}},{key:"handleButtonToggle",value:function handleButtonToggle(e){var t=this;e.addEventListener("click",(function(){for(var e in t.elements.checkboxes)t.elements.checkboxes[e].checked=t.toggleToStatus;t.toggleToStatus=!t.toggleToStatus}))}},{key:"handleButtonSave",value:function handleButtonSave(e){var t=this;e.addEventListener("click",(function(){var e,n=_createForOfIteratorHelper(t.cookieGroups);try{for(n.s();!(e=n.n()).done;){var o=e.value;"necessary"!==o&&(t.userConsent.cookieGroups[o]=t.elements.checkboxes[o].checked)}}catch(e){n.e(e)}finally{n.f()}t.saveConsent()}))}},{key:"handleButtonAskForConsent",value:function handleButtonAskForConsent(e){var t=this;e.addEventListener("click",(function(){var n=e.dataset;t.userConsent.cookieGroups[n.consentCategory]=!0,t.syncConsentToCheckboxes(),t.saveConsent(),e.parentElement.remove()}))}},{key:"handleButtonExternalTrigger",value:function handleButtonExternalTrigger(e){var t=this;e.addEventListener("click",(function(e){e.preventDefault(),t.showOptions()}))}},{key:"syncConsentToCheckboxes",value:function syncConsentToCheckboxes(){var e,t=_createForOfIteratorHelper(this.cookieGroups);try{for(t.s();!(e=t.n()).done;){var n=e.value;"necessary"!==n&&(this.elements.checkboxes[n].checked=this.userConsent.cookieGroups[n])}}catch(e){t.e(e)}finally{t.f()}}},{key:"checkForValidConsent",value:function checkForValidConsent(){return this.userConsent.version>0&&this.userConsent.version===this.settings.version||(this.settings.bots?this.checkForBots():this.settings.dnt&&!0===this.checkForUsersDNT())}},{key:"checkForUsersDNT",value:function checkForUsersDNT(){return!(!this.settings.dnt||"1"!==navigator.doNotTrack)&&(this.userConsent=this.getDefaultConsent(),this.saveConsent(!0),!0)}},{key:"detectRobot",value:function detectRobot(){return new RegExp([/bot/,/spider/,/crawl/,/APIs-Google/,/AdsBot/,/Googlebot/,/mediapartners/,/Google Favicon/,/Google Page Speed Insights/,/Chrome-Lighthouse/,/FeedFetcher/,/Google-Read-Aloud/,/DuplexWeb-Google/,/googleweblight/,/bing/,/yandex/,/baidu/,/duckduck/,/yahoo/,/ecosia/,/ia_archiver/,/facebook/,/instagram/,/pinterest/,/reddit/,/slack/,/twitter/,/whatsapp/,/youtube/,/semrush/].map((function(e){return e.source})).join("|"),"i").test(navigator.userAgent)}},{key:"checkForBots",value:function checkForBots(){return!!this.detectRobot()&&(this.userConsent=this.getDefaultConsent(),this.saveConsent(!0),!0)}},{key:"updateBodyClasses",value:function updateBodyClasses(){var e,t=_createForOfIteratorHelper(this.cookieGroups);try{for(t.s();!(e=t.n()).done;){var n=e.value,o="consent-".concat(n);this.userConsent.cookieGroups[n]?document.body.classList.add(o):document.body.classList.remove(o)}}catch(e){t.e(e)}finally{t.f()}}},{key:"saveConsent",value:function saveConsent(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.userConsent.version=this.settings.version,this.userConsent.storedAt=Date.now(),window.localStorage.removeItem(this.name),window.localStorage.setItem(this.name,JSON.stringify(this.userConsent)),this.hideBannerAndOptions(),e||this.showMessage(),this.checkElementsWithRequiredConsent(),this.updateBodyClasses(),this.triggerCustomFunction()}},{key:"triggerCustomFunction",value:function triggerCustomFunction(){this.settings.customFunction.length&&"function"==typeof window[this.settings.customFunction]&&window[this.settings.customFunction]()}},{key:"hideBannerAndOptions",value:function hideBannerAndOptions(){this.elements.banner.wrapper.classList.remove("show-banner","show-options"),document.body.classList.remove("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireBannerAndOptionsClosed"))}},{key:"showBanner",value:function showBanner(){this.elements.banner.wrapper.classList.add("show-banner"),document.body.classList.add("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireBannerOpened"))}},{key:"showOptions",value:function showOptions(){this.elements.banner.wrapper.classList.remove("show-banner"),this.elements.banner.wrapper.classList.add("show-options"),document.body.classList.add("has-privacywire-window-opened"),document.dispatchEvent(new CustomEvent("PrivacyWireOptionsOpened"))}},{key:"showMessage",value:function showMessage(){var e=this;this.elements.banner.wrapper.classList.add("show-message"),setTimeout((function(){e.elements.banner.wrapper.classList.remove("show-message")}),this.settings.messageTimeout)}},{key:"checkElementsWithRequiredConsent",value:function checkElementsWithRequiredConsent(){if(!1===this.settings.consentByClass&&(this.elements.elementsWithRequiredConsent=document.querySelectorAll("[data-category]")),this.cleanOldConsentWindows(),this.elements.elementsWithRequiredConsent){var e,t=_createForOfIteratorHelper(this.elements.elementsWithRequiredConsent);try{for(t.s();!(e=t.n()).done;){var n=e.value,o=n.dataset.category;if(o){var s=!1;for(var r in this.userConsent.cookieGroups)if(r===o&&!0===this.userConsent.cookieGroups[r]){s=!0;break}s?this.updateAllowedElement(n):this.updateDisallowedElement(n)}}}catch(e){t.e(e)}finally{t.f()}}}},{key:"cleanOldConsentWindows",value:function cleanOldConsentWindows(){if(this.elements.consentWindows){var e,t=_createForOfIteratorHelper(this.elements.consentWindows);try{for(t.s();!(e=t.n()).done;){var n=e.value,o=n.dataset.disallowedConsentCategory,s=!1;for(var r in this.userConsent.cookieGroups)if(r===o&&!0===this.userConsent.cookieGroups[r]){s=!0;break}s&&n.remove()}}catch(e){t.e(e)}finally{t.f()}}}},{key:"updateDisallowedElement",value:function updateDisallowedElement(e){var t=e.dataset;if(t.askConsent&&"1"!==t.askConsentRendered){var n=t.category,o=this.settings.cookieGroups[n],s=document.createElement("div");s.classList.add("privacywire-ask-consent","consent-category-".concat(n)),s.dataset.disallowedConsentCategory=n,s.innerHTML=this.elements.blueprint.innerHTML.formatUnicorn({category:o,categoryname:n}),t.askConsentMessage&&(s.querySelector(".privacywire-consent-message").textContent=t.askConsentMessage),t.askConsentButtonLabel&&(s.querySelector("button").textContent=t.askConsentButtonLabel),e.insertAdjacentElement("afterend",s),e.dataset.askConsentRendered="1"}}},{key:"updateAllowedElement",value:function updateAllowedElement(e){"script"===e.tagName.toLowerCase()?this.updateAllowedElementScript(e):this.updateAllowedElementOther(e)}},{key:"updateAllowedElementScript",value:function updateAllowedElementScript(e){for(var t,n=e.dataset,o=document.createElement(e.tagName),s=0,r=Object.keys(n);s= this.getConsentExpiryTimestamp(storedAt); + } + + getConsentExpiryTimestamp(storedAt) { + const expiryDate = new Date(storedAt); + const originalDay = expiryDate.getUTCDate(); + + expiryDate.setUTCDate(1); + expiryDate.setUTCMonth( + expiryDate.getUTCMonth() + this.settings.consentStorageDurationMonths + ); + expiryDate.setUTCDate( + Math.min(originalDay, this.getDaysInUtcMonth(expiryDate)) + ); + + return expiryDate.getTime(); + } + + getDaysInUtcMonth(date) { + return new Date( + Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0) + ).getUTCDate(); + } + initiateElements() { const elements = {}; elements.banner = {}; @@ -353,6 +413,7 @@ class PrivacyWire { saveConsent(silent = false) { this.userConsent.version = this.settings.version; + this.userConsent.storedAt = Date.now(); window.localStorage.removeItem(this.name); window.localStorage.setItem(this.name, JSON.stringify(this.userConsent)); this.hideBannerAndOptions(); From 160cffd3742065816520763f9c9139eb406ca294 Mon Sep 17 00:00:00 2001 From: webworkerJoshua Date: Mon, 13 Apr 2026 22:14:24 +0200 Subject: [PATCH 2/3] chore: lint/format --- src/js/PrivacyWire.js | 135 ++++++++++++------------------------------ 1 file changed, 37 insertions(+), 98 deletions(-) diff --git a/src/js/PrivacyWire.js b/src/js/PrivacyWire.js index f674214..a242b86 100644 --- a/src/js/PrivacyWire.js +++ b/src/js/PrivacyWire.js @@ -36,14 +36,10 @@ class PrivacyWire { settings.dnt = Boolean(Number.parseInt(PrivacyWireSettings.dnt)); settings.bots = Boolean(Number.parseInt(PrivacyWireSettings.bots)); settings.customFunction = `${PrivacyWireSettings.customFunction}`; - settings.messageTimeout = Number.parseInt( - PrivacyWireSettings.messageTimeout - ); + settings.messageTimeout = Number.parseInt(PrivacyWireSettings.messageTimeout); settings.consentStorageDurationMonths = Number.parseInt(PrivacyWireSettings.consentStorageDurationMonths) || 0; - settings.consentByClass = Boolean( - Number.parseInt(PrivacyWireSettings.consentByClass) - ); + settings.consentByClass = Boolean(Number.parseInt(PrivacyWireSettings.consentByClass)); settings.cookieGroups = {}; for (const key of this.cookieGroups) { @@ -58,19 +54,20 @@ class PrivacyWire { * @returns {Object} either empty object or sanitized stored consent object if version matches with settings version */ sanitizeStoredConsent() { - if (!window.localStorage.getItem(this.name)) { + const localStorageConsentItem = window.localStorage.getItem(this.name); + if (!localStorageConsentItem) { return this.getDefaultConsent(); } let storedConsentRaw; try { - storedConsentRaw = JSON.parse(window.localStorage.getItem(this.name)); + storedConsentRaw = JSON.parse(localStorageConsentItem); } catch { this.removeStoredConsent(); return this.getDefaultConsent(); } - if (Number.parseInt(storedConsentRaw.version) !== this.settings.version) { + if (Number.parseInt(storedConsentRaw?.version) !== this.settings.version) { return this.getDefaultConsent(); } @@ -90,9 +87,7 @@ class PrivacyWire { storedConsent.cookieGroups = {}; for (const key of this.cookieGroups) { - storedConsent.cookieGroups[key] = Boolean( - storedConsentRaw.cookieGroups[key] - ); + storedConsent.cookieGroups[key] = Boolean(storedConsentRaw.cookieGroups[key]); } return storedConsent; @@ -141,52 +136,33 @@ class PrivacyWire { const originalDay = expiryDate.getUTCDate(); expiryDate.setUTCDate(1); - expiryDate.setUTCMonth( - expiryDate.getUTCMonth() + this.settings.consentStorageDurationMonths - ); - expiryDate.setUTCDate( - Math.min(originalDay, this.getDaysInUtcMonth(expiryDate)) - ); + expiryDate.setUTCMonth(expiryDate.getUTCMonth() + this.settings.consentStorageDurationMonths); + expiryDate.setUTCDate(Math.min(originalDay, this.getDaysInUtcMonth(expiryDate))); return expiryDate.getTime(); } getDaysInUtcMonth(date) { - return new Date( - Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0) - ).getUTCDate(); + return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0)).getUTCDate(); } initiateElements() { const elements = {}; elements.banner = {}; elements.banner.wrapper = document.getElementById("privacywire-wrapper"); - elements.banner.intro = - elements.banner.wrapper.getElementsByClassName("privacywire-banner"); - elements.banner.options = elements.banner.wrapper.getElementsByClassName( - "privacywire-options" - ); - elements.banner.message = elements.banner.wrapper.getElementsByClassName( - "privacywire-message" - ); + elements.banner.intro = elements.banner.wrapper.getElementsByClassName("privacywire-banner"); + elements.banner.options = elements.banner.wrapper.getElementsByClassName("privacywire-options"); + elements.banner.message = elements.banner.wrapper.getElementsByClassName("privacywire-message"); elements.buttons = {}; - elements.buttons.acceptAll = - elements.banner.wrapper.getElementsByClassName("allow-all"); + elements.buttons.acceptAll = elements.banner.wrapper.getElementsByClassName("allow-all"); elements.buttons.acceptNecessary = elements.banner.wrapper.getElementsByClassName("allow-necessary"); - elements.buttons.choose = - elements.banner.wrapper.getElementsByClassName("choose"); - elements.buttons.toggle = - elements.banner.wrapper.getElementsByClassName("toggle"); - elements.buttons.save = - elements.banner.wrapper.getElementsByClassName("save"); - elements.buttons.askForConsent = document.getElementsByClassName( - "privacywire-consent-button" - ); - elements.buttons.externalTrigger = document.getElementsByClassName( - "privacywire-show-options" - ); + elements.buttons.choose = elements.banner.wrapper.getElementsByClassName("choose"); + elements.buttons.toggle = elements.banner.wrapper.getElementsByClassName("toggle"); + elements.buttons.save = elements.banner.wrapper.getElementsByClassName("save"); + elements.buttons.askForConsent = document.getElementsByClassName("privacywire-consent-button"); + elements.buttons.externalTrigger = document.getElementsByClassName("privacywire-show-options"); elements.checkboxes = {}; for (const key of this.cookieGroups) { @@ -196,42 +172,26 @@ class PrivacyWire { elements.checkboxes[key] = document.getElementById(key); } - elements.blueprint = document.getElementById( - "privacywire-ask-consent-blueprint" - ); + elements.blueprint = document.getElementById("privacywire-ask-consent-blueprint"); elements.elementsWithRequiredConsent = this.settings.consentByClass === true ? document.getElementsByClassName("require-consent") : document.querySelectorAll("[data-category]"); - elements.consentWindows = document.getElementsByClassName( - "privacywire-ask-consent" - ); + elements.consentWindows = document.getElementsByClassName("privacywire-ask-consent"); return elements; } handleButtons() { - this.handleButtonHelper( - this.elements.buttons.acceptAll, - "handleButtonAcceptAll" - ); - this.handleButtonHelper( - this.elements.buttons.acceptNecessary, - "handleButtonAcceptNecessary" - ); + this.handleButtonHelper(this.elements.buttons.acceptAll, "handleButtonAcceptAll"); + this.handleButtonHelper(this.elements.buttons.acceptNecessary, "handleButtonAcceptNecessary"); this.handleButtonHelper(this.elements.buttons.choose, "handleButtonChoose"); this.handleButtonHelper(this.elements.buttons.toggle, "handleButtonToggle"); this.handleButtonHelper(this.elements.buttons.save, "handleButtonSave"); - this.handleButtonHelper( - this.elements.buttons.askForConsent, - "handleButtonAskForConsent" - ); - this.handleButtonHelper( - this.elements.buttons.externalTrigger, - "handleButtonExternalTrigger" - ); + this.handleButtonHelper(this.elements.buttons.askForConsent, "handleButtonAskForConsent"); + this.handleButtonHelper(this.elements.buttons.externalTrigger, "handleButtonExternalTrigger"); } handleButtonHelper(buttons, method) { @@ -244,12 +204,9 @@ class PrivacyWire { reHandleExternalButtons() { this.elements.buttons.externalTrigger = document.getElementsByClassName( - "privacywire-show-options" - ); - this.handleButtonHelper( - this.elements.buttons.externalTrigger, - "handleButtonExternalTrigger" + "privacywire-show-options", ); + this.handleButtonHelper(this.elements.buttons.externalTrigger, "handleButtonExternalTrigger"); } handleButtonAcceptAll(btn) { @@ -291,8 +248,7 @@ class PrivacyWire { if (key === "necessary") { continue; } - this.userConsent.cookieGroups[key] = - this.elements.checkboxes[key].checked; + this.userConsent.cookieGroups[key] = this.elements.checkboxes[key].checked; } this.saveConsent(); }); @@ -320,16 +276,12 @@ class PrivacyWire { if (key === "necessary") { continue; } - this.elements.checkboxes[key].checked = - this.userConsent.cookieGroups[key]; + this.elements.checkboxes[key].checked = this.userConsent.cookieGroups[key]; } } checkForValidConsent() { - if ( - this.userConsent.version > 0 && - this.userConsent.version === this.settings.version - ) { + if (this.userConsent.version > 0 && this.userConsent.version === this.settings.version) { return true; } if (this.settings.bots) { @@ -385,7 +337,7 @@ class PrivacyWire { ] .map((r) => r.source) .join("|"), - "i" + "i", ); // BUILD REGEXP + "i" FLAG return robots.test(navigator.userAgent); @@ -437,14 +389,9 @@ class PrivacyWire { } hideBannerAndOptions() { - this.elements.banner.wrapper.classList.remove( - "show-banner", - "show-options" - ); + this.elements.banner.wrapper.classList.remove("show-banner", "show-options"); document.body.classList.remove("has-privacywire-window-opened"); - document.dispatchEvent( - new CustomEvent("PrivacyWireBannerAndOptionsClosed") - ); + document.dispatchEvent(new CustomEvent("PrivacyWireBannerAndOptionsClosed")); } showBanner() { @@ -469,8 +416,7 @@ class PrivacyWire { checkElementsWithRequiredConsent() { if (this.settings.consentByClass === false) { - this.elements.elementsWithRequiredConsent = - document.querySelectorAll("[data-category]"); + this.elements.elementsWithRequiredConsent = document.querySelectorAll("[data-category]"); } this.cleanOldConsentWindows(); @@ -533,18 +479,14 @@ class PrivacyWire { const categoryLabel = this.settings.cookieGroups[category]; const newEl = document.createElement("div"); - newEl.classList.add( - "privacywire-ask-consent", - `consent-category-${category}` - ); + newEl.classList.add("privacywire-ask-consent", `consent-category-${category}`); newEl.dataset.disallowedConsentCategory = category; newEl.innerHTML = this.elements.blueprint.innerHTML.formatUnicorn({ category: categoryLabel, categoryname: category, }); if (dataset.askConsentMessage) { - newEl.querySelector(".privacywire-consent-message").textContent = - dataset.askConsentMessage; + newEl.querySelector(".privacywire-consent-message").textContent = dataset.askConsentMessage; } if (dataset.askConsentButtonLabel) { newEl.querySelector("button").textContent = dataset.askConsentButtonLabel; @@ -612,10 +554,7 @@ class PrivacyWire { refresh() { this.checkElementsWithRequiredConsent(); - this.handleButtonHelper( - this.elements.buttons.askForConsent, - "handleButtonAskForConsent" - ); + this.handleButtonHelper(this.elements.buttons.askForConsent, "handleButtonAskForConsent"); } removeStoredConsent() { From 290aae7724092242991e7d7f880f0e762f6db837 Mon Sep 17 00:00:00 2001 From: webworkerJoshua Date: Mon, 13 Apr 2026 22:15:11 +0200 Subject: [PATCH 3/3] fix: default to string, as defined in select --- PrivacyWireConfig.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PrivacyWireConfig.php b/PrivacyWireConfig.php index 31522b0..09678d4 100644 --- a/PrivacyWireConfig.php +++ b/PrivacyWireConfig.php @@ -414,7 +414,7 @@ public function getDefaults() 'textformatter_choose_label' => $this->_("Show or edit my Cookie Consent"), 'trigger_custom_js_function' => "", 'messageTimeout' => 1500, - 'consent_storage_duration_months' => 0, + 'consent_storage_duration_months' => "0", 'add_basic_css_styling' => true, 'ask_consent_message' => $this->_("To load this element, it is required to consent to the following cookie category: {category}."), 'ask_content_button_label' => $this->_("Load {category} cookies"),