1(function ($) { 2 'use strict'; 3 4 function init() { 5 var cfg = window.MIGravityPopup || {}; 6 var overlay = document.getElementById('mi-gp-overlay'); 7 if (!overlay) return; 8 9 var dialog = overlay.querySelector('.mi-gp-dialog'); 10 var closeButton = overlay.querySelector('.mi-gp-close'); 11 var lastFocused = null; 12 var hasOpened = false; 13 var submittedStorageKey = 'mi_gp_any_form_submitted'; 14 15 function viewportWidth() { 16 return window.innerWidth || document.documentElement.clientWidth; 17 } 18 19 function deviceMatches() { 20 var w = viewportWidth(); 21 if (cfg.deviceTarget === 'mobile') return w <= 767; 22 if (cfg.deviceTarget === 'tablet') return w >= 768 && w <= 1024; 23 if (cfg.deviceTarget === 'desktop') return w >= 1025; 24 return true; 25 } 26 27 function scrollDepthThreshold() { 28 var isMobile = viewportWidth() <= 767; 29 var value = parseInt(isMobile ? cfg.scrollDepthMobile : cfg.scrollDepthDesktop, 10); 30 var fallback = isMobile ? 60 : 50; 31 var min = 0; 32 var max = 100; 33 34 if (isNaN(value)) value = fallback; 35 return Math.min(max, Math.max(min, value)); 36 } 37 38 function currentScrollDepth() { 39 var doc = document.documentElement; 40 var body = document.body || doc; 41 var scrollTop = window.pageYOffset || doc.scrollTop || body.scrollTop || 0; 42 var viewportHeight = window.innerHeight || doc.clientHeight || 0; 43 var documentHeight = Math.max( 44 body.scrollHeight, 45 doc.scrollHeight, 46 body.offsetHeight, 47 doc.offsetHeight, 48 body.clientHeight, 49 doc.clientHeight 50 ); 51 var scrollableHeight = documentHeight - viewportHeight; 52 53 if (scrollableHeight <= 0) return 0; 54 return (scrollTop / scrollableHeight) * 100; 55 } 56 57 function alreadySeen() { 58 if (cfg.frequency === 'always') return false; 59 if (cfg.frequency === 'session') return sessionStorage.getItem(cfg.storageKey) === '1'; 60 var value = localStorage.getItem(cfg.storageKey); 61 if (!value) return false; 62 var age = Date.now() - parseInt(value, 10); 63 var days = cfg.frequency === 'daily' ? 1 : Math.max(1, parseInt(cfg.frequencyDays || 7, 10)); 64 return age < days * 86400000; 65 } 66 67 function markSeen() { 68 if (cfg.frequency === 'session') sessionStorage.setItem(cfg.storageKey, '1'); 69 else if (cfg.frequency !== 'always') localStorage.setItem(cfg.storageKey, String(Date.now())); 70 } 71 72 function localStorageValue(key) { 73 try { 74 return localStorage.getItem(key); 75 } catch (e) { 76 return ''; 77 } 78 } 79 80 function setLocalStorageValue(key, value) { 81 try { 82 localStorage.setItem(key, value); 83 } catch (e) {} 84 } 85 86 function readCookie(name) { 87 var prefix = name + '='; 88 return document.cookie.split(';').map(function (v) { return v.trim(); }).filter(function (v) { return v.indexOf(prefix) === 0; }).map(function (v) { return decodeURIComponent(v.substring(prefix.length)); })[0] || ''; 89 } 90 91 function setCookie(name, value, maxAge) { 92 document.cookie = name + '=' + encodeURIComponent(value) + '; path=/; max-age=' + maxAge + '; SameSite=Lax'; 93 } 94 95 function alreadySubmitted() { 96 return localStorageValue(submittedStorageKey) === '1' || readCookie(submittedStorageKey) === '1'; 97 } 98 99 function markSubmitted() { 100 setLocalStorageValue(submittedStorageKey, '1'); 101 setCookie(submittedStorageKey, '1', 31536000); 102 } 103 104 function storedValue(key) { 105 if (key === 'submissionpageurl') return window.location.href; 106 var value = readCookie(key); 107 if (!value) value = localStorage.getItem(key) || sessionStorage.getItem(key) || ''; 108 return value; 109 } 110 111 function populateAttribution() { 112 var form = overlay.querySelector('#gform_' + cfg.formId); 113 if (!form) return; 114 Object.keys(cfg.fieldMap || {}
114).forEach(function (key) { 115 var fieldId = cfg.fieldMap[key]; 116 var input = form.querySelector('[name="input_' + fieldId + '"]'); 117 var value = storedValue(key); 118 if (input && value) input.value = value; 119 }); 120 } 121 122 function rememberDialogHeight() { 123 if (!dialog) return; 124 var height = dialog.getBoundingClientRect().height; 125 if (height > 0) dialog.style.setProperty('--mi-gp-confirmed-min-height', Math.ceil(height) + 'px'); 126 } 127 128 function openPopup() { 129 if (hasOpened || alreadySubmitted() || !deviceMatches() || alreadySeen()) return false; 130 hasOpened = true; 131 lastFocused = document.activeElement; 132 overlay.hidden = false; 133 overlay.setAttribute('aria-hidden', 'false'); 134 document.documentElement.classList.add('mi-gp-open'); 135 document.body.classList.add('mi-gp-open'); 136 populateAttribution(); 137 markSeen(); 138 if (closeButton) closeButton.focus(); 139 return true; 140 } 141 142 function closePopup() { 143 overlay.hidden = true; 144 overlay.setAttribute('aria-hidden', 'true'); 145 document.documentElement.classList.remove('mi-gp-open'); 146 document.body.classList.remove('mi-gp-open'); 147 if (lastFocused && typeof lastFocused.focus === 'function') lastFocused.focus(); 148 } 149 150 closeButton && closeButton.addEventListener('click', closePopup); 151 overlay.addEventListener('click', function (e) { if (e.target === overlay) closePopup(); }); 152 document.addEventListener('keydown', function (e) { 153 if (overlay.hidden) return; 154 if (e.key === 'Escape') closePopup(); 155 if (e.key === 'Tab') { 156 var focusables = dialog.querySelectorAll('a,button,input,select,textarea,[tabindex]:not([tabindex="-1"])'); 157 if (!focusables.length) return; 158 var first = focusables[0], last = focusables[focusables.length - 1]; 159 if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); } 160 else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); } 161 } 162 }); 163 164 overlay.addEventListener('submit', function (e) { 165 if (!e.target || e.target.id !== 'gform_' + cfg.formId) return; 166 rememberDialogHeight(); 167 }, true); 168 169 function pushSuccess(formId) { 170 markSubmitted(); 171 if (String(formId) !== String(cfg.formId)) return; 172 if (!dialog.style.getPropertyValue('--mi-gp-confirmed-min-height')) rememberDialogHeight(); 173 overlay.classList.add('mi-gp-confirmed'); 174 window.dataLayer = window.dataLayer || []; 175 window.dataLayer.push({ 176 event: cfg.gtmEventName || 'gravity_form_success', 177 form_id: String(formId), 178 form_location: 'popup', 179 page_location: window.location.href, 180 page_path: window.location.pathname, 181 page_title: document.title 182 }); 183 } 184 185 $(document).on('gform_confirmation_loaded', function (event, formId) { pushSuccess(formId); }); 186 document.addEventListener('gform_confirmation_loaded', function (event) { 187 var detail = event.detail || {}; 188 pushSuccess(detail.formId || detail.form_id || detail); 189 }); 190 191 function scheduleTimeTrigger() { 192 window.setTimeout(openPopup, Math.max(0, parseInt(cfg.delayMs || 0, 10))); 193 } 194 195 function scheduleScrollTrigger() { 196 if (alreadySubmitted() || !deviceMatches() || alreadySeen()) return; 197 198 var onScroll = function () { 199 if (currentScrollDepth() < scrollDepthThreshold()) return; 200 window.removeEventListener('scroll', onScroll); 201 openPopup(); 202 }; 203 204 window.addEventListener('scroll', onScroll, { passive: true }); 205 } 206 207 if (cfg.triggerType === 'scroll') scheduleScrollTrigger(); 208 else scheduleTimeTrigger(); 209 } 210 211 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); 212 else init(); 213})(jQuery);
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.