1/* Popup-only behavior. No jQuery, cookies, storage or replacement of theme handlers. */ 2(function () { 3 'use strict'; 4 5 function initBannerPopup() { 6 var overlay = document.getElementById('apibet-hulk-banner-popup'); 7 if (!overlay || overlay.getAttribute('data-apibet-popup-ready') === '1') { 8 return; 9 } 10 var dialog = overlay.querySelector('.apibet-popup__dialog'); 11 var closeButton = overlay.querySelector('.apibet-popup__close'); 12 var image = overlay.querySelector('.apibet-popup__image'); 13 if (!dialog || !closeButton || !image) { 14 return; 15 } 16 overlay.setAttribute('data-apibet-popup-ready', '1'); 17 18 // If a stylesheet failed to load, do not reveal an unstyled page-blocking box. 19 if (window.getComputedStyle(overlay).position !== 'fixed') { 20 return; 21 } 22 var isOpen = false; 23 var previousFocus = null; 24 var savedOverflow = []; 25 26 function focusWithoutScrolling(element) { 27 if (!element || typeof element.focus !== 'function') { 28 return; 29 } 30 try { 31 element.focus({ preventScroll: true }); 32 } catch (error) { 33 element.focus(); 34 } 35 } 36 37 function lockBackground() { 38 [document.documentElement, document.body].forEach(function (element) { 39 savedOverflow.push({ 40 element: element, 41 x: element.style.getPropertyValue('overflow-x'), 42 y: element.style.getPropertyValue('overflow-y'), 43 xPriority: element.style.getPropertyPriority('overflow-x'), 44 yPriority: element.style.getPropertyPriority('overflow-y'), 45 hadStyle: element.hasAttribute('style') 46 }); 47 element.style.setProperty('overflow', 'hidden', 'important'); 48 }); 49 } 50 51 function unlockBackground() { 52 savedOverflow.forEach(function (state) { 53 // Leave newer changes from another component alone. 54 if (state.element.style.getPropertyValue('overflow') !== 'hidden' || 55 state.element.style.getPropertyPriority('overflow') !== 'important') { 56 return; 57 } 58 state.element.style.removeProperty('overflow'); 59 if (state.x) { 60 state.element.style.setProperty('overflow-x', state.x, state.xPriority); 61 } 62 if (state.y) { 63 state.element.style.setProperty('overflow-y', state.y, state.yPriority); 64 } 65 if (!state.hadStyle && !state.element.getAttribute('style')) { 66 state.element.removeAttribute('style'); 67 } 68 }); 69 savedOverflow = []; 70 } 71 72 function closePopup() { 73 if (!isOpen) { 74 return; 75 } 76 isOpen = false; 77 overlay.hidden = true; 78 unlockBackground(); 79 document.removeEventListener('keydown', onKeyDown, true); 80 document.removeEventListener('focusin', onFocusIn, true); 81 if (previousFocus && document.documentElement.contains(previousFocus)) { 82 focusWithoutScrolling(previousFocus); 83 } 84 } 85 86 function onKeyDown(event) { 87 if (!isOpen) { 88 return; 89 } 90 if (event.key === 'Escape' || event.key === 'Esc') { 91 event.preventDefault(); 92 event.stopPropagation(); 93 closePopup(); 94 return; 95 } 96 if (event.key !== 'Tab') { 97 return; 98 } 99 var items = Array.prototype.filter.call( 100 dialog.querySelectorAll('a[href],button:not([disabled]),[tabindex]:not([tabindex="-1"])'), 101 function (element) { return element.getClientRects().length > 0; } 102 ); 103 if (!items.length) { 104 event.preventDefault(); 105 focusWithoutScrolling(dialog); 106 return; 107 } 108 var first = items[0]; 109 var last = items[items.length - 1]; 110 if (event.shiftKey && (document.activeElement === first || !dialog.contains(document.activeElement))) { 111 event.preventDefault(); 112 focusWithoutScrolling(last); 113 } else if (!event.shiftKey && (document.activeElement === last || !dialog.contains(document.activeElement))) { 114 event.preventDefault(); 115 focusWithoutScrolling(first); 116 } 117 } 118 119 function onFocusIn(event) { 120 if (isOpen && !dialog.contains(event.target)) { 121 focusWithoutScrolling(closeButton); 122 } 123 } 124 125 closeButton.addEventListener('click', closePopup); 126 overlay.addEventListener('click', function (event) { 127 if (event.target === overlay) { 128 closePopup(); 129 } 130 }); 131 image.addEventListener('error', closePopup); 132 133 // A broken upload must not leave a broken-image modal blocking the site.
134 if (image.complete && image.naturalWidth === 0) { 135 return; 136 } 137 previousFocus = document.activeElement; 138 overlay.hidden = false; 139 isOpen = true; 140 lockBackground(); 141 document.addEventListener('keydown', onKeyDown, true); 142 document.addEventListener('focusin', onFocusIn, true); 143 focusWithoutScrolling(closeButton); 144 // Display on each new page load, just like the supplied TXT; no persistent dismissal. 145 } 146 147 if (document.readyState === 'loading') { 148 document.addEventListener('DOMContentLoaded', initBannerPopup); 149 } else { 150 initBannerPopup(); 151 } 152}());
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.