media/js/base/consent/init.es6.js (116 lines of code) (raw):

/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import MozConsentBanner from '@mozmeao/consent-banner'; import { consentRequired, dntEnabled, getConsentCookie, getConsentState, gpcEnabled, hasConsentCookie, isURLExceptionAllowed, isURLPermitted } from './utils.es6'; const banner = document.querySelector('.moz-consent-banner'); const footer = document.getElementById('colophon'); /** * Helper to debounce a function. * @param {Function} func - Function to debounce. * @param {Number} delay - The delay in milliseconds. * @returns */ function debounce(func, delay) { let timer; return function () { clearTimeout(timer); timer = setTimeout(() => { func.apply(this, arguments); }, delay); }; } /** * Adds extra padding to the page footer to prevent the banner * from overlapping. */ function updateBodyPadding() { if (!footer) { return; } if (window.innerHeight > 600) { footer.style.paddingBottom = banner.offsetHeight + 'px'; } else { footer.style.paddingBottom = '0px'; } } const onResize = debounce(updateBodyPadding, 200); /** * If user clicks back button from /cookie-settings/ and * the page is in bfcache, reload the page if they have * set a consent cookie to avoid showing the banner again * inadvertently. * @param {Object} e - The page navigation event. */ function handleBfCacheNavigation(e) { if (e.persisted && hasConsentCookie()) { window.location.reload(); } } /** * Opens the consent banner and binds button click event listeners. */ function openBanner() { // Bind event listeners document .getElementById('moz-consent-banner-button-accept') .addEventListener('click', MozConsentBanner.onAcceptClick, false); document .getElementById('moz-consent-banner-button-reject') .addEventListener('click', MozConsentBanner.onRejectClick, false); window.addEventListener('pageshow', handleBfCacheNavigation, false); // Show banner document.getElementById('moz-consent-banner').classList.add('is-visible'); // Add padding to the footer setTimeout(updateBodyPadding, 0); window.addEventListener('resize', onResize, false); } /** * Close the consent banner and unbinds button click event listeners. */ function closeBanner() { // Unbind event listeners document .getElementById('moz-consent-banner-button-accept') .removeEventListener('click', MozConsentBanner.onAcceptClick, false); document .getElementById('moz-consent-banner-button-reject') .removeEventListener('click', MozConsentBanner.onRejectClick, false); window.removeEventListener('pageshow', handleBfCacheNavigation, false); // Hide banner document .getElementById('moz-consent-banner') .classList.remove('is-visible'); // Remove padding from the footer document.body.style.paddingBottom = '0'; window.removeEventListener('resize', onResize, false); } /** * Initialize the consent banner and bind open and close events. */ function initializeBanner() { // Make sure to bind open and close events before calling init(). window.addEventListener('mozConsentOpen', openBanner, false); window.addEventListener('mozConsentClose', closeBanner, false); MozConsentBanner.init({ helper: window.Mozilla.Cookies }); } /** * Helper function to dispatch the mozConsentStatus event. * @param {Object} consent - The consent object. */ function dispatchEvent(consent) { MozConsentBanner.dispatchEvent('mozConsentStatus', consent); } /** * Initialize the consent banner based on the current state. */ function init() { const state = getConsentState({ hasConsentCookie: hasConsentCookie(), gpcEnabled: gpcEnabled(), dntEnabled: dntEnabled(), consentRequired: consentRequired(), isURLExceptionAllowed: isURLExceptionAllowed(window.location.search), isURLPermitted: isURLPermitted(window.location.pathname) }); switch (state) { case 'STATE_GPC_ENABLED': case 'STATE_DNT_ENABLED': { /** * If GPC or DNT are enabled we interpret this as a * rejection signal for cookie and analytics. As such, * we do not show a consent banner and no not load * analytics that require opt-in. */ break; } case 'STATE_HAS_CONSENT_COOKIE': { const cookie = getConsentCookie(); if (cookie) { dispatchEvent(cookie); } break; } case 'STATE_SHOW_COOKIE_BANNER': { initializeBanner(); break; } case 'STATE_COOKIES_PERMITTED': { dispatchEvent({ analytics: true, preference: true }); break; } default: break; } // Global helper function to get consent state for debugging purposes. if (typeof window.Mozilla !== 'undefined') { window.Mozilla.getConsentStateMsg = () => { return state; }; } } init();