1const scrollLockTranslations = { 2 overlayScrollIsLocked: { 3 fr: 'Le défilement est vérrouillé dans cette zone.', 4 en: 'Scrolling is locked in this area.', 5 de: 'Der Bildlauf ist in diesem Bereich gesperrt.', 6 it: 'Lo scorrimento è bloccato in quest\'area', 7 }, 8 overlayUnlockButtonText: { 9 fr: 'Déverrouiller', 10 en: 'Unlock', 11 de: 'freischalten', 12 it: 'Sblocca', 13 } 14}; 15 16const initStyles = () => { 17 const css = ` 18 .${scrollLockOverlayClassName} { 19 background: rgba(0,0,0,0.3); 20 color: rgb(255,255,255); 21 position: absolute; 22 top: 0; 23 left: 0; 24 width: 100%; 25 height: 100%; 26 z-index: 1; 27 opacity: 0; 28 transition: opacity 1s; 29 display: flex; 30 flex-direction: column; 31 flex-wrap: nowrap; 32 justify-content: center; 33 pointer-events: none; 34 } 35 .${scrollLockOverlayClassName}-content { 36 text-align: center; 37 padding: 1rem; 38 font-size: 1.4rem; 39 margin: 0; 40 } 41 .${scrollLockOverlayClassName}-unlock-button-container { 42 text-align: center; 43 font-size: 1.4rem; 44 } 45 .${scrollLockOverlayClassName}-unlock-button { 46 display: inline-block; 47 text-decoration: none; 48 color: rgb(255,255,255, 0.8); 49 border: 1px solid rgb(255,255,255, 0.8); 50 border-radius: 0.25rem; 51 padding: 0.2rem 0.4rem; 52 pointer-events: auto; 53 } 54 .${scrollLockOverlayClassName}-unlock-button:hover { 55 color: rgb(255,255,255, 1.0); 56 border-color: rgb(255,255,255, 1.0); 57 } 58 `; 59 const style = document.createElement('style'); 60 if (style.styleSheet) { 61 style.styleSheet.cssText = css; 62 } else { 63 style.appendChild(document.createTextNode(css)); 64 } 65 document.getElementsByTagName('head')[ 0 ].appendChild(style); 66}; 67 68const scrollLockLang = document.documentElement.lang; 69const scrollLockOverlayTimeouts = {}; 70const scrollLockOverlayClassName = 'scroll-lockable-overlay'; 71const scrollLockListeners = {}; 72 73const getScrollLockOverlay = (element) => { 74 return element.getElementsByClassName(scrollLockOverlayClassName)[ 0 ]; 75}; 76 77const isOverlayActive = (element) => { 78 const overlay = getScrollLockOverlay(element); 79 return !!overlay && overlay.style.pointerEvents === 'auto'; 80}; 81 82const restoreElementScroll = (element) => { 83 element.style.overflow = element.dataset.scrolllockOverflow || ''; 84 element.style.overflowX = element.dataset.scrolllockOverflowX || ''; 85 element.style.overflowY = element.dataset.scrolllockOverflowY || ''; 86}; 87 88const removeScrollLockOverlay = (element) => { 89 let overlay = getScrollLockOverlay(element); 90 if (overlay) { 91 if (scrollLockOverlayTimeouts[ overlay.id ]) { 92 clearTimeout(scrollLockOverlayTimeouts[ overlay.id ]); 93 } 94 element.removeChild(overlay); 95 } 96}; 97 98const clearEventListeners = (element) => { 99 const scrollLockId = element.dataset.scrolllockid; 100 const listeners = scrollLockListeners[ scrollLockId ]; 101 if (!listeners) { 102 return; 103 } 104 const elementEventNames = Object.keys(listeners.element); 105 elementEventNames.forEach(eventName => { 106 element.removeEventListener(eventName, listeners.element[ eventName ], listeners.elementOptions[ eventName ]); 107 }); 108 109 const overlay = getScrollLockOverlay(element); 110 if (overlay) { 111 const overlayEventNames = Object.keys(listeners.overlay); 112 overlayEventNames.forEach(eventName => { 113 overlay.removeEventListener(eventName, listeners.overlay[ eventName ], listeners.overlayOptions[ eventName ]); 114 }); 115 } 116 117 scrollLockListeners[ scrollLockId ] = undefined; 118}; 119 120const lockElement = (element) => { 121 element.dataset.scrolllockOverflow = element.style.overflow; 122 element.dataset.scrolllockOverflowX = element.style.overflowX; 123 element.dataset.scrolllockOverflowY = element.style.overflowY; 124 element.dataset.scrollLocked = true; 125 element.style.overflow = 'hidden'; 126}; 127 128const unlockElement = (element) => { 129 element.dataset.scrollLocked = false; 130 restoreElementScroll(element); 131 delete element.dataset.scrolllockOverflow; 132 delete element.dataset.scrolllockOverflowX; 133 delete element.dataset.scrolllockOverflowY; 134 clearEventListeners(element); 135 removeScrollLockOverlay(element); 136}; 137 138const isElementLocked = (element) => { 139 return element.dataset.scrollLocked === 'true'; 140}; 141 142const createLockOverlay = (element) => { 143 const scrollLockId = element.dataset.scrolllockid;
144 const overlay = document.createElement('div'); 145 overlay.id = `${scrollLockOverlayClassName}_${scrollLockId}`; 146 overlay.className = scrollLockOverlayClassName; 147 const generalContent = document.createElement('p'); 148 generalContent.className = `${scrollLockOverlayClassName}-content`; 149 generalContent.innerText = scrollLockTranslations.overlayScrollIsLocked[ scrollLockLang ]; 150 const unlockLinkContainer = document.createElement('div'); 151 unlockLinkContainer.className = `${scrollLockOverlayClassName}-unlock-button-container`; 152 const unlockLink = document.createElement('a'); 153 unlockLink.className = `${scrollLockOverlayClassName}-unlock-button`; 154 unlockLink.href = ""; 155 unlockLink.innerText = scrollLockTranslations.overlayUnlockButtonText[ scrollLockLang ]; 156 unlockLink.onclick = (event) => { 157 event.preventDefault(); 158 event.stopPropagation(); 159 unlockElement(element); 160 }; 161 generalContent.appendChild(document.createElement('br')); 162 overlay.appendChild(generalContent); 163 unlockLinkContainer.appendChild(unlockLink); 164 overlay.appendChild(unlockLinkContainer); 165 return overlay; 166}; 167 168const showScrollLockOverlay = (element) => { 169 const overlay = getScrollLockOverlay(element); 170 if (!overlay) { 171 return; 172 } 173 overlay.style.pointerEvents = 'auto'; 174 overlay.style.opacity = 1; 175 if (scrollLockOverlayTimeouts[ overlay.id ]) { 176 clearTimeout(scrollLockOverlayTimeouts[ overlay.id ]); 177 } 178 scrollLockOverlayTimeouts[ overlay.id ] = setTimeout(() => overlay.style.opacity = 0.3, 3000); 179}; 180 181const bindOverlayEvents = (element, overlay) => { 182 const blockScrollEvent = (event) => { 183 if (!isElementLocked(element)) { 184 return; 185 } 186 187 event.stopPropagation(); 188 showScrollLockOverlay(element); 189 }; 190 191 const blockPointerDragEvent = (event) => { 192 if (!isElementLocked(element) || !isOverlayActive(element)) { 193 return; 194 } 195 196 event.preventDefault(); 197 event.stopPropagation(); 198 }; 199 200 const listeners = scrollLockListeners[ element.dataset.scrolllockid ]; 201 listeners.overlay = { 202 'mousedown': blockPointerDragEvent, 203 'mousemove': blockPointerDragEvent, 204 'pointerdown': blockPointerDragEvent, 205 'pointermove': blockPointerDragEvent, 206 'touchstart': blockScrollEvent, 207 'touchmove': blockScrollEvent, 208 'wheel': blockScrollEvent, 209 }; 210 listeners.overlayOptions = { 211 'mousedown': false, 212 'mousemove': false, 213 'pointerdown': false, 214 'pointermove': false, 215 'touchstart': { passive: false }, 216 'touchmove': { passive: false }, 217 'wheel': { passive: false }, 218 }; 219 220 Object.keys(listeners.overlay).forEach(eventName => { 221 overlay.addEventListener(eventName, listeners.overlay[ eventName ], listeners.overlayOptions[ eventName ]); 222 }); 223}; 224 225const interceptScrollEvent = (element) => { 226 const scrollLockId = Math.round(Math.random() * 1000000); 227 element.dataset.scrolllockid = scrollLockId; 228 lockElement(element); 229 element.style.position = 'relative'; 230 231 const activateLock = (event) => { 232 if (!isElementLocked(element)) { 233 return; 234 } 235 236 event.stopPropagation(); 237 showScrollLockOverlay(element); 238 }; 239 240 const blockActivePointerDrag = (event) => { 241 if (!isElementLocked(element) || !isOverlayActive(element)) { 242 return; 243 } 244 245 event.preventDefault(); 246 event.stopPropagation(); 247 }; 248 249 scrollLockListeners[ scrollLockId ] = { 250 element: { 251 'wheel': activateLock, 252 'touchstart': activateLock, 253 'touchmove': activateLock, 254 'mousedown': blockActivePointerDrag, 255 'mousemove': blockActivePointerDrag, 256 'pointerdown': blockActivePointerDrag, 257 'pointermove': blockActivePointerDrag, 258 }, 259 elementOptions: { 260 'wheel': { passive: false, capture: true }, 261 'touchstart': { passive: false, capture: true }, 262 'touchmove': { passive: false, capture: true }, 263 'mousedown': { capture: true }, 264 'mousemove': { capture: true }, 265 'pointerdown': { capture: true }, 266 'pointermove': { capture: true }, 267 }, 268 overlay: {}, 269 overlayOptions: {}, 270 }; 271 272 const overlay = createLockOverlay(element); 273 element.appendChild(overlay); 274 bindOverlayEvents(element, overlay); 275 276 Object.keys(scrollLockListeners[ scrollLockId ].element).forEach(eventName => { 277 element.addEventListener( 278 eventName, 279 scrollLockListeners[ scrollLockId ].element[ eventName ], 280 scrollLockListeners[ scrollLockId ].elementOptions[ eventName ] 281 ); 282 }); 283}; 284 285initStyles(); 286const scrollLockableContainers = document.getElementsByClassName('scroll-lockable'); 287Array.prototype.forEach.call(scrollLockableContainers, element => { 288 interceptScrollEvent(element); 289});
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.