1/** 2 * b247-newsletter.js 3 * 4 * Newsletter modal controller. The modal markup is printed in the footer on 5 * every view by b247_output_newsletter_modal() (inc/ui/newsletter-modal.php) 6 * and hosts the br247-newsletter plugin's Resend subscribe form. The form's 7 * submit â Resend flow is handled by the plugin's subscribe.js (loaded 8 * site-wide); this script only wires the open/close behaviour. 9 * 10 * Triggers: any element with [data-action="open-newsletter"] â the header 11 * envelope (patterns/header.php) and the in-article follow button 12 * (inc/article-render.php). 13 */ 14(function () { 15 'use strict'; 16 17 var modal = document.getElementById('b247-newsletter-modal'); 18 if (!modal) { return; } 19 20 var lastFocus = null; 21 22 /** 23 * Is the modal actually a dialog right now? 24 * 25 * newsletter-modal.css makes it `position: fixed`. If that stylesheet failed 26 * to load, the element is a plain static block at the foot of the document: 27 * unhiding it would show nothing while the scroll lock froze the page. This 28 * is computable while the element is still [hidden] â `display:none` does not 29 * erase the computed `position`. 30 */ 31 function isDialog() { 32 return window.getComputedStyle(modal).position === 'fixed'; 33 } 34 35 function openModal(trigger) { 36 if (!isDialog()) { 37 // Degrade to the /newsletter/ landing page rather than trap the reader. 38 var fallback = modal.getAttribute('data-fallback'); 39 if (fallback) { window.location.assign(fallback); } 40 return; 41 } 42 43 lastFocus = trigger || document.activeElement; 44 modal.hidden = false; 45 document.body.classList.add('b247-modal-open'); 46 47 var field = modal.querySelector('input[type="email"]') 48 || modal.querySelector('.b247-newsletter-close'); 49 if (field) { field.focus(); } 50 } 51 52 function closeModal() { 53 modal.hidden = true; 54 document.body.classList.remove('b247-modal-open'); 55 if (lastFocus && typeof lastFocus.focus === 'function') { lastFocus.focus(); } 56 lastFocus = null; 57 } 58 59 document.addEventListener('click', function (e) { 60 var target = e.target; 61 if (!target || typeof target.closest !== 'function') { return; } 62 63 var opener = target.closest('[data-action="open-newsletter"]'); 64 if (opener) { 65 e.preventDefault(); 66 openModal(opener); 67 return; 68 } 69 if (target.closest('[data-action="close-newsletter"]')) { 70 closeModal(); 71 } 72 }); 73 74 document.addEventListener('keydown', function (e) { 75 if (e.key === 'Escape' && !modal.hidden) { closeModal(); } 76 }); 77}());
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.