Keep Cookie Consent Banner hidden once Users Accepted Cookies - javascript

I've managed to get the cookie consent banner to work, where the cookies aren't set when the page loads. Only once the user clicks on the "Accept" button, the cookies will set and show up within the dev tool Application. Once the "Accept" button has been clicked, the banner is hidden, but only temporarily. Because when I refresh the page, or click on a different page, the cookie consent banner shows up again, even though User has already accepted cookies.
I've tried out a bunch of stuff, and am stuck on how I can keep the banner hidden, after user has accepted the cookies.
Note: I have a custom cookie made and use the Google Tag Manager/Google Analytics cookies.
I would appreciate any help on this! Thank you!
HEAD SCRIPTS
<head>
<!-- Cookie Consent Banner -->
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {dataLayer.push(arguments);}
gtag('consent', 'default', { 'ad_storage': 'denied', 'analytics_storage': 'denied' });
</script>
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'TAG_ID');
</script>
<script>
function consentGranted() {
gtag('consent', 'update', { 'ad_storage': 'granted', 'analytics_storage': 'granted' });};
</script>
<script>
function dismissCookieBanner() {
gtag('consent', 'update', { 'ad_storage': 'denied', 'analytics_storage': 'denied' });};
</script>
<!-- Cookie Consent Banner -->
</head>
HTML
<div role="region" aria-label="cookie-consent-banner" id="cookie-banner">
<div class="cookie-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
<div class="cookie-buttons">
<button type="button" class="accept-cookies" onclick="consentGranted()">Accept</button>
<button type="button" class="dismiss-cookies" onclick="dismissCookieBanner()">Dismiss</button>
</div>
</div>
JAVASCRIPT
function consentGranted() {
var cookieConsentBanner = $('#cookie-banner');
if ( cookieConsentBanner.length ) {
if ( Cookies.get('CUSTOM_COOKIE') != 'true' ) {
var acceptCookieButton= cookieConsentBanner.find('.cookie-buttons .accept-cookies');
acceptCookieButton.on('click', function() {
Cookies.set( 'CUSTOM_COOKIE', 'true', { expires: 365 } );
cookieConsentBanner.remove();
});
};
};
};
function dismissCookieBanner() {
var cookieConsentBanner = $('#cookie-banner');
var dismissCookieBanner= cookieConsentBanner.find('.cookie-buttons .dismiss-cookies');
dismissCookieBanner.on('click', function() {
cookieConsentBanner.remove();
});
};

I would recommend using localStorage to store the cookie consent data, and then once the page loads, put the banner onscreen if no answer was given, else, not place it. Example:
function consentGranted() {
localStorage.setItem('consent', true)
var cookieConsentBanner = $('#cookie-banner');
if ( cookieConsentBanner.length ) {
if ( Cookies.get('CUSTOM_COOKIE') != 'true' ) {
var acceptCookieButton= cookieConsentBanner.find('.cookie-buttons .accept-cookies');
acceptCookieButton.on('click', function() {
Cookies.set( 'CUSTOM_COOKIE', 'true', { expires: 365 } );
cookieConsentBanner.remove();
});
};
};
};
function dismissCookieBanner() {
localStorage.setItem('consent', false)
var cookieConsentBanner = $('#cookie-banner');
var dismissCookieBanner= cookieConsentBanner.find('.cookie-buttons .dismiss-cookies');
dismissCookieBanner.on('click', function() {
cookieConsentBanner.remove();
});
};
document.getElementById('cookie-banner').hidden = localStorage.getItem('consent') != null
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<head>
<!-- Cookie Consent Banner -->
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {dataLayer.push(arguments);}
gtag('consent', 'default', { 'ad_storage': 'denied', 'analytics_storage': 'denied' });
</script>
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'TAG_ID');
</script>
<script>
function consentGranted() {
gtag('consent', 'update', { 'ad_storage': 'granted', 'analytics_storage': 'granted' });};
</script>
<script>
function dismissCookieBanner() {
gtag('consent', 'update', { 'ad_storage': 'denied', 'analytics_storage': 'denied' });};
</script>
<!-- Cookie Consent Banner -->
</head>
<h1>My site</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Dui vivamus arcu felis bibendum ut tristique et egestas quis. Nunc consequat interdum varius sit amet. Ac odio tempor orci dapibus. Eu consequat ac felis donec et odio pellentesque diam. Faucibus nisl tincidunt eget nullam. Aenean et tortor at risus viverra adipiscing at in. Lacinia at quis risus sed vulputate odio ut enim. Sagittis eu volutpat odio facilisis mauris sit amet massa. Maecenas volutpat blandit aliquam etiam erat velit scelerisque. Vitae tempus quam pellentesque nec nam. Vitae proin sagittis nisl rhoncus mattis rhoncus urna.
</p>
<div role="region" aria-label="cookie-consent-banner" id="cookie-banner">
<div class="cookie-text">Do you accept the cookie policy?</div>
<div class="cookie-buttons">
<button type="button" class="accept-cookies" onclick="consentGranted()">Accept</button>
<button type="button" class="dismiss-cookies" onclick="dismissCookieBanner()">Dismiss</button>
</div>
</div>
JSFiddle

Related

Is it possible to change an attribute value from another html file?

So I have a website right now and I want to change the aria-expanded value of an exapandable paragraph in another page when I press an anchor element in the main page. What will I need to change in my main.html so i can somehow change the aria-expanded value on the help.html file?
main.html
<a href="help">
<h2>Returns Policy</h2>
</a>
help.html
<div class="accordion-item">
<button id="accordion-button-3" aria-expanded="false"><span
class="accordion-title">Returns Policy</span><span
class="icon" aria-hidden="true"></span></button>
<div class="accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Elementum sagittis vitae et
leo duis ut. Ut tortor pretium viverra suspendisse potenti.
</p>
</div>
</div>
//and this is the script used to expand the paragraph
const items = document.querySelectorAll(".accordion button");
function toggleAccordion() {
const itemToggle = this.getAttribute('aria-expanded');
for (i = 0; i < items.length; i++) {
items[i].setAttribute('aria-expanded', 'false');
}
if (itemToggle == 'false') {
this.setAttribute('aria-expanded', 'true');
}
}
items.forEach(item => item.addEventListener('click', toggleAccordion));
your button id is "accordion-button-3" so in querySeletorAll you need "#accordion-button-3"
const items = document.querySelectorAll("#accordion-button-3");

Is there an option in CSS or JS to force single-character words at the end of a line to move to the next one?

While creating a responsive web design it often happens that a one-letter word remains as the last word in a paragraph's line:
This is a
paragraph
I would like to move such a single-letter word as follows:
This is
a paragraph
Is there any built-in property in CSS which allows to achieve this effect?
If there is none, how can this be done in JavaScript?
If you want to ALWAYS keep "a" and "paragraph" together, add a "non-breaking-space" between them:
<div style="width:100px;border:1px solid #333;padding:5px">
<p>
This is a paragraph
</p>
</div>
In order to keep single-letter words (like 'a' or 'I') on the same line as the following word, you can replace the space character between them with the non-breaking space Unicode character \u00A0.
This could be automated with a little JavaScript. For example, this code replaces [space][letter][space] with [space][letter][non-breaking space]:
const modifySingleChars = str => str.replace(/ ([a-zA-Z]) /g,
' $1' + '\u00A0');
To change all instances on a page, first collect all the text nodes within the body (skipping anything inside a <script> tag.
Then simply iterate through the text nodes, making the appropriate substitutions.
A working example:
// form array of all text nodes in parentNode
function allTextNodes(parentNode) {
let arr = [];
if (!parentNode) {
return arr;
}
let nodes = parentNode.childNodes;
nodes.forEach(node => {
if (node.nodeName === 'SCRIPT') {
return;
}
if (node.nodeType === Node.TEXT_NODE) {
arr.push(node);
} else {
arr = arr.concat(allTextNodes(node));
}
});
return arr;
}
// convert [space][letter][space] to [space][letter][non-breaking space];
const modifySingleCharWords = str => str.replace(/ ([a-zA-Z]) /g,
' $1' + '\u00A0');
function fixAllSingleCharWordsInBody() {
let tNodes = allTextNodes(document.body);
tNodes.forEach(tNode => {
tNode.nodeValue = modifySingleCharWords(tNode.nodeValue);
});
}
<body>
<div id="wrapper" style="width:20rem">
<h4>Prevent single character words at end of line</h4>
<button type="button" onclick="fixAllSingleCharWordsInBody();">Fix All Words
</button>
<p>Lorem ipsum dolor i amet, consectetur a dipiscing elit, sed o eiusmod tempor incididunt u labore et dolore magna aliqua. <span>Nisl purus i mollis</span> nunc.
</p>
<p>In vitae turpis massa e elementum tempusus a sed. Eget mi proin e libero enim i faucibus. Quis lectus nulla a volutpat diam ut.
</p>
<p>Pharetra e ultrices neque ornare. Donec a tristique risus e feugiat in fermentum. Consectetur adipiscing e u aliquam purus sit amet.
</p>
<p>Vitae congue mauris rhoncus aenean e elit scelerisque mauris pellentesque. Mauris u eros i cursus turpis a tincidunt dui.
</p>
<p>At volutpat diam u venenatis tellus. Tellus integer feugiat scelerisque varius morbi i nunc faucibus at.</p>
<script>
const b = 'Do not modify anything inside a script tag';
</script>
</div>
</body>
from few years we have ES6 so...
[...document.body.querySelectorAll('*')]
.map(n => n.firstChild)
.filter(n => (n != null && n.nodeType === Node.TEXT_NODE && !['SCRIPT', 'STYLE'].includes(n.parentNode.nodeName)))
.forEach(el => {
el.nodeValue = el.nodeValue.replace(/ ([a-zA-Z]) /g, ` $1\u00A0`)
});
document.body can be replaced by any node, here is for simplicity

Combining functions to one button

I would like to have a single button that says, "Viewer One" and is tied to a section with the ID, "viewer_one". When the user clicks the button, I would like it to change to show, "Viewer Two" and also show the section with the ID "viewer_two" in place of where the other nav had been. Each time the button is clicked it will switch to the other.
I have two sets of script that perform each function individually, but I cannot figure out how to make them work at same time. At moment, I can either have a button that changes its value on click but does not impact the rest of the code or I can have the button impact the rest of the code but its own text does not change.
I have included my code below - I have included both sets of javascript so that you can see what I have but they only work when I include one or the other - I need help figuring out how to get them to work together.
Below is a condensed version of the code to the pertinent parts - the main code has several more list items for each viewer.
<!-- this gets the button click to change which list is visible-->
function switchVisible() {
if (document.getElementById('viewer_one')) {
if (document.getElementById('viewer_one').style.display == 'none') {
document.getElementById('viewer_one').style.display = 'block';
document.getElementById('viewer_two').style.display = 'none';
}
else {
document.getElementById('viewer_one').style.display = 'none';
document.getElementById('viewer_two').style.display = 'block';
}
}
}
<!--This gets the button text to change-->
function myFunction() {
var x = document.getElementById("Button1");
if (x.innerHTML === "Viewer Two") {
x.innerHTML = "Viewer One";
} else {
x.innerHTML = "Viewer Two";
}
}
<section id="second_nav">
<input id="Button1" type="button" value="Viewer One" onclick="switchVisible();"/>
<button id="Button1" onclick="myFunction()">Viewer One</button>
<nav class="viewer_nav" id="viewer_one">
<ul>
<li style="color: blue;"><b>VIEWER ONE:</b></li>
<li>Client Info</li>
<li>Scripts</li>
</ul>
</nav>
<nav class="viewer_nav" id="viewer_two">
<ul>
<li style="color: blue;"><b>VIEWER TWO:</b></li>
<li>Client Info</li>
<li>Scripts</li>
</ul>
</nav>
</section>
<div id="content_area">
<section class="viewer_class" id="view_area_one">
<h3 class="viewer_title" style="text-align: center;">VIEWER ONE</h3>
<span id="client1"></span>
<h4>Client Info</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<span id="scripts1"></span>
<h4>Scripts</h4>
<p>Et odio pellentesque diam volutpat. Vulputate eu scelerisque felis imperdiet proin. Turpis in eu mi bibendum neque.</p>
</section>
<section class="viewer_class" id="view_area_two">
<h3 class="viewer_title" style="text-align: center;">VIEWER TWO</h3>
<span id="client2"></span>
<h4>Client Info</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<span id="scripts2"></span>
<h4>Scripts</h4>
<p>Et odio pellentesque diam volutpat. Vulputate eu scelerisque felis imperdiet proin. Turpis in eu mi bibendum neque.</p>
</section>
No error messages, but I can only get one or the other to work, not in combination.
Thanks in advance for any help.
var currentViewer = 1
updatePage(currentViewer)
function switchViewer() {
if (currentViewer === 1) {
currentViewer = 2
} else if (currentViewer === 2) {
currentViewer = 1
}
updatePage(currentViewer)
}
function updatePage(viewer) {
switch(viewer) {
case 1:
document.getElementById('viewer_one').style.display = 'block';
document.getElementById('viewer_two').style.display = 'none';
document.getElementById('view_area_one').style.display = 'block';
document.getElementById('view_area_two').style.display = 'none';
document.getElementById('switchViewerButton').innerHTML = "Viewer 2"
break;
case 2:
document.getElementById('viewer_one').style.display = 'none';
document.getElementById('viewer_two').style.display = 'block';
document.getElementById('view_area_one').style.display = 'none';
document.getElementById('view_area_two').style.display = 'block';
document.getElementById('switchViewerButton').innerHTML = "Viewer 1"
break;
}
}
<section id="second_nav">
<button id="switchViewerButton" onclick="switchViewer()">Viewer One</button>
<nav class="viewer_nav" id="viewer_one">
<ul>
<li style="color: blue;"><b>VIEWER ONE:</b></li>
<li>Client Info</li>
<li>Scripts</li>
</ul>
</nav>
<nav class="viewer_nav" id="viewer_two">
<ul>
<li style="color: blue;"><b>VIEWER TWO:</b></li>
<li>Client Info</li>
<li>Scripts</li>
</ul>
</nav>
</section>
<div id="content_area">
<section class="viewer_class" id="view_area_one">
<h3 class="viewer_title" style="text-align: center;">VIEWER ONE</h3>
<span id="client1"></span>
<h4>Client Info (view_area_one)</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<span id="scripts1"></span>
<h4>Scripts</h4>
<p>Et odio pellentesque diam volutpat. Vulputate eu scelerisque felis imperdiet proin. Turpis in eu mi bibendum neque.</p>
</section>
<section class="viewer_class" id="view_area_two">
<h3 class="viewer_title" style="text-align: center;">VIEWER TWO</h3>
<span id="client2"></span>
<h4>Client Info (view_area_two)</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Some other text...</p>
<span id="scripts2"></span>
<h4>Scripts From V2</h4>
<p>Et odio pellentesque diam volutpat. Vulputate eu scelerisque felis imperdiet proin. Turpis in eu mi bibendum neque.</p>
</section>
Here's my version - I separated out the logic for controlling which viewer is currently visible from the code that changes the DOM, so you can more directly see how the current viewer changes the content of the page. I also didn't fully understand what you wanted to change on the button press, I've made it a content toggle as that seemed to be what you were going for? Your example only toggles the navbar. Let me know how this suits you.
So, If you want both to work together, write your javascript code as:
<!-- this gets the button click to change which list is visible-->
function switchVisible() {
<!-- Your Code -->
}
<!--This gets the button text to change-->
function myFunction() {
<!-- Your Code -->
}
<!-- My Code -->
window.onload = function(){
const button = document.querySelector("#switchViewerButton");
if (button) {
button.onclick = function(event){
event.preventDefault();
switchVisible();
myFunction();
}
}
}
And Replace the HTML line
<button id="switchViewerButton" onclick="switchViewer()">Viewer One</button>
with the line
<button id="switchViewerButton">Viewer One</button>
I hope it should work. Please comment if you face any problem in implementing the solution.

Load html page for this tabbed angularjs page

I found this jsfiddle sample code which is provides multiple tabs for a single angularjs webapge.
http://jsfiddle.net/helpme128/99z393hn/
I adapted it to my own code. I wanted a certain tab to load a certain webpage my-custom-page.html.
Here are my relevant code. The html code;
<div id="tabs" ng-controller="StkViewMainCtrl">
<ul>
<li ng-repeat="tab in tabs"
ng-class="{active:isActiveTab(tab.url)}"
ng-click="onClickTab(tab)">{{tab.title}}
</li>
</ul>
<div id="mainView">
<div ng-include="currentTab"></div>
</div>
</div>
<script type="text/ng-template" id="one.tpl.html">
<div id="viewOne">
<h1>View One</h1>
<p>Praesent id metus massa, ut blandit odio. Proin quis tortor orci. Etiam at risus et justo dignissim
congue. Donec congue lacinia dui, a porttitor lectus condimentum laoreet. Nunc.</p>
</div>
</script>
<script type="text/ng-template" id="my-custom-page.html">
<div id="viewTwo">
<h1>View Two</h1>
<p>Curabitur vulputate, ligula lacinia scelerisque tempor, lacus lacus ornare ante, ac egestas est urna sit
amet arcu. Class aptent taciti sociosqu.</p>
</div>
</script>
The controller code;
.controller('StkViewMainCtrl', ['$scope', 'configuration',
function ($scope, $configuration) {
$scope.tabs = [{
title: 'One',
url: 'one.tpl.html'
}, {
title: 'Two',
url: 'my-custom-page.html'
}, {
title: 'Three',
url: 'three.tpl.html'
}];
$scope.currentTab = 'one.tpl.html';
$scope.onClickTab = function (tab) {
$scope.currentTab = tab.url;
}
$scope.isActiveTab = function(tabUrl) {
return tabUrl == $scope.currentTab;
}
}]);
No effect took place. my-custom-page.html does not load. my-custom-page.html is on the same folder as the single webpage that is being run.
Html is loading from main page, so if you want to load html from another html file in folder you should use something like ng-include.
So try to change
<script type="text/ng-template" id="my-custom-page.html">
<div id="viewTwo">
<h1>View Two</h1>
<p>Curabitur vulputate, ligula lacinia scelerisque tempor, lacus lacus ornare ante, ac egestas est urna sit
amet arcu. Class aptent taciti sociosqu.</p>
</div>
to
<script type="text/ng-template" id="my-custom-page.html">
<div id="viewTwo" ng-include="my-custom-page.html"></div>
i changed a code and here is a new code on plunker

add value to existing class in jQuery

First of all, I have searched quite some hours to find this.. I presume it has an easy fix but I'm really new to jQuery and Javascript, so I'm here for your help.
The problem
I'm working with multiple divs and jQuery ToggleSlide(). I want the script to find the right div to open when I click the corresponding div.
For example, when I click the div 'hackandfly', I want it to open the div 'hackandfly-open'.
The code
$(document).ready(function() {
$('.project-open').hide();
$('.hackandfly, .scanergy, .connecting-food').click(function() {
$slidah = $(this);
$slidah.slideToggle();
$('div.project-open').not($slidah).slideUp();
});
});
HTML
<div class="content projects">
<h3>Projects</h3>
<div class="project project-big hackandfly">
<h3>Hack and Fly</h3>
</div>
<div class="hackandfly-open project-open" style="display: none;">
<img src="images/schiphol-logo.png" class="img-project-open"> Proin nec elit ac sapien facilisis ultrices. Integer pellentesque ex a luctus fringilla. Aenean in quam quam. Integer gravida quam eget mauris laoreet hendrerit. Vestibulum feugiat ipsum id.
<br>
<br>
Metus aliquet iaculis. Proin massa justo, maximus in tortor et, Proin massa justo, maximus in tortor et. In aliquam laoreet magna et iaculis. Vestibulum vel orci lobortis, elementum nulla eget, porta eros. Interdum et malesuada fames ac ante ipsum primis in faucibus.
<br>
<br>
Proin massa justo, maximus in tortor et, tincidunt efficitur nibh. Mauris vulputate euismod lorem, vel rutrum ipsum iaculis eu.
</div>
So what I'm looking for, is that when I push 'hackandfly' div, 'scanergy' div or the 'connecting-food' div, I want it to slideToggle the corresponding div that has -open behind it (I have 3 divs with info called hackandfly-open, scanergy-open, connecting-food-open).
I tried some things like:
$slidah = $(this).after('-open');
And some other stuff but it didn't work. Who can help me?
Cheers!
Use attr() like
$(document).ready(function() {
$('.project-open').hide();
$('.hackandfly, .scanergy, .connecting-food').click(function() {
$slidah = $($(this).attr('class')+'-open');
$slidah.slideToggle();
$('div.project-open').not($slidah).slideUp();
});
});
However, the above will fail if you have multiple classes.
A workaround would be to add data-* to the clicked elements like
<div class="hackandfly other-class" data-class-target="hackandfly-open"></div>
and then
$(document).ready(function() {
$('.project-open').hide();
$('.hackandfly, .scanergy, .connecting-food').click(function() {
$slidah = $('.'+$(this).attr('data-class-target'));
$slidah.slideToggle();
$('div.project-open').not($slidah).slideUp();
});
});
I would generate a unique click handler for each class. That way, you can store all the applicable class names in an array:
// Creates a new unique click function for each class name
function generateClickHandler(className) {
return function(e) {
// select the open class here
$slidah = $('.'+className+'-open');
$slidah.slideToggle();
$('div.project-open').not($slidah).slideUp();
};
}
// Iterate over all the class names and add a new function for each
var clsList = ["hackandfly", "scanergy", "connecting-food"];
$.each(clsList, function(className) {
$("."+className).click(generateClickHandler(className));
});
Use:
$('.hackandfly, .scanergy, .connecting-food').click(function() {
$slidah = $("."+$(this).attr('class')+"-open");
$slidah.slideToggle();
});
If you added a wrapper around each section like so:
<div class="content projects">
<h3>Projects</h3>
<div class="project-wrapper">
<div class="project project-big hackandfly">
<h3>Hack and Fly</h3>
</div>
<div class="hackandfly-open project-open" style="display: none;">
{...}
</div>
</div>
</div>
you could use parent and find to get the corresponding element as follows:
$('.hackandfly, .scanergy, .connecting-food').click(function() {
$(this).parent().find('.project-open').eq(0).slideToggle();
}

Categories

Resources