diff --git a/themes/custom/ts_wrin/js/components/wri_cta_banners.js b/themes/custom/ts_wrin/js/components/wri_cta_banners.js new file mode 100644 index 000000000..db0adc694 --- /dev/null +++ b/themes/custom/ts_wrin/js/components/wri_cta_banners.js @@ -0,0 +1,135 @@ +/** + * @file + * + * WRI CTA Banners - random with a thank you message. + */ + +export default function(context) { + const modals = context.querySelectorAll(".region-top-modals .block-modal"); + const ctaCookie = "wri_cta_displayed"; + const thankYouCookie = "wri_cta_thank_you"; + + // Accessibility: aria-live region for announcements + const announceRegion = document.createElement("div"); + announceRegion.setAttribute("aria-live", "assertive"); + announceRegion.setAttribute("role", "alert"); + announceRegion.style.position = "absolute"; + announceRegion.style.left = "-9999px"; + document.body.appendChild(announceRegion); + + function announce(message) { + announceRegion.textContent = ""; + // Timeout ensures the message is re-announced when modal changes. + setTimeout(() => { + announceRegion.textContent = message; + }, 100); + } + + function getCookie(name) { + const value = `; ${document.cookie}`; + const parts = value.split(`; ${name}=`); + return parts.length === 2 + ? parts + .pop() + .split(";") + .shift() + : null; + } + + function setCookie(name, value, days) { + const date = new Date(); + date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); + document.cookie = `${name}=${value}; expires=${date.toUTCString()}; path=/`; + } + + function closeModal(modal) { + modal.style.display = "none"; + setCookie( + getCookie(thankYouCookie) ? thankYouCookie : ctaCookie, + "true", + 1 + ); + document.removeEventListener("keydown", closeOnEscape); + document.removeEventListener("click", clickOutsideModal); + announce("Modal closed."); + } + + function closeOnEscape(event) { + if (event.key === "Escape") { + const visibleModal = context.querySelector( + '.block-modal[style*="display: block"]' + ); + if (visibleModal) closeModal(visibleModal); + } + } + + function clickOutsideModal(event) { + const visibleModal = context.querySelector( + '.block-modal[style*="display: block"]' + ); + if ( + visibleModal && + !visibleModal.querySelector(".modal_inner").contains(event.target) + ) { + closeModal(visibleModal); + } + } + + function showModal(modal) { + modal.style.display = "block"; + modal.querySelector(".modal-close").addEventListener("click", function() { + closeModal(modal); + }); + document.addEventListener("keydown", closeOnEscape); + document.addEventListener("click", clickOutsideModal); + announce( + "A message for you: " + + modal.querySelector(".field--name-field-title").textContent + ); + } + + function displayThankYouModal() { + const thankYouMessage = document.createElement("div"); + thankYouMessage.classList.add("block-modal", "thank-you-modal"); + thankYouMessage.innerHTML = ` + `; + document.body.appendChild(thankYouMessage); + showModal(thankYouMessage); + } + + function displayRandomModal() { + if (!modals.length) return; + const randomIndex = Math.floor(Math.random() * modals.length); + const selectedModal = modals[randomIndex]; + selectedModal.setAttribute("role", "dialog"); + selectedModal.setAttribute("aria-labelledby", "modalTitle"); + selectedModal.setAttribute("aria-describedby", "modalMessage"); + if (selectedModal.querySelector(".field--name-field-title")) { + selectedModal.querySelector(".field--name-field-title").id = "modalTitle"; + } + if (selectedModal.querySelector(".field--name-field-intro")) { + selectedModal.querySelector(".field--name-field-intro").id = + "modalMessage"; + } + showModal(selectedModal); + } + + const classyCookie = getCookie("classy_donation"); + const hasDonated = classyCookie && classyCookie === "true"; + + if (!getCookie(thankYouCookie) && hasDonated) { + displayThankYouModal(); + } else if (!getCookie(ctaCookie)) { + displayRandomModal(); + } +} diff --git a/themes/custom/ts_wrin/js/main.js b/themes/custom/ts_wrin/js/main.js index dad6148e8..9288c974f 100644 --- a/themes/custom/ts_wrin/js/main.js +++ b/themes/custom/ts_wrin/js/main.js @@ -12,6 +12,7 @@ import wriMaps from "./components/wri_maps.js"; import wriModals from "./components/wri_modals.js"; import wriMoreOn from "./components/wri_more_on.js"; import wriMedia from "./components/wri_media.js"; +import wriCtaBanners from "./components/wri_cta_banners.js"; import tsExternalLinks from "./components/ts_external_links.js"; (($, Drupal) => { @@ -54,6 +55,10 @@ import tsExternalLinks from "./components/ts_external_links.js"; attach: wriMoreOn }; + Drupal.behaviors.wriCtaBanners = { + attach: wriCtaBanners + }; + Drupal.behaviors.wriMedia = { attach: wriMedia }; diff --git a/themes/custom/ts_wrin/sass/components/_popup_modal.scss b/themes/custom/ts_wrin/sass/components/_popup_modal.scss index 3e5e03ef5..9d95dd608 100644 --- a/themes/custom/ts_wrin/sass/components/_popup_modal.scss +++ b/themes/custom/ts_wrin/sass/components/_popup_modal.scss @@ -2,6 +2,51 @@ display: none; } +.region-top-modals .block-modal { + display: none; + z-index: 100; + button.ui-button { + all: unset; + display: block; + height: 30px; + overflow: hidden; + position: absolute; + right: 10px; + text-indent: -9999px; + top: 10px; + width: 30px; + + .ui-icon-closethick { + all: unset; + + &:after, + &:before { + background-color: $white; + content: ""; + height: 100%; + left: 50%; + position: absolute; + top: 50%; + transition: background-color $transition-defaults; + width: 3px; + } + &:after { + transform: translate(-50%, -50%) rotate(-45deg); + } + &:before { + transform: translate(-50%, -50%) rotate(45deg); + } + } + &:hover, + &:focus { + .ui-icon-closethick:before, + .ui-icon-closethick:after { + background-color: $gold-hover; + } + } + } +} + .block-modal, .simple-popup-blocks-global { @include font($acumin-semi-cond, "light"); @@ -9,6 +54,7 @@ &.has-blue-background-color, &.has-green-background-color, + &.has-teal-background-color, &.has-black-background-color { color: $white; diff --git a/themes/custom/ts_wrin/templates/blocks/block--bundle--modal.html.twig b/themes/custom/ts_wrin/templates/blocks/block--bundle--modal.html.twig index 624034d82..58720d2f6 100644 --- a/themes/custom/ts_wrin/templates/blocks/block--bundle--modal.html.twig +++ b/themes/custom/ts_wrin/templates/blocks/block--bundle--modal.html.twig @@ -1,26 +1,7 @@ {# /** * @file - * Theme override to display a block. - * - * Available variables: - * - plugin_id: The ID of the block implementation. - * - label: The configured label of the block if visible. - * - configuration: A list of the block's configuration values. - * - label: The configured label for the block. - * - label_display: The display settings for the label. - * - provider: The module or other provider that provided this block plugin. - * - Block plugin specific settings will also be stored here. - * - content: The content of this block. - * - attributes: array of HTML attributes populated by modules, intended to - * be added to the main container tag of this template. - * - id: A valid HTML ID and guaranteed unique. - * - title_attributes: Same as attributes, except applied to the main title - * tag that appears in the template. - * - title_prefix: Additional output populated by modules, intended to be - * displayed in front of the main title tag that appears in the template. - * - title_suffix: Additional output populated by modules, intended to be - * displayed after the main title tag that appears in the template. + * Theme override to display a modal block. * * @see template_preprocess_block() */ @@ -43,7 +24,8 @@ {{ content.field_image_full_width }} {% endif %} - +