1/** 2 * Author and copyright: Stefan Haack (https://shaack.com) 3 * Repository: https://github.com/shaack/cookie-consent-js 4 * License: MIT, see file 'LICENSE' 5 */ 6 7"use strict" 8 9export default function CookieConsent(props) 10{ 11 12 const self = this 13 self.props = { 14 buttonPrimaryClass: "btn btn-primary", // the "accept all" buttons class, only used for styling 15 buttonSecondaryClass: "btn btn-secondary", // the "accept necessary" buttons class, only used for styling 16 autoShowModal: true, // disable autoShowModal on the privacy policy page, to make that page readable 17 blockAccess: false, // set "true" to block the access to the website before choosing a cookie configuration 18 position: "right", // position ("left" or "right"), if blockAccess is false 19 postSelectionCallback: undefined, // callback, after the user has made a selection 20 lang: navigator.language, // the language, in which the dialog is shown 21 defaultLang: "en", // default language, if the `lang` is not available as translation in `cookie-consent-content` 22 content: [], // deprecated, we now have a `content` folder, which contains the language files 23 contentUrl: "./cookie-consent-content", // the url of the "cookie-consent-content" folder, which contains the language files 24 privacyPolicyUrl: "privacy-policy.html", 25 cookieName: "cookie-consent-tracking-allowed", // the name of the cookie, the cookie is `true` if tracking was accepted 26 modalId: "cookieConsentModal" // the id of the modal dialog element 27 } 28 for (let property in props) { 29 if (property !== "content") { 30 // noinspection JSUnfilteredForInLoop 31 self.props[property] = props[property] 32 } 33 } 34 self.lang = self.props.lang 35 if (self.lang.indexOf("-") !== -1) { 36 self.lang = self.lang.split("-")[0] 37 } 38 for (let contentProperty in props.content) { 39 self.props.content[contentProperty] = props.content[contentProperty] 40 } 41 if (!self.props.content[self.lang]) { 42 fetchContent(self.lang, (result) => { 43 this.props.content = result 44 renderModal() 45 }) 46 } else { 47 renderModal() 48 } 49 50 function renderModal() 51 { 52 const _t = self.props.content 53 const linkPrivacyPolicy = '<a href="' + self.props.privacyPolicyUrl + '">' + _t.privacyPolicy + '</a>' 54 if (self.props.content[self.lang] === undefined) { 55 self.lang = self.props.defaultLang 56 } 57 let modalClass = "cookie-consent-modal" 58 if (self.props.blockAccess) { 59 modalClass += " block-access" 60 } 61 self.modalContent = '<!-- cookie banner => https://github.com/shaack/cookie-consent-js -->' + 62 '<div class="' + modalClass + '">' + 63 '<div class="modal-content-wrap ' + self.props.position + '">' + 64 '<div class="modal-content">' + 65 '<div class="modal-header">--header--</div>' + 66 '<div class="modal-body">--body--</div>' + 67 '<div class="modal-footer">--footer--</div>' + 68 '</div></div><!-- end cookie-consent.js -->' 69 self.modalContent = self.modalContent.replace(/--header--/, "<h3 class=\"modal-title\">" + _t.title + "</h3>") 70 self.modalContent = self.modalContent.replace( 71 /--body--/, 72 _t.body.replace(/--privacy-policy--/, linkPrivacyPolicy) 73 ) 74 self.modalContent = self.modalContent.replace( 75 /--footer--/, 76 "<div class='buttons'>" + 77 "<button class='btn-accept-necessary " + self.props.buttonSecondaryClass + "'>" + _t.buttonAcceptTechnical + "</button>" + 78 "<button class='btn-accept-all " + self.props.buttonPrimaryClass + "'>" + _t.buttonAcceptAll + "</button>" + 79 "</div>" 80 ) 81 if (getCookie(self.props.cookieName) === undefined && self.props.autoShowModal) { 82 showDialog() 83 } 84 } 85 86 async function fetchContent(lang, callback) 87 { 88 89 let langsAvailable = ['de', 'en', 'fr', 'it'] 90 if (!langsAvailable.includes(lang)) { 91 lang = 'en'; 92 }
93 let myRequest = new Request("/cookie-consent-content/" + lang + ".json"); 94 let translations = await fetch(myRequest).then((response) => response.json()) 95 callback(translations) 96 } 97 98 function setCookie(name, value, days) 99 { 100 let expires = "" 101 if (days) { 102 const date = new Date() 103 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)) 104 expires = "; expires=" + date.toUTCString() 105 } 106 document.cookie = name + "=" + (value || "") + expires + "; Path=/; SameSite=Strict;" 107 } 108 109 function getCookie(name) 110 { 111 const nameEQ = name + "=" 112 const ca = document.cookie.split(';') 113 for (let i = 0; i < ca.length; i++) { 114 let c = ca[i] 115 while (c.charAt(0) === ' ') { 116 c = c.substring(1, c.length) 117 } 118 if (c.indexOf(nameEQ) === 0) { 119 return c.substring(nameEQ.length, c.length) 120 } 121 } 122 return undefined 123 } 124 125 function removeCookie(name) 126 { 127 document.cookie = name + '=; Path=/; SameSite=Strict; Expires=Thu, 01 Jan 1970 00:00:01 GMT;' 128 } 129 130 function documentReady(fn) 131 { 132 if (document.readyState !== 'loading') { 133 fn() 134 } else { 135 document.addEventListener('DOMContentLoaded', fn) 136 } 137 } 138 139 function hideDialog() 140 { 141 self.modal.style.display = "none" 142 } 143 144 function showDialog() 145 { 146 documentReady(function () { 147 self.modal = document.getElementById(self.props.modalId) 148 if (!self.modal) { 149 self.modal = document.createElement("div") 150 self.modal.id = self.props.modalId 151 self.modal.innerHTML = self.modalContent 152 document.body.append(self.modal) 153 self.modal.querySelector(".btn-accept-necessary").addEventListener("click", function () { 154 setCookie(self.props.cookieName, "false", 365) 155 hideDialog() 156 if (self.props.postSelectionCallback) { 157 self.props.postSelectionCallback() 158 } 159 }) 160 self.modal.querySelector(".btn-accept-all").addEventListener("click", function () { 161 setCookie(self.props.cookieName, "true", 365) 162 hideDialog() 163 if (self.props.postSelectionCallback) { 164 self.props.postSelectionCallback() 165 } 166 }) 167 } else { 168 self.modal.style.display = "block" 169 } 170 }.bind(this)) 171 } 172 173 // API 174 175 self.reset = function () { 176 removeCookie(self.props.cookieName) 177 showDialog() 178 } 179 180 self.trackingAllowed = function () { 181 return getCookie(self.props.cookieName) === "true" 182 } 183 184}; 185 186
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.