From eb953b022b784d25082dffb6dbdc9a12d57c8474 Mon Sep 17 00:00:00 2001 From: Abhiram Datla Date: Sun, 10 Mar 2024 03:34:40 -0400 Subject: [PATCH 01/19] cloes button --- src/glowCookies.css | 2 ++ src/glowCookies.js | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/glowCookies.css b/src/glowCookies.css index cf46d79..785d87e 100644 --- a/src/glowCookies.css +++ b/src/glowCookies.css @@ -81,6 +81,8 @@ } } + + /* BANNER STYLE 1 */ /* ========================= */ .glowCookies__banner__1 { diff --git a/src/glowCookies.js b/src/glowCookies.js index 6aadeb8..bc2c29d 100644 --- a/src/glowCookies.js +++ b/src/glowCookies.js @@ -48,6 +48,7 @@ class GlowCookies { class="glowCookies__banner glowCookies__banner__${this.config.bannerStyle} glowCookies__${this.config.border} glowCookies__${this.config.position}" style="background-color: ${this.banner.background};" > +

${this.banner.heading}

${this.banner.description} @@ -257,6 +258,8 @@ class GlowCookies { link: obj.policyLink || '#link', background: obj.bannerBackground || '#fff', color: obj.bannerColor || '#1d2e38', + closeColor: obj.closeColor || '#000', + closeBtnHiddenText: obj.closeBtnHidden ? 'hidden' : '', heading: obj.bannerHeading !== 'none' ? obj.bannerHeading || lang.bannerHeading : '', acceptBtn: { text: obj.acceptBtnText || lang.acceptBtnText, From 5e4b4fa47c914602c412d28985606e734eb6885e Mon Sep 17 00:00:00 2001 From: avgentile <108200235+avgentile@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:28:32 -0400 Subject: [PATCH 02/19] Added glowcookies customizer options This includes a completely new button that allows more in-depth cookie selection. Previously, you could only accept all or reject all, but now you are able to specify what specifically you want to accept or reject using different switches. More customization options coming soon to this for styling and such. --- src/glowCookies.css | 70 ++++++++++++++++++++++++-- src/glowCookies.js | 119 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 183 insertions(+), 6 deletions(-) diff --git a/src/glowCookies.css b/src/glowCookies.css index 785d87e..ec0ab31 100644 --- a/src/glowCookies.css +++ b/src/glowCookies.css @@ -17,6 +17,72 @@ transform: scale(1) !important; } +.glowCookies__customize { + position: fixed; + bottom: 15px; + z-index: 999; + min-height: 200px; + min-width: 300px; + font-family: inherit; + font-size: 15px; + font-weight: bolder; + line-height: normal; + border: none; + padding: 12px 18px; + text-decoration: none; + user-select: none; + display: flex; + flex-direction: column; + gap: 50px; + -webkit-box-shadow: 0 .625em 1.875em rgba(2,2,3,.1); + -moz-box-shadow: 0 .625em 1.875em rgba(2,2,3,.1); + box-shadow: 0 .625em 1.875em rgba(2,2,3,.1); +} + +.glowCookies__customize_item_container{ + display: flex; + width: 100%; + flex-direction: row; + font-size: 1em; + justify-content: space-between; +} + +.glowCookies__customize_text{ + justify-self: flex-start; +} + +.glowCookies__customize_switch_button { + justify-self: flex-start; + align-self: flex-start; + align-self: center; + display : inline-block; + min-width: 40px; + height: 1.5em; + display: flex; + align-items: center; + border-radius: 20px; +} + +.glowCookies__customize_switch_button_on{ + background-color: blue; + border: 2px solid gray; + justify-content: flex-end; +} + +.glowCookies__customize_switch_button_off{ + background-color: gray; + border: 2px solid gray; + justify-content: flex-start; +} + +.glowCookies__customize_switch_circle { + background-color: white; + height: 1.4em; + width: 1.4em; + border-radius: 100%; + +} + /* COMMON STYLES */ /* ========================= */ .glowCookies__banner { @@ -28,12 +94,10 @@ width: auto; max-width: 375px; z-index: 999; - -webkit-box-shadow: 0 .625em 1.875em rgba(2,2,3,.2); - -moz-box-shadow: 0 .625em 1.875em rgba(2,2,3,.2); - box-shadow: 0 .625em 1.875em rgba(2,2,3,.2); transition: transform .2s ease, opacity .2s ease !important; } + .glowCookies__banner .accept__btn__styles { border: none; padding: 13px 15px; diff --git a/src/glowCookies.js b/src/glowCookies.js index bc2c29d..f068957 100644 --- a/src/glowCookies.js +++ b/src/glowCookies.js @@ -14,6 +14,7 @@ class GlowCookies { this.tracking = undefined // DOM ELEMENTS this.PreBanner = undefined + this.CustomizeSwitches = [undefined, undefined, undefined] // At most 3 valid switches this.Cookies = undefined this.DOMbanner = undefined } @@ -27,7 +28,7 @@ class GlowCookies { addCss() { const stylesheet = document.createElement('link'); stylesheet.setAttribute('rel', 'stylesheet'); - stylesheet.setAttribute('href', `https://cdn.jsdelivr.net/gh/manucaralmo/GlowCookies@3.1.3/src/glowCookies.min.css`); + stylesheet.setAttribute('href', `./glowCookies.css`); document.head.appendChild(stylesheet); } @@ -46,7 +47,10 @@ class GlowCookies { this.Cookies.innerHTML = `

${this.banner.heading}

@@ -65,6 +69,9 @@ class GlowCookies { + @@ -74,11 +81,72 @@ class GlowCookies { document.body.appendChild(this.Cookies); this.DOMbanner = document.getElementById('glowCookies-banner') + // COOKIES BANNER + this.switch_on = ["glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off"]; + this.Customizer = document.createElement("div"); + this.Customizer.innerHTML = `
+

Customize Cookies

+
+
+ User Preferences +
+
+ +
+
+
+
+ Analytics +
+
+ +
+
+
+
+ Third Party Cookies +
+
+ +
+
+ +
+
+ `; + document.body.appendChild(this.Customizer); + for(let i = 1; i < 4; i++){ + this.CustomizeSwitches[i - 1] = document.getElementById('glowCookies-customize-switch-' + i) + } + // SET EVENT LISTENERS document.getElementById('prebannerBtn').addEventListener('click', () => this.openSelector()) document.getElementById('acceptCookies').addEventListener('click', () => this.acceptCookies()) document.getElementById('rejectCookies').addEventListener('click', () => this.rejectCookies()) + document.getElementById('customizeButton').addEventListener('click', () => this.openCustomizer()) + document.getElementById('glowCookies-customize-switch-1').addEventListener('click', () => this.switchCustomizer(1)) + document.getElementById('glowCookies-customize-switch-2').addEventListener('click', () => this.switchCustomizer(2)) + document.getElementById('glowCookies-customize-switch-3').addEventListener('click', () => this.switchCustomizer(3)) + document.getElementById('glowCookies-customize-save').addEventListener('click', () => this.savePreferences()) + // Add a new click listener for the 'closeManager' } checkStatus() { @@ -99,6 +167,7 @@ class GlowCookies { openManageCookies() { this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" this.DOMbanner.classList.remove('glowCookies__show') + this.Customizer.style.display = "none" } openSelector() { @@ -119,6 +188,37 @@ class GlowCookies { this.disableTracking(); } + openCustomizer() { + // Close out the banner, and we need to open the new banner + this.DOMbanner.classList.remove('glowCookies__show'); + this.Customizer.style.display = "block"; + for(let i = 1; i < 4; i++){ + this.CustomizeSwitches[i - 1].classList.add("glowCookies__customize_switch_button_off"); + } + } + + switchCustomizer(switch_num) { + switch_num = switch_num - 1 + this.CustomizeSwitches[switch_num].classList.remove(this.switch_on[switch_num]); + if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ + // Off to on + this.switch_on[switch_num] = "glowCookies__customize_switch_button_on"; + + }else{ + // On to off + this.switch_on[switch_num] = "glowCookies__customize_switch_button_off" + } + this.CustomizeSwitches[switch_num].classList.add(this.switch_on[switch_num]); + } + + savePreferences(){ + this.DOMbanner.classList.add('glowCookies__show'); + this.Customizer.style.display = "none"; + for(let i = 1; i < 4; i++){ + this.CustomizeSwitches[i - 1].classList.remove("glowCookies__customize_switch_button_off"); + } + } + activateTracking() { // Google Analytics Tracking if (this.tracking.AnalyticsCode) { @@ -251,12 +351,17 @@ class GlowCookies { HotjarTrackingCode: obj.hotjar || undefined, customScript: obj.customScript || undefined } - + let customizeBtnDisplayVal = 'block'; + if (!obj.customizeBtnDisplay){ + customizeBtnDisplayVal = 'none'; + } this.banner = { description: obj.bannerDescription || lang.bannerDescription, linkText: obj.bannerLinkText || lang.bannerLinkText, link: obj.policyLink || '#link', background: obj.bannerBackground || '#fff', + shadowSpread: obj.shadowSpread || 0, + shadowColor: obj.shadowColor || 'rgb(0,0,0,0)', color: obj.bannerColor || '#1d2e38', closeColor: obj.closeColor || '#000', closeBtnHiddenText: obj.closeBtnHidden ? 'hidden' : '', @@ -266,6 +371,12 @@ class GlowCookies { background: obj.acceptBtnBackground || '#253b48', color: obj.acceptBtnColor || '#fff' }, + customizeButton: { + display: customizeBtnDisplayVal, + text: obj.customizeBtnText || lang.customizeBtnText, + background: obj.customizeBtnBackground || '#E8E8E8', + color: obj.customizeBtnColor || '#636363' + }, rejectBtn: { text: obj.rejectBtnText || lang.rejectBtnText, background: obj.rejectBtnBackground || '#E8E8E8', @@ -292,6 +403,7 @@ class LanguagesGC { this.bannerLinkText = lang['bannerLinkText'] this.acceptBtnText = lang['acceptBtnText'] this.rejectBtnText = lang['rejectBtnText'] + this.customizeBtnText = lang['customizeBtnText'] this.manageText = lang['manageText'] } @@ -327,6 +439,7 @@ class LanguagesGC { 'bannerLinkText': 'Read more about cookies', 'acceptBtnText': 'Accept cookies', 'rejectBtnText': 'Reject', + 'customizeBtnText': 'More options', 'manageText': 'Manage cookies' }, sv: { From a7029c2d39ce437cb1e1bb83df9b0cef98d034e1 Mon Sep 17 00:00:00 2001 From: avgentile <108200235+avgentile@users.noreply.github.com> Date: Wed, 27 Mar 2024 12:28:17 -0400 Subject: [PATCH 03/19] Updated customization options for the selector and added starting test suite --- src/glowCookies.css | 18 +- src/glowCookies.js | 92 ++++- src/glowCookiesTest.js | 804 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 901 insertions(+), 13 deletions(-) create mode 100644 src/glowCookiesTest.js diff --git a/src/glowCookies.css b/src/glowCookies.css index ec0ab31..b4a533c 100644 --- a/src/glowCookies.css +++ b/src/glowCookies.css @@ -61,16 +61,15 @@ display: flex; align-items: center; border-radius: 20px; + cursor: pointer; } .glowCookies__customize_switch_button_on{ - background-color: blue; border: 2px solid gray; justify-content: flex-end; } .glowCookies__customize_switch_button_off{ - background-color: gray; border: 2px solid gray; justify-content: flex-start; } @@ -83,6 +82,21 @@ } +.glowCookies-customize-save { + border: none; + padding: 10px 13px; + font-size: 15px; + width: 50%; + align-self: center; + border-radius: 5%; + cursor: pointer; +} + +.glowCookies-customize-save:hover { + -webkit-filter: contrast(85%); + filter: contrast(85%); +} + /* COMMON STYLES */ /* ========================= */ .glowCookies__banner { diff --git a/src/glowCookies.js b/src/glowCookies.js index f068957..8082931 100644 --- a/src/glowCookies.js +++ b/src/glowCookies.js @@ -9,12 +9,15 @@ class GlowCookies { constructor() { // Cookies banner this.banner = undefined + // Selection banner + this.selector = undefined // Config this.config = undefined this.tracking = undefined // DOM ELEMENTS this.PreBanner = undefined this.CustomizeSwitches = [undefined, undefined, undefined] // At most 3 valid switches + this.cookiesAllowed = [undefined, undefined, undefined] // Upon saving a selection or selecting accept/ reject these will be updated accordingly this.Cookies = undefined this.DOMbanner = undefined } @@ -83,13 +86,14 @@ class GlowCookies { // COOKIES BANNER this.switch_on = ["glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off"]; + this.switch_colors = ["switch_color_off", "switch_color_off", "switch_color_off"] this.Customizer = document.createElement("div"); this.Customizer.innerHTML = `
-

Customize Cookies

-
+

${this.selector.titleText}

+
User Preferences
@@ -101,7 +105,7 @@ class GlowCookies {
-
+
Analytics
@@ -113,7 +117,7 @@ class GlowCookies {
-
+
Third Party Cookies
@@ -125,8 +129,9 @@ class GlowCookies {
-
@@ -193,32 +198,48 @@ class GlowCookies { this.DOMbanner.classList.remove('glowCookies__show'); this.Customizer.style.display = "block"; for(let i = 1; i < 4; i++){ - this.CustomizeSwitches[i - 1].classList.add("glowCookies__customize_switch_button_off"); + if(this.cookiesAllowed[i - 1] == undefined || this.cookiesAllowed[i - 1] == false){ + this.switch_on[i - 1] = "glowCookies__customize_switch_button_off"; + this.switch_colors[i - 1] = "switch_color_off"; + }else{ + this.switch_on[i - 1] = "glowCookies__customize_switch_button_on"; + this.switch_colors[i - 1] = "switch_color_on"; + } + this.CustomizeSwitches[i - 1].classList.add(this.switch_on[i-1]); + this.CustomizeSwitches[i - 1].classList.add(this.switch_colors[i-1]); } } switchCustomizer(switch_num) { switch_num = switch_num - 1 this.CustomizeSwitches[switch_num].classList.remove(this.switch_on[switch_num]); + this.CustomizeSwitches[switch_num].classList.remove(this.switch_colors[switch_num]); if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ // Off to on this.switch_on[switch_num] = "glowCookies__customize_switch_button_on"; - + this.switch_colors[switch_num] = "switch_color_on"; }else{ // On to off this.switch_on[switch_num] = "glowCookies__customize_switch_button_off" + this.switch_colors[switch_num] = "switch_color_off"; } this.CustomizeSwitches[switch_num].classList.add(this.switch_on[switch_num]); + this.CustomizeSwitches[switch_num].classList.add(this.switch_colors[switch_num]); } savePreferences(){ - this.DOMbanner.classList.add('glowCookies__show'); this.Customizer.style.display = "none"; - for(let i = 1; i < 4; i++){ - this.CustomizeSwitches[i - 1].classList.remove("glowCookies__customize_switch_button_off"); + for(let switch_num = 0; switch_num < 3; switch_num++){ + if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ + this.cookiesAllowed[switch_num] = false; + }else{ + this.cookiesAllowed[switch_num] = true; + } } + this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" } + activateTracking() { // Google Analytics Tracking if (this.tracking.AnalyticsCode) { @@ -388,7 +409,56 @@ class GlowCookies { text: obj.manageText || lang.manageText, } } + let customizeUserPreferencesDisplay = 'flex'; + if (!obj.customizeUserPreferences){ + customizeUserPreferencesDisplay = 'none'; + } + let customizeAnalyticsDisplay = 'flex'; + if (!obj.customizeAnalytics){ + customizeAnalyticsDisplay = 'none'; + } + let customizeThirdPartyDisplay = 'flex'; + if (!obj.customizeThirdParty){ + customizeThirdPartyDisplay = 'none'; + } + this.selector = { + titleText: obj.selectorTitleText || 'Customize Cookies', + titleColor: obj.selectorTitleColor || 'black', + btnText: obj.selectorBtnText || 'Save cookie preferences', + btnBackground: obj.selectorBtnBackground || 'blue', + btnColor: obj.selectorBtnColor || 'white', + customizeUserPreferences: { + display: customizeUserPreferencesDisplay + }, + customizeAnalytics: { + display: customizeAnalyticsDisplay + }, + customizeThirdParty: { + display: customizeThirdPartyDisplay + }, + customizeSwitch: { + offColor: obj.customizeSwitchOffColor || 'gray', + onColor: obj.customizeSwitchOnColor || 'blue', + } + } + // Append two CSS classes to represent each background color for + for(let i = 0; i < 2; i++){ + var style = document.createElement('style'); + document.head.appendChild(style); + let css = undefined + if(i == 0){ + css = '.switch_color_off' + ' { background-color: ' + this.selector.customizeSwitch.offColor + ';}'; + }else{ + css = '.switch_color_on' + ' { background-color: ' + this.selector.customizeSwitch.onColor + ';}'; + } + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.appendChild(document.createTextNode(css)); + } + document.head.appendChild(style); + } // Draw banner window.addEventListener('load', () => { this.render() }) } diff --git a/src/glowCookiesTest.js b/src/glowCookiesTest.js new file mode 100644 index 0000000..159c0eb --- /dev/null +++ b/src/glowCookiesTest.js @@ -0,0 +1,804 @@ +/* + GLOW COOKIES + CREATED BY MANUEL CARRILLO + https://github.com/manucaralmo/GlowCookies + 2021 - v 3.1.3 +*/ + +class CombinatorialTestingSetup { + + + // numOfInputs is how many parameters will be tested + // labels is a list of the parameter names for each input. Leave this blank if it does not matter and you want permutations + // types is the type of variable each label can take on. If this is only 1 such as 'bool', all inputs can take on true or false. + constructor(numOfInputs, types) { + // We are making a 2d array of different combinations of inputs + // For now, mainly n testing where if there n inputs, we will make a 2d array of size 2^n x n. So 2 inputs will mean our array is 4 x 2 + Array(numOfInputs) + let potentialOptions = [] + if(types[0] == 'bool'){ + potentialOptions[0] = false + potentialOptions[1] = true + } + let permutationList = Array() + this.generateBoolPermutations(numOfInputs, [], potentialOptions, permutationList); + this.inputCombinations = permutationList; + // for(let row = 0; row < numOfInputs; row++){ + // for(let col = 0; col < numOfInputs; col++){ + // console.log("Bool vals are: " + potentialOptions[row] + " " + potentialOptions[col]) + // } + // } + } + + // Used ChatGPT by asking "How to do boolean permutations generalizable to n in JavaScrip?" + generateBoolPermutations(n, prefix = [], potentialOptions, permutationList) { + if (n === 0) { + //console.log(prefix); + permutationList.push(prefix); + return; + } + for (const value of potentialOptions) { + this.generateBoolPermutations(n - 1, [...prefix, value], potentialOptions, permutationList); + } + } + +} + +class GlowCookiesTester { + constructor() { + // Cookies banner + this.banner = undefined + // Selection banner + this.selector = undefined + // Config + this.config = undefined + this.tracking = undefined + // DOM ELEMENTS + this.PreBanner = undefined + this.CustomizeSwitches = [undefined, undefined, undefined] // At most 3 valid switches + this.cookiesAllowed = [undefined, undefined, undefined] // Upon saving a selection or selecting accept/ reject these will be updated accordingly + this.Cookies = undefined + this.DOMbanner = undefined + } + + assert(condition, lineNum) { + if(condition != true){ + throw new Error("Assert failed on line: " + lineNum) + }else{ + return; + } + } + + render() { + this.addCss() + this.createDOMElements() + this.checkStatus() + + // Tests need to be called after render + // Call tests as necessary + //this.test1() + //this.test2() + //this.test3() + + this.ctest1() + } + + addCss() { + const stylesheet = document.createElement('link'); + stylesheet.setAttribute('rel', 'stylesheet'); + stylesheet.setAttribute('href', `./glowCookies.css`); + document.head.appendChild(stylesheet); + } + + createDOMElements() { + // COOKIES BUTTON + this.PreBanner = document.createElement("div"); + this.PreBanner.innerHTML = ``; + this.PreBanner.style.display = "none"; + document.body.appendChild(this.PreBanner); + + // COOKIES BANNER + this.Cookies = document.createElement("div"); + this.Cookies.innerHTML = `
+ +

${this.banner.heading}

+

+ ${this.banner.description} + + ${this.banner.linkText} + +

+
+ + + +
+
+ `; + document.body.appendChild(this.Cookies); + this.DOMbanner = document.getElementById('glowCookies-banner') + + // COOKIES BANNER + this.switch_on = ["glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off"]; + this.switch_colors = ["switch_color_off", "switch_color_off", "switch_color_off"] + this.Customizer = document.createElement("div"); + this.Customizer.innerHTML = `
+

${this.selector.titleText}

+
+
+ User Preferences +
+
+ +
+
+
+
+ Analytics +
+
+ +
+
+
+
+ Third Party Cookies +
+
+ +
+
+ +
+ + `; + document.body.appendChild(this.Customizer); + for(let i = 1; i < 4; i++){ + this.CustomizeSwitches[i - 1] = document.getElementById('glowCookies-customize-switch-' + i) + } + + + // SET EVENT LISTENERS + document.getElementById('prebannerBtn').addEventListener('click', () => this.openSelector()) + document.getElementById('acceptCookies').addEventListener('click', () => this.acceptCookies()) + document.getElementById('rejectCookies').addEventListener('click', () => this.rejectCookies()) + document.getElementById('customizeButton').addEventListener('click', () => this.openCustomizer()) + document.getElementById('glowCookies-customize-switch-1').addEventListener('click', () => this.switchCustomizer(1)) + document.getElementById('glowCookies-customize-switch-2').addEventListener('click', () => this.switchCustomizer(2)) + document.getElementById('glowCookies-customize-switch-3').addEventListener('click', () => this.switchCustomizer(3)) + document.getElementById('glowCookies-customize-save').addEventListener('click', () => this.savePreferences()) + // Add a new click listener for the 'closeManager' + } + + checkStatus() { + switch (localStorage.getItem("GlowCookies")) { + case "1": + this.openManageCookies(); + this.activateTracking(); + this.addCustomScript(); + break; + case "0": + this.openManageCookies(); + break; + default: + this.openSelector(); + } + } + + openManageCookies() { + this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" + this.DOMbanner.classList.remove('glowCookies__show') + this.Customizer.style.display = "none" + } + + openSelector() { + this.PreBanner.style.display = "none"; + this.DOMbanner.classList.add('glowCookies__show') + } + + acceptCookies() { + localStorage.setItem("GlowCookies", "1") + this.openManageCookies() + this.activateTracking() + this.addCustomScript() + } + + rejectCookies() { + localStorage.setItem("GlowCookies", "0"); + this.openManageCookies(); + this.disableTracking(); + } + + openCustomizer() { + // Close out the banner, and we need to open the new banner + this.DOMbanner.classList.remove('glowCookies__show'); + this.Customizer.style.display = "block"; + for(let i = 1; i < 4; i++){ + if(this.cookiesAllowed[i - 1] == undefined || this.cookiesAllowed[i - 1] == false){ + this.switch_on[i - 1] = "glowCookies__customize_switch_button_off"; + this.switch_colors[i - 1] = "switch_color_off"; + }else{ + this.switch_on[i - 1] = "glowCookies__customize_switch_button_on"; + this.switch_colors[i - 1] = "switch_color_on"; + } + this.CustomizeSwitches[i - 1].classList.add(this.switch_on[i-1]); + this.CustomizeSwitches[i - 1].classList.add(this.switch_colors[i-1]); + } + } + + switchCustomizer(switch_num) { + switch_num = switch_num - 1 + this.CustomizeSwitches[switch_num].classList.remove(this.switch_on[switch_num]); + this.CustomizeSwitches[switch_num].classList.remove(this.switch_colors[switch_num]); + if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ + // Off to on + this.switch_on[switch_num] = "glowCookies__customize_switch_button_on"; + this.switch_colors[switch_num] = "switch_color_on"; + }else{ + // On to off + this.switch_on[switch_num] = "glowCookies__customize_switch_button_off" + this.switch_colors[switch_num] = "switch_color_off"; + } + this.CustomizeSwitches[switch_num].classList.add(this.switch_on[switch_num]); + this.CustomizeSwitches[switch_num].classList.add(this.switch_colors[switch_num]); + } + + savePreferences(){ + this.Customizer.style.display = "none"; + for(let switch_num = 0; switch_num < 3; switch_num++){ + if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ + this.cookiesAllowed[switch_num] = false; + }else{ + this.cookiesAllowed[switch_num] = true; + } + } + this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" + } + + + activateTracking() { + // Google Analytics Tracking + if (this.tracking.AnalyticsCode) { + let Analytics = document.createElement('script'); + Analytics.setAttribute('src', `https://www.googletagmanager.com/gtag/js?id=${this.tracking.AnalyticsCode}`); + document.head.appendChild(Analytics); + let AnalyticsData = document.createElement('script'); + AnalyticsData.text = `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', '${this.tracking.AnalyticsCode}');`; + document.head.appendChild(AnalyticsData); + } + + // Facebook pixel tracking code + if (this.tracking.FacebookPixelCode) { + let FacebookPixelData = document.createElement('script'); + FacebookPixelData.text = ` + !function(f,b,e,v,n,t,s) + {if(f.fbq)return;n=f.fbq=function(){n.callMethod? + n.callMethod.apply(n,arguments):n.queue.push(arguments)}; + if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; + n.queue=[];t=b.createElement(e);t.async=!0; + t.src=v;s=b.getElementsByTagName(e)[0]; + s.parentNode.insertBefore(t,s)}(window, document,'script', + 'https://connect.facebook.net/en_US/fbevents.js'); + fbq('init', '${this.tracking.FacebookPixelCode}'); + fbq('track', 'PageView'); + `; + document.head.appendChild(FacebookPixelData); + let FacebookPixel = document.createElement('noscript'); + FacebookPixel.setAttribute('height', `1`); + FacebookPixel.setAttribute('width', `1`); + FacebookPixel.setAttribute('style', `display:none`); + FacebookPixel.setAttribute('src', `https://www.facebook.com/tr?id=${this.tracking.FacebookPixelCode}&ev=PageView&noscript=1`); + document.head.appendChild(FacebookPixel); + } + + // Hotjar Tracking + if (this.tracking.HotjarTrackingCode) { + let hotjarTrackingData = document.createElement('script'); + hotjarTrackingData.text = ` + (function(h,o,t,j,a,r){ + h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)}; + h._hjSettings={hjid:${this.tracking.HotjarTrackingCode},hjsv:6}; + a=o.getElementsByTagName('head')[0]; + r=o.createElement('script');r.async=1; + r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv; + a.appendChild(r); + })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv='); + `; + document.head.appendChild(hotjarTrackingData); + } + } + + disableTracking() { + // Google Analytics Tracking ('client_storage': 'none') + if (this.tracking.AnalyticsCode) { + let Analytics = document.createElement('script'); + Analytics.setAttribute('src', `https://www.googletagmanager.com/gtag/js?id=${this.tracking.AnalyticsCode}`); + document.head.appendChild(Analytics); + let AnalyticsData = document.createElement('script'); + AnalyticsData.text = `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', '${this.tracking.AnalyticsCode}' , { + 'client_storage': 'none', + 'anonymize_ip': true + });`; + document.head.appendChild(AnalyticsData); + } + + // Clear cookies - not working 100% + this.clearCookies() + } + + clearCookies() { + let cookies = document.cookie.split("; "); + for (let c = 0; c < cookies.length; c++) { + let d = window.location.hostname.split("."); + while (d.length > 0) { + let cookieBase = encodeURIComponent(cookies[c].split(";")[0].split("=")[0]) + '=; expires=Thu, 01-Jan-1970 00:00:01 GMT; domain=' + d.join('.') + ' ;path='; + let p = location.pathname.split('/'); + document.cookie = cookieBase + '/'; + while (p.length > 0) { + document.cookie = cookieBase + p.join('/'); + p.pop(); + }; + d.shift(); + } + } + } + + addCustomScript() { + if (this.tracking.customScript !== undefined) { + let customScriptTag + + this.tracking.customScript.forEach(script => { + if (script.type === 'src') { + customScriptTag = document.createElement('script'); + customScriptTag.setAttribute('src', script.content); + } else if (script.type === 'custom') { + customScriptTag = document.createElement('script'); + customScriptTag.text = script.content; + } + + if (script.position === 'head') { + document.head.appendChild(customScriptTag); + } else { + document.body.appendChild(customScriptTag); + } + }) + } + } + + start(languaje, obj) { + if (!obj) obj = {} + const lang = new LanguagesGC(languaje) + + this.config = { + border: obj.border || 'border', + position: obj.position || 'left', + hideAfterClick: obj.hideAfterClick || false, + bannerStyle: obj.style || 2 + } + + this.tracking = { + AnalyticsCode: obj.analytics || undefined, + FacebookPixelCode: obj.facebookPixel || undefined, + HotjarTrackingCode: obj.hotjar || undefined, + customScript: obj.customScript || undefined + } + let customizeBtnDisplayVal = 'block'; + if (!obj.customizeBtnDisplay){ + customizeBtnDisplayVal = 'none'; + } + this.banner = { + description: obj.bannerDescription || lang.bannerDescription, + linkText: obj.bannerLinkText || lang.bannerLinkText, + link: obj.policyLink || '#link', + background: obj.bannerBackground || '#fff', + shadowSpread: obj.shadowSpread || 0, + shadowColor: obj.shadowColor || 'rgb(0,0,0,0)', + color: obj.bannerColor || '#1d2e38', + closeColor: obj.closeColor || '#000', + closeBtnHiddenText: obj.closeBtnHidden ? 'hidden' : '', + heading: obj.bannerHeading !== 'none' ? obj.bannerHeading || lang.bannerHeading : '', + acceptBtn: { + text: obj.acceptBtnText || lang.acceptBtnText, + background: obj.acceptBtnBackground || '#253b48', + color: obj.acceptBtnColor || '#fff' + }, + customizeButton: { + display: customizeBtnDisplayVal, + text: obj.customizeBtnText || lang.customizeBtnText, + background: obj.customizeBtnBackground || '#E8E8E8', + color: obj.customizeBtnColor || '#636363' + }, + rejectBtn: { + text: obj.rejectBtnText || lang.rejectBtnText, + background: obj.rejectBtnBackground || '#E8E8E8', + color: obj.rejectBtnColor || '#636363' + }, + manageCookies: { + color: obj.manageColor || '#1d2e38', + background: obj.manageBackground || '#fff', + text: obj.manageText || lang.manageText, + } + } + let customizeUserPreferencesDisplay = 'flex'; + if (!obj.customizeUserPreferences){ + customizeUserPreferencesDisplay = 'none'; + } + let customizeAnalyticsDisplay = 'flex'; + if (!obj.customizeAnalytics){ + customizeAnalyticsDisplay = 'none'; + } + let customizeThirdPartyDisplay = 'flex'; + if (!obj.customizeThirdParty){ + customizeThirdPartyDisplay = 'none'; + } + + this.selector = { + titleText: obj.selectorTitleText || 'Customize Cookies', + titleColor: obj.selectorTitleColor || 'black', + btnText: obj.selectorBtnText || 'Save cookie preferences', + btnBackground: obj.selectorBtnBackground || 'blue', + btnColor: obj.selectorBtnColor || 'white', + customizeUserPreferences: { + display: customizeUserPreferencesDisplay + }, + customizeAnalytics: { + display: customizeAnalyticsDisplay + }, + customizeThirdParty: { + display: customizeThirdPartyDisplay + }, + customizeSwitch: { + offColor: obj.customizeSwitchOffColor || 'gray', + onColor: obj.customizeSwitchOnColor || 'blue', + } + } + // Append two CSS classes to represent each background color for + for(let i = 0; i < 2; i++){ + var style = document.createElement('style'); + document.head.appendChild(style); + let css = undefined + if(i == 0){ + css = '.switch_color_off' + ' { background-color: ' + this.selector.customizeSwitch.offColor + ';}'; + }else{ + css = '.switch_color_on' + ' { background-color: ' + this.selector.customizeSwitch.onColor + ';}'; + } + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.appendChild(document.createTextNode(css)); + } + document.head.appendChild(style); + } + // Draw banner + window.addEventListener('load', () => { this.render() }) + } + + // Default Testing + // Assuming no user input + // Testing purely for accepting cookies + test1 = () => { + console.log("Running Test 1"); + this.openManageCookies(); + this.acceptCookies(); + this.assert(localStorage.getItem("GlowCookies") == '1', new Error().lineNumber) + console.log("Passed all parts of Test 1") + } + + test2 = () => { + console.log("Running Test 2"); + // Ensure that hideafterclick is not true + this.config.hideAfterClick = false + this.openManageCookies(); + this.acceptCookies(); + this.assert(localStorage.getItem("GlowCookies") == '1', new Error().lineNumber) + this.openManageCookies(); + this.rejectCookies(); + this.assert(localStorage.getItem("GlowCookies") == '0', new Error().lineNumber) + console.log("Passed all parts of Test 2") + } + + test3 = () => { + console.log("Running Test 3"); + this.openManageCookies(); + this.rejectCookies(); + this.assert(localStorage.getItem("GlowCookies") == '0', new Error().lineNumber) + console.log("Passed all parts of Test 3") + } + + ctest1 = () => { + console.log("Running Combinatorial Test 1 for selector"); + // Ensure hide after click is false + this.config.hideAfterClick = false + let selectorTestInputs = new CombinatorialTestingSetup(3, ['bool'])['inputCombinations']; + console.log(selectorTestInputs) + selectorTestInputs.forEach((selectorTestComb) => { + this.openManageCookies(); + this.openSelector(); + // Go through each comb, and set switches + console.log("Testing selector combination: " + selectorTestComb) + for(let switch_num = 0; switch_num < 3; switch_num++){ + + this.CustomizeSwitches[switch_num].classList.remove(this.switch_on[switch_num]); + this.CustomizeSwitches[switch_num].classList.remove(this.switch_colors[switch_num]); + if(selectorTestComb[switch_num]){ + this.switch_on[switch_num] = "glowCookies__customize_switch_button_on"; + this.switch_colors[switch_num] = "switch_color_on"; + }else{ + this.switch_on[switch_num] = "glowCookies__customize_switch_button_off"; + this.switch_colors[switch_num] = "switch_color_off"; + } + this.CustomizeSwitches[switch_num].classList.add(this.switch_on[switch_num]); + this.CustomizeSwitches[switch_num].classList.add(this.switch_colors[switch_num]); + } + this.savePreferences(); + // After saving, let's ensure that all of the selections held and are now applied + for(let switch_num = 0; switch_num < 3; switch_num++){ + this.assert(this.cookiesAllowed[switch_num] == selectorTestComb[switch_num], new Error().lineNumber); + } + console.log("Selector combination: " + selectorTestComb + " was saved correctly.") + }) + console.log("Passed Combinatorial Test 1 for selector"); + } +} + + + class LanguagesGC { + constructor(code) { + this.init() + let lang = this.arrLang[code] || this.arrLang['en'] + this.bannerHeading = lang['bannerHeading'] + this.bannerDescription = lang['bannerDescription'] + this.bannerLinkText = lang['bannerLinkText'] + this.acceptBtnText = lang['acceptBtnText'] + this.rejectBtnText = lang['rejectBtnText'] + this.customizeBtnText = lang['customizeBtnText'] + this.manageText = lang['manageText'] + } + + init() { + this.arrLang = { + af: { + 'bannerHeading': 'Ons gebruik koekies', + 'bannerDescription': 'Ons gebruik ons eie koekies en die van derdepartye, om inhoud te verpersoonlik en om webverkeer te ontleed.', + 'bannerLinkText': 'Lees meer oor koekies', + 'acceptBtnText': 'Aanvaar koekies', + 'rejectBtnText': 'Weier', + 'manageText': 'Koekie-instellings' + }, + bg: { + 'bannerHeading': 'Ние използваме бисквитки', + 'bannerDescription': 'Използваме наши и бисквитки на трети страни, за да запазим Вашите предпочитания и да събираме аналитични данни.', + 'bannerLinkText': 'Прочетете повече за бисквитките', + 'acceptBtnText': 'Приеми бисквитките', + 'rejectBtnText': 'Откажи', + 'manageText': 'Настрой бисквитките' + }, + de: { + 'bannerHeading': 'Verwendung von Cookies', + 'bannerDescription': 'Wir nutzen Cookies (auch von Drittanbietern), um Inhalte zu personalisieren und Surfverhalten zu analysieren.', + 'bannerLinkText': 'Mehr über Cookies', + 'acceptBtnText': 'Cookies akzeptieren', + 'rejectBtnText': 'Ablehnen', + 'manageText': 'Cookies verwalten' + }, + en: { + 'bannerHeading': 'We use cookies', + 'bannerDescription': 'We use our own and third-party cookies to personalize content and to analyze web traffic.', + 'bannerLinkText': 'Read more about cookies', + 'acceptBtnText': 'Accept cookies', + 'rejectBtnText': 'Reject', + 'customizeBtnText': 'More options', + 'manageText': 'Manage cookies' + }, + sv: { + 'bannerHeading': 'Vi använder cookies', + 'bannerDescription' : 'Vi använder våra egna och tredjepartscookies för att personalisera innehåll och till statistik.', + 'bannerLinkText' : 'Läs mer om cookies', + 'acceptBtnText' : 'Acceptera cookies', + 'rejectBtnText' : 'Avslå', + 'manageText' : 'Hantera cookies' + }, + no: { + 'bannerHeading': 'Vi benytter cookies', + 'bannerDescription' : 'Vi benytter våre egne og tredjepartscookies for å personalisere innehold og til statistikk.', + 'bannerLinkText' : 'Les mer om cookies', + 'acceptBtnText' : 'Aksepter cookies', + 'rejectBtnText' : 'Avslå', + 'manageText' : 'Håndter cookies' + }, + da: { + 'bannerHeading': 'Vi bruger cookies', + 'bannerDescription' : 'Vi bruger vores egne og tredjepartscookies til at tilpasse indhold og måle statistik.', + 'bannerLinkText' : 'Læs mere om cookies', + 'acceptBtnText' : 'Accepter cookies', + 'rejectBtnText' : 'Afvis', + 'manageText' : 'Administrer cookies' + }, + es: { + 'bannerHeading': 'Uso de cookies', + 'bannerDescription': 'Utilizamos cookies propias y de terceros para personalizar el contenido y para analizar el tráfico de la web.', + 'bannerLinkText': 'Ver más sobre las cookies', + 'acceptBtnText': 'Aceptar cookies', + 'rejectBtnText': 'Rechazar', + 'manageText': 'Cookies' + }, + fr: { + 'bannerHeading': 'Nous utilisons des cookies', + 'bannerDescription': 'Nous utilisons nos propres cookies et ceux de tiers pour adapter le contenu et analyser le trafic web.', + 'bannerLinkText': 'En savoir plus sur les cookies', + 'acceptBtnText': 'Accepter les cookies', + 'rejectBtnText': 'Refuser', + 'manageText': 'Paramétrez les cookies' + }, + it: { + 'bannerHeading': 'Utilizziamo i cookie', + 'bannerDescription': 'Utilizziamo cookie nostri e di terze parti per personalizzare il contenuto e analizzare il traffico web.', + 'bannerLinkText': 'Per saperne di più riguardo i cookie', + 'acceptBtnText': 'Accetta i cookie', + 'rejectBtnText': 'Rifiuta', + 'manageText': 'Gestisci i cookie' + }, + mg: { + 'bannerHeading': 'Izahay dia mampiasa cookies', + 'bannerDescription': "Mampiasa ny cookies anay manokana sy ireo an'ny antoko fahatelo izahay hampifanarahana ny atiny sy hamakafaka ny fivezivezena amin'ny tranonkala.", + 'bannerLinkText': 'Maniry halala bebe kokoa momba ny cookies', + 'acceptBtnText': 'Manaiky ireo cookies', + 'rejectBtnText': 'Tsy mety', + 'manageText': 'Hamboarina ny cookies' + }, + nl: { + 'bannerHeading': 'We gebruiken cookies', + 'bannerDescription': 'We gebruiken onze en third-party cookies om content te personaliseren en web traffic te analyseren.', + 'bannerLinkText': 'Lees meer over cookies', + 'acceptBtnText': 'Cookies accepteren', + 'rejectBtnText': 'Weigeren', + 'manageText': 'Cookies beheren' + }, + oc: { + 'bannerHeading': 'Utilizam de cookies', + 'bannerDescription': 'Utilizam nòstres pròpris cookies e de cookies tèrces per adaptar lo contengut e analisar lo trafic web.', + 'bannerLinkText': 'Ne saber mai suls cookies', + 'acceptBtnText': 'Acceptar los cookies', + 'rejectBtnText': 'Refusar', + 'manageText': 'Configurar los cookies' + }, + pl: { + 'bannerHeading': 'Używamy plików cookie', + 'bannerDescription': 'Ta strona używa plików cookie - zarówno własnych, jak i od zewnętrznych dostawców, w celu personalizacji treści i analizy ruchu.', + 'bannerLinkText': 'Więcej o plikach cookie', + 'acceptBtnText': 'Zaakceptuj pliki cookie', + 'rejectBtnText': 'Odrzuć', + 'manageText': 'Ustawienia plików cookie' + }, + pt_BR: { + 'bannerHeading': 'Uso de cookies', + 'bannerDescription': 'Usamos cookies próprios e de terceiros para personalizar o conteúdo e analisar o tráfego da web.', + 'bannerLinkText': 'Leia mais sobre os cookies', + 'acceptBtnText': 'Aceitar cookies', + 'rejectBtnText': 'Rejeitar', + 'manageText': 'Gerenciar cookies' + }, + ru: { + 'bannerHeading': 'Позвольте использовать куки?', + 'bannerDescription': 'Мы используем собственные и сторонние куки для персонализации контента и анализа веб-трафика.', + 'bannerLinkText': 'Узнать больше про куки.', + 'acceptBtnText': 'Ок, используйте', + 'rejectBtnText': 'Не разрешаю', + 'manageText': 'Разрешите использовать куки?' + }, + sk: { + 'bannerHeading': 'Používame cookies', + 'bannerDescription': 'Na prispôsobenie obsahu a analýzu webovej stránky používame vlastné cookies a cookies tretích strán.', + 'bannerLinkText': 'Čo sú cookies?', + 'acceptBtnText': 'Povoliť cookies', + 'rejectBtnText': 'Nepovoliť', + 'manageText': 'Spravovať cookies' + }, + th: { + 'bannerHeading': 'Cookies', + 'bannerDescription': 'พวกเราใช้คุกกี้บุคคลที่สาม เพื่อปรับแต่งเนื้อหาและวิเคราะห์การเข้าชมเว็บ', + 'bannerLinkText': 'อ่านเพิ่มเติมเกี่ยวกับคุกกี้', + 'acceptBtnText': 'ยอมรับคุกกี้', + 'rejectBtnText': 'ปฏิเสธคุกกี้', + 'manageText': 'Cookies' + }, + tr: { + 'bannerHeading': 'Çerez kullanımı', + 'bannerDescription': 'İçeriği kişiselleştirmek ve web trafiğini analiz etmek için kendi ve üçüncü taraf çerezlerimizi kullanıyoruz.', + 'bannerLinkText': 'Çerezler hakkında daha fazlasını okuyun', + 'acceptBtnText': 'Çerezleri kabul et', + 'rejectBtnText': 'Reddet', + 'manageText': 'Çerezleri yönet' + }, + uk: { + 'bannerHeading': 'Ми використовуємо кукі', + 'bannerDescription': 'Ми використовуємо власні та сторонні cookie для персоналізації досвіду користування та аналізу веб-трафіку.', + 'bannerLinkText': 'Дізнайтеся більше про cookie', + 'acceptBtnText': 'Прийняти', + 'rejectBtnText': 'Відхилити', + 'manageText': 'Налаштування cookie' + }, + ja: { + 'bannerHeading': 'Cookies を使用しています', + 'bannerDescription': '私たちは、コンテンツのパーソナライズやトラフィックの分析のために、独自およびサードパーティー製 Cookies を使用しています。', + 'bannerLinkText': 'Cookiesについて詳しく見る', + 'acceptBtnText': 'Cookiesを受け入れる', + 'rejectBtnText': '拒否', + 'manageText': 'cookies管理' + }, + zh_TW: { + 'bannerHeading': '我們使用 Cookies', + 'bannerDescription' : '我們使用了自己和第三方的 cookies 來個人化您的內容和分析網頁的流量。', + 'bannerLinkText' : '閱讀更多關於 cookies', + 'acceptBtnText' : '同意 cookies', + 'rejectBtnText' : '拒絕', + 'manageText' : '管理 cookies' + }, + zh: { + 'bannerHeading': '我们使用 Cookies', + 'bannerDescription': '我们使用了自己和第三方的 cookies 来个性化您的内容和分析网页的流量。', + 'bannerLinkText': '阅读更多关于 cookies', + 'acceptBtnText': '同意 cookies', + 'rejectBtnText': '拒绝', + 'manageText': '管理 cookies' + }, + ca: { + 'bannerHeading': 'Ús de Cookies', + 'bannerDescription': 'Utilitzem cookies pròpies i de tercers per a personalitzar el contingut i per a analitzar el trànsit del lloc web.', + 'bannerLinkText': 'Vegeu més informació sobre les Cookies', + 'acceptBtnText': 'Acceptar les Cookies', + 'rejectBtnText': 'Declinar', + 'manageText': 'Cookies' + } + } + } + + } + + const glowCookies = new GlowCookiesTester() + From f10801f06957900e17cb85bf4f967b5307a356a4 Mon Sep 17 00:00:00 2001 From: avgentile <108200235+avgentile@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:40:02 -0400 Subject: [PATCH 04/19] Fixed customizer issue Customizer would pop up when first entering the site because it wasn't set to display: none on the default case. --- src/glowCookies.js | 1 + src/glowCookiesTest.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/glowCookies.js b/src/glowCookies.js index 8082931..de7e12d 100644 --- a/src/glowCookies.js +++ b/src/glowCookies.js @@ -178,6 +178,7 @@ class GlowCookies { openSelector() { this.PreBanner.style.display = "none"; this.DOMbanner.classList.add('glowCookies__show') + this.Customizer.style.display = "none" } acceptCookies() { diff --git a/src/glowCookiesTest.js b/src/glowCookiesTest.js index 159c0eb..a661fa0 100644 --- a/src/glowCookiesTest.js +++ b/src/glowCookiesTest.js @@ -233,6 +233,7 @@ class GlowCookiesTester { openSelector() { this.PreBanner.style.display = "none"; this.DOMbanner.classList.add('glowCookies__show') + this.Customizer.style.display = "none"; } acceptCookies() { From d68a092b4d6cfbe27e5d222ce2cff3a2fd5c1f0b Mon Sep 17 00:00:00 2001 From: Abhiram Datla Date: Thu, 28 Mar 2024 15:58:07 -0400 Subject: [PATCH 05/19] closebtn on customizer --- src/glowCookies.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/glowCookies.js b/src/glowCookies.js index 8082931..48ac50e 100644 --- a/src/glowCookies.js +++ b/src/glowCookies.js @@ -92,6 +92,7 @@ class GlowCookies { id="glowCookies-customize" class="glowCookies__customize glowCookies__${this.config.position}" style=""> +

${this.selector.titleText}

@@ -178,6 +179,7 @@ class GlowCookies { openSelector() { this.PreBanner.style.display = "none"; this.DOMbanner.classList.add('glowCookies__show') + this.Customizer.style.display = "none" } acceptCookies() { @@ -677,4 +679,4 @@ class LanguagesGC { } -const glowCookies = new GlowCookies() +const glowCookies = new GlowCookies() \ No newline at end of file From 2fd5613e4aa878e5f08aa4d68354e3ecd888c414 Mon Sep 17 00:00:00 2001 From: PL-666 Date: Fri, 29 Mar 2024 22:23:38 -0400 Subject: [PATCH 06/19] Added cookie retention period --- src/glowCookies.js | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/glowCookies.js b/src/glowCookies.js index 48ac50e..def443e 100644 --- a/src/glowCookies.js +++ b/src/glowCookies.js @@ -30,8 +30,8 @@ class GlowCookies { addCss() { const stylesheet = document.createElement('link'); - stylesheet.setAttribute('rel', 'stylesheet'); - stylesheet.setAttribute('href', `./glowCookies.css`); + // stylesheet.setAttribute('rel', 'stylesheet'); + // stylesheet.setAttribute('href', `GlowCookies/src/glowCookies.css`); document.head.appendChild(stylesheet); } @@ -161,6 +161,7 @@ class GlowCookies { this.openManageCookies(); this.activateTracking(); this.addCustomScript(); + this.setRetentionPeriod(this.tracking.retentionPeriod); break; case "0": this.openManageCookies(); @@ -187,6 +188,7 @@ class GlowCookies { this.openManageCookies() this.activateTracking() this.addCustomScript() + this.setRetentionPeriod(this.tracking.retentionPeriod); } rejectCookies() { @@ -334,6 +336,26 @@ class GlowCookies { } } } + setRetentionPeriod(daystoLive) { + let cookies = document.cookie.split("; "); + for(let c = 0; c < cookies.length; c++) { + let d = window.location.hostname.split("."); + const date = new Date(); + date.setTime(date.getTime() + (daystoLive * 24* 60 * 60 *1000)); + // date.setTime(date.getTime() + (daystoLive *1000)); + + while (d.length > 0) { + let cookieBase = encodeURIComponent(cookies[c].split(";")[0].split("=")[0]) + `=; expires=${date.toUTCString()}; domain=` + d.join('.') + ' ;path='; + let p = location.pathname.split('/'); + document.cookie = cookieBase + '/'; + // while (p.length > 0) { + // document.cookie = cookieBase + p.join('/'); + // p.pop(); + // }; + d.shift(); + } + } + } addCustomScript() { if (this.tracking.customScript !== undefined) { @@ -372,7 +394,8 @@ class GlowCookies { AnalyticsCode: obj.analytics || undefined, FacebookPixelCode: obj.facebookPixel || undefined, HotjarTrackingCode: obj.hotjar || undefined, - customScript: obj.customScript || undefined + customScript: obj.customScript || undefined, + retentionPeriod: obj.retentionPeriod || 1 } let customizeBtnDisplayVal = 'block'; if (!obj.customizeBtnDisplay){ From ea0f29662552b3d94db4b36dfaae7a6441a5f35d Mon Sep 17 00:00:00 2001 From: PL-666 Date: Sat, 30 Mar 2024 11:19:04 -0400 Subject: [PATCH 07/19] added customizable retention period --- src/glowCookies.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/glowCookies.js b/src/glowCookies.js index def443e..035a07a 100644 --- a/src/glowCookies.js +++ b/src/glowCookies.js @@ -188,8 +188,9 @@ class GlowCookies { this.openManageCookies() this.activateTracking() this.addCustomScript() - this.setRetentionPeriod(this.tracking.retentionPeriod); + this.setRetentionPeriod(this.tracking.retentionPeriod) } + rejectCookies() { localStorage.setItem("GlowCookies", "0"); From b46bd14f5f280c77c5ac58d932d43fdade377c0a Mon Sep 17 00:00:00 2001 From: Arryan Bhatnagar Date: Sat, 30 Mar 2024 17:03:14 -0400 Subject: [PATCH 08/19] session-only cookies with demo code - added support for session only cookies - added index.html to create the object and view it - added addcookie.js to add cookies for the demo --- .gitignore | 3 +- src/addcookie.js | 22 +++++++++++++ src/glowCookies.js | 37 +++++++++++++++++++++- src/index.html | 79 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 src/addcookie.js create mode 100644 src/index.html diff --git a/.gitignore b/.gitignore index 29527b9..fc06756 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ # Ignore Mac system files -.DS_store \ No newline at end of file +.DS_store +.idea \ No newline at end of file diff --git a/src/addcookie.js b/src/addcookie.js new file mode 100644 index 0000000..604b496 --- /dev/null +++ b/src/addcookie.js @@ -0,0 +1,22 @@ +const firstText = document.querySelector("#firstText"); +const submitBtn = document.querySelector("#submitBtn"); + +submitBtn.addEventListener("click", () => { + setCookie(firstText.value, firstText.value, 365); +}); + +function setCookie(name, value, daysToLive) { + const isSessionOnly = sessionStorage.getItem('isSessionOnly') === 'true'; + + let expires = ""; + if (!isSessionOnly && daysToLive !== null) { // If not session-only and daysToLive is specified + const date = new Date(); + date.setTime(date.getTime() + (daysToLive * 24 * 60 * 60 * 1000)); + expires = "expires=" + date.toUTCString(); + } + document.cookie = `${name}=${value}; ${expires}; path=/`; +} + +function deleteCookie(name){ + setCookie(name, null, null); +} diff --git a/src/glowCookies.js b/src/glowCookies.js index 035a07a..0b3655d 100644 --- a/src/glowCookies.js +++ b/src/glowCookies.js @@ -96,7 +96,7 @@ class GlowCookies {

${this.selector.titleText}

- User Preferences + Session Only
+
+ + + + + + From 355eda0fc80b7d7c9e3b6a5269c9a2ce6bbc0132 Mon Sep 17 00:00:00 2001 From: avgentile <108200235+avgentile@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:47:47 -0400 Subject: [PATCH 09/19] Added session-only integration and updated test suite Session only cookies is now the fourth switch in the cookie customizer. Upon saving this selection, it either activates or deactivates sessiononly cookies. Test suite is now stand alone class that can be used on the overall GlowCookies class. Combinatorial testing class has also been updated so it can create combinations of multiple types. --- src/glowCookies.js | 159 +++--- src/glowCookiesTest.js | 1179 ++++++++++++++++++++++------------------ 2 files changed, 757 insertions(+), 581 deletions(-) diff --git a/src/glowCookies.js b/src/glowCookies.js index 0b3655d..2611906 100644 --- a/src/glowCookies.js +++ b/src/glowCookies.js @@ -16,8 +16,8 @@ class GlowCookies { this.tracking = undefined // DOM ELEMENTS this.PreBanner = undefined - this.CustomizeSwitches = [undefined, undefined, undefined] // At most 3 valid switches - this.cookiesAllowed = [undefined, undefined, undefined] // Upon saving a selection or selecting accept/ reject these will be updated accordingly + this.CustomizeSwitches = [undefined, undefined, undefined, undefined] // At most 3 valid switches + this.cookiesAllowed = [undefined, undefined, undefined, undefined] // Upon saving a selection or selecting accept/ reject these will be updated accordingly this.Cookies = undefined this.DOMbanner = undefined } @@ -85,8 +85,8 @@ class GlowCookies { this.DOMbanner = document.getElementById('glowCookies-banner') // COOKIES BANNER - this.switch_on = ["glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off"]; - this.switch_colors = ["switch_color_off", "switch_color_off", "switch_color_off"] + this.switch_on = ["glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off"]; + this.switch_colors = ["switch_color_off", "switch_color_off", "switch_color_off", "switch_color_off"] this.Customizer = document.createElement("div"); this.Customizer.innerHTML = `
${this.selector.titleText}
- Session Only + User Preferences
+
+
+ Session Only Cookies +
+
+ +
+
`; document.body.appendChild(this.Customizer); - for(let i = 1; i < 4; i++){ + for(let i = 1; i < 5; i++){ this.CustomizeSwitches[i - 1] = document.getElementById('glowCookies-customize-switch-' + i) } @@ -151,6 +163,7 @@ class GlowCookies { document.getElementById('glowCookies-customize-switch-1').addEventListener('click', () => this.switchCustomizer(1)) document.getElementById('glowCookies-customize-switch-2').addEventListener('click', () => this.switchCustomizer(2)) document.getElementById('glowCookies-customize-switch-3').addEventListener('click', () => this.switchCustomizer(3)) + document.getElementById('glowCookies-customize-switch-4').addEventListener('click', () => this.switchCustomizer(4)) document.getElementById('glowCookies-customize-save').addEventListener('click', () => this.savePreferences()) // Add a new click listener for the 'closeManager' } @@ -202,7 +215,7 @@ class GlowCookies { // Close out the banner, and we need to open the new banner this.DOMbanner.classList.remove('glowCookies__show'); this.Customizer.style.display = "block"; - for(let i = 1; i < 4; i++){ + for(let i = 1; i < 5; i++){ if(this.cookiesAllowed[i - 1] == undefined || this.cookiesAllowed[i - 1] == false){ this.switch_on[i - 1] = "glowCookies__customize_switch_button_off"; this.switch_colors[i - 1] = "switch_color_off"; @@ -231,54 +244,64 @@ class GlowCookies { this.CustomizeSwitches[switch_num].classList.add(this.switch_on[switch_num]); this.CustomizeSwitches[switch_num].classList.add(this.switch_colors[switch_num]); - - // 1st switch (user preferences / session only) - if (switch_num === 0) { - let isSessionOnly = 0 - if (this.switch_on[switch_num ] == "glowCookies__customize_switch_button_on") { - isSessionOnly = 1 - } else { - isSessionOnly = 0 - } - sessionStorage.setItem('isSessionOnly', isSessionOnly ? 'true' : 'false'); - - // split document.cookie string to get all cookies - let cookies = document.cookie.split(';'); - - for (let i = 0; i < cookies.length; i++) { - let cookie = cookies[i]; - let eqPos = cookie.indexOf('='); - let name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; - let value = eqPos > -1 ? cookie.substr(eqPos + 1) : null; - if (isSessionOnly) { - // makes it a session cookie - document.cookie = `${name}=${value}; path=/`; - } else { - // set cookie with 8-hour expiration - // need to change to the custom retention period - const date = new Date(); - date.setTime(date.getTime() + (8 * 60 * 60 * 1000)); // 8 hours - let expires = "expires=" + date.toUTCString(); - document.cookie = `${name}=${value}; ${expires}; path=/`; - } - } - - } } savePreferences(){ this.Customizer.style.display = "none"; - for(let switch_num = 0; switch_num < 3; switch_num++){ + let isSessionOnly = 0; + for(let switch_num = 0; switch_num < 4; switch_num++){ if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ this.cookiesAllowed[switch_num] = false; }else{ + if(switch_num == 0){ + if(this.tracking.userPreferencesScript != undefined){ + this.addNewScript(this.tracking.userPreferencesScript) + } + }else if(switch_num == 1){ + if(this.tracking.userPreferencesScript != undefined){ + this.addNewScript(this.tracking.thirdPartyScript) + } + }else if(switch_num == 2){ + if(this.tracking.userPreferencesScript != undefined){ + this.addNewScript(this.tracking.analyticsScript) + } + }else{ + // if we are on switch 4 it must be session onl + isSessionOnly = 1 + } this.cookiesAllowed[switch_num] = true; } } + this.activateSessionCookies(isSessionOnly); this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" } + activateSessionCookies(isSessionOnly){ + sessionStorage.setItem('isSessionOnly', isSessionOnly ? 'true' : 'false'); + + // split document.cookie string to get all cookies + let cookies = document.cookie.split(';'); + + for (let i = 0; i < cookies.length; i++) { + let cookie = cookies[i]; + let eqPos = cookie.indexOf('='); + let name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; + let value = eqPos > -1 ? cookie.substr(eqPos + 1) : null; + if (isSessionOnly) { + // makes it a session cookie + document.cookie = `${name}=${value}; path=/`; + } else { + // set cookie with 8-hour expiration + // need to change to the custom retention period + const date = new Date(); + date.setTime(date.getTime() + (8 * 60 * 60 * 1000)); // 8 hours + let expires = "expires=" + date.toUTCString(); + document.cookie = `${name}=${value}; ${expires}; path=/`; + } + } + } + activateTracking() { // Google Analytics Tracking @@ -395,26 +418,30 @@ class GlowCookies { addCustomScript() { if (this.tracking.customScript !== undefined) { - let customScriptTag - - this.tracking.customScript.forEach(script => { - if (script.type === 'src') { - customScriptTag = document.createElement('script'); - customScriptTag.setAttribute('src', script.content); - } else if (script.type === 'custom') { - customScriptTag = document.createElement('script'); - customScriptTag.text = script.content; - } - - if (script.position === 'head') { - document.head.appendChild(customScriptTag); - } else { - document.body.appendChild(customScriptTag); - } - }) + this.addNewScript(this.tracking.customScript) } } + addNewScript(customScript) { + let customScriptTag + customScript.forEach(script => { + if (script.type === 'src') { + customScriptTag = document.createElement('script'); + customScriptTag.setAttribute('src', script.content); + } else if (script.type === 'custom') { + customScriptTag = document.createElement('script'); + customScriptTag.text = script.content; + } + + if (script.position === 'head') { + document.head.appendChild(customScriptTag); + } else { + document.body.appendChild(customScriptTag); + } + }) + } + + start(languaje, obj) { if (!obj) obj = {} const lang = new LanguagesGC(languaje) @@ -431,6 +458,9 @@ class GlowCookies { FacebookPixelCode: obj.facebookPixel || undefined, HotjarTrackingCode: obj.hotjar || undefined, customScript: obj.customScript || undefined, + userPreferencesScript: obj.userPreferencesScript || undefined, + thirdPartyScript: obj.thirdPartyScript || undefined, + analyticsScript: obj.analyticsScript || undefined, retentionPeriod: obj.retentionPeriod || 1 } let customizeBtnDisplayVal = 'block'; @@ -471,17 +501,21 @@ class GlowCookies { } } let customizeUserPreferencesDisplay = 'flex'; - if (!obj.customizeUserPreferences){ + if (obj.customizeUserPreferences == false){ customizeUserPreferencesDisplay = 'none'; } let customizeAnalyticsDisplay = 'flex'; - if (!obj.customizeAnalytics){ + if (obj.customizeAnalytics == false){ customizeAnalyticsDisplay = 'none'; } let customizeThirdPartyDisplay = 'flex'; - if (!obj.customizeThirdParty){ + if (obj.customizeThirdParty == false){ customizeThirdPartyDisplay = 'none'; } + let customizeSessionCookiesDisplay = 'flex'; + if(obj.customizeSessionCookies == false){ + customizeSessionCookiesDisplay = 'none' + } this.selector = { titleText: obj.selectorTitleText || 'Customize Cookies', @@ -498,6 +532,9 @@ class GlowCookies { customizeThirdParty: { display: customizeThirdPartyDisplay }, + customizeSessionCookies: { + display: customizeSessionCookiesDisplay + }, customizeSwitch: { offColor: obj.customizeSwitchOffColor || 'gray', onColor: obj.customizeSwitchOnColor || 'blue', diff --git a/src/glowCookiesTest.js b/src/glowCookiesTest.js index a661fa0..7851e8f 100644 --- a/src/glowCookiesTest.js +++ b/src/glowCookiesTest.js @@ -5,30 +5,59 @@ 2021 - v 3.1.3 */ +function assert(condition, lineNum) { + if(condition != true){ + throw new Error("Assert failed on line: " + lineNum) + }else{ + return; + } +} + + class CombinatorialTestingSetup { - // numOfInputs is how many parameters will be tested - // labels is a list of the parameter names for each input. Leave this blank if it does not matter and you want permutations - // types is the type of variable each label can take on. If this is only 1 such as 'bool', all inputs can take on true or false. - constructor(numOfInputs, types) { - // We are making a 2d array of different combinations of inputs - // For now, mainly n testing where if there n inputs, we will make a 2d array of size 2^n x n. So 2 inputs will mean our array is 4 x 2 - Array(numOfInputs) - let potentialOptions = [] - if(types[0] == 'bool'){ - potentialOptions[0] = false - potentialOptions[1] = true + // // numOfInputs is how many parameters will be tested + // // labels is a list of the parameter names for each input. Leave this blank if it does not matter and you want permutations + // // types is the type of variable each label can take on. If this is only 1 such as 'bool', all inputs can take on true or false. + // constructor(numOfInputs, types) { + // // We are making a 2d array of different combinations of inputs + // // For now, mainly n testing where if there n inputs, we will make a 2d array of size 2^n x n. So 2 inputs will mean our array is 4 x 2 + // let potentialOptions = [] + // if(types[0] == 'bool'){ + // potentialOptions[0] = false + // potentialOptions[1] = true + // } + // let permutationList = Array() + // this.generateBoolPermutations(numOfInputs, [], potentialOptions, permutationList); + // this.inputCombinations = permutationList; + // // for(let row = 0; row < numOfInputs; row++){ + // // for(let col = 0; col < numOfInputs; col++){ + // // console.log("Bool vals are: " + potentialOptions[row] + " " + potentialOptions[col]) + // // } + // // } + // } + + // This will generate combinations bassed off of the types + // types is the type of variable each label can take on. The length of labels must equal types if you use this constructor + // type_infos is a list of the extra information for types + constructor(types, type_infos) { + assert(type_infos.length == types.length, new Error().lineNumber) + // We are making a 2d array of different combinations of inputs + // For now, mainly n testing where if there n inputs, we will make a 2d array of size 2^n x n. So 2 inputs will mean our array is 4 x 2 + let potentialOptionsList = [] + for(let i = 0; i < types.length; i++){ + if(types[i] == 'bool'){ + potentialOptionsList.push([false, true]); + }else if(types[i] == 'num'){ + // pass in list for type_info (e.g. [1, 2, 5]) + potentialOptionsList.push(type_infos[i]) } - let permutationList = Array() - this.generateBoolPermutations(numOfInputs, [], potentialOptions, permutationList); - this.inputCombinations = permutationList; - // for(let row = 0; row < numOfInputs; row++){ - // for(let col = 0; col < numOfInputs; col++){ - // console.log("Bool vals are: " + potentialOptions[row] + " " + potentialOptions[col]) - // } - // } - } + } + let permutationList = Array() + this.generateCombinations(types.length, [], potentialOptionsList, permutationList, types.length); + this.inputCombinations = permutationList; + } // Used ChatGPT by asking "How to do boolean permutations generalizable to n in JavaScrip?" generateBoolPermutations(n, prefix = [], potentialOptions, permutationList) { @@ -40,551 +69,661 @@ class CombinatorialTestingSetup { for (const value of potentialOptions) { this.generateBoolPermutations(n - 1, [...prefix, value], potentialOptions, permutationList); } + } + + generateCombinations(n, prefix = [], potentialOptions, permutationList, max_options) { + if (n === 0) { + //console.log(prefix); + permutationList.push(prefix); + return; + } + for (const value of potentialOptions[max_options - n]) { + this.generateCombinations(n - 1, [...prefix, value], potentialOptions, permutationList, max_options); + } } + + } class GlowCookiesTester { - constructor() { - // Cookies banner - this.banner = undefined - // Selection banner - this.selector = undefined - // Config - this.config = undefined - this.tracking = undefined - // DOM ELEMENTS - this.PreBanner = undefined - this.CustomizeSwitches = [undefined, undefined, undefined] // At most 3 valid switches - this.cookiesAllowed = [undefined, undefined, undefined] // Upon saving a selection or selecting accept/ reject these will be updated accordingly - this.Cookies = undefined - this.DOMbanner = undefined - } + constructor(glowCookies){ + this.glowCookies = glowCookies; - assert(condition, lineNum) { - if(condition != true){ - throw new Error("Assert failed on line: " + lineNum) - }else{ - return; - } - } - - render() { - this.addCss() - this.createDOMElements() - this.checkStatus() - - // Tests need to be called after render - // Call tests as necessary - //this.test1() - //this.test2() - //this.test3() - - this.ctest1() - } - - addCss() { - const stylesheet = document.createElement('link'); - stylesheet.setAttribute('rel', 'stylesheet'); - stylesheet.setAttribute('href', `./glowCookies.css`); - document.head.appendChild(stylesheet); - } - - createDOMElements() { - // COOKIES BUTTON - this.PreBanner = document.createElement("div"); - this.PreBanner.innerHTML = ``; - this.PreBanner.style.display = "none"; - document.body.appendChild(this.PreBanner); - - // COOKIES BANNER - this.Cookies = document.createElement("div"); - this.Cookies.innerHTML = `
- -

${this.banner.heading}

-

- ${this.banner.description} - - ${this.banner.linkText} - -

-
- - - -
-
- `; - document.body.appendChild(this.Cookies); - this.DOMbanner = document.getElementById('glowCookies-banner') - - // COOKIES BANNER - this.switch_on = ["glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off"]; - this.switch_colors = ["switch_color_off", "switch_color_off", "switch_color_off"] - this.Customizer = document.createElement("div"); - this.Customizer.innerHTML = `
-

${this.selector.titleText}

-
-
- User Preferences -
-
- -
+ // Tests + //this.test1(); + //this.test2(); + //this.test3(); + + this.ctest1(); + } + + // Default Testing + // Assuming no user input + // Testing purely for accepting cookies + test1 = () => { + console.log("Running Test 1"); + this.glowCookies.openManageCookies(); + this.glowCookies.acceptCookies(); + assert(localStorage.getItem("GlowCookies") == '1', new Error().lineNumber) + console.log("Passed all parts of Test 1") + } + + test2 = () => { + console.log("Running Test 2"); + // Ensure that hideafterclick is not true + this.glowCookies.config.hideAfterClick = false + this.glowCookies.openManageCookies(); + this.glowCookies.acceptCookies(); + assert(localStorage.getItem("GlowCookies") == '1', new Error().lineNumber) + this.glowCookies.openManageCookies(); + this.glowCookies.rejectCookies(); + assert(localStorage.getItem("GlowCookies") == '0', new Error().lineNumber) + console.log("Passed all parts of Test 2") + } + + test3 = () => { + console.log("Running Test 3"); + this.glowCookies.openManageCookies(); + this.glowCookies.rejectCookies(); + assert(localStorage.getItem("GlowCookies") == '0', new Error().lineNumber) + console.log("Passed all parts of Test 3") + } + + ctest1 = () => { + console.log("Running Combinatorial Test 1 for selector"); + // Ensure hide after click is false + this.glowCookies.config.hideAfterClick = false + let selectorTestInputs = new CombinatorialTestingSetup(['bool', 'bool', 'bool', 'bool'], ['','','', ''])['inputCombinations']; + console.log(selectorTestInputs) + selectorTestInputs.forEach((selectorTestComb) => { + this.glowCookies.openManageCookies(); + this.glowCookies.openSelector(); + // Go through each comb, and set switches + console.log("Testing selector combination: " + selectorTestComb) + for(let switch_num = 0; switch_num < 4; switch_num++){ + + this.glowCookies.CustomizeSwitches[switch_num].classList.remove(this.glowCookies.switch_on[switch_num]); + this.glowCookies.CustomizeSwitches[switch_num].classList.remove(this.glowCookies.switch_colors[switch_num]); + if(selectorTestComb[switch_num]){ + this.glowCookies.switch_on[switch_num] = "glowCookies__customize_switch_button_on"; + this.glowCookies.switch_colors[switch_num] = "switch_color_on"; + }else{ + this.glowCookies.switch_on[switch_num] = "glowCookies__customize_switch_button_off"; + this.glowCookies.switch_colors[switch_num] = "switch_color_off"; + } + this.glowCookies.CustomizeSwitches[switch_num].classList.add(this.glowCookies.switch_on[switch_num]); + this.glowCookies.CustomizeSwitches[switch_num].classList.add(this.glowCookies.switch_colors[switch_num]); + } + this.glowCookies.savePreferences(); + // After saving, let's ensure that all of the selections held and are now applied + for(let switch_num = 0; switch_num < 4; switch_num++){ + assert(this.glowCookies.cookiesAllowed[switch_num] == selectorTestComb[switch_num], new Error().lineNumber); + } + console.log("Selector combination: " + selectorTestComb + " was saved correctly.") + }) + console.log("Passed Combinatorial Test 1 for selector"); + } +} + + +class GlowCookies { + constructor() { + // Cookies banner + this.banner = undefined + // Selection banner + this.selector = undefined + // Config + this.config = undefined + this.tracking = undefined + // DOM ELEMENTS + this.PreBanner = undefined + this.CustomizeSwitches = [undefined, undefined, undefined, undefined] // At most 3 valid switches + this.cookiesAllowed = [undefined, undefined, undefined, undefined] // Upon saving a selection or selecting accept/ reject these will be updated accordingly + this.Cookies = undefined + this.DOMbanner = undefined + } + + render() { + this.addCss() + this.createDOMElements() + this.checkStatus() + + new GlowCookiesTester(this); + } + + addCss() { + const stylesheet = document.createElement('link'); + // stylesheet.setAttribute('rel', 'stylesheet'); + // stylesheet.setAttribute('href', `GlowCookies/src/glowCookies.css`); + document.head.appendChild(stylesheet); + } + + createDOMElements() { + // COOKIES BUTTON + this.PreBanner = document.createElement("div"); + this.PreBanner.innerHTML = ``; + this.PreBanner.style.display = "none"; + document.body.appendChild(this.PreBanner); + + // COOKIES BANNER + this.Cookies = document.createElement("div"); + this.Cookies.innerHTML = `
+ +

${this.banner.heading}

+

+ ${this.banner.description} + + ${this.banner.linkText} + +

+
+ + + +
+
+ `; + document.body.appendChild(this.Cookies); + this.DOMbanner = document.getElementById('glowCookies-banner') + + // COOKIES BANNER + this.switch_on = ["glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off"]; + this.switch_colors = ["switch_color_off", "switch_color_off", "switch_color_off", "switch_color_off"] + this.Customizer = document.createElement("div"); + this.Customizer.innerHTML = `
+ +

${this.selector.titleText}

+
+
+ User Preferences
-
-
- Analytics -
-
- +
+
-
+
+
- Third Party Cookies + Analytics
-
- +
+
+ Third Party Cookies +
+
+ +
+
+
+ Session Only Cookies
- `; - document.body.appendChild(this.Customizer); - for(let i = 1; i < 4; i++){ - this.CustomizeSwitches[i - 1] = document.getElementById('glowCookies-customize-switch-' + i) - } - - - // SET EVENT LISTENERS - document.getElementById('prebannerBtn').addEventListener('click', () => this.openSelector()) - document.getElementById('acceptCookies').addEventListener('click', () => this.acceptCookies()) - document.getElementById('rejectCookies').addEventListener('click', () => this.rejectCookies()) - document.getElementById('customizeButton').addEventListener('click', () => this.openCustomizer()) - document.getElementById('glowCookies-customize-switch-1').addEventListener('click', () => this.switchCustomizer(1)) - document.getElementById('glowCookies-customize-switch-2').addEventListener('click', () => this.switchCustomizer(2)) - document.getElementById('glowCookies-customize-switch-3').addEventListener('click', () => this.switchCustomizer(3)) - document.getElementById('glowCookies-customize-save').addEventListener('click', () => this.savePreferences()) - // Add a new click listener for the 'closeManager' - } - - checkStatus() { - switch (localStorage.getItem("GlowCookies")) { - case "1": - this.openManageCookies(); - this.activateTracking(); - this.addCustomScript(); - break; - case "0": - this.openManageCookies(); - break; - default: - this.openSelector(); - } - } - - openManageCookies() { - this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" - this.DOMbanner.classList.remove('glowCookies__show') - this.Customizer.style.display = "none" - } - - openSelector() { - this.PreBanner.style.display = "none"; - this.DOMbanner.classList.add('glowCookies__show') - this.Customizer.style.display = "none"; - } - - acceptCookies() { - localStorage.setItem("GlowCookies", "1") - this.openManageCookies() - this.activateTracking() - this.addCustomScript() +
+ +
+
+ +
+
+ `; + document.body.appendChild(this.Customizer); + for(let i = 1; i < 5; i++){ + this.CustomizeSwitches[i - 1] = document.getElementById('glowCookies-customize-switch-' + i) } - - rejectCookies() { - localStorage.setItem("GlowCookies", "0"); - this.openManageCookies(); - this.disableTracking(); + + + // SET EVENT LISTENERS + document.getElementById('prebannerBtn').addEventListener('click', () => this.openSelector()) + document.getElementById('acceptCookies').addEventListener('click', () => this.acceptCookies()) + document.getElementById('rejectCookies').addEventListener('click', () => this.rejectCookies()) + document.getElementById('customizeButton').addEventListener('click', () => this.openCustomizer()) + document.getElementById('glowCookies-customize-switch-1').addEventListener('click', () => this.switchCustomizer(1)) + document.getElementById('glowCookies-customize-switch-2').addEventListener('click', () => this.switchCustomizer(2)) + document.getElementById('glowCookies-customize-switch-3').addEventListener('click', () => this.switchCustomizer(3)) + document.getElementById('glowCookies-customize-switch-4').addEventListener('click', () => this.switchCustomizer(4)) + document.getElementById('glowCookies-customize-save').addEventListener('click', () => this.savePreferences()) + // Add a new click listener for the 'closeManager' + } + + checkStatus() { + switch (localStorage.getItem("GlowCookies")) { + case "1": + this.openManageCookies(); + this.activateTracking(); + this.addCustomScript(); + this.setRetentionPeriod(this.tracking.retentionPeriod); + break; + case "0": + this.openManageCookies(); + break; + default: + this.openSelector(); } + } + + openManageCookies() { + this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" + this.DOMbanner.classList.remove('glowCookies__show') + this.Customizer.style.display = "none" + } + + openSelector() { + this.PreBanner.style.display = "none"; + this.DOMbanner.classList.add('glowCookies__show') + this.Customizer.style.display = "none" + } + + acceptCookies() { + localStorage.setItem("GlowCookies", "1") + this.openManageCookies() + this.activateTracking() + this.addCustomScript() + this.setRetentionPeriod(this.tracking.retentionPeriod) + } - openCustomizer() { - // Close out the banner, and we need to open the new banner - this.DOMbanner.classList.remove('glowCookies__show'); - this.Customizer.style.display = "block"; - for(let i = 1; i < 4; i++){ - if(this.cookiesAllowed[i - 1] == undefined || this.cookiesAllowed[i - 1] == false){ - this.switch_on[i - 1] = "glowCookies__customize_switch_button_off"; - this.switch_colors[i - 1] = "switch_color_off"; - }else{ - this.switch_on[i - 1] = "glowCookies__customize_switch_button_on"; - this.switch_colors[i - 1] = "switch_color_on"; - } - this.CustomizeSwitches[i - 1].classList.add(this.switch_on[i-1]); - this.CustomizeSwitches[i - 1].classList.add(this.switch_colors[i-1]); + + rejectCookies() { + localStorage.setItem("GlowCookies", "0"); + this.openManageCookies(); + this.disableTracking(); + } + + openCustomizer() { + // Close out the banner, and we need to open the new banner + this.DOMbanner.classList.remove('glowCookies__show'); + this.Customizer.style.display = "block"; + for(let i = 1; i < 5; i++){ + if(this.cookiesAllowed[i - 1] == undefined || this.cookiesAllowed[i - 1] == false){ + this.switch_on[i - 1] = "glowCookies__customize_switch_button_off"; + this.switch_colors[i - 1] = "switch_color_off"; + }else{ + this.switch_on[i - 1] = "glowCookies__customize_switch_button_on"; + this.switch_colors[i - 1] = "switch_color_on"; } + this.CustomizeSwitches[i - 1].classList.add(this.switch_on[i-1]); + this.CustomizeSwitches[i - 1].classList.add(this.switch_colors[i-1]); } - - switchCustomizer(switch_num) { - switch_num = switch_num - 1 - this.CustomizeSwitches[switch_num].classList.remove(this.switch_on[switch_num]); - this.CustomizeSwitches[switch_num].classList.remove(this.switch_colors[switch_num]); + } + + switchCustomizer(switch_num) { + switch_num = switch_num - 1 + this.CustomizeSwitches[switch_num].classList.remove(this.switch_on[switch_num]); + this.CustomizeSwitches[switch_num].classList.remove(this.switch_colors[switch_num]); + if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ + // Off to on + this.switch_on[switch_num] = "glowCookies__customize_switch_button_on"; + this.switch_colors[switch_num] = "switch_color_on"; + }else{ + // On to off + this.switch_on[switch_num] = "glowCookies__customize_switch_button_off" + this.switch_colors[switch_num] = "switch_color_off"; + } + this.CustomizeSwitches[switch_num].classList.add(this.switch_on[switch_num]); + this.CustomizeSwitches[switch_num].classList.add(this.switch_colors[switch_num]); + + + } + + savePreferences(){ + this.Customizer.style.display = "none"; + let isSessionOnly = 0; + for(let switch_num = 0; switch_num < 4; switch_num++){ if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ - // Off to on - this.switch_on[switch_num] = "glowCookies__customize_switch_button_on"; - this.switch_colors[switch_num] = "switch_color_on"; + this.cookiesAllowed[switch_num] = false; }else{ - // On to off - this.switch_on[switch_num] = "glowCookies__customize_switch_button_off" - this.switch_colors[switch_num] = "switch_color_off"; - } - this.CustomizeSwitches[switch_num].classList.add(this.switch_on[switch_num]); - this.CustomizeSwitches[switch_num].classList.add(this.switch_colors[switch_num]); - } - - savePreferences(){ - this.Customizer.style.display = "none"; - for(let switch_num = 0; switch_num < 3; switch_num++){ - if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ - this.cookiesAllowed[switch_num] = false; + if(switch_num == 0){ + if(this.tracking.userPreferencesScript != undefined){ + this.addNewScript(this.tracking.userPreferencesScript) + } + }else if(switch_num == 1){ + if(this.tracking.userPreferencesScript != undefined){ + this.addNewScript(this.tracking.thirdPartyScript) + } + }else if(switch_num == 2){ + if(this.tracking.userPreferencesScript != undefined){ + this.addNewScript(this.tracking.analyticsScript) + } }else{ - this.cookiesAllowed[switch_num] = true; + // if we are on switch 4 it must be session onl + isSessionOnly = 1 } + this.cookiesAllowed[switch_num] = true; } - this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" } - - - activateTracking() { - // Google Analytics Tracking - if (this.tracking.AnalyticsCode) { - let Analytics = document.createElement('script'); - Analytics.setAttribute('src', `https://www.googletagmanager.com/gtag/js?id=${this.tracking.AnalyticsCode}`); - document.head.appendChild(Analytics); - let AnalyticsData = document.createElement('script'); - AnalyticsData.text = `window.dataLayer = window.dataLayer || []; - function gtag(){dataLayer.push(arguments);} - gtag('js', new Date()); - gtag('config', '${this.tracking.AnalyticsCode}');`; - document.head.appendChild(AnalyticsData); - } - - // Facebook pixel tracking code - if (this.tracking.FacebookPixelCode) { - let FacebookPixelData = document.createElement('script'); - FacebookPixelData.text = ` - !function(f,b,e,v,n,t,s) - {if(f.fbq)return;n=f.fbq=function(){n.callMethod? - n.callMethod.apply(n,arguments):n.queue.push(arguments)}; - if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; - n.queue=[];t=b.createElement(e);t.async=!0; - t.src=v;s=b.getElementsByTagName(e)[0]; - s.parentNode.insertBefore(t,s)}(window, document,'script', - 'https://connect.facebook.net/en_US/fbevents.js'); - fbq('init', '${this.tracking.FacebookPixelCode}'); - fbq('track', 'PageView'); - `; - document.head.appendChild(FacebookPixelData); - let FacebookPixel = document.createElement('noscript'); - FacebookPixel.setAttribute('height', `1`); - FacebookPixel.setAttribute('width', `1`); - FacebookPixel.setAttribute('style', `display:none`); - FacebookPixel.setAttribute('src', `https://www.facebook.com/tr?id=${this.tracking.FacebookPixelCode}&ev=PageView&noscript=1`); - document.head.appendChild(FacebookPixel); - } - - // Hotjar Tracking - if (this.tracking.HotjarTrackingCode) { - let hotjarTrackingData = document.createElement('script'); - hotjarTrackingData.text = ` - (function(h,o,t,j,a,r){ - h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)}; - h._hjSettings={hjid:${this.tracking.HotjarTrackingCode},hjsv:6}; - a=o.getElementsByTagName('head')[0]; - r=o.createElement('script');r.async=1; - r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv; - a.appendChild(r); - })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv='); - `; - document.head.appendChild(hotjarTrackingData); + this.activateSessionCookies(isSessionOnly); + this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" + } + + activateSessionCookies(isSessionOnly){ + sessionStorage.setItem('isSessionOnly', isSessionOnly ? 'true' : 'false'); + + // split document.cookie string to get all cookies + let cookies = document.cookie.split(';'); + + for (let i = 0; i < cookies.length; i++) { + let cookie = cookies[i]; + let eqPos = cookie.indexOf('='); + let name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; + let value = eqPos > -1 ? cookie.substr(eqPos + 1) : null; + if (isSessionOnly) { + // makes it a session cookie + document.cookie = `${name}=${value}; path=/`; + } else { + // set cookie with 8-hour expiration + // need to change to the custom retention period + const date = new Date(); + date.setTime(date.getTime() + (8 * 60 * 60 * 1000)); // 8 hours + let expires = "expires=" + date.toUTCString(); + document.cookie = `${name}=${value}; ${expires}; path=/`; } } - - disableTracking() { - // Google Analytics Tracking ('client_storage': 'none') - if (this.tracking.AnalyticsCode) { - let Analytics = document.createElement('script'); - Analytics.setAttribute('src', `https://www.googletagmanager.com/gtag/js?id=${this.tracking.AnalyticsCode}`); - document.head.appendChild(Analytics); - let AnalyticsData = document.createElement('script'); - AnalyticsData.text = `window.dataLayer = window.dataLayer || []; - function gtag(){dataLayer.push(arguments);} - gtag('js', new Date()); - gtag('config', '${this.tracking.AnalyticsCode}' , { - 'client_storage': 'none', - 'anonymize_ip': true - });`; - document.head.appendChild(AnalyticsData); - } - - // Clear cookies - not working 100% - this.clearCookies() + } + + + activateTracking() { + // Google Analytics Tracking + if (this.tracking.AnalyticsCode) { + let Analytics = document.createElement('script'); + Analytics.setAttribute('src', `https://www.googletagmanager.com/gtag/js?id=${this.tracking.AnalyticsCode}`); + document.head.appendChild(Analytics); + let AnalyticsData = document.createElement('script'); + AnalyticsData.text = `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', '${this.tracking.AnalyticsCode}');`; + document.head.appendChild(AnalyticsData); } - - clearCookies() { - let cookies = document.cookie.split("; "); - for (let c = 0; c < cookies.length; c++) { - let d = window.location.hostname.split("."); - while (d.length > 0) { - let cookieBase = encodeURIComponent(cookies[c].split(";")[0].split("=")[0]) + '=; expires=Thu, 01-Jan-1970 00:00:01 GMT; domain=' + d.join('.') + ' ;path='; - let p = location.pathname.split('/'); - document.cookie = cookieBase + '/'; - while (p.length > 0) { - document.cookie = cookieBase + p.join('/'); - p.pop(); - }; - d.shift(); - } - } + + // Facebook pixel tracking code + if (this.tracking.FacebookPixelCode) { + let FacebookPixelData = document.createElement('script'); + FacebookPixelData.text = ` + !function(f,b,e,v,n,t,s) + {if(f.fbq)return;n=f.fbq=function(){n.callMethod? + n.callMethod.apply(n,arguments):n.queue.push(arguments)}; + if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; + n.queue=[];t=b.createElement(e);t.async=!0; + t.src=v;s=b.getElementsByTagName(e)[0]; + s.parentNode.insertBefore(t,s)}(window, document,'script', + 'https://connect.facebook.net/en_US/fbevents.js'); + fbq('init', '${this.tracking.FacebookPixelCode}'); + fbq('track', 'PageView'); + `; + document.head.appendChild(FacebookPixelData); + let FacebookPixel = document.createElement('noscript'); + FacebookPixel.setAttribute('height', `1`); + FacebookPixel.setAttribute('width', `1`); + FacebookPixel.setAttribute('style', `display:none`); + FacebookPixel.setAttribute('src', `https://www.facebook.com/tr?id=${this.tracking.FacebookPixelCode}&ev=PageView&noscript=1`); + document.head.appendChild(FacebookPixel); } - - addCustomScript() { - if (this.tracking.customScript !== undefined) { - let customScriptTag - - this.tracking.customScript.forEach(script => { - if (script.type === 'src') { - customScriptTag = document.createElement('script'); - customScriptTag.setAttribute('src', script.content); - } else if (script.type === 'custom') { - customScriptTag = document.createElement('script'); - customScriptTag.text = script.content; - } - - if (script.position === 'head') { - document.head.appendChild(customScriptTag); - } else { - document.body.appendChild(customScriptTag); - } - }) - } + + // Hotjar Tracking + if (this.tracking.HotjarTrackingCode) { + let hotjarTrackingData = document.createElement('script'); + hotjarTrackingData.text = ` + (function(h,o,t,j,a,r){ + h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)}; + h._hjSettings={hjid:${this.tracking.HotjarTrackingCode},hjsv:6}; + a=o.getElementsByTagName('head')[0]; + r=o.createElement('script');r.async=1; + r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv; + a.appendChild(r); + })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv='); + `; + document.head.appendChild(hotjarTrackingData); } - - start(languaje, obj) { - if (!obj) obj = {} - const lang = new LanguagesGC(languaje) - - this.config = { - border: obj.border || 'border', - position: obj.position || 'left', - hideAfterClick: obj.hideAfterClick || false, - bannerStyle: obj.style || 2 - } - - this.tracking = { - AnalyticsCode: obj.analytics || undefined, - FacebookPixelCode: obj.facebookPixel || undefined, - HotjarTrackingCode: obj.hotjar || undefined, - customScript: obj.customScript || undefined - } - let customizeBtnDisplayVal = 'block'; - if (!obj.customizeBtnDisplay){ - customizeBtnDisplayVal = 'none'; - } - this.banner = { - description: obj.bannerDescription || lang.bannerDescription, - linkText: obj.bannerLinkText || lang.bannerLinkText, - link: obj.policyLink || '#link', - background: obj.bannerBackground || '#fff', - shadowSpread: obj.shadowSpread || 0, - shadowColor: obj.shadowColor || 'rgb(0,0,0,0)', - color: obj.bannerColor || '#1d2e38', - closeColor: obj.closeColor || '#000', - closeBtnHiddenText: obj.closeBtnHidden ? 'hidden' : '', - heading: obj.bannerHeading !== 'none' ? obj.bannerHeading || lang.bannerHeading : '', - acceptBtn: { - text: obj.acceptBtnText || lang.acceptBtnText, - background: obj.acceptBtnBackground || '#253b48', - color: obj.acceptBtnColor || '#fff' - }, - customizeButton: { - display: customizeBtnDisplayVal, - text: obj.customizeBtnText || lang.customizeBtnText, - background: obj.customizeBtnBackground || '#E8E8E8', - color: obj.customizeBtnColor || '#636363' - }, - rejectBtn: { - text: obj.rejectBtnText || lang.rejectBtnText, - background: obj.rejectBtnBackground || '#E8E8E8', - color: obj.rejectBtnColor || '#636363' - }, - manageCookies: { - color: obj.manageColor || '#1d2e38', - background: obj.manageBackground || '#fff', - text: obj.manageText || lang.manageText, - } - } - let customizeUserPreferencesDisplay = 'flex'; - if (!obj.customizeUserPreferences){ - customizeUserPreferencesDisplay = 'none'; - } - let customizeAnalyticsDisplay = 'flex'; - if (!obj.customizeAnalytics){ - customizeAnalyticsDisplay = 'none'; - } - let customizeThirdPartyDisplay = 'flex'; - if (!obj.customizeThirdParty){ - customizeThirdPartyDisplay = 'none'; + } + + disableTracking() { + // Google Analytics Tracking ('client_storage': 'none') + if (this.tracking.AnalyticsCode) { + let Analytics = document.createElement('script'); + Analytics.setAttribute('src', `https://www.googletagmanager.com/gtag/js?id=${this.tracking.AnalyticsCode}`); + document.head.appendChild(Analytics); + let AnalyticsData = document.createElement('script'); + AnalyticsData.text = `window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', '${this.tracking.AnalyticsCode}' , { + 'client_storage': 'none', + 'anonymize_ip': true + });`; + document.head.appendChild(AnalyticsData); + } + + // Clear cookies - not working 100% + this.clearCookies() + } + + clearCookies() { + let cookies = document.cookie.split("; "); + for (let c = 0; c < cookies.length; c++) { + let d = window.location.hostname.split("."); + while (d.length > 0) { + let cookieBase = encodeURIComponent(cookies[c].split(";")[0].split("=")[0]) + '=; expires=Thu, 01-Jan-1970 00:00:01 GMT; domain=' + d.join('.') + ' ;path='; + let p = location.pathname.split('/'); + document.cookie = cookieBase + '/'; + while (p.length > 0) { + document.cookie = cookieBase + p.join('/'); + p.pop(); + }; + d.shift(); } - - this.selector = { - titleText: obj.selectorTitleText || 'Customize Cookies', - titleColor: obj.selectorTitleColor || 'black', - btnText: obj.selectorBtnText || 'Save cookie preferences', - btnBackground: obj.selectorBtnBackground || 'blue', - btnColor: obj.selectorBtnColor || 'white', - customizeUserPreferences: { - display: customizeUserPreferencesDisplay - }, - customizeAnalytics: { - display: customizeAnalyticsDisplay - }, - customizeThirdParty: { - display: customizeThirdPartyDisplay - }, - customizeSwitch: { - offColor: obj.customizeSwitchOffColor || 'gray', - onColor: obj.customizeSwitchOnColor || 'blue', - } + } + } + setRetentionPeriod(daystoLive) { + let cookies = document.cookie.split("; "); + for(let c = 0; c < cookies.length; c++) { + let d = window.location.hostname.split("."); + const date = new Date(); + date.setTime(date.getTime() + (daystoLive * 24* 60 * 60 *1000)); + // date.setTime(date.getTime() + (daystoLive *1000)); + + while (d.length > 0) { + let cookieBase = encodeURIComponent(cookies[c].split(";")[0].split("=")[0]) + `=; expires=${date.toUTCString()}; domain=` + d.join('.') + ' ;path='; + let p = location.pathname.split('/'); + document.cookie = cookieBase + '/'; + // while (p.length > 0) { + // document.cookie = cookieBase + p.join('/'); + // p.pop(); + // }; + d.shift(); } - // Append two CSS classes to represent each background color for - for(let i = 0; i < 2; i++){ - var style = document.createElement('style'); - document.head.appendChild(style); - let css = undefined - if(i == 0){ - css = '.switch_color_off' + ' { background-color: ' + this.selector.customizeSwitch.offColor + ';}'; - }else{ - css = '.switch_color_on' + ' { background-color: ' + this.selector.customizeSwitch.onColor + ';}'; - } - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.appendChild(document.createTextNode(css)); - } - document.head.appendChild(style); - } - // Draw banner - window.addEventListener('load', () => { this.render() }) } + } - // Default Testing - // Assuming no user input - // Testing purely for accepting cookies - test1 = () => { - console.log("Running Test 1"); - this.openManageCookies(); - this.acceptCookies(); - this.assert(localStorage.getItem("GlowCookies") == '1', new Error().lineNumber) - console.log("Passed all parts of Test 1") + addCustomScript() { + if (this.tracking.customScript !== undefined) { + this.addNewScript(this.tracking.customScript) } + } - test2 = () => { - console.log("Running Test 2"); - // Ensure that hideafterclick is not true - this.config.hideAfterClick = false - this.openManageCookies(); - this.acceptCookies(); - this.assert(localStorage.getItem("GlowCookies") == '1', new Error().lineNumber) - this.openManageCookies(); - this.rejectCookies(); - this.assert(localStorage.getItem("GlowCookies") == '0', new Error().lineNumber) - console.log("Passed all parts of Test 2") + addNewScript(customScript) { + let customScriptTag + customScript.forEach(script => { + if (script.type === 'src') { + customScriptTag = document.createElement('script'); + customScriptTag.setAttribute('src', script.content); + } else if (script.type === 'custom') { + customScriptTag = document.createElement('script'); + customScriptTag.text = script.content; + } + + if (script.position === 'head') { + document.head.appendChild(customScriptTag); + } else { + document.body.appendChild(customScriptTag); + } + }) + } + + + start(languaje, obj) { + if (!obj) obj = {} + const lang = new LanguagesGC(languaje) + + this.config = { + border: obj.border || 'border', + position: obj.position || 'left', + hideAfterClick: obj.hideAfterClick || false, + bannerStyle: obj.style || 2 } - test3 = () => { - console.log("Running Test 3"); - this.openManageCookies(); - this.rejectCookies(); - this.assert(localStorage.getItem("GlowCookies") == '0', new Error().lineNumber) - console.log("Passed all parts of Test 3") + this.tracking = { + AnalyticsCode: obj.analytics || undefined, + FacebookPixelCode: obj.facebookPixel || undefined, + HotjarTrackingCode: obj.hotjar || undefined, + customScript: obj.customScript || undefined, + userPreferencesScript: obj.userPreferencesScript || undefined, + thirdPartyScript: obj.thirdPartyScript || undefined, + analyticsScript: obj.analyticsScript || undefined, + retentionPeriod: obj.retentionPeriod || 1 + } + let customizeBtnDisplayVal = 'block'; + if (!obj.customizeBtnDisplay){ + customizeBtnDisplayVal = 'none'; + } + this.banner = { + description: obj.bannerDescription || lang.bannerDescription, + linkText: obj.bannerLinkText || lang.bannerLinkText, + link: obj.policyLink || '#link', + background: obj.bannerBackground || '#fff', + shadowSpread: obj.shadowSpread || 0, + shadowColor: obj.shadowColor || 'rgb(0,0,0,0)', + color: obj.bannerColor || '#1d2e38', + closeColor: obj.closeColor || '#000', + closeBtnHiddenText: obj.closeBtnHidden ? 'hidden' : '', + heading: obj.bannerHeading !== 'none' ? obj.bannerHeading || lang.bannerHeading : '', + acceptBtn: { + text: obj.acceptBtnText || lang.acceptBtnText, + background: obj.acceptBtnBackground || '#253b48', + color: obj.acceptBtnColor || '#fff' + }, + customizeButton: { + display: customizeBtnDisplayVal, + text: obj.customizeBtnText || lang.customizeBtnText, + background: obj.customizeBtnBackground || '#E8E8E8', + color: obj.customizeBtnColor || '#636363' + }, + rejectBtn: { + text: obj.rejectBtnText || lang.rejectBtnText, + background: obj.rejectBtnBackground || '#E8E8E8', + color: obj.rejectBtnColor || '#636363' + }, + manageCookies: { + color: obj.manageColor || '#1d2e38', + background: obj.manageBackground || '#fff', + text: obj.manageText || lang.manageText, + } + } + let customizeUserPreferencesDisplay = 'flex'; + if (obj.customizeUserPreferences == false){ + customizeUserPreferencesDisplay = 'none'; + } + let customizeAnalyticsDisplay = 'flex'; + if (obj.customizeAnalytics == false){ + customizeAnalyticsDisplay = 'none'; + } + let customizeThirdPartyDisplay = 'flex'; + if (obj.customizeThirdParty == false){ + customizeThirdPartyDisplay = 'none'; + } + let customizeSessionCookiesDisplay = 'flex'; + if(obj.customizeSessionCookies == false){ + customizeSessionCookiesDisplay = 'none' } - ctest1 = () => { - console.log("Running Combinatorial Test 1 for selector"); - // Ensure hide after click is false - this.config.hideAfterClick = false - let selectorTestInputs = new CombinatorialTestingSetup(3, ['bool'])['inputCombinations']; - console.log(selectorTestInputs) - selectorTestInputs.forEach((selectorTestComb) => { - this.openManageCookies(); - this.openSelector(); - // Go through each comb, and set switches - console.log("Testing selector combination: " + selectorTestComb) - for(let switch_num = 0; switch_num < 3; switch_num++){ - - this.CustomizeSwitches[switch_num].classList.remove(this.switch_on[switch_num]); - this.CustomizeSwitches[switch_num].classList.remove(this.switch_colors[switch_num]); - if(selectorTestComb[switch_num]){ - this.switch_on[switch_num] = "glowCookies__customize_switch_button_on"; - this.switch_colors[switch_num] = "switch_color_on"; - }else{ - this.switch_on[switch_num] = "glowCookies__customize_switch_button_off"; - this.switch_colors[switch_num] = "switch_color_off"; - } - this.CustomizeSwitches[switch_num].classList.add(this.switch_on[switch_num]); - this.CustomizeSwitches[switch_num].classList.add(this.switch_colors[switch_num]); - } - this.savePreferences(); - // After saving, let's ensure that all of the selections held and are now applied - for(let switch_num = 0; switch_num < 3; switch_num++){ - this.assert(this.cookiesAllowed[switch_num] == selectorTestComb[switch_num], new Error().lineNumber); - } - console.log("Selector combination: " + selectorTestComb + " was saved correctly.") - }) - console.log("Passed Combinatorial Test 1 for selector"); + this.selector = { + titleText: obj.selectorTitleText || 'Customize Cookies', + titleColor: obj.selectorTitleColor || 'black', + btnText: obj.selectorBtnText || 'Save cookie preferences', + btnBackground: obj.selectorBtnBackground || 'blue', + btnColor: obj.selectorBtnColor || 'white', + customizeUserPreferences: { + display: customizeUserPreferencesDisplay + }, + customizeAnalytics: { + display: customizeAnalyticsDisplay + }, + customizeThirdParty: { + display: customizeThirdPartyDisplay + }, + customizeSessionCookies: { + display: customizeSessionCookiesDisplay + }, + customizeSwitch: { + offColor: obj.customizeSwitchOffColor || 'gray', + onColor: obj.customizeSwitchOnColor || 'blue', + } } + // Append two CSS classes to represent each background color for + for(let i = 0; i < 2; i++){ + var style = document.createElement('style'); + document.head.appendChild(style); + let css = undefined + if(i == 0){ + css = '.switch_color_off' + ' { background-color: ' + this.selector.customizeSwitch.offColor + ';}'; + }else{ + css = '.switch_color_on' + ' { background-color: ' + this.selector.customizeSwitch.onColor + ';}'; + } + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.appendChild(document.createTextNode(css)); + } + document.head.appendChild(style); + } + // Draw banner + window.addEventListener('load', () => { this.render() }) + } } @@ -801,5 +940,5 @@ class GlowCookiesTester { } - const glowCookies = new GlowCookiesTester() + const glowCookies = new GlowCookies() From 1ce469a45f40a48e1cd657ecaa6448bd7758d696 Mon Sep 17 00:00:00 2001 From: Abhiram Datla Date: Wed, 10 Apr 2024 21:00:57 -0400 Subject: [PATCH 10/19] fuzzer --- src/glowCookiesTest.js | 142 ++++++++++++++++++++++++++++++++++++++++- src/index.html | 6 +- 2 files changed, 143 insertions(+), 5 deletions(-) diff --git a/src/glowCookiesTest.js b/src/glowCookiesTest.js index 7851e8f..22da456 100644 --- a/src/glowCookiesTest.js +++ b/src/glowCookiesTest.js @@ -13,6 +13,20 @@ function assert(condition, lineNum) { } } +function assertParameters(parameters, glowCookiesObj) { + let keys = Object.keys(glowCookiesObj); + + for (i in keys) { + console.log("\n" + keys[i] + ", " + typeof glowCookiesObj[keys[i]]); + if (typeof glowCookiesObj[keys[i]] === 'object') { + let inner_keys = Object.keys(glowCookiesObj[keys[i]]); + for (in_i in inner_keys) { + console.log(inner_keys[in_i] + ", " + typeof glowCookiesObj[keys[i]][inner_keys[in_i]]); + } + } + } +} + class CombinatorialTestingSetup { @@ -86,6 +100,8 @@ class CombinatorialTestingSetup { } + + class GlowCookiesTester { constructor(glowCookies){ this.glowCookies = glowCookies; @@ -96,6 +112,7 @@ class GlowCookiesTester { //this.test3(); this.ctest1(); + //assertParameters({}, this.glowCookies); } // Default Testing @@ -164,6 +181,7 @@ class GlowCookiesTester { }) console.log("Passed Combinatorial Test 1 for selector"); } + } @@ -182,12 +200,20 @@ class GlowCookies { this.cookiesAllowed = [undefined, undefined, undefined, undefined] // Upon saving a selection or selecting accept/ reject these will be updated accordingly this.Cookies = undefined this.DOMbanner = undefined + + // Selections + this.customizers = undefined; } render() { - this.addCss() - this.createDOMElements() - this.checkStatus() + try { + this.addCss() + this.createDOMElements() + this.checkStatus() + } catch (error) { + console.log(error); + console.log(this.customizers); + } new GlowCookiesTester(this); } @@ -610,6 +636,8 @@ class GlowCookies { if (!obj) obj = {} const lang = new LanguagesGC(languaje) + this.customizers = obj; + this.config = { border: obj.border || 'border', position: obj.position || 'left', @@ -941,4 +969,112 @@ class GlowCookies { } const glowCookies = new GlowCookies() + + function getRandomColorHex() { + var hexDigits = '0123456789ABCDEF'; + var randomColor = '#'; + for (let i = 0; i < 6; i++) { + randomColor += hexDigits[Math.floor(Math.random() * 16)]; + } + return randomColor; + } + + function getRandomColorWithOpacity() { + var randomColor = 'rgba('; + for (let i = 0; i < 3; i++) { + randomColor += Math.floor(Math.random() * 256); + randomColor += ","; + } + randomColor += Math.random(); + randomColor += ")"; + return randomColor; + } + + function getRandomString(length) { + var randomString = ""; + var strLength = Math.floor(Math.random() * length); + for (let i = 0; i < strLength; i++) { + randomString += String.fromCharCode(Math.floor(Math.random() * (126 - 33) + 33)) + } + return randomString; + } + + const customizationOptions = { + selections: { + style: [1, 2, 3], + analytics: ['G-FH87DE17XF'], + facebookPixel: ['990955817632355'], + customScript: [{ type: 'custom', position: 'body', content: `console.log('my custom js');` }], + hideAfterClick: [false], // SHOULD BE [true, false] + border: ["border", "none"], + position: ["left", "right"], + customizeBtnDisplay: [true, false], + customizeUserPreferences: [true, false], + customizeAnalytics: [true, false], + customizeThirdParty: [true, false], + policyLink: ['https://policies.google.com/technologies/cookies'], + shadowSpread: ["0em", "0.5em", "1em", "1.25em", "1.75em", "2.0000em", "2.5em"] + }, + hexColors: ["bannerBackground", "bannerColor", "acceptBtnColor", "acceptBtnBackground", + "customizeBtnBackground", "customizeBtnColor", "rejectBtnBackground", "rejectBtnColor", + "manageColor", "manageBackground", "selectorTitleColor", "customizeSwitchOnColor", "selectorBtnBackground"], + opacityColors: ["shadowColor"], + strings: ["bannerDescription", "bannerLinkText", "bannerHeading", "acceptBtnText", "rejectBtnText", "customizeBtnText", "manageText", "selectorTitleText"] + } + + class Fuzzer { + constructor(numTests, setProbability) { + this.numTests = numTests; + this.setProbability = setProbability; + this.customizers = {}; + this.glowCookies = undefined; + } + + + + setCustomizers() { + var keys = Object.keys(customizationOptions.selections); + for (let i = 0; i < keys.length; i++) { + if (Math.random() < this.setProbability) { + this.customizers[keys[i]] = customizationOptions.selections[keys[i]][Math.floor(Math.random() * customizationOptions.selections[keys[i]].length)]; + } + } + + for (let i = 0; i < customizationOptions.hexColors.length; i++) { + if (Math.random() < this.setProbability) { + this.customizers[customizationOptions.hexColors[i]] = getRandomColorHex(); + } + } + + for (let i = 0; i < customizationOptions.opacityColors.length; i++) { + if (Math.random() < this.setProbability) { + this.customizers[customizationOptions.opacityColors[i]] = getRandomColorWithOpacity(); + } + } + + for (let i = 0; i < customizationOptions.strings.length; i++) { + if (Math.random() < this.setProbability) { + this.customizers[customizationOptions.strings[i]] = getRandomString(20); + } + } + } + + fuzz() { + try { + for (let i = 0; i < this.numTests; i++) { + this.setCustomizers(); + this.glowCookies = new GlowCookies() + this.glowCookies.start('en', this.customizers); + // delete the object + console.log(this.customizers); + } + } catch (error) { + console.log(error); + console.log(this.customizers); + } + } + } + + const fuzzer = new Fuzzer(1, 0.5); + fuzzer.fuzz(); diff --git a/src/index.html b/src/index.html index 40a4491..94556fa 100644 --- a/src/index.html +++ b/src/index.html @@ -17,9 +17,11 @@ - + From 7fd123aed359926d1798320d61a8e30e24ca18c7 Mon Sep 17 00:00:00 2001 From: avgentile <108200235+avgentile@users.noreply.github.com> Date: Mon, 15 Apr 2024 18:00:45 -0400 Subject: [PATCH 11/19] Updated customization options and refactored test setup For the customization options, you can now change the width of the main cookies banner as necessary. Additionally, you can dynamically add new switches to the cookie customizer. Lastly, moved all the tests into one test class and refactored as necessary and added additional default testing/ --- src/glowCookies.css | 8 +- src/glowCookies.js | 252 +++++---- src/glowCookiesTest.js | 1179 +++++++++------------------------------- 3 files changed, 404 insertions(+), 1035 deletions(-) diff --git a/src/glowCookies.css b/src/glowCookies.css index b4a533c..4c34edc 100644 --- a/src/glowCookies.css +++ b/src/glowCookies.css @@ -33,7 +33,7 @@ user-select: none; display: flex; flex-direction: column; - gap: 50px; + gap: 40px; -webkit-box-shadow: 0 .625em 1.875em rgba(2,2,3,.1); -moz-box-shadow: 0 .625em 1.875em rgba(2,2,3,.1); box-shadow: 0 .625em 1.875em rgba(2,2,3,.1); @@ -82,6 +82,12 @@ } +.glowCookies-customize-save-container { + width: 100%; + display: flex; + justify-content: center; +} + .glowCookies-customize-save { border: none; padding: 10px 13px; diff --git a/src/glowCookies.js b/src/glowCookies.js index 2611906..8f45341 100644 --- a/src/glowCookies.js +++ b/src/glowCookies.js @@ -16,16 +16,18 @@ class GlowCookies { this.tracking = undefined // DOM ELEMENTS this.PreBanner = undefined - this.CustomizeSwitches = [undefined, undefined, undefined, undefined] // At most 3 valid switches - this.cookiesAllowed = [undefined, undefined, undefined, undefined] // Upon saving a selection or selecting accept/ reject these will be updated accordingly - this.Cookies = undefined + // this.CustomizeSwitches = [undefined, undefined, undefined, undefined] // At most 4 valid switches + // this.cookiesAllowed = [undefined, undefined, undefined, undefined] // Upon saving a selection or selecting accept/ reject these will be updated accordingly + // this.Cookies = undefined this.DOMbanner = undefined + this.rendered = false } render() { this.addCss() this.createDOMElements() this.checkStatus() + this.rendered = true } addCss() { @@ -53,7 +55,8 @@ class GlowCookies { style="background-color: ${this.banner.background}; -webkit-box-shadow: 0 .625em 1.875em rgba(2,2,3,.2); -moz-box-shadow: 0 .625em 1.875em rgba(2,2,3,.2); - box-shadow: 0 .625em ${this.banner.shadowSpread} ${this.banner.shadowColor};" + box-shadow: 0 .625em ${this.banner.shadowSpread} ${this.banner.shadowColor}; + max-width: ${this.banner.maxWidth}" >

${this.banner.heading}

@@ -84,9 +87,22 @@ class GlowCookies { document.body.appendChild(this.Cookies); this.DOMbanner = document.getElementById('glowCookies-banner') - // COOKIES BANNER - this.switch_on = ["glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off"]; - this.switch_colors = ["switch_color_off", "switch_color_off", "switch_color_off", "switch_color_off"] + // SELECTOR BANNER + this.CustomizeSwitches = []; + this.cookiesAllowed = []; + this.switch_on = []; + this.switch_names = ["User Preferences", 'Analytics', 'Third Party', 'Session Only']; + this.switch_colors = []; + for(let switch_num = 0; switch_num < 4 + this.selector.additionalCookies.length; switch_num++){ + this.switch_on.push("glowCookies__customize_switch_button_off"); + this.switch_colors.push("switch_color_off"); + if(switch_num >= this.switch_names.length){ + this.switch_names.push(this.selector.additionalCookies[switch_num - 4]); + } + this.CustomizeSwitches.push(undefined); + this.cookiesAllowed.push(undefined); + } + this.Customizer = document.createElement("div"); this.Customizer.innerHTML = `

${this.selector.titleText}

-
-
- User Preferences -
-
- -
-
-
-
- Analytics -
-
-
+ `; + //this.CustomSwitches = document.createElement('div'); + this.CustomSwitchesHTML = []; + + // We have at minimum 4 custom switches (some might not be displayed) + for(let switch_num = 0; switch_num < this.cookiesAllowed.length; switch_num++){ + let newSelection = document.createElement('div'); + if(!this.selector.customizeDefaultDisplaySettings[switch_num]){ + newSelection.style.display = 'none'; + } + newSelection.innerHTML = ` +
+ ${this.switch_names[switch_num]} +
+
+ -
-
-
-
- Third Party Cookies -
-
- -
-
-
-
- Session Only Cookies -
-
- -
-
- -
- `; - document.body.appendChild(this.Customizer); - for(let i = 1; i < 5; i++){ - this.CustomizeSwitches[i - 1] = document.getElementById('glowCookies-customize-switch-' + i) + `; + newSelection.classList.add('glowCookies__customize_item_container'); + this.CustomSwitchesHTML.push(newSelection); } + this.SaveButton = document.createElement('div'); + this.SaveButton.innerHTML = ` + `; + this.SaveButton.classList.add('glowCookies-customize-save-container'); + document.body.appendChild(this.Customizer); + this.CustomSwitchesHTML.forEach(selector => { + document.getElementById('glowCookies-customize').appendChild(selector); + }); + document.getElementById('glowCookies-customize').appendChild(this.SaveButton); // SET EVENT LISTENERS @@ -160,10 +155,17 @@ class GlowCookies { document.getElementById('acceptCookies').addEventListener('click', () => this.acceptCookies()) document.getElementById('rejectCookies').addEventListener('click', () => this.rejectCookies()) document.getElementById('customizeButton').addEventListener('click', () => this.openCustomizer()) - document.getElementById('glowCookies-customize-switch-1').addEventListener('click', () => this.switchCustomizer(1)) - document.getElementById('glowCookies-customize-switch-2').addEventListener('click', () => this.switchCustomizer(2)) - document.getElementById('glowCookies-customize-switch-3').addEventListener('click', () => this.switchCustomizer(3)) - document.getElementById('glowCookies-customize-switch-4').addEventListener('click', () => this.switchCustomizer(4)) + document.getElementById('glowCookies-customize-switch-1').addEventListener('click', () => this.switchCustomizer(0)) + document.getElementById('glowCookies-customize-switch-2').addEventListener('click', () => this.switchCustomizer(1)) + document.getElementById('glowCookies-customize-switch-3').addEventListener('click', () => this.switchCustomizer(2)) + document.getElementById('glowCookies-customize-switch-4').addEventListener('click', () => this.switchCustomizer(3)) + // Add any more based off of additional + for(let i = 4; i < this.cookiesAllowed.length; i++){ + document.getElementById('glowCookies-customize-switch-' + (i + 1)).addEventListener('click', () => this.switchCustomizer(i)); + } + for(let i = 0; i < this.cookiesAllowed.length; i++){ + this.CustomizeSwitches[i] = document.getElementById('glowCookies-customize-switch-' + (i + 1)); + } document.getElementById('glowCookies-customize-save').addEventListener('click', () => this.savePreferences()) // Add a new click listener for the 'closeManager' } @@ -197,39 +199,52 @@ class GlowCookies { } acceptCookies() { - localStorage.setItem("GlowCookies", "1") this.openManageCookies() - this.activateTracking() - this.addCustomScript() - this.setRetentionPeriod(this.tracking.retentionPeriod) + // accept all cookies + for(let switch_num = 0; switch_num < this.cookiesAllowed.length; switch_num++){ + this.updateSpecificCookieAllowed(switch_num, true); + } + this.runCookieFunctions(); + this.addCustomScript(); + this.setRetentionPeriod(this.tracking.retentionPeriod); } rejectCookies() { - localStorage.setItem("GlowCookies", "0"); + // Reject all + for(let switch_num = 0; switch_num < this.cookiesAllowed.length; switch_num++){ + this.updateSpecificCookieAllowed(switch_num, false); + } + this.runCookieFunctions(); this.openManageCookies(); - this.disableTracking(); + } + + // This function ensures that the display of the switches will match up with the new value + updateSpecificCookieAllowed(switch_num, new_val) { + if(new_val != this.cookiesAllowed[switch_num]){ + this.switchCustomizer(switch_num); + this.cookiesAllowed[switch_num] = new_val; + } } openCustomizer() { // Close out the banner, and we need to open the new banner this.DOMbanner.classList.remove('glowCookies__show'); this.Customizer.style.display = "block"; - for(let i = 1; i < 5; i++){ - if(this.cookiesAllowed[i - 1] == undefined || this.cookiesAllowed[i - 1] == false){ - this.switch_on[i - 1] = "glowCookies__customize_switch_button_off"; - this.switch_colors[i - 1] = "switch_color_off"; + for(let i = 0; i < this.cookiesAllowed.length; i++){ + if(this.cookiesAllowed[i] == undefined || this.cookiesAllowed[i] == false){ + this.switch_on[i] = "glowCookies__customize_switch_button_off"; + this.switch_colors[i] = "switch_color_off"; }else{ - this.switch_on[i - 1] = "glowCookies__customize_switch_button_on"; - this.switch_colors[i - 1] = "switch_color_on"; + this.switch_on[i] = "glowCookies__customize_switch_button_on"; + this.switch_colors[i] = "switch_color_on"; } - this.CustomizeSwitches[i - 1].classList.add(this.switch_on[i-1]); - this.CustomizeSwitches[i - 1].classList.add(this.switch_colors[i-1]); + this.CustomizeSwitches[i].classList.add(this.switch_on[i]); + this.CustomizeSwitches[i].classList.add(this.switch_colors[i]); } } switchCustomizer(switch_num) { - switch_num = switch_num - 1 this.CustomizeSwitches[switch_num].classList.remove(this.switch_on[switch_num]); this.CustomizeSwitches[switch_num].classList.remove(this.switch_colors[switch_num]); if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ @@ -250,7 +265,7 @@ class GlowCookies { savePreferences(){ this.Customizer.style.display = "none"; let isSessionOnly = 0; - for(let switch_num = 0; switch_num < 4; switch_num++){ + for(let switch_num = 0; switch_num < this.cookiesAllowed.length; switch_num++){ if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ this.cookiesAllowed[switch_num] = false; }else{ @@ -259,7 +274,7 @@ class GlowCookies { this.addNewScript(this.tracking.userPreferencesScript) } }else if(switch_num == 1){ - if(this.tracking.userPreferencesScript != undefined){ + if(this.tracking.analyticsScript != undefined){ this.addNewScript(this.tracking.thirdPartyScript) } }else if(switch_num == 2){ @@ -273,10 +288,45 @@ class GlowCookies { this.cookiesAllowed[switch_num] = true; } } - this.activateSessionCookies(isSessionOnly); this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" } + runCookieFunctions(){ + // First look at the first 4 + for(let switch_num = 0; switch_num < this.cookiesAllowed.length; switch_num++){ + if(!this.cookiesAllowed[switch_num]){ + if(switch_num == 1){ + this.disableTracking(); + localStorage.setItem("GlowCookies", "0") // GlowCookies corresponds to tracking being disabled + } + continue; + } + if(switch_num == 0){ + if(this.tracking.userPreferencesScript != undefined){ + this.addNewScript(this.tracking.userPreferencesScript) + } + }else if(switch_num == 1){ + this.activateTracking(); + localStorage.setItem("GlowCookies", "1") // GlowCookies corresponds to tracking being activated + if(this.tracking.analyticsScript != undefined){ + this.addNewScript(this.tracking.analyticsScript) + } + }else if(switch_num == 2){ + if(this.tracking.thirdPartyScript != undefined){ + this.addNewScript(this.tracking.thirdPartyScript) + } + }else if(switch_num == 3){ + // if we are on switch 4 it must be session onl + this.activateSessionCookies('true'); + }else{ + let additional_num = switch_num - 4; + if(additional_num < this.selector.additionalCookieScripts.length){ + this.addNewScript(this.selector.additionalCookieScripts[additional_num]); + } + } + } + } + activateSessionCookies(isSessionOnly){ sessionStorage.setItem('isSessionOnly', isSessionOnly ? 'true' : 'false'); @@ -424,6 +474,9 @@ class GlowCookies { addNewScript(customScript) { let customScriptTag + if(customScript == undefined || typeof(customScript) != "object"){ + return + } customScript.forEach(script => { if (script.type === 'src') { customScriptTag = document.createElement('script'); @@ -472,6 +525,7 @@ class GlowCookies { linkText: obj.bannerLinkText || lang.bannerLinkText, link: obj.policyLink || '#link', background: obj.bannerBackground || '#fff', + maxWidth: obj.maxWidth || '375px', shadowSpread: obj.shadowSpread || 0, shadowColor: obj.shadowColor || 'rgb(0,0,0,0)', color: obj.bannerColor || '#1d2e38', @@ -500,41 +554,33 @@ class GlowCookies { text: obj.manageText || lang.manageText, } } - let customizeUserPreferencesDisplay = 'flex'; + let customizeDefaultDisplaySettings = [true, true, true, true] // User Preferences, Analytics, Third Party, Session Only in that order if (obj.customizeUserPreferences == false){ - customizeUserPreferencesDisplay = 'none'; + customizeDefaultDisplaySettings[0] = false; } - let customizeAnalyticsDisplay = 'flex'; if (obj.customizeAnalytics == false){ - customizeAnalyticsDisplay = 'none'; + customizeDefaultDisplaySettings[1] = false; } - let customizeThirdPartyDisplay = 'flex'; if (obj.customizeThirdParty == false){ - customizeThirdPartyDisplay = 'none'; + customizeDefaultDisplaySettings[2] = false; } - let customizeSessionCookiesDisplay = 'flex'; if(obj.customizeSessionCookies == false){ - customizeSessionCookiesDisplay = 'none' + customizeDefaultDisplaySettings[3] = false; + } + if(obj.additionalCookies != null){ + for(let i = 0; i < obj.additionalCookies.length; i++){ + customizeDefaultDisplaySettings.push(true); + } } - this.selector = { titleText: obj.selectorTitleText || 'Customize Cookies', titleColor: obj.selectorTitleColor || 'black', btnText: obj.selectorBtnText || 'Save cookie preferences', btnBackground: obj.selectorBtnBackground || 'blue', btnColor: obj.selectorBtnColor || 'white', - customizeUserPreferences: { - display: customizeUserPreferencesDisplay - }, - customizeAnalytics: { - display: customizeAnalyticsDisplay - }, - customizeThirdParty: { - display: customizeThirdPartyDisplay - }, - customizeSessionCookies: { - display: customizeSessionCookiesDisplay - }, + customizeDefaultDisplaySettings: customizeDefaultDisplaySettings, + additionalCookies: obj.additionalCookies || [], + additionalCookieScripts: obj.additionalCookieScripts || [], customizeSwitch: { offColor: obj.customizeSwitchOffColor || 'gray', onColor: obj.customizeSwitchOnColor || 'blue', diff --git a/src/glowCookiesTest.js b/src/glowCookiesTest.js index 22da456..4eb907b 100644 --- a/src/glowCookiesTest.js +++ b/src/glowCookiesTest.js @@ -28,29 +28,55 @@ function assertParameters(parameters, glowCookiesObj) { } -class CombinatorialTestingSetup { +function presetParams(){ + return { + style: 1, + analytics: 'G-FH87DE17XF', + facebookPixel: '990955817632355', + hideAfterClick: false, + shadowSpread: '1.875em', + shadowColor: 'rgba(255,0,0,.2)', + border: 'none', + position: 'right', + policyLink: 'https://google.es', + customScript: [{ type: 'custom', position: 'body', content: `console.log('my custom js');` }], + bannerDescription: 'banner desc', + bannerLinkText: 'banner link text', + bannerBackground: '#fff', + bannerColor: '#fafafa', + bannerHeading: '

Cookies

', + acceptBtnText: 'accept btn text', + acceptBtnColor: 'green', + acceptBtnBackground: 'red', + rejectBtnText: 'reject btn text', + customizeBtnDisplay: true, + customizeBtnText: 'More options', + customizeBtnBackground: 'gray', + customizeBtnColor: 'black', + rejectBtnBackground: 'lightblue', + rejectBtnColor: 'blue', + manageColor: 'white', + manageBackground: 'blue', + manageText: 'cookies text', + selectorTitleText: 'Customize your cookies', + selectorTitleColor: 'green', + additionalCookies: ['Test 1', 'Test 2'], + //additionalCookieScripts: [[{ type: 'custom', position: 'body', content: `console.log('test 1');` }], + //[{ type: 'custom', position: 'body', content: `console.log('test 2');` }]], + customizeUserPreferences: false, + //userPreferencesScript: [{ type: 'custom', position: 'body', content: `console.log('my user preferences js');` }], + //thirdPartyScript: [{ type: 'custom', position: 'body', content: `console.log('my third party js');` }], + //analyticsScript: [{ type: 'custom', position: 'body', content: `console.log('my analytics js');` }], + customizeAnalytics: true, + customizeThirdParty: true, + customizeSessionCookies: true, + customizeSwitchOnColor: 'green', + selectorBtnBackground: 'green', + } +} - // // numOfInputs is how many parameters will be tested - // // labels is a list of the parameter names for each input. Leave this blank if it does not matter and you want permutations - // // types is the type of variable each label can take on. If this is only 1 such as 'bool', all inputs can take on true or false. - // constructor(numOfInputs, types) { - // // We are making a 2d array of different combinations of inputs - // // For now, mainly n testing where if there n inputs, we will make a 2d array of size 2^n x n. So 2 inputs will mean our array is 4 x 2 - // let potentialOptions = [] - // if(types[0] == 'bool'){ - // potentialOptions[0] = false - // potentialOptions[1] = true - // } - // let permutationList = Array() - // this.generateBoolPermutations(numOfInputs, [], potentialOptions, permutationList); - // this.inputCombinations = permutationList; - // // for(let row = 0; row < numOfInputs; row++){ - // // for(let col = 0; col < numOfInputs; col++){ - // // console.log("Bool vals are: " + potentialOptions[row] + " " + potentialOptions[col]) - // // } - // // } - // } +class CombinatorialTestingSetup { // This will generate combinations bassed off of the types // types is the type of variable each label can take on. The length of labels must equal types if you use this constructor @@ -73,18 +99,8 @@ class CombinatorialTestingSetup { this.inputCombinations = permutationList; } - // Used ChatGPT by asking "How to do boolean permutations generalizable to n in JavaScrip?" - generateBoolPermutations(n, prefix = [], potentialOptions, permutationList) { - if (n === 0) { - //console.log(prefix); - permutationList.push(prefix); - return; - } - for (const value of potentialOptions) { - this.generateBoolPermutations(n - 1, [...prefix, value], potentialOptions, permutationList); - } - } - + // Used ChatGPT by asking "How to do boolean permutations generalizable to n in JavaScript?" + // Then, expanded it to be able to handle more than just boolean permutation generateCombinations(n, prefix = [], potentialOptions, permutationList, max_options) { if (n === 0) { //console.log(prefix); @@ -98,27 +114,182 @@ class CombinatorialTestingSetup { +} + + function getRandomColorHex() { + var hexDigits = '0123456789ABCDEF'; + var randomColor = '#'; + for (let i = 0; i < 6; i++) { + randomColor += hexDigits[Math.floor(Math.random() * 16)]; + } + return randomColor; + } + + function getRandomColorWithOpacity() { + var randomColor = 'rgba('; + for (let i = 0; i < 3; i++) { + randomColor += Math.floor(Math.random() * 256); + randomColor += ","; + } + randomColor += Math.random(); + randomColor += ")"; + return randomColor; + } + + function getRandomString(length) { + var randomString = ""; + var strLength = Math.floor(Math.random() * length); + for (let i = 0; i < strLength; i++) { + randomString += String.fromCharCode(Math.floor(Math.random() * (126 - 33) + 33)) + } + return randomString; + } + +const customizationOptions = { + selections: { + style: [1, 2, 3], + analytics: ['G-FH87DE17XF'], + facebookPixel: ['990955817632355'], + customScript: [{ type: 'custom', position: 'body', content: `console.log('my custom js');` }], + hideAfterClick: [false], // SHOULD BE [true, false] + border: ["border", "none"], + position: ["left", "right"], + customizeBtnDisplay: [true, false], + customizeUserPreferences: [true, false], + customizeAnalytics: [true, false], + customizeThirdParty: [true, false], + policyLink: ['https://policies.google.com/technologies/cookies'], + shadowSpread: ["0em", "0.5em", "1em", "1.25em", "1.75em", "2.0000em", "2.5em"] + }, + hexColors: ["bannerBackground", "bannerColor", "acceptBtnColor", "acceptBtnBackground", + "customizeBtnBackground", "customizeBtnColor", "rejectBtnBackground", "rejectBtnColor", + "manageColor", "manageBackground", "selectorTitleColor", "customizeSwitchOnColor", "selectorBtnBackground"], + opacityColors: ["shadowColor"], + strings: ["bannerDescription", "bannerLinkText", "bannerHeading", "acceptBtnText", "rejectBtnText", "customizeBtnText", "manageText", "selectorTitleText"] +} + +class Fuzzer { + constructor(numTests, setProbability) { + this.numTests = numTests; + this.setProbability = setProbability; + this.customizers = {}; + this.glowCookies = undefined; + } + + + + setCustomizers() { + var keys = Object.keys(customizationOptions.selections); + for (let i = 0; i < keys.length; i++) { + if (Math.random() < this.setProbability) { + this.customizers[keys[i]] = customizationOptions.selections[keys[i]][Math.floor(Math.random() * customizationOptions.selections[keys[i]].length)]; + } + } + + for (let i = 0; i < customizationOptions.hexColors.length; i++) { + if (Math.random() < this.setProbability) { + this.customizers[customizationOptions.hexColors[i]] = getRandomColorHex(); + } + } + + for (let i = 0; i < customizationOptions.opacityColors.length; i++) { + if (Math.random() < this.setProbability) { + this.customizers[customizationOptions.opacityColors[i]] = getRandomColorWithOpacity(); + } + } + + for (let i = 0; i < customizationOptions.strings.length; i++) { + if (Math.random() < this.setProbability) { + this.customizers[customizationOptions.strings[i]] = getRandomString(20); + } + } + } + + fuzz() { + try { + for (let i = 0; i < this.numTests; i++) { + this.setCustomizers(); + this.glowCookies = new GlowCookies() + this.glowCookies.start('en', this.customizers); + // delete the object + console.log(this.customizers); + } + } catch (error) { + console.log(error); + console.log(this.customizers); + } + } } +// Pass in labels for tests to run each corresponding test class GlowCookiesTester { - constructor(glowCookies){ - this.glowCookies = glowCookies; + constructor(test_inputs){ + this.glowCookies = new GlowCookies() + // If you are running the fuzzer, it must be on its own, as default + combinatorial tests + // use a preset to go through the tests, while the fuzzer generates random values. + this.containsFuzzer = false + test_inputs.forEach(test_input => { + if(test_input.length > 0 && test_input[0] == 'fuzz'){ + this.containsFuzzer = true; + } + }); + if(this.containsFuzzer){ + if(test_inputs.length != 1){ + return; + } + }else{ + this.glowCookies.start('en', presetParams()); + } + this.test_inputs = test_inputs; // Test inputs are in the following form: [test_name, test_args...] + this.test_object = { + 'test1': this.test1, + 'test2': this.test2, + 'test3': this.test3, + 'test4': this.test4, + 'test5': this.test5, + 'ctest1': this.ctest1, + 'fuzz': this.fuzz, + } + this.waitForRender(); + } + waitForRender = () => { + if(!this.glowCookies.rendered && !this.containsFuzzer) { + window.setTimeout(this.waitForRender, 100); + } else { + this.runTests() + } + } + + runTests = () => { // Tests + this.test_inputs.forEach(test_input => { + console.log(Object.keys(this.test_object)); + if(test_input.length >= 1 && Object.keys(this.test_object).includes(test_input[0])){ + let args = []; + for(let i = 1; i < test_input.length; i++){ + args.push(test_input[i]); + } + this.test_object[test_input[0]](...args); + } + + + }); //this.test1(); //this.test2(); //this.test3(); - this.ctest1(); + //this.ctest1(); //assertParameters({}, this.glowCookies); } - // Default Testing - // Assuming no user input - // Testing purely for accepting cookies - test1 = () => { + + // Default Testing + // Assuming no user input + // Testing purely for accepting cookies + test1 = () => { console.log("Running Test 1"); this.glowCookies.openManageCookies(); this.glowCookies.acceptCookies(); @@ -147,6 +318,37 @@ class GlowCookiesTester { console.log("Passed all parts of Test 3") } + test4 = () => { + console.log("Running Test 4"); + this.glowCookies.addNewScript([{ type: 'custom', position: 'body', content: `console.log('Test script for Test 4!');` }]); + let foundScript = false; + Object.keys(document.body.children).forEach(child => { + if(document.body.children[child].outerHTML != undefined && document.body.children[child].outerHTML == ""){ + foundScript = true; + } + }); + assert(foundScript, new Error().lineNumber) + console.log("Passed all parts of Test 4") + } + + test5 = () => { + console.log("Running Test 5"); + let foundScripts = [false, false]; + this.glowCookies.addNewScript([{ type: 'custom', position: 'body', content: `console.log('Test script 1 for Test 5!');` }, + { type: 'custom', position: 'body', content: `console.log('Test script 2 for Test 5!');` }]); + Object.keys(document.body.children).forEach(child => { + if(document.body.children[child].outerHTML != undefined){ + if(document.body.children[child].outerHTML == ""){ + foundScripts[0] = true; + }else if(document.body.children[child].outerHTML == ""){ + foundScripts[1] = true; + } + } + }); + assert(foundScripts[0] && foundScripts[1], new Error().lineNumber) + console.log("Passed all parts of Test 5") + } + ctest1 = () => { console.log("Running Combinatorial Test 1 for selector"); // Ensure hide after click is false @@ -182,899 +384,14 @@ class GlowCookiesTester { console.log("Passed Combinatorial Test 1 for selector"); } -} - - -class GlowCookies { - constructor() { - // Cookies banner - this.banner = undefined - // Selection banner - this.selector = undefined - // Config - this.config = undefined - this.tracking = undefined - // DOM ELEMENTS - this.PreBanner = undefined - this.CustomizeSwitches = [undefined, undefined, undefined, undefined] // At most 3 valid switches - this.cookiesAllowed = [undefined, undefined, undefined, undefined] // Upon saving a selection or selecting accept/ reject these will be updated accordingly - this.Cookies = undefined - this.DOMbanner = undefined - - // Selections - this.customizers = undefined; - } - - render() { - try { - this.addCss() - this.createDOMElements() - this.checkStatus() - } catch (error) { - console.log(error); - console.log(this.customizers); - } - - new GlowCookiesTester(this); - } - - addCss() { - const stylesheet = document.createElement('link'); - // stylesheet.setAttribute('rel', 'stylesheet'); - // stylesheet.setAttribute('href', `GlowCookies/src/glowCookies.css`); - document.head.appendChild(stylesheet); - } - - createDOMElements() { - // COOKIES BUTTON - this.PreBanner = document.createElement("div"); - this.PreBanner.innerHTML = ``; - this.PreBanner.style.display = "none"; - document.body.appendChild(this.PreBanner); - - // COOKIES BANNER - this.Cookies = document.createElement("div"); - this.Cookies.innerHTML = `
- -

${this.banner.heading}

-

- ${this.banner.description} - - ${this.banner.linkText} - -

-
- - - -
-
- `; - document.body.appendChild(this.Cookies); - this.DOMbanner = document.getElementById('glowCookies-banner') - - // COOKIES BANNER - this.switch_on = ["glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off", "glowCookies__customize_switch_button_off"]; - this.switch_colors = ["switch_color_off", "switch_color_off", "switch_color_off", "switch_color_off"] - this.Customizer = document.createElement("div"); - this.Customizer.innerHTML = `
- -

${this.selector.titleText}

-
-
- User Preferences -
-
- -
-
-
-
- Analytics -
-
- -
-
-
-
- Third Party Cookies -
-
- -
-
-
-
- Session Only Cookies -
-
- -
-
- -
-
- `; - document.body.appendChild(this.Customizer); - for(let i = 1; i < 5; i++){ - this.CustomizeSwitches[i - 1] = document.getElementById('glowCookies-customize-switch-' + i) - } - - - // SET EVENT LISTENERS - document.getElementById('prebannerBtn').addEventListener('click', () => this.openSelector()) - document.getElementById('acceptCookies').addEventListener('click', () => this.acceptCookies()) - document.getElementById('rejectCookies').addEventListener('click', () => this.rejectCookies()) - document.getElementById('customizeButton').addEventListener('click', () => this.openCustomizer()) - document.getElementById('glowCookies-customize-switch-1').addEventListener('click', () => this.switchCustomizer(1)) - document.getElementById('glowCookies-customize-switch-2').addEventListener('click', () => this.switchCustomizer(2)) - document.getElementById('glowCookies-customize-switch-3').addEventListener('click', () => this.switchCustomizer(3)) - document.getElementById('glowCookies-customize-switch-4').addEventListener('click', () => this.switchCustomizer(4)) - document.getElementById('glowCookies-customize-save').addEventListener('click', () => this.savePreferences()) - // Add a new click listener for the 'closeManager' - } - - checkStatus() { - switch (localStorage.getItem("GlowCookies")) { - case "1": - this.openManageCookies(); - this.activateTracking(); - this.addCustomScript(); - this.setRetentionPeriod(this.tracking.retentionPeriod); - break; - case "0": - this.openManageCookies(); - break; - default: - this.openSelector(); - } - } - - openManageCookies() { - this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" - this.DOMbanner.classList.remove('glowCookies__show') - this.Customizer.style.display = "none" - } - - openSelector() { - this.PreBanner.style.display = "none"; - this.DOMbanner.classList.add('glowCookies__show') - this.Customizer.style.display = "none" - } - - acceptCookies() { - localStorage.setItem("GlowCookies", "1") - this.openManageCookies() - this.activateTracking() - this.addCustomScript() - this.setRetentionPeriod(this.tracking.retentionPeriod) - } - - - rejectCookies() { - localStorage.setItem("GlowCookies", "0"); - this.openManageCookies(); - this.disableTracking(); - } - - openCustomizer() { - // Close out the banner, and we need to open the new banner - this.DOMbanner.classList.remove('glowCookies__show'); - this.Customizer.style.display = "block"; - for(let i = 1; i < 5; i++){ - if(this.cookiesAllowed[i - 1] == undefined || this.cookiesAllowed[i - 1] == false){ - this.switch_on[i - 1] = "glowCookies__customize_switch_button_off"; - this.switch_colors[i - 1] = "switch_color_off"; - }else{ - this.switch_on[i - 1] = "glowCookies__customize_switch_button_on"; - this.switch_colors[i - 1] = "switch_color_on"; - } - this.CustomizeSwitches[i - 1].classList.add(this.switch_on[i-1]); - this.CustomizeSwitches[i - 1].classList.add(this.switch_colors[i-1]); - } - } - - switchCustomizer(switch_num) { - switch_num = switch_num - 1 - this.CustomizeSwitches[switch_num].classList.remove(this.switch_on[switch_num]); - this.CustomizeSwitches[switch_num].classList.remove(this.switch_colors[switch_num]); - if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ - // Off to on - this.switch_on[switch_num] = "glowCookies__customize_switch_button_on"; - this.switch_colors[switch_num] = "switch_color_on"; - }else{ - // On to off - this.switch_on[switch_num] = "glowCookies__customize_switch_button_off" - this.switch_colors[switch_num] = "switch_color_off"; - } - this.CustomizeSwitches[switch_num].classList.add(this.switch_on[switch_num]); - this.CustomizeSwitches[switch_num].classList.add(this.switch_colors[switch_num]); - - - } - - savePreferences(){ - this.Customizer.style.display = "none"; - let isSessionOnly = 0; - for(let switch_num = 0; switch_num < 4; switch_num++){ - if(this.switch_on[switch_num] == "glowCookies__customize_switch_button_off"){ - this.cookiesAllowed[switch_num] = false; - }else{ - if(switch_num == 0){ - if(this.tracking.userPreferencesScript != undefined){ - this.addNewScript(this.tracking.userPreferencesScript) - } - }else if(switch_num == 1){ - if(this.tracking.userPreferencesScript != undefined){ - this.addNewScript(this.tracking.thirdPartyScript) - } - }else if(switch_num == 2){ - if(this.tracking.userPreferencesScript != undefined){ - this.addNewScript(this.tracking.analyticsScript) - } - }else{ - // if we are on switch 4 it must be session onl - isSessionOnly = 1 - } - this.cookiesAllowed[switch_num] = true; - } - } - this.activateSessionCookies(isSessionOnly); - this.PreBanner.style.display = this.config.hideAfterClick ? "none" : "block" - } - - activateSessionCookies(isSessionOnly){ - sessionStorage.setItem('isSessionOnly', isSessionOnly ? 'true' : 'false'); - - // split document.cookie string to get all cookies - let cookies = document.cookie.split(';'); - - for (let i = 0; i < cookies.length; i++) { - let cookie = cookies[i]; - let eqPos = cookie.indexOf('='); - let name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; - let value = eqPos > -1 ? cookie.substr(eqPos + 1) : null; - if (isSessionOnly) { - // makes it a session cookie - document.cookie = `${name}=${value}; path=/`; - } else { - // set cookie with 8-hour expiration - // need to change to the custom retention period - const date = new Date(); - date.setTime(date.getTime() + (8 * 60 * 60 * 1000)); // 8 hours - let expires = "expires=" + date.toUTCString(); - document.cookie = `${name}=${value}; ${expires}; path=/`; - } - } - } - - - activateTracking() { - // Google Analytics Tracking - if (this.tracking.AnalyticsCode) { - let Analytics = document.createElement('script'); - Analytics.setAttribute('src', `https://www.googletagmanager.com/gtag/js?id=${this.tracking.AnalyticsCode}`); - document.head.appendChild(Analytics); - let AnalyticsData = document.createElement('script'); - AnalyticsData.text = `window.dataLayer = window.dataLayer || []; - function gtag(){dataLayer.push(arguments);} - gtag('js', new Date()); - gtag('config', '${this.tracking.AnalyticsCode}');`; - document.head.appendChild(AnalyticsData); - } - - // Facebook pixel tracking code - if (this.tracking.FacebookPixelCode) { - let FacebookPixelData = document.createElement('script'); - FacebookPixelData.text = ` - !function(f,b,e,v,n,t,s) - {if(f.fbq)return;n=f.fbq=function(){n.callMethod? - n.callMethod.apply(n,arguments):n.queue.push(arguments)}; - if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; - n.queue=[];t=b.createElement(e);t.async=!0; - t.src=v;s=b.getElementsByTagName(e)[0]; - s.parentNode.insertBefore(t,s)}(window, document,'script', - 'https://connect.facebook.net/en_US/fbevents.js'); - fbq('init', '${this.tracking.FacebookPixelCode}'); - fbq('track', 'PageView'); - `; - document.head.appendChild(FacebookPixelData); - let FacebookPixel = document.createElement('noscript'); - FacebookPixel.setAttribute('height', `1`); - FacebookPixel.setAttribute('width', `1`); - FacebookPixel.setAttribute('style', `display:none`); - FacebookPixel.setAttribute('src', `https://www.facebook.com/tr?id=${this.tracking.FacebookPixelCode}&ev=PageView&noscript=1`); - document.head.appendChild(FacebookPixel); - } - - // Hotjar Tracking - if (this.tracking.HotjarTrackingCode) { - let hotjarTrackingData = document.createElement('script'); - hotjarTrackingData.text = ` - (function(h,o,t,j,a,r){ - h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)}; - h._hjSettings={hjid:${this.tracking.HotjarTrackingCode},hjsv:6}; - a=o.getElementsByTagName('head')[0]; - r=o.createElement('script');r.async=1; - r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv; - a.appendChild(r); - })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv='); - `; - document.head.appendChild(hotjarTrackingData); - } - } - - disableTracking() { - // Google Analytics Tracking ('client_storage': 'none') - if (this.tracking.AnalyticsCode) { - let Analytics = document.createElement('script'); - Analytics.setAttribute('src', `https://www.googletagmanager.com/gtag/js?id=${this.tracking.AnalyticsCode}`); - document.head.appendChild(Analytics); - let AnalyticsData = document.createElement('script'); - AnalyticsData.text = `window.dataLayer = window.dataLayer || []; - function gtag(){dataLayer.push(arguments);} - gtag('js', new Date()); - gtag('config', '${this.tracking.AnalyticsCode}' , { - 'client_storage': 'none', - 'anonymize_ip': true - });`; - document.head.appendChild(AnalyticsData); - } - - // Clear cookies - not working 100% - this.clearCookies() - } - - clearCookies() { - let cookies = document.cookie.split("; "); - for (let c = 0; c < cookies.length; c++) { - let d = window.location.hostname.split("."); - while (d.length > 0) { - let cookieBase = encodeURIComponent(cookies[c].split(";")[0].split("=")[0]) + '=; expires=Thu, 01-Jan-1970 00:00:01 GMT; domain=' + d.join('.') + ' ;path='; - let p = location.pathname.split('/'); - document.cookie = cookieBase + '/'; - while (p.length > 0) { - document.cookie = cookieBase + p.join('/'); - p.pop(); - }; - d.shift(); - } - } - } - setRetentionPeriod(daystoLive) { - let cookies = document.cookie.split("; "); - for(let c = 0; c < cookies.length; c++) { - let d = window.location.hostname.split("."); - const date = new Date(); - date.setTime(date.getTime() + (daystoLive * 24* 60 * 60 *1000)); - // date.setTime(date.getTime() + (daystoLive *1000)); - - while (d.length > 0) { - let cookieBase = encodeURIComponent(cookies[c].split(";")[0].split("=")[0]) + `=; expires=${date.toUTCString()}; domain=` + d.join('.') + ' ;path='; - let p = location.pathname.split('/'); - document.cookie = cookieBase + '/'; - // while (p.length > 0) { - // document.cookie = cookieBase + p.join('/'); - // p.pop(); - // }; - d.shift(); - } - } - } - - addCustomScript() { - if (this.tracking.customScript !== undefined) { - this.addNewScript(this.tracking.customScript) - } - } - - addNewScript(customScript) { - let customScriptTag - customScript.forEach(script => { - if (script.type === 'src') { - customScriptTag = document.createElement('script'); - customScriptTag.setAttribute('src', script.content); - } else if (script.type === 'custom') { - customScriptTag = document.createElement('script'); - customScriptTag.text = script.content; - } - - if (script.position === 'head') { - document.head.appendChild(customScriptTag); - } else { - document.body.appendChild(customScriptTag); - } - }) + fuzz = (numTests, prob) => { + console.log("fuzzing") + const fuzzer = new Fuzzer(numTests, prob); + fuzzer.fuzz(); } - - start(languaje, obj) { - if (!obj) obj = {} - const lang = new LanguagesGC(languaje) - - this.customizers = obj; - - this.config = { - border: obj.border || 'border', - position: obj.position || 'left', - hideAfterClick: obj.hideAfterClick || false, - bannerStyle: obj.style || 2 - } - - this.tracking = { - AnalyticsCode: obj.analytics || undefined, - FacebookPixelCode: obj.facebookPixel || undefined, - HotjarTrackingCode: obj.hotjar || undefined, - customScript: obj.customScript || undefined, - userPreferencesScript: obj.userPreferencesScript || undefined, - thirdPartyScript: obj.thirdPartyScript || undefined, - analyticsScript: obj.analyticsScript || undefined, - retentionPeriod: obj.retentionPeriod || 1 - } - let customizeBtnDisplayVal = 'block'; - if (!obj.customizeBtnDisplay){ - customizeBtnDisplayVal = 'none'; - } - this.banner = { - description: obj.bannerDescription || lang.bannerDescription, - linkText: obj.bannerLinkText || lang.bannerLinkText, - link: obj.policyLink || '#link', - background: obj.bannerBackground || '#fff', - shadowSpread: obj.shadowSpread || 0, - shadowColor: obj.shadowColor || 'rgb(0,0,0,0)', - color: obj.bannerColor || '#1d2e38', - closeColor: obj.closeColor || '#000', - closeBtnHiddenText: obj.closeBtnHidden ? 'hidden' : '', - heading: obj.bannerHeading !== 'none' ? obj.bannerHeading || lang.bannerHeading : '', - acceptBtn: { - text: obj.acceptBtnText || lang.acceptBtnText, - background: obj.acceptBtnBackground || '#253b48', - color: obj.acceptBtnColor || '#fff' - }, - customizeButton: { - display: customizeBtnDisplayVal, - text: obj.customizeBtnText || lang.customizeBtnText, - background: obj.customizeBtnBackground || '#E8E8E8', - color: obj.customizeBtnColor || '#636363' - }, - rejectBtn: { - text: obj.rejectBtnText || lang.rejectBtnText, - background: obj.rejectBtnBackground || '#E8E8E8', - color: obj.rejectBtnColor || '#636363' - }, - manageCookies: { - color: obj.manageColor || '#1d2e38', - background: obj.manageBackground || '#fff', - text: obj.manageText || lang.manageText, - } - } - let customizeUserPreferencesDisplay = 'flex'; - if (obj.customizeUserPreferences == false){ - customizeUserPreferencesDisplay = 'none'; - } - let customizeAnalyticsDisplay = 'flex'; - if (obj.customizeAnalytics == false){ - customizeAnalyticsDisplay = 'none'; - } - let customizeThirdPartyDisplay = 'flex'; - if (obj.customizeThirdParty == false){ - customizeThirdPartyDisplay = 'none'; - } - let customizeSessionCookiesDisplay = 'flex'; - if(obj.customizeSessionCookies == false){ - customizeSessionCookiesDisplay = 'none' - } - - this.selector = { - titleText: obj.selectorTitleText || 'Customize Cookies', - titleColor: obj.selectorTitleColor || 'black', - btnText: obj.selectorBtnText || 'Save cookie preferences', - btnBackground: obj.selectorBtnBackground || 'blue', - btnColor: obj.selectorBtnColor || 'white', - customizeUserPreferences: { - display: customizeUserPreferencesDisplay - }, - customizeAnalytics: { - display: customizeAnalyticsDisplay - }, - customizeThirdParty: { - display: customizeThirdPartyDisplay - }, - customizeSessionCookies: { - display: customizeSessionCookiesDisplay - }, - customizeSwitch: { - offColor: obj.customizeSwitchOffColor || 'gray', - onColor: obj.customizeSwitchOnColor || 'blue', - } - } - // Append two CSS classes to represent each background color for - for(let i = 0; i < 2; i++){ - var style = document.createElement('style'); - document.head.appendChild(style); - let css = undefined - if(i == 0){ - css = '.switch_color_off' + ' { background-color: ' + this.selector.customizeSwitch.offColor + ';}'; - }else{ - css = '.switch_color_on' + ' { background-color: ' + this.selector.customizeSwitch.onColor + ';}'; - } - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.appendChild(document.createTextNode(css)); - } - document.head.appendChild(style); - } - // Draw banner - window.addEventListener('load', () => { this.render() }) - } } - class LanguagesGC { - constructor(code) { - this.init() - let lang = this.arrLang[code] || this.arrLang['en'] - this.bannerHeading = lang['bannerHeading'] - this.bannerDescription = lang['bannerDescription'] - this.bannerLinkText = lang['bannerLinkText'] - this.acceptBtnText = lang['acceptBtnText'] - this.rejectBtnText = lang['rejectBtnText'] - this.customizeBtnText = lang['customizeBtnText'] - this.manageText = lang['manageText'] - } - - init() { - this.arrLang = { - af: { - 'bannerHeading': 'Ons gebruik koekies', - 'bannerDescription': 'Ons gebruik ons eie koekies en die van derdepartye, om inhoud te verpersoonlik en om webverkeer te ontleed.', - 'bannerLinkText': 'Lees meer oor koekies', - 'acceptBtnText': 'Aanvaar koekies', - 'rejectBtnText': 'Weier', - 'manageText': 'Koekie-instellings' - }, - bg: { - 'bannerHeading': 'Ние използваме бисквитки', - 'bannerDescription': 'Използваме наши и бисквитки на трети страни, за да запазим Вашите предпочитания и да събираме аналитични данни.', - 'bannerLinkText': 'Прочетете повече за бисквитките', - 'acceptBtnText': 'Приеми бисквитките', - 'rejectBtnText': 'Откажи', - 'manageText': 'Настрой бисквитките' - }, - de: { - 'bannerHeading': 'Verwendung von Cookies', - 'bannerDescription': 'Wir nutzen Cookies (auch von Drittanbietern), um Inhalte zu personalisieren und Surfverhalten zu analysieren.', - 'bannerLinkText': 'Mehr über Cookies', - 'acceptBtnText': 'Cookies akzeptieren', - 'rejectBtnText': 'Ablehnen', - 'manageText': 'Cookies verwalten' - }, - en: { - 'bannerHeading': 'We use cookies', - 'bannerDescription': 'We use our own and third-party cookies to personalize content and to analyze web traffic.', - 'bannerLinkText': 'Read more about cookies', - 'acceptBtnText': 'Accept cookies', - 'rejectBtnText': 'Reject', - 'customizeBtnText': 'More options', - 'manageText': 'Manage cookies' - }, - sv: { - 'bannerHeading': 'Vi använder cookies', - 'bannerDescription' : 'Vi använder våra egna och tredjepartscookies för att personalisera innehåll och till statistik.', - 'bannerLinkText' : 'Läs mer om cookies', - 'acceptBtnText' : 'Acceptera cookies', - 'rejectBtnText' : 'Avslå', - 'manageText' : 'Hantera cookies' - }, - no: { - 'bannerHeading': 'Vi benytter cookies', - 'bannerDescription' : 'Vi benytter våre egne og tredjepartscookies for å personalisere innehold og til statistikk.', - 'bannerLinkText' : 'Les mer om cookies', - 'acceptBtnText' : 'Aksepter cookies', - 'rejectBtnText' : 'Avslå', - 'manageText' : 'Håndter cookies' - }, - da: { - 'bannerHeading': 'Vi bruger cookies', - 'bannerDescription' : 'Vi bruger vores egne og tredjepartscookies til at tilpasse indhold og måle statistik.', - 'bannerLinkText' : 'Læs mere om cookies', - 'acceptBtnText' : 'Accepter cookies', - 'rejectBtnText' : 'Afvis', - 'manageText' : 'Administrer cookies' - }, - es: { - 'bannerHeading': 'Uso de cookies', - 'bannerDescription': 'Utilizamos cookies propias y de terceros para personalizar el contenido y para analizar el tráfico de la web.', - 'bannerLinkText': 'Ver más sobre las cookies', - 'acceptBtnText': 'Aceptar cookies', - 'rejectBtnText': 'Rechazar', - 'manageText': 'Cookies' - }, - fr: { - 'bannerHeading': 'Nous utilisons des cookies', - 'bannerDescription': 'Nous utilisons nos propres cookies et ceux de tiers pour adapter le contenu et analyser le trafic web.', - 'bannerLinkText': 'En savoir plus sur les cookies', - 'acceptBtnText': 'Accepter les cookies', - 'rejectBtnText': 'Refuser', - 'manageText': 'Paramétrez les cookies' - }, - it: { - 'bannerHeading': 'Utilizziamo i cookie', - 'bannerDescription': 'Utilizziamo cookie nostri e di terze parti per personalizzare il contenuto e analizzare il traffico web.', - 'bannerLinkText': 'Per saperne di più riguardo i cookie', - 'acceptBtnText': 'Accetta i cookie', - 'rejectBtnText': 'Rifiuta', - 'manageText': 'Gestisci i cookie' - }, - mg: { - 'bannerHeading': 'Izahay dia mampiasa cookies', - 'bannerDescription': "Mampiasa ny cookies anay manokana sy ireo an'ny antoko fahatelo izahay hampifanarahana ny atiny sy hamakafaka ny fivezivezena amin'ny tranonkala.", - 'bannerLinkText': 'Maniry halala bebe kokoa momba ny cookies', - 'acceptBtnText': 'Manaiky ireo cookies', - 'rejectBtnText': 'Tsy mety', - 'manageText': 'Hamboarina ny cookies' - }, - nl: { - 'bannerHeading': 'We gebruiken cookies', - 'bannerDescription': 'We gebruiken onze en third-party cookies om content te personaliseren en web traffic te analyseren.', - 'bannerLinkText': 'Lees meer over cookies', - 'acceptBtnText': 'Cookies accepteren', - 'rejectBtnText': 'Weigeren', - 'manageText': 'Cookies beheren' - }, - oc: { - 'bannerHeading': 'Utilizam de cookies', - 'bannerDescription': 'Utilizam nòstres pròpris cookies e de cookies tèrces per adaptar lo contengut e analisar lo trafic web.', - 'bannerLinkText': 'Ne saber mai suls cookies', - 'acceptBtnText': 'Acceptar los cookies', - 'rejectBtnText': 'Refusar', - 'manageText': 'Configurar los cookies' - }, - pl: { - 'bannerHeading': 'Używamy plików cookie', - 'bannerDescription': 'Ta strona używa plików cookie - zarówno własnych, jak i od zewnętrznych dostawców, w celu personalizacji treści i analizy ruchu.', - 'bannerLinkText': 'Więcej o plikach cookie', - 'acceptBtnText': 'Zaakceptuj pliki cookie', - 'rejectBtnText': 'Odrzuć', - 'manageText': 'Ustawienia plików cookie' - }, - pt_BR: { - 'bannerHeading': 'Uso de cookies', - 'bannerDescription': 'Usamos cookies próprios e de terceiros para personalizar o conteúdo e analisar o tráfego da web.', - 'bannerLinkText': 'Leia mais sobre os cookies', - 'acceptBtnText': 'Aceitar cookies', - 'rejectBtnText': 'Rejeitar', - 'manageText': 'Gerenciar cookies' - }, - ru: { - 'bannerHeading': 'Позвольте использовать куки?', - 'bannerDescription': 'Мы используем собственные и сторонние куки для персонализации контента и анализа веб-трафика.', - 'bannerLinkText': 'Узнать больше про куки.', - 'acceptBtnText': 'Ок, используйте', - 'rejectBtnText': 'Не разрешаю', - 'manageText': 'Разрешите использовать куки?' - }, - sk: { - 'bannerHeading': 'Používame cookies', - 'bannerDescription': 'Na prispôsobenie obsahu a analýzu webovej stránky používame vlastné cookies a cookies tretích strán.', - 'bannerLinkText': 'Čo sú cookies?', - 'acceptBtnText': 'Povoliť cookies', - 'rejectBtnText': 'Nepovoliť', - 'manageText': 'Spravovať cookies' - }, - th: { - 'bannerHeading': 'Cookies', - 'bannerDescription': 'พวกเราใช้คุกกี้บุคคลที่สาม เพื่อปรับแต่งเนื้อหาและวิเคราะห์การเข้าชมเว็บ', - 'bannerLinkText': 'อ่านเพิ่มเติมเกี่ยวกับคุกกี้', - 'acceptBtnText': 'ยอมรับคุกกี้', - 'rejectBtnText': 'ปฏิเสธคุกกี้', - 'manageText': 'Cookies' - }, - tr: { - 'bannerHeading': 'Çerez kullanımı', - 'bannerDescription': 'İçeriği kişiselleştirmek ve web trafiğini analiz etmek için kendi ve üçüncü taraf çerezlerimizi kullanıyoruz.', - 'bannerLinkText': 'Çerezler hakkında daha fazlasını okuyun', - 'acceptBtnText': 'Çerezleri kabul et', - 'rejectBtnText': 'Reddet', - 'manageText': 'Çerezleri yönet' - }, - uk: { - 'bannerHeading': 'Ми використовуємо кукі', - 'bannerDescription': 'Ми використовуємо власні та сторонні cookie для персоналізації досвіду користування та аналізу веб-трафіку.', - 'bannerLinkText': 'Дізнайтеся більше про cookie', - 'acceptBtnText': 'Прийняти', - 'rejectBtnText': 'Відхилити', - 'manageText': 'Налаштування cookie' - }, - ja: { - 'bannerHeading': 'Cookies を使用しています', - 'bannerDescription': '私たちは、コンテンツのパーソナライズやトラフィックの分析のために、独自およびサードパーティー製 Cookies を使用しています。', - 'bannerLinkText': 'Cookiesについて詳しく見る', - 'acceptBtnText': 'Cookiesを受け入れる', - 'rejectBtnText': '拒否', - 'manageText': 'cookies管理' - }, - zh_TW: { - 'bannerHeading': '我們使用 Cookies', - 'bannerDescription' : '我們使用了自己和第三方的 cookies 來個人化您的內容和分析網頁的流量。', - 'bannerLinkText' : '閱讀更多關於 cookies', - 'acceptBtnText' : '同意 cookies', - 'rejectBtnText' : '拒絕', - 'manageText' : '管理 cookies' - }, - zh: { - 'bannerHeading': '我们使用 Cookies', - 'bannerDescription': '我们使用了自己和第三方的 cookies 来个性化您的内容和分析网页的流量。', - 'bannerLinkText': '阅读更多关于 cookies', - 'acceptBtnText': '同意 cookies', - 'rejectBtnText': '拒绝', - 'manageText': '管理 cookies' - }, - ca: { - 'bannerHeading': 'Ús de Cookies', - 'bannerDescription': 'Utilitzem cookies pròpies i de tercers per a personalitzar el contingut i per a analitzar el trànsit del lloc web.', - 'bannerLinkText': 'Vegeu més informació sobre les Cookies', - 'acceptBtnText': 'Acceptar les Cookies', - 'rejectBtnText': 'Declinar', - 'manageText': 'Cookies' - } - } - } - - } - - const glowCookies = new GlowCookies() - - function getRandomColorHex() { - var hexDigits = '0123456789ABCDEF'; - var randomColor = '#'; - for (let i = 0; i < 6; i++) { - randomColor += hexDigits[Math.floor(Math.random() * 16)]; - } - return randomColor; - } - - function getRandomColorWithOpacity() { - var randomColor = 'rgba('; - for (let i = 0; i < 3; i++) { - randomColor += Math.floor(Math.random() * 256); - randomColor += ","; - } - randomColor += Math.random(); - randomColor += ")"; - return randomColor; - } - - function getRandomString(length) { - var randomString = ""; - var strLength = Math.floor(Math.random() * length); - for (let i = 0; i < strLength; i++) { - randomString += String.fromCharCode(Math.floor(Math.random() * (126 - 33) + 33)) - } - return randomString; - } - - const customizationOptions = { - selections: { - style: [1, 2, 3], - analytics: ['G-FH87DE17XF'], - facebookPixel: ['990955817632355'], - customScript: [{ type: 'custom', position: 'body', content: `console.log('my custom js');` }], - hideAfterClick: [false], // SHOULD BE [true, false] - border: ["border", "none"], - position: ["left", "right"], - customizeBtnDisplay: [true, false], - customizeUserPreferences: [true, false], - customizeAnalytics: [true, false], - customizeThirdParty: [true, false], - policyLink: ['https://policies.google.com/technologies/cookies'], - shadowSpread: ["0em", "0.5em", "1em", "1.25em", "1.75em", "2.0000em", "2.5em"] - }, - hexColors: ["bannerBackground", "bannerColor", "acceptBtnColor", "acceptBtnBackground", - "customizeBtnBackground", "customizeBtnColor", "rejectBtnBackground", "rejectBtnColor", - "manageColor", "manageBackground", "selectorTitleColor", "customizeSwitchOnColor", "selectorBtnBackground"], - opacityColors: ["shadowColor"], - strings: ["bannerDescription", "bannerLinkText", "bannerHeading", "acceptBtnText", "rejectBtnText", "customizeBtnText", "manageText", "selectorTitleText"] - } - - class Fuzzer { - constructor(numTests, setProbability) { - this.numTests = numTests; - this.setProbability = setProbability; - this.customizers = {}; - this.glowCookies = undefined; - } - - - - setCustomizers() { - var keys = Object.keys(customizationOptions.selections); - for (let i = 0; i < keys.length; i++) { - if (Math.random() < this.setProbability) { - this.customizers[keys[i]] = customizationOptions.selections[keys[i]][Math.floor(Math.random() * customizationOptions.selections[keys[i]].length)]; - } - } - - for (let i = 0; i < customizationOptions.hexColors.length; i++) { - if (Math.random() < this.setProbability) { - this.customizers[customizationOptions.hexColors[i]] = getRandomColorHex(); - } - } - - for (let i = 0; i < customizationOptions.opacityColors.length; i++) { - if (Math.random() < this.setProbability) { - this.customizers[customizationOptions.opacityColors[i]] = getRandomColorWithOpacity(); - } - } - - for (let i = 0; i < customizationOptions.strings.length; i++) { - if (Math.random() < this.setProbability) { - this.customizers[customizationOptions.strings[i]] = getRandomString(20); - } - } - } - - fuzz() { - try { - for (let i = 0; i < this.numTests; i++) { - this.setCustomizers(); - this.glowCookies = new GlowCookies() - this.glowCookies.start('en', this.customizers); - // delete the object - console.log(this.customizers); - } - } catch (error) { - console.log(error); - console.log(this.customizers); - } - } - } - - const fuzzer = new Fuzzer(1, 0.5); - fuzzer.fuzz(); - +new GlowCookiesTester([["test4"], ["test5"]]); +//new GlowCookiesTester([["fuzz", 1, 0.5]]); \ No newline at end of file From 9eae73d9a4c31494e1219b35d6213903052875a3 Mon Sep 17 00:00:00 2001 From: avgentile <108200235+avgentile@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:42:24 -0400 Subject: [PATCH 12/19] Updated README.md with new customization options --- README.md | 99 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 37d3cf1..eb785b6 100644 --- a/README.md +++ b/README.md @@ -63,8 +63,8 @@ Now you can choose between these available languages: Set language in the first parameter of `glowCookies.start('en', { })` method. -## Tracking options -These are the parameters that you can modify to add your tracking codes or custom scripts. +## Cookie functionality options +These are the parameters that you can modify to add your tracking codes, or custom scripts used throughout. | Parameter | Type | Values | | ----------------------- | ------ | ------------------------------------------------------------------------------------------------------------------- | @@ -73,6 +73,10 @@ These are the parameters that you can modify to add your tracking codes or custo | `HotjarTrackingCode` | String | Example: `"990955817632355"` (Hotjar tracking code) | | `customScript` (Inline) | Object | Example: `[{ type: 'custom', position: 'body', content: 'console.log('custom script');' }]` | | `customScript` (src) | Object | Example: `[{ type: 'src', position: 'head', content: 'https://www.googletagmanager.com/gtag/js?id=G-FH87DE17XF' }]` | +| `userPreferencesScript` | Object | Example: `[{ type: 'custom', position: 'body', content: 'console.log('custom script');' }]` | +| `thirdPartyScript` | Object | Example: `[{ type: 'custom', position: 'body', content: 'console.log('custom script');' }]` | +| `analyticsScript` | Object | Example: `[{ type: 'custom', position: 'body', content: 'console.log('custom script');' }]` | +| `additionalCookieScripts`| Object Array | Example: `[[{ type: 'custom', position: 'body', content: 'console.log('custom script');' }]]` | ## Config Banner These are the parameters that you can modify to change certain banner options @@ -83,7 +87,7 @@ These are the parameters that you can modify to change certain banner options | `hideAfterClick` | Boolean | (`true` or `false`) Default: `true` (Hide banner after Accept or Reject cookies) | -## Customize Banner +## Customize Cookie Main Banner Now there are certain parameters that you can change to customize your banner. | Parameter | Type | Values | @@ -104,36 +108,77 @@ Now there are certain parameters that you can change to customize your banner. | `manageColor` | String | Example: `"#fff"` Example: `"white"` | | `manageBackground` | String | Example: `"#f2f2f2"` Example: `"blue"` | | `manageText` | String | Example: `"Manage cookies"` | +| `maxBannerWidth` | String | Example `"300px"` | +| `shadowSpread` | String | Example `"300px"` | +| `shadowColor` | String | Example: `"#f2f2f2"` Example: `"blue"` | +| `customizeBtnDisplay` | Boolean | (`true` or `false`) Default: `false` (Include the customize cookies button or not) | +| `customizeBtnText` | String | Example: `"More options"` | +| `customizeBtnColor` | String | Example: `"#f2f2f2"` Example: `"blue"` | +| `customizeBtnBackground` | String | Example: `"#f2f2f2"` Example: `"blue"` | +## Customize Cookie Selector Menu +There are certain perameters that you can change to customize the selector menu banner. + +| Parameter | Type | Values | +| --------------------- | ------ | ------------------------------------------------------------------------------------------------------ | +| `selectorSwitchOffColor` | String | Example: `"#f2f2f2"` Example: `"blue"` | +| `selectorSwitchOnColor` | String | Example: `"#f2f2f2"` Example: `"blue"` | +| `selectorTitleText` | String | Example: `"Customize your cookies"` | +| `selectorTitleColor` | String | Example: `"#f2f2f2"` Example: `"blue"` | +| `customizeUserPreferemnces` | Boolean | (`true` or `false`) Default: `true` (Include a switch for this type of cookie) | +| `customizeAnalytics` | Boolean | (`true` or `false`) Default: `true` (Include a switch for this type of cookie) | +| `customizeThirdParty` | Boolean | (`true` or `false`) Default: `true` (Include a switch for this type of cookie) | +| `customizeSessionCookies` | Boolean | (`true` or `false`) Default: `true` (Include a switch for this type of cookie) | +| `additionalCookies` | String Array | Example: `"[Unique Cookie 1", "Unique Cookie 2"]` | ## Fully customized banner ```html ``` From 590c1004a20329c5a5b9d3ead0c03a10d90c8991 Mon Sep 17 00:00:00 2001 From: avgentile <108200235+avgentile@users.noreply.github.com> Date: Tue, 16 Apr 2024 21:54:04 -0400 Subject: [PATCH 13/19] Updated tests Added a couple new tests, and added comments for the GlowCookiesTester class --- src/glowCookiesTest.js | 102 +++++++++++++++++++++++++++++++++-------- 1 file changed, 84 insertions(+), 18 deletions(-) diff --git a/src/glowCookiesTest.js b/src/glowCookiesTest.js index 4eb907b..9350234 100644 --- a/src/glowCookiesTest.js +++ b/src/glowCookiesTest.js @@ -63,7 +63,7 @@ function presetParams(){ additionalCookies: ['Test 1', 'Test 2'], //additionalCookieScripts: [[{ type: 'custom', position: 'body', content: `console.log('test 1');` }], //[{ type: 'custom', position: 'body', content: `console.log('test 2');` }]], - customizeUserPreferences: false, + customizeUserPreferences: true, //userPreferencesScript: [{ type: 'custom', position: 'body', content: `console.log('my user preferences js');` }], //thirdPartyScript: [{ type: 'custom', position: 'body', content: `console.log('my third party js');` }], //analyticsScript: [{ type: 'custom', position: 'body', content: `console.log('my analytics js');` }], @@ -221,10 +221,12 @@ class Fuzzer { } } - - -// Pass in labels for tests to run each corresponding test class GlowCookiesTester { + + // Test inputs is an array of arrays. + // Each input array should be as followed: [test_name, test_args...] + // For instance, if you want to use the fuzzer, it would be [["fuzz", 0.5, 1]], or if you + // wanted to use test1 and test 2 it would look like [["test1"], ["test2"]]. constructor(test_inputs){ this.glowCookies = new GlowCookies() // If you are running the fuzzer, it must be on its own, as default + combinatorial tests @@ -242,19 +244,25 @@ class GlowCookiesTester { }else{ this.glowCookies.start('en', presetParams()); } - this.test_inputs = test_inputs; // Test inputs are in the following form: [test_name, test_args...] + this.test_inputs = test_inputs; + // Map each test string to the correspondng function, so we can call it later this.test_object = { 'test1': this.test1, 'test2': this.test2, 'test3': this.test3, 'test4': this.test4, 'test5': this.test5, + 'test6': this.test6, 'ctest1': this.ctest1, + 'ctest2': this.ctest2, 'fuzz': this.fuzz, } this.waitForRender(); } + // waitForRender() is a function dedicated to waiting for the page to render + // before actually running tests. This does not matter for the fuzzer, so we choose + // to go straight to this test in this case. waitForRender = () => { if(!this.glowCookies.rendered && !this.containsFuzzer) { window.setTimeout(this.waitForRender, 100); @@ -263,8 +271,9 @@ class GlowCookiesTester { } } + // runTests() simply runs each test case based off the provided name in the input, + // and passes in the arguments if possible as well. runTests = () => { - // Tests this.test_inputs.forEach(test_input => { console.log(Object.keys(this.test_object)); if(test_input.length >= 1 && Object.keys(this.test_object).includes(test_input[0])){ @@ -274,21 +283,14 @@ class GlowCookiesTester { } this.test_object[test_input[0]](...args); } - - }); - //this.test1(); - //this.test2(); - //this.test3(); - - //this.ctest1(); - //assertParameters({}, this.glowCookies); } // Default Testing - // Assuming no user input - // Testing purely for accepting cookies + + // Test1 + // Checking whether accepting cookies successfully updates local storage test1 = () => { console.log("Running Test 1"); this.glowCookies.openManageCookies(); @@ -297,6 +299,8 @@ class GlowCookiesTester { console.log("Passed all parts of Test 1") } + // Test2 + // Checking whether accepting cookies and then rejecting them updates correctly (twice) test2 = () => { console.log("Running Test 2"); // Ensure that hideafterclick is not true @@ -310,6 +314,8 @@ class GlowCookiesTester { console.log("Passed all parts of Test 2") } + // Test3 + // Checking whether just rejecting cookies updates correctly test3 = () => { console.log("Running Test 3"); this.glowCookies.openManageCookies(); @@ -318,6 +324,8 @@ class GlowCookiesTester { console.log("Passed all parts of Test 3") } + // Test4 + // Ensures that glowCookies can add a new script, and that this is saved into the body of the doc test4 = () => { console.log("Running Test 4"); this.glowCookies.addNewScript([{ type: 'custom', position: 'body', content: `console.log('Test script for Test 4!');` }]); @@ -331,6 +339,8 @@ class GlowCookiesTester { console.log("Passed all parts of Test 4") } + // Test5 + // Ensures that glowCookies can add a two parts of one script, and that both are saved into the body of the doc test5 = () => { console.log("Running Test 5"); let foundScripts = [false, false]; @@ -349,6 +359,24 @@ class GlowCookiesTester { console.log("Passed all parts of Test 5") } + // Test6 + // Checks that updating a specific cookie switch, makes that change + test6 = () => { + console.log("Running Test 6"); + this.glowCookies.updateSpecificCookieAllowed(0, true) + assert(this.glowCookies.cookiesAllowed[0] == true) + assert(this.glowCookies.switch_on[0] == "glowCookies__customize_switch_button_on") + assert(this.glowCookies.switch_colors[0] == "switch_color_on") + this.glowCookies.updateSpecificCookieAllowed(0, false) + assert(this.glowCookies.cookiesAllowed[0] == false) + assert(this.glowCookies.switch_on[0] == "glowCookies__customize_switch_button_off") + assert(this.glowCookies.switch_colors[0] == "switch_color_off") + console.log("Passed all parts of Test 6") + } + + // Combinatorial test 1 + // This test is dedicated at ensuring that the four default switches in the cookie + // customizer save the preferences correctly no matter the combination. ctest1 = () => { console.log("Running Combinatorial Test 1 for selector"); // Ensure hide after click is false @@ -384,8 +412,46 @@ class GlowCookiesTester { console.log("Passed Combinatorial Test 1 for selector"); } + // Combinatorial test 2 + // This test is dedicated at ensuring that the four default switches as well as + // 2 additional switches added by the developer in the cookie customizer + // save the preferences correctly no matter the combination. + ctest2 = () => { + console.log("Running Combinatorial Test 2 for selector"); + // Ensure hide after click is false + this.glowCookies.config.hideAfterClick = false + let selectorTestInputs = new CombinatorialTestingSetup(['bool', 'bool', 'bool', 'bool', 'bool', 'bool'], ['','','', '', '', ''])['inputCombinations']; + console.log(selectorTestInputs) + selectorTestInputs.forEach((selectorTestComb) => { + this.glowCookies.openManageCookies(); + this.glowCookies.openSelector(); + // Go through each comb, and set switches + console.log("Testing selector combination: " + selectorTestComb) + for(let switch_num = 0; switch_num < 6; switch_num++){ + + this.glowCookies.CustomizeSwitches[switch_num].classList.remove(this.glowCookies.switch_on[switch_num]); + this.glowCookies.CustomizeSwitches[switch_num].classList.remove(this.glowCookies.switch_colors[switch_num]); + if(selectorTestComb[switch_num]){ + this.glowCookies.switch_on[switch_num] = "glowCookies__customize_switch_button_on"; + this.glowCookies.switch_colors[switch_num] = "switch_color_on"; + }else{ + this.glowCookies.switch_on[switch_num] = "glowCookies__customize_switch_button_off"; + this.glowCookies.switch_colors[switch_num] = "switch_color_off"; + } + this.glowCookies.CustomizeSwitches[switch_num].classList.add(this.glowCookies.switch_on[switch_num]); + this.glowCookies.CustomizeSwitches[switch_num].classList.add(this.glowCookies.switch_colors[switch_num]); + } + this.glowCookies.savePreferences(); + // After saving, let's ensure that all of the selections held and are now applied + for(let switch_num = 0; switch_num < 6; switch_num++){ + assert(this.glowCookies.cookiesAllowed[switch_num] == selectorTestComb[switch_num], new Error().lineNumber); + } + console.log("Selector combination: " + selectorTestComb + " was saved correctly.") + }) + console.log("Passed Combinatorial Test 2 for selector"); +} + fuzz = (numTests, prob) => { - console.log("fuzzing") const fuzzer = new Fuzzer(numTests, prob); fuzzer.fuzz(); } @@ -393,5 +459,5 @@ class GlowCookiesTester { } -new GlowCookiesTester([["test4"], ["test5"]]); +//new GlowCookiesTester([["test1"], ["test2"], ["test3"], ["test4"], ["test5"], ["test6"], ["ctest1"], ["ctest2"]]); //new GlowCookiesTester([["fuzz", 1, 0.5]]); \ No newline at end of file From d191a9152c6e9936ae0e073a8a3e407b68877464 Mon Sep 17 00:00:00 2001 From: Abhiram Datla Date: Wed, 17 Apr 2024 18:29:55 -0400 Subject: [PATCH 14/19] don't merge this pls --- src/glowCookiesTest.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/glowCookiesTest.js b/src/glowCookiesTest.js index 22da456..09d4536 100644 --- a/src/glowCookiesTest.js +++ b/src/glowCookiesTest.js @@ -95,9 +95,6 @@ class CombinatorialTestingSetup { this.generateCombinations(n - 1, [...prefix, value], potentialOptions, permutationList, max_options); } } - - - } From 844bb1f6597a9a12f7700a29719d7acc90b098a1 Mon Sep 17 00:00:00 2001 From: Abhiram Datla Date: Wed, 17 Apr 2024 20:40:21 -0400 Subject: [PATCH 15/19] readme demo --- README.md | 2 +- src/index.html | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eb785b6..29c2e54 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ # GlowCookies 🍪 - Powerful Cookie Consent Banner In JavaScript Simple and full automated cookies banner for any website. Complies with the new European regulations with GlowCookies. Activate and deactivate Google Analytics, Facebook Pixel, Hotjar (and coming soon) cookies whenever the user wishes, with just 1 click. -[![Foo](https://cdn.glowmedia.es/upload/uploads/ed1952btn.svg)](https://manucaralmo.github.io/glow-cookies-web/) +[![Foo](https://cdn.glowmedia.es/upload/uploads/ed1952btn.svg)](https://abhird11.github.io/GlowCookies/src/) ## The cookies banner diff --git a/src/index.html b/src/index.html index 94556fa..95240ce 100644 --- a/src/index.html +++ b/src/index.html @@ -19,9 +19,7 @@ From d00c7795b8eeb73f3206969da033b7f34ff2aecf Mon Sep 17 00:00:00 2001 From: Abhiram Datla Date: Wed, 17 Apr 2024 20:41:00 -0400 Subject: [PATCH 16/19] demo fix --- src/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.html b/src/index.html index 95240ce..40a4491 100644 --- a/src/index.html +++ b/src/index.html @@ -17,7 +17,7 @@ - + ``` From 479e84f89b93d83b96d50bbcb2deb02165ec814f Mon Sep 17 00:00:00 2001 From: Abhiram Datla Date: Fri, 3 May 2024 12:38:09 -0400 Subject: [PATCH 19/19] Updated README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 29c2e54..21f356f 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,8 @@ Now there are certain parameters that you can change to customize your banner. | `maxBannerWidth` | String | Example `"300px"` | | `shadowSpread` | String | Example `"300px"` | | `shadowColor` | String | Example: `"#f2f2f2"` Example: `"blue"` | +| `closeBtnHidden` | String | (`"hidden"` or `""`) Default: `""` | +| `closeColor` | String | Example: `"#f00"` Default: `"#000"` | | `customizeBtnDisplay` | Boolean | (`true` or `false`) Default: `false` (Include the customize cookies button or not) | | `customizeBtnText` | String | Example: `"More options"` | | `customizeBtnColor` | String | Example: `"#f2f2f2"` Example: `"blue"` |