PageSourceSearch

https://verschickungsheime.de/wp-content/plugins/termine/frontend.js?ver=1788656411

js verschickungsheime.de collected 2026-10-02 10:24:10 UTC 7,625 bytes, 273 lines download raw bytes

1document.addEventListener('DOMContentLoaded', function () {
2  var nav = document.querySelector('.terminklassen-tage-nav');
3  if (!nav) return;
4
5  /* Aus möglichen Stacking-Contexts des Contents herauslösen. */
6  if (nav.parentNode !== document.body) {
7    document.body.appendChild(nav);
8  }
9
10  var sections = Array.prototype.slice.call(document.querySelectorAll('.contentMenu[id]'));
11  if (!sections.length) {
12    nav.style.display = 'none';
13    return;
14  }
15
16  function makeLabel(id) {
17    if (!id) return '';
18    return id
19      .replace(/[-_]+/g, ' ')
20      .replace(/\b\w/g, function (char) { return char.toUpperCase(); });
21  }
22
23  var items = sections.map(function (section) {
24    var id = section.getAttribute('id');
25    var customLabel = section.getAttribute('data-menu-label');
26
27    return {
28      id: id,
29      label: customLabel && customLabel.trim() ? customLabel.trim() : makeLabel(id),
30      section: section
31    };
32  }).filter(function (item) {
33    return !!item.id;
34  });
35
36  if (!items.length) {
37    nav.style.display = 'none';
38    return;
39  }
40
41  nav.innerHTML = ''
42    + '<div class="terminklassen-control">'
43    + '  <div class="terminklassen-drawer" aria-hidden="true">'
44    + '    <div class="terminklassen-drawer-head">'
45    + '      <strong>Bereiche</strong>'
46    + '      <button type="button" class="terminklassen-drawer-close" aria-label="Menü schließen">×</button>'
47    + '    </div>'
48    + '    <div class="terminklassen-drawer-list"></div>'
49    + '  </div>'
50    + '  <div class="terminklassen-radar" tabindex="0" role="button" aria-label="Abschnittsnavigation öffnen">'
51    + '    <div class="terminklassen-radar-ring"></div>'
52    + '    <div class="terminklassen-radar-window">'
53    + '      <button type="button" class="terminklassen-radar-item is-prev"></button>'
54    + '      <button type="button" class="terminklassen-radar-item is-current"></button>'
55    + '      <button type="button" class="terminklassen-radar-item is-next"></button>'
56    + '    </div>'
57    + '  </div>'
58    + '</div>';
59
60  var control = nav.querySelector('.terminklassen-control');
61  var radar = nav.querySelector('.terminklassen-radar');
62  var radarPrev = nav.querySelector('.terminklassen-radar-item.is-prev');
63  var radarCurrent = nav.querySelector('.terminklassen-radar-item.is-current');
64  var radarNext = nav.querySelector('.terminklassen-radar-item.is-next');
65  var drawer = nav.querySelector('.terminklassen-drawer');
66  var drawerList = nav.querySelector('.terminklassen-drawer-list');
67  var closeBtn = nav.querySelector('.terminklassen-drawer-close');
68
69  var currentIndex = 0;
70  var closeTimer = null;
71  var openLockUntil = 0;
72
73  items.forEach(function (item, index) {
74    var link = document.createElement('a');
75    link.href = '#' + item.id;
76    link.textContent = item.label;
77    link.className = 'terminklassen-drawer-link';
78    link.dataset.index = String(index);
79
80    link.addEventListener('click', function () {
81      currentIndex = index;
82      updateRadar(true);
83      closeDrawer();
84    });
85
86    drawerList.appendChild(link);
87    item.link = link;
88  });
89
90  function wrapIndex(index) {
91    if (index < 0) return items.length - 1;
92    if (index >= items.length) return 0;
93    return index;
94  }
95
96  function setRadarButton(button, index) {
97    var actualIndex = wrapIndex(index);
98    var item = items[actualIndex];
99
100    button.textContent = item.label;
101    button.onclick = function (event) {
102      event.stopPropagation();
103      var target = document.getElementById(item.id);
104      if (target) {
105        target.scrollIntoView({ behavior: 'smooth', block: 'start' });
106      }
107    };
108  }
109
110  function updateRadar(animate) {
111    setRadarButton(radarPrev, currentIndex - 1);
112    setRadarButton(radarCurrent, currentIndex);
113    setRadarButton(radarNext, currentIndex + 1);
114
115    items.forEach(function (item, index) {
116      if (item.link) {
117        item.link.classList.toggle('is-active', index === currentIndex);
118      }
119    });
120
121    if (animate) {
122      radar.classList.remove('is-turning');
123      void radar.offsetWidth;
124      radar.classList.add('is-turning');
125
126      setTimeout(function () {
127        radar.classList.remove('is-turning');
128      }, 360);
129    }
130  }
131
132  function findCurrentIndex() {
133    var marker = window.scrollY + Math.min(240, window.innerHeight * 0.34);
134    var found = 0;
135
136    items.forEach(function (item, index) {
137      if (item.section.offsetTop <= marker) {
138        found = index;
139      }
140    });
141
142    return found;
143  }
144
145  function openDrawer() {
146    if (closeTimer) {
147      clearTimeout(closeTimer);
148      closeTimer = null;
149    }
150
151    openLockUntil = performance.now() + 900;
152
153    nav.classList.add('is-open');
154    drawer.setAttribute('aria-hidden', 'false');
155
156    var activeLink = items[currentIndex].link;
157    if (activeLink) {
158      setTimeout(function () {
159        activeLink.scrollIntoView({ block: 'center' });
160      }, 80);
161    }
162  }
163
164  function closeDrawer(force) {
165    if (!force && performance.now() < openLockUntil) {
166      scheduleClose(950);
167      return;
168    }
169
170    nav.classList.remove('is-open');
171    drawer.setAttribute('aria-hidden', 'true');
172  }
173
174  function scheduleClose(delay) {
175    if (closeTimer) clearTimeout(closeTimer);
176
177    closeTimer = setTimeout(function () {
178      if (!control.matches(':hover') &&
179          !drawer.matches(':hover') &&
180          !radar.matches(':hover') &&
181          !control.matches(':focus-within')) {
182        closeDrawer(false);
183      }
184    }, typeof delay === 'number' ? delay : 1100);
185  }
186
187  radar.addEventListener('pointerenter', openDrawer);
188  drawer.addEventListener('pointerenter', function () {
189    if (closeTimer) clearTimeout(closeTimer);
190    openLockUntil = performance.now() + 350;
191  });
192
193  radar.addEventListener('click', function () {
194    nav.classList.contains('is-open') ? closeDrawer(true) : openDrawer();
195  });
196
197  radar.addEventListener('keydown', function (event) {
198    if (event.key === 'Enter' || event.key === ' ') {
199      event.preventDefault();
200      openDrawer();
201    }
202
203    if (event.key === 'Escape') {
204      closeDrawer();
205    }
206  });
207
208  control.addEventListener('pointerenter', function () {
209    if (closeTimer) clearTimeout(closeTimer);
210  });
211
212  control.addEventListener('pointerleave', function () {
213    scheduleClose(1100);
214  });
215
216  drawer.addEventListener('pointerleave', function () {
217    scheduleClose(1100);
218  });
219
220  closeBtn.addEventListener('click', function (event) {
221    event.stopPropagation();
222    closeDrawer(true);
223  });
224
225  document.addEventListener('keydown', function (event) {
226    if (event.key === 'Escape') closeDrawer(true);
227  });
228
229  function getFooter() {
230    return document.querySelector('#colophon, footer.site-footer, footer[role="contentinfo"]');
231  }
232
233  function updateFooterAvoidance() {
234    var footer = getFooter();
235    var baseBottom = document.body.classList.contains('logged-in') ? 18 : 38;
236    var gap = 14;
237
238    if (!footer) {
239      nav.style.bottom = baseBottom + 'px';
240      return;
241    }
242
243    var rect = footer.getBoundingClientRect();
244
245    if (rect.top >= window.innerHeight) {
246      nav.style.bottom = baseBottom + 'px';
247      return;
248    }
249
250    nav.style.bottom = Math.max(
251      baseBottom,
252      window.innerHeight - rect.top + gap
253    ) + 'px';
254  }
255
256  function onScroll() {
257    var nextIndex = findCurrentIndex();
258
259    if (nextIndex !== currentIndex) {
260      currentIndex = nextIndex;
261      updateRadar(true);
262    }
263
264    updateFooterAvoidance();
265  }
266
267  window.addEventListener('scroll', onScroll, { passive: true });
268  window.addEventListener('resize', onScroll);
269
270  currentIndex = findCurrentIndex();
271  updateRadar(false);
272  updateFooterAvoidance();
273});

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.