PageSourceSearch

https://airshopapp.com/js/shopboard-signup.js?v=20260430

js airshopapp.com collected 2026-10-05 19:23:54 UTC 4,281 bytes, 130 lines download raw bytes

1(function() {
2    var API_URL = 'https://airshop.work/api/leads/shopboard-signup';
3    var modal = document.getElementById('shopboard-signup-modal');
4    var form = document.getElementById('shopboard-signup-form');
5    var messageEl = document.getElementById('shopboard-signup-message');
6    var emailInput = document.getElementById('shopboard-signup-email');
7    var closeButtons = document.querySelectorAll('[data-shopboard-signup-close]');
8    var triggerButtons = document.querySelectorAll('[data-shopboard-signup-open]');
9    var lastActiveElement = null;
10    var formLoadTime = Date.now();
11
12    if (!modal || !form || !messageEl || !emailInput || !triggerButtons.length) return;
13
14    function openModal() {
15        lastActiveElement = document.activeElement;
16        modal.hidden = false;
17        document.body.classList.add('shopboard-signup-open');
18        messageEl.textContent = '';
19        messageEl.className = 'shopboard-signup-message';
20        window.setTimeout(function() {
21            emailInput.focus();
22        }, 0);
23    }
24
25    function closeModal() {
26        modal.hidden = true;
27        document.body.classList.remove('shopboard-signup-open');
28
29        if (lastActiveElement && typeof lastActiveElement.focus === 'function') {
30            lastActiveElement.focus();
31        }
32    }
33
34    triggerButtons.forEach(function(button) {
35        button.addEventListener('click', openModal);
36    });
37
38    closeButtons.forEach(function(button) {
39        button.addEventListener('click', closeModal);
40    });
41
42    modal.addEventListener('click', function(event) {
43        if (event.target === modal) {
44            closeModal();
45        }
46    });
47
48    document.addEventListener('keydown', function(event) {
49        if (modal.hidden) {
50            return;
51        }
52
53        if (event.key === 'Escape') {
54            closeModal();
55        }
56
57        if (event.key !== 'Tab') {
58            return;
59        }
60
61        var focusable = modal.querySelectorAll('button, input, [href], select, textarea, [tabindex]:not([tabindex="-1"])');
62        if (!focusable.length) {
63            return;
64        }
65
66        var first = focusable[0];
67        var last = focusable[focusable.length - 1];
68
69        if (event.shiftKey && document.activeElement === first) {
70            event.preventDefault();
71            last.focus();
72        } else if (!event.shiftKey && document.activeElement === last) {
73            event.preventDefault();
74            first.focus();
75        }
76    });
77
78    form.addEventListener('submit', async function(event) {
79        event.preventDefault();
80
81        var submitBtn = form.querySelector('button[type="submit"]');
82        var honeypot = form.querySelector('input[name="website"]');
83        var email = emailInput.value.trim();
84
85        if (honeypot && honeypot.value.trim()) {
86            return;
87        }
88
89        if (!email) {
90            messageEl.textContent = 'Please enter your email.';
91            messageEl.className = 'shopboard-signup-message error';
92            return;
93        }
94
95        submitBtn.disabled = true;
96        messageEl.textContent = '';
97        messageEl.className = 'shopboard-signup-message';
98
99        try {
100            var response = await fetch(API_URL, {
101                method: 'POST',
102                headers: { 'Content-Type': 'application/json' },
103                body: JSON.stringify({
104                    email: email,
105                    website: honeypot ? honeypot.value : '',
106                    form_load_time: formLoadTime,
107                    leadType: 'shopboard_signup',
108                    topic: 'Shopboard'
109                })
110            });
111
112            var data = await response.json().catch(function() {
113                return {};
114            });
115
116            if (!response.ok) {
117                throw new Error(data.error || 'Something went wrong');
118            }
119
120            messageEl.textContent = 'You are on the Shopboard update list.';
121            messageEl.className = 'shopboard-signup-message success';
122            form.reset();
123        } catch (err) {
124            messageEl.textContent = err.message || 'Failed to sign up. Please try again.';
125            messageEl.className = 'shopboard-signup-message error';
126        } finally {
127            submitBtn.disabled = false;
128        }
129    });
130})();

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.