PageSourceSearch

https://www.mi.edu/wp-content/plugins/mi-gravity-popup/assets/popup.js?ver=2.1.18

js mi.edu collected 2026-10-02 04:21:54 UTC 8,775 bytes, 213 lines download raw bytes

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.