UNPKG

cookie-consent-js

Version:

A simple dialog and framework to handle the EU law (as written by EuGH, 1.10.2019 – C-673/17) about cookies in a website.

185 lines (169 loc) 7.5 kB
/** * Author and copyright: Stefan Haack (https://shaack.com) * Repository: https://github.com/shaack/cookie-consent-js * License: MIT, see file 'LICENSE' */ "use strict" function CookieConsent(props) { const self = this self.props = { buttonPrimaryClass: "btn btn-primary", // the "accept all" buttons class, only used for styling buttonSecondaryClass: "btn btn-secondary", // the "accept necessary" buttons class, only used for styling autoShowModal: true, // disable autoShowModal on the privacy policy page, to make that page readable blockAccess: false, // set "true" to block the access to the website before choosing a cookie configuration position: "right", // position ("left" or "right"), if blockAccess is false postSelectionCallback: undefined, // callback, after the user has made a selection lang: navigator.language, // the language, in which the dialog is shown defaultLang: "en", // default language, if the `lang` is not available as translation in `cookie-consent-content` content: [], // deprecated, we now have a `content` folder, which contains the language files contentUrl: "./cookie-consent-content", // the url of the "cookie-consent-content" folder, which contains the language files privacyPolicyUrl: "privacy-policy.html", cookieName: "cookie-consent-tracking-allowed", // the name of the cookie, the cookie is `true` if tracking was accepted modalId: "cookieConsentModal" // the id of the modal dialog element } for (const property in props) { if (property !== "content") { self.props[property] = props[property] } } self.lang = self.props.lang if (self.lang.indexOf("-") !== -1) { self.lang = self.lang.split("-")[0] } for (let contentProperty in props.content) { self.props.content[contentProperty] = props.content[contentProperty] } if (!self.props.content[self.lang]) { fetchContent(self.lang, (result) => { this.props.content = JSON.parse(result) renderModal() }) } else { renderModal() } function renderModal() { const _t = self.props.content const linkPrivacyPolicy = '<a href="' + self.props.privacyPolicyUrl + '">' + _t.privacyPolicy + '</a>' if (self.props.content[self.lang] === undefined) { self.lang = self.props.defaultLang } let modalClass = "cookie-consent-modal" if (self.props.blockAccess) { modalClass += " block-access" } self.modalContent = '<!-- cookie banner => https://github.com/shaack/cookie-consent-js -->' + '<div class="' + modalClass + '">' + '<div class="modal-content-wrap ' + self.props.position + '">' + '<div class="modal-content">' + '<div class="modal-header">--header--</div>' + '<div class="modal-body">--body--</div>' + '<div class="modal-footer">--footer--</div>' + '</div></div><!-- end cookie-consent.js -->' self.modalContent = self.modalContent.replace(/--header--/, "<h3 class=\"modal-title\">" + _t.title + "</h3>") self.modalContent = self.modalContent.replace(/--body--/, _t.body.replace(/--privacy-policy--/, linkPrivacyPolicy) ) self.modalContent = self.modalContent.replace(/--footer--/, "<div class='buttons'>" + "<button class='btn-accept-necessary " + self.props.buttonSecondaryClass + "'>" + _t.buttonAcceptTechnical + "</button>" + "<button class='btn-accept-all " + self.props.buttonPrimaryClass + "'>" + _t.buttonAcceptAll + "</button>" + "</div>" ) if (getCookie(self.props.cookieName) === undefined && self.props.autoShowModal) { showDialog() } } function fetchContent(lang, callback) { const request = new XMLHttpRequest() request.overrideMimeType("application/json") const url = self.props.contentUrl + '/' + lang + '.json' request.open('GET', url, true) request.onreadystatechange = function () { if (request.readyState === 4 && request.status === 200) { if (request.status === 200) { callback(request.responseText) } else { console.error(url, request.status) } } } request.onloadend = function () { if (request.status === 404 && lang !== self.props.defaultLang) { console.warn("language " + lang + " not found trying defaultLang " + self.props.defaultLang) fetchContent(self.props.defaultLang, callback) } } request.send(null) } function setCookie(name, value, days) { let expires = "" if (days) { const date = new Date() date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)) expires = "; expires=" + date.toUTCString() } document.cookie = name + "=" + (value || "") + expires + "; Path=/; SameSite=Strict;" } 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 c.substring(nameEQ.length, c.length) } } return undefined } function removeCookie(name) { document.cookie = name + '=; Path=/; SameSite=Strict; Expires=Thu, 01 Jan 1970 00:00:01 GMT;' } function documentReady(fn) { if (document.readyState !== 'loading') { fn() } else { document.addEventListener('DOMContentLoaded', fn) } } function hideDialog() { self.modal.style.display = "none" } function showDialog() { documentReady(function () { self.modal = document.getElementById(self.props.modalId) if (!self.modal) { self.modal = document.createElement("div") self.modal.id = self.props.modalId self.modal.innerHTML = self.modalContent document.body.append(self.modal) self.modal.querySelector(".btn-accept-necessary").addEventListener("click", function () { setCookie(self.props.cookieName, "false", 365) hideDialog() if (self.props.postSelectionCallback) { self.props.postSelectionCallback() } }) self.modal.querySelector(".btn-accept-all").addEventListener("click", function () { setCookie(self.props.cookieName, "true", 365) hideDialog() if (self.props.postSelectionCallback) { self.props.postSelectionCallback() } }) } else { self.modal.style.display = "block" } }.bind(this)) } // API self.reset = function () { removeCookie(self.props.cookieName) showDialog() } self.trackingAllowed = function () { return getCookie(self.props.cookieName) === "true" } }