PageSourceSearch

https://www.infoflora.ch/assets/js/scrollLock.js?v2026

js infoflora.ch collected 2026-09-24 08:59:01 UTC 8,995 bytes, 289 lines download raw bytes

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.