1// Will hold previously focused element 2document.addEventListener('DOMContentLoaded', () => { 3 4 if (getCookie('newsletter-popup-shown') !== '') 5 { 6 return; 7 } 8 let newsletterOpen = false; 9 const scrollThreshold = 2200; 10 11 //get elements 12 const newsletterPopup = document.querySelector('#newsletter_popup'); 13 const overlay= document.querySelector('#popup_overlay'); 14 let focusedElementBeforeModal = document.activeElement; 15 const closeButton = document.querySelector('#newsletter_popup a.close'); 16 17 //add event to close button 18 closeButton.addEventListener('click', e => { 19 e.preventDefault(); 20 closeNewsletterPopup(); 21 }); 22 23 // scroll event throttling 24 let lastScrollPosition = 0, 25 tick = false; // Track whether call is currently in process 26 27 function checkScrollPos(scrollPos) { 28 if (scrollPos > scrollThreshold && !newsletterOpen && window.innerWidth > 780) 29 { 30 openNewsletterPopup(); 31 } 32 } 33 34 window.addEventListener('scroll', function(e) { 35 lastScrollPosition = window.scrollY; 36 if (!tick) { 37 setTimeout(function () { 38 checkScrollPos(lastScrollPosition); 39 tick = false; 40 }, 16) 41 } 42 tick = true; 43 }); 44 45 46 function openNewsletterPopup() { 47 48 newsletterOpen = true; 49 50 newsletterPopup.style.display = 'grid'; 51 overlay.style.display = 'block'; 52 53 // Save current focus 54 focusedElementBeforeModal = document.activeElement; 55 // Listen for and trap the keyboard 56 newsletterPopup.addEventListener('keydown', trapTabKey); 57 // Find all focusable children 58 let focusableElementsString = 'a[href], area[href], input:not([disabled]), input:not([tabindex="-1"]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]'; 59 let focusableElements = newsletterPopup.querySelectorAll(focusableElementsString); 60 focusableElements = Array.from(focusableElements); 61 let firstTabStop = focusableElements[0]; 62 let lastTabStop = focusableElements[focusableElements.length - 1]; 63 64 // Focus first child 65 firstTabStop.focus(); 66 67 function trapTabKey(e) { 68 // Check for TAB key press 69 if (e.keyCode === 9) { 70 71 // SHIFT + TAB 72 if (e.shiftKey) { 73 if (document.activeElement === firstTabStop) { 74 e.preventDefault(); 75 lastTabStop.focus(); 76 } 77 78 // TAB 79 } else { 80 if (document.activeElement === lastTabStop) { 81 e.preventDefault(); 82 firstTabStop.focus(); 83 } 84 } 85 } 86 87 // ESCAPE 88 if (e.keyCode === 27) { 89 closeNewsletterPopup(); 90 } 91 } 92 } 93 94 function closeNewsletterPopup() { 95 96 newsletterPopup.style.display = 'none'; 97 overlay.style.display = 'none'; 98 99 // Set focus back to element that had it before the modal was opened 100 focusedElementBeforeModal.focus(); 101 102 //store a cookie so that the user isn't bothered again 103 setCookie('newsletter-popup-shown', 'true', 28); 104 } 105 106 107 function setCookie(cname, cvalue, exdays) { 108 const d = new Date(); 109 d.setTime(d.getTime() + (exdays*24*60*60*1000)); 110 let expires = "expires="+ d.toUTCString(); 111 document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; 112 } 113 114 function getCookie(cname) { 115 let name = cname + "="; 116 let decodedCookie = decodeURIComponent(document.cookie); 117 let ca = decodedCookie.split(';'); 118 for(let i = 0; i <ca.length; i++) { 119 let c = ca[i]; 120 while (c.charAt(0) == ' ') { 121 c = c.substring(1); 122 } 123 if (c.indexOf(name) == 0) { 124 return c.substring(name.length, c.length); 125 } 126 } 127 return ""; 128 } 129 130}) 131
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.