1document.addEventListener("DOMContentLoaded", function () { 2 // --- Load YouTube IFrame API (non-blocking) 3 var tag = document.createElement('script'); 4 tag.src = "https://www.youtube.com/iframe_api"; 5 var firstScriptTag = document.getElementsByTagName('script')[0]; 6 if (firstScriptTag && firstScriptTag.parentNode) { 7 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 8 } else { 9 document.head.appendChild(tag); 10 } 11 12 // --- Helpers 13 function setCookie(name, value, days) { 14 var expires = ""; 15 if (days) { 16 var date = new Date(); 17 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 18 expires = "; expires=" + date.toUTCString(); 19 } 20 document.cookie = name + "=" + (value || "") + expires + "; path=/"; 21 } 22 23 function getCookie(name) { 24 var nameEQ = name + "="; 25 var ca = document.cookie.split(';'); 26 for (var i = 0; i < ca.length; i++) { 27 var c = ca[i]; 28 while (c.charAt(0) === ' ') c = c.substring(1, c.length); 29 if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); 30 } 31 return null; 32 } 33 34 function playVideo(modal) { 35 var iframe = modal.querySelector('iframe'); 36 if (!iframe) return; 37 38 if (iframe.src.includes('player.vimeo.com')) { 39 iframe.contentWindow.postMessage('{"method":"play"}', '*'); 40 } else if (iframe.src.includes('youtube.com') || iframe.src.includes('youtu.be')) { 41 if (!iframe.src.includes('autoplay=1')) { 42 iframe.src += (iframe.src.includes('?') ? '&' : '?') + 'autoplay=1'; 43 } 44 iframe.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 45 } 46 } 47 48 function stopVideos(modal) { 49 var iframes = modal.querySelectorAll('iframe'); 50 iframes.forEach(function (iframe) { 51 if (iframe.src.includes('player.vimeo.com')) { 52 iframe.contentWindow.postMessage('{"method":"pause"}', '*'); 53 } else if (iframe.src.includes('youtube.com') || iframe.src.includes('youtu.be')) { 54 iframe.contentWindow.postMessage('{"event":"command","func":"stopVideo","args":""}', '*'); 55 iframe.src = iframe.src.replace('autoplay=1', ''); 56 } 57 }); 58 } 59 60 function openModal(modal) { 61 if (!modal) return; 62 modal.style.display = "flex"; 63 modal.classList.add('show-modal'); 64 playVideo(modal); 65 } 66 67 function closeModal(modal) { 68 if (!modal) return; 69 modal.style.display = "none"; 70 modal.classList.remove('show-modal'); 71 stopVideos(modal); 72 } 73 74 // --- Global close handlers 75 window.addEventListener('click', function (event) { 76 if (event.target.classList && event.target.classList.contains('modal')) { 77 closeModal(event.target); 78 } 79 }); 80 81 // Delegate close button clicks (covers legacy & new) 82 document.addEventListener('click', function (e) { 83 var closeEl = e.target.closest('.close'); 84 if (!closeEl) return; 85 var modal = closeEl.closest('.modal'); 86 if (modal) { 87 e.preventDefault(); 88 closeModal(modal); 89 } 90 }); 91 92 // ================================ 93 // NEW SYSTEM: .popup-wrapper support 94 // ================================ 95 var wrappers = document.querySelectorAll('.popup-wrapper'); 96 wrappers.forEach(function (wrapper, index) { 97 var triggerType = wrapper.dataset.trigger || 'button'; 98 var delay = parseInt(wrapper.dataset.delay, 10) || 0; 99 var scrollPercent = parseInt(wrapper.dataset.scroll, 10) || 0; 100 var freqCap = parseInt(wrapper.dataset['frequencyCap'], 10) || 0; 101 var popupKey = wrapper.dataset.key || ''; 102 103 // Locate modal by key if provided (global), else fallback to inner modal 104 var modal = null; 105 if (popupKey) { 106 modal = document.querySelector('.modal.' + popupKey); 107 } 108 if (!modal) { 109 modal = wrapper.querySelector('.modal'); 110 } 111 if (!modal) return; // nothing to do 112 113 // Frequency cap (per wrapper/key) 114 var cookieKey = 'popupShown_' + (popupKey || ('wrapper_' + index)); 115 if (freqCap > 0 && getCookie(cookieKey)) return; 116 117 // Find a trigger button inside wrapper (supports legacy + modern) 118 var btn = wrapper.querySelector('[class*="popup-btn-"] a, .wp-block-button a, .wp-element-button'); 119 120 if (triggerType === 'button' && btn) { 121 btn.addEventListener('click', function (e) { 122 e.preventDefault(); 123 openModal(modal); 124 if (freqCap > 0) setCookie(cookieKey, 'true', freqCap); 125 }); 126 } 127 128 if (triggerType === 'immediate') { 129 openModal(modal); 130 if (freqCap > 0) setCookie(cookieKey, 'true', freqCap); 131 } 132 133 if (triggerType === 'timeDelay') { 134 setTimeout(function () { 135 openModal(modal); 136 if (freqCap > 0) setCookie(cookieKey, 'true', freqCap); 137 }, delay); 138 } 139 140 if (triggerType === 'scroll') { 141 function onScrollTrigger() { 142 var scrollTop = window.scrollY || document.documentElement.scrollTop; 143 var docHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight; 144 var scrolled = (docHeight > 0) ? (scrollTop / docHeight) * 100 : 0; 145 146 if (scrolled >= scrollPercent) { 147 openModal(modal); 148 if (freqCap > 0) setCookie(cookieKey, 'true', freqCap); 149 window.removeEventListener('scroll', onScrollTrigger); 150 } 151 } 152 window.addEventListener('scroll', onScrollTrigger); 153 } 154 }); 155 156 // ================================ 157 // LEGACY SYSTEM: no .popup-wrapper 158 // ================================ 159 document.addEventListener('click', function (e) { 160 var triggerEl = e.target.closest('[class*="popup-btn-"]'); 161 if (!triggerEl) return; 162 163 var legacyNum = null; 164 triggerEl.classList.forEach(function (cls) { 165 var m = cls.match(/^popup-btn-(\d+)$/); 166 if (m && m[1]) { legacyNum = m[1]; } 167 }); 168 if (!legacyNum) return; 169 170 var modal = document.querySelector('.popup-' + legacyNum); 171 if (!modal) return; 172 173 var clickable = e.target.closest('a, button'); 174 if (clickable) e.preventDefault(); 175 176 openModal(modal); 177 }); 178 179 // ================================ 180 // GRAVITY FORMS SUPPORT (NEW) 181 // Close modal & set cookie on successful form submission 182 // ================================ 183 document.addEventListener('gform_confirmation_loaded', function (event, formId) { 184 var formEl = document.getElementById('gform_' + formId); 185 if (!formEl) return; 186 187 var modal = formEl.closest('.modal'); 188 if (!modal) return; 189 190 var wrapper = modal.closest('.popup-wrapper'); 191 if (!wrapper) return; 192 193 var freqCap = parseInt(wrapper.dataset['frequencyCap'], 10) || 0; 194 var popupKey = wrapper.dataset.key || ''; 195 var index = Array.prototype.indexOf.call(document.querySelectorAll('.popup-wrapper'), wrapper); 196 var cookieKey = 'popupShown_' + (popupKey || ('wrapper_' + index)); 197 198 if (freqCap > 0) setCookie(cookieKey, 'true', freqCap); 199 closeModal(modal); 200 }); 201});
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.