PageSourceSearch

https://www.zm-online.de/typo3conf/ext/lns_gadgets/Resources/Public/JavaScript/scroll.js

js zm-online.de collected 2026-09-24 09:20:58 UTC 7,406 bytes, 218 lines download raw bytes

1/*! data-type: scrolltotop, viewport, sticky */
2(function() {
3  'use strict';
4
5  /* scroll eventListener :( */
6  var supportsPassive = false;
7  try {
8    var opts = Object.defineProperty({}, 'passive', {
9      get: function() {
10        supportsPassive = true;
11      }
12    });
13    window.addEventListener("testPassive", null, opts);
14    window.removeEventListener("testPassive", null, opts);
15  } catch (e) {}
16
17  /* smooth scroll to anchor */
18  function smoothScrollTo(event) {
19    // extract hash from url
20    let href = this.getAttribute('href');
21    let hash = href.split('#')[1];
22    if (hash !== "") {
23      // find element to scroll to
24      var el = document.getElementById(hash);
25      if (el) {
26        // prevent default anchor click behavior
27        event.preventDefault();
28        // fix scrollto position behind header
29        let header = document.getElementsByTagName('header'), headerHeight = 80;
30        if (header.length > 0) {
31          headerHeight = header[0].offsetWidth;
32        }
33        var to = - headerHeight;
34        var from = window.pageYOffset;
35        do {
36          to += el.offsetTop;
37          el = el.offsetParent;
38        } while (el);
39        if (from != to) {
40          if ('scrollBehavior' in document.documentElement.style) {
41            // new smooth scroll behavior
42            window.scrollTo({ top: to, left: 0, behavior: "smooth" });
43          } else {
44            // fallback ease scroll, by request anaimation frame
45            var start = Date.now();
46            var tick = function () {
47              var t = Math.min(1, ((Date.now() - start) / 1000));
48              var eased = t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1;
49              var val = (eased * (to - from)) + from;
50              window.scrollTo(0, val);
51              if (t<1) {
52                window.requestAnimationFrame(tick);
53              }
54            };
55            tick();
56          }
57        }
58        // todo: check if it is in use and if it is the right place heare
59        document.body.classList.remove('mainmenu-isopen');
60      }
61    }
62  }
63
64  // add event listener to all elements with hash in href
65  // that link to another element on same page
66  if (!'scrollBehavior' in document.documentElement.style ) {
67    let refs = document.querySelectorAll("[href*='#']");
68    for (let i = 0; i < refs.length; i++) {
69      let href = refs[i].getAttribute('href');
70      href = href.replace(window.location.href, '');
71      href = href.replace(window.location.pathname, '');
72      if (href.indexOf('#') === 0) {
73        let id = href.substr(1);
74        if (document.getElementById(id)) {
75          refs[i].addEventListener('click', smoothScrollTo);
76        }
77      }
78    }
79  }
80
81  /* viewport by observer */
82  let viewport = document.querySelectorAll("[data-type='viewport'], .data-viewport");
83  if (viewport) {
84    let observer = new IntersectionObserver(function(entries) {
85      for (let i=0; i < entries.length; i++) {
86        if (entries[i].isIntersecting) {
87          entries[i].target.classList.add('in-viewport');
88        } else {
89          entries[i].target.classList.remove('in-viewport');
90        }
91      }
92    },
93    {
94      threshold: [0.1],
95      delay: 100
96    });
97    for (let i=0; i<viewport.length; i++) {
98      observer.observe(viewport[i]);
99    }
100  }
101
102  /* sticky header by observer */
103  let stickyHeader = document.querySelector("header[data-type='sticky']");
104  if (stickyHeader) {
105    let observer = new IntersectionObserver(function(entries) {
106      if (entries[0].intersectionRatio < 1) {
107        entries[0].target.classList.add('is-sticky');
108      } else {
109        entries[0].target.classList.remove('is-sticky');
110      }
111    },
112    {
113      threshold: [1]
114    });
115    var positionSticky = window.getComputedStyle(stickyHeader).getPropertyValue("position");
116    let style = window.getComputedStyle(stickyHeader);
117    if (positionSticky == 'sticky') {
118      stickyHeader.style.top = (parseInt(style.getPropertyValue('top'), 10) -1) + 'px';
119      stickyHeader.style.paddingTop = (parseInt(style.getPropertyValue('padding-top'), 10) +1) + 'px';
120      observer.observe(stickyHeader);
121    } else {
122      var scrollPos = 0;
123      var marginTop = - window.getComputedStyle(stickyHeader).getPropertyValue("top") || 0;
124      var height = style.getPropertyValue('height');
125      var main = document.querySelector('main');
126      function getScrollPos() {
127        let pos = 0;
128        var el = stickyHeader;
129        do {
130          pos += el.offsetTop;
131          el = el.offsetParent;
132        } while(el);
133        pos += marginTop;
134        if (pos != 0) {
135          scrollPos = pos;
136        }
137      }
138      function stickyElement() {
139        if ((window.scrollY||window.pageYOffset)>scrollPos) {
140          stickyHeader.classList.add('fixed');
141          stickyHeader.classList.add('is-sticky');
142          main.style.marginTop = height;
143        } else {
144          stickyHeader.classList.remove('fixed');
145          stickyHeader.classList.remove('is-sticky');
146          main.style.marginTop = '';
147        }
148      }
149      window.addEventListener('scroll', stickyElement, supportsPassive ? {capture: false, passive: true}: true);
150      window.addEventListener('resize', function(){ getScrollPos(); stickyElement(); }, supportsPassive ? {capture: false, passive: true}: true);
151      getScrollPos();
152      stickyElement();
153    }
154  }
155
156
157  /*
158   * scroll to top
159   * Only a single Element allowed with data-type="scrolltotop"
160   */
161  var scrolltotop = document.querySelector("[data-type='scrolltotop']");
162  // add scroll event listener to window, to display scrolltotop button
163  // scroll to top is handled by smoothScrollTo
164  if (scrolltotop) {
165    function scrollToTop (event) {
166      let scroll = this ? this.scrollY : window.scrollY;
167      let triggerPoint = scrolltotop.dataset.position || 10;
168      if (scroll > triggerPoint){
169        scrolltotop.dataset.fade = 'in';
170      } else {
171        scrolltotop.dataset.fade = 'out';
172      }
173    }
174    window.addEventListener('scroll', scrollToTop, supportsPassive ? {capture: false, passive: true} : true);
175    if ('scrollBehavior' in document.documentElement.style ) {
176      scrolltotop.addEventListener('click', function(){
177        window.scrollTo(0, 0);
178      });
179    } else {
180      scrolltotop.addEventListener('click', function(){
181        // Smooth scroll fallback for Safari < 15.4
182        let start = Date.now();
183        let to = 0;
184        let from = window.scrollY;
185        let tick = function () {
186          var t = Math.min(1, ((Date.now() - start) / 1000));
187          var eased = t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1;
188          var val = (eased * (to - from)) + from;
189          window.scrollTo(0, val);
190          if (t<1) {
191            window.requestAnimationFrame(tick);
192          }
193        };
194        tick();
195      });
196    }
197    scrollToTop();
198  }
199
200  /* scrolled */
201  // add class scrolled to element if window is scrolled
202  const scrolled = document.querySelectorAll('[data-type="scrolled"]');
203
204  const isScrolled = () => {
205    let value = (window.scrollY||window.pageYOffset) > 0;
206    for (let i=0; i < scrolled.length; i++) {
207      if (value) {
208        scrolled[i].classList.add('scrolled');
209      } else {
210        scrolled[i].classList.remove('scrolled');
211      }
212    }
213  };
214
215  if (scrolled.length > 0) {
216    window.addEventListener('scroll', isScrolled, supportsPassive ? {capture: false, passive: true}: true);
217  }
218})();

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.