PageSourceSearch

https://pagespeed.ninja/js/modal.js

js pagespeed.ninja collected 2026-10-02 06:46:52 UTC 5,439 bytes, 184 lines download raw bytes

1/* Based on SqueezeBox for MooTools (http://digitarald.de/project/squeezebox/) */
2(function () {
3    'use strict';
4
5    var $overlay,
6        $winwrapper,
7        $win,
8        $content,
9        $close,
10        $body,
11        root,
12        scrollOffset;
13
14    /**
15     * @param {string} tag
16     * @param {object} attributes
17     * @returns {HTMLElement}
18     */
19    function $createNode(tag, attributes = {}) {
20        var node = document.createElement(tag);
21        for (var attrName in attributes) {
22            node.setAttribute(attrName, attributes[attrName]);
23        }
24        return node;
25    }
26
27    function initialize() {
28        $overlay = $createNode('div', {
29            'id': 'sbox-overlay',
30            'aria-hidden': 'true',
31            'tabindex': '-1',
32            'style': 'z-index:65555;opacity:0.7'
33        });
34        $winwrapper = $createNode('div', {
35            'id': 'sbox-window-wrapper',
36            'role': 'dialog',
37            'aria-hidden': 'true',
38            'style': 'z-index:65557'
39        });
40        $win = $createNode('div', {
41            'id': 'sbox-window',
42            'aria-hidden': 'true',
43            'class': 'shadow',
44        });
45        $content = $createNode('div', {'id': 'sbox-content'});
46        $close = $createNode('a', {
47            'id': 'sbox-btn-close',
48            'href': '#',
49            'role': 'button',
50            'aria-controls': 'sbox-window'
51        });
52        $body = document.body;
53        root = document.documentElement || document.body;
54
55        $win.append($content, $close);
56        $winwrapper.append($win);
57        $body.append($overlay, $winwrapper);
58
59        $overlay.addEventListener('click', close);
60        $close.addEventListener('click', close);
61
62        document.addEventListener('sbox-iframe-focus-keyboard', onFocus);
63        document.addEventListener('sbox-iframe-blur-keyboard', onBlur);
64
65        $body.addEventListener('submit', function (e) {
66            var form = e.target.closest('[data-popup]');
67            if (form) {
68                open(form);
69                e.preventDefault();
70            }
71        });
72    }
73
74    var keyboard_mode = false;
75    function onFocus() {
76        keyboard_mode = true;
77//        document.body.classList.add('sbox-keyboard');
78    }
79
80    function onBlur() {
81        keyboard_mode = false;
82//        document.body.classList.remove('sbox-keyboard');
83//        reposition();
84        $win.scrollIntoView({block: 'nearest'});
85    }
86
87    /**
88     * @param {Element} form
89     */
90    function open(form) {
91        var url = form.action + '?' + (new URLSearchParams(new FormData(form))).toString();
92        var size = {
93            x: Math.min(600, document.documentElement.clientWidth - 16),
94            y: 490 // Math.min(490, document.documentElement.clientHeight - 16)
95        };
96
97        var $iframe = $createNode('iframe', {'frameborder': '0'});
98        $iframe.setAttribute('src', url);
99        $iframe.setAttribute('width', size.x);
100        $iframe.setAttribute('height', size.y);
101
102        $content.innerHTML = '';
103        $content.append($iframe);
104
105        toggleOverlay(true);
106
107        reposition();
108
109        document.addEventListener('keydown', onKey);
110        document.addEventListener('mousewheel', checkTarget);
111        window.addEventListener('resize', reposition);
112        window.addEventListener('scroll', reposition);
113    }
114
115    /**
116     * @param {UIEvent} e
117     */
118    function close(e) {
119        $content.innerHTML = '';
120
121        toggleOverlay(false);
122
123        document.removeEventListener('keydown', onKey);
124        document.removeEventListener('mousewheel', checkTarget);
125        window.removeEventListener('resize', reposition);
126        window.removeEventListener('scroll', reposition);
127
128        e.preventDefault();
129    }
130
131    /**
132     * @param {boolean} state
133     */
134    function toggleOverlay(state) {
135        var full = root.offsetWidth;
136        $overlay.setAttribute('aria-hidden', state ? 'false' : 'true');
137        $winwrapper.setAttribute('aria-hidden', state ? 'false' : 'true');
138        $win.setAttribute('aria-hidden', state ? 'false' : 'true');
139        if (state) {
140            $body.classList.add('body-overlayed');
141            scrollOffset = root.offsetWidth - full;
142        } else {
143            $body.classList.remove('body-overlayed');
144        }
145    }
146
147    function reposition() {
148        if (keyboard_mode) return;
149        var j = parseInt($overlay.style.height);
150        if (root.scrollHeight > j && root.offsetHeight >= j) {
151            $overlay.style.width = root.scrollWidth + 'px';
152            $overlay.style.height = root.scrollHeight + 'px';
153        }
154        $winwrapper.style.left = Math.round(root.scrollLeft + (document.documentElement.clientWidth - $win.offsetWidth) / 2 - scrollOffset) + 'px';
155        $winwrapper.style.top = Math.round(root.scrollTop + (document.documentElement.clientHeight - $win.offsetHeight) / 2) + 'px';
156    }
157
158    /**
159     * @param {KeyboardEvent} e
160     */
161    function onKey(e) {
162        switch (e.key) {
163            case 'esc':
164                close(e);
165                break;
166            case 'up':
167            case 'down':
168                e.preventDefault();
169                break;
170        }
171    }
172
173    /**
174     * @param {MouseEvent} e
175     */
176    function checkTarget(e) {
177        if (!$content.contains(e.target)) {
178            e.preventDefault();
179        }
180    }
181
182    document.addEventListener('DOMContentLoaded', initialize);
183
184})();

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.