PageSourceSearch

https://besafesuite.com/wp-content/themes/besafe/assets/js/vendor/headroom.js

js besafesuite.com collected 2026-10-06 08:09:14 UTC 11,586 bytes, 438 lines download raw bytes

vendor: 11,586 bytes, lines 1-438
1/*!
2 * headroom.js v0.12.0 - Give your page some headroom. Hide your header until you need it
3 * Copyright (c) 2020 Nick Williams - http://wicky.nillia.ms/headroom.js
4 * License: MIT
5 */
6
7(function (global, factory) {
8    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
9    typeof define === 'function' && define.amd ? define(factory) :
10    (global = global || self, global.Headroom = factory());
11  }(this, function () { 'use strict';
12  
13    function isBrowser() {
14      return typeof window !== "undefined";
15    }
16  
17    /**
18     * Used to detect browser support for adding an event listener with options
19     * Credit: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
20     */
21    function passiveEventsSupported() {
22      var supported = false;
23  
24      try {
25        var options = {
26          // eslint-disable-next-line getter-return
27          get passive() {
28            supported = true;
29          }
30        };
31        window.addEventListener("test", options, options);
32        window.removeEventListener("test", options, options);
33      } catch (err) {
34        supported = false;
35      }
36  
37      return supported;
38    }
39  
40    function isSupported() {
41      return !!(
42        isBrowser() &&
43        function() {}.bind &&
44        "classList" in document.documentElement &&
45        Object.assign &&
46        Object.keys &&
47        requestAnimationFrame
48      );
49    }
50  
51    function isDocument(obj) {
52      return obj.nodeType === 9; // Node.DOCUMENT_NODE === 9
53    }
54  
55    function isWindow(obj) {
56      // `obj === window` or `obj instanceof Window` is not sufficient,
57      // as the obj may be the window of an iframe.
58      return obj && obj.document && isDocument(obj.document);
59    }
60  
61    function windowScroller(win) {
62      var doc = win.document;
63      var body = doc.body;
64      var html = doc.documentElement;
65  
66      return {
67        /**
68         * @see http://james.padolsey.com/javascript/get-document-height-cross-browser/
69         * @return {Number} the scroll height of the document in pixels
70         */
71        scrollHeight: function() {
72          return Math.max(
73            body.scrollHeight,
74            html.scrollHeight,
75            body.offsetHeight,
76            html.offsetHeight,
77            body.clientHeight,
78            html.clientHeight
79          );
80        },
81  
82        /**
83         * @see http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript
84         * @return {Number} the height of the viewport in pixels
85         */
86        height: function() {
87          return win.innerHeight || html.clientHeight || body.clientHeight;
88        },
89  
90        /**
91         * Gets the Y scroll position
92         * @return {Number} pixels the page has scrolled along the Y-axis
93         */
94        scrollY: function() {
95          if (win.pageYOffset !== undefined) {
96            return win.pageYOffset;
97          }
98  
99          return (html || body.parentNode || body).scrollTop;
100        }
101      };
102    }
103  
104    function elementScroller(element) {
105      return {
106        /**
107         * @return {Number} the scroll height of the element in pixels
108         */
109        scrollHeight: function() {
110          return Math.max(
111            element.scrollHeight,
112            element.offsetHeight,
113            element.clientHeight
114          );
115        },
116  
117        /**
118         * @return {Number} the height of the element in pixels
119         */
120        height: function() {
121          return Math.max(element.offsetHeight, element.clientHeight);
122        },
123  
124        /**
125         * Gets the Y scroll position
126         * @return {Number} pixels the element has scrolled along the Y-axis
127         */
128        scrollY: function() {
129          return element.scrollTop;
130        }
131      };
132    }
133  
134    function createScroller(element) {
135      return isWindow(element) ? windowScroller(element) : elementScroller(element);
136    }
137  
138    /**
139     * @param element EventTarget
140     */
141    function trackScroll(element, options, callback) {
142      var isPassiveSupported = passiveEventsSupported();
143      var rafId;
144      var scrolled = false;
145      var scroller = createScroller(element);
146      var lastScrollY = scroller.scrollY();
147      var details = {};
148  
149      function update() {
150        var scrollY = Math.round(scroller.scrollY());
151        var height = scroller.height();
152        var scrollHeight = scroller.scrollHeight();
153  
154        // reuse object for less memory churn
155        details.scrollY = scrollY;
156        details.lastScrollY = lastScrollY;
157        details.direction = scrollY > lastScrollY ? "down" : "up";
158        details.distance = Math.abs(scrollY - lastScrollY);
159        details.isOutOfBounds = scrollY < 0 || scrollY + height > scrollHeight;
160        details.top = scrollY <= options.offset[details.direction];
161        details.bottom = scrollY + height >= scrollHeight;
162        details.toleranceExceeded =
163          details.distance > options.tolerance[details.direction];
164  
165        callback(details);
166  
167        lastScrollY = scrollY;
168        scrolled = false;
169      }
170  
171      function handleScroll() {
172        if (!scrolled) {
173          scrolled = true;
174          rafId = requestAnimationFrame(update);
175        }
176      }
177  
178      var eventOptions = isPassiveSupported
179        ? { passive: true, capture: false }
180        : false;
181  
182      element.addEventListener("scroll", handleScroll, eventOptions);
183      update();
184  
185      return {
186        destroy: function() {
187          cancelAnimationFrame(rafId);
188          element.removeEventListener("scroll", handleScroll, eventOptions);
189        }
190      };
191    }
192  
193    function normalizeUpDown(t) {
194      return t === Object(t) ? t : { down: t, up: t };
195    }
196  
197    /**
198     * UI enhancement for fixed headers.
199     * Hides header when scrolling down
200     * Shows header when scrolling up
201     * @constructor
202     * @param {DOMElement} elem the header element
203     * @param {Object} options options for the widget
204     */
205    function Headroom(elem, options) {
206      options = options || {};
207      Object.assign(this, Headroom.options, options);
208      this.classes = Object.assign({}, Headroom.options.classes, options.classes);
209  
210      this.elem = elem;
211      this.tolerance = normalizeUpDown(this.tolerance);
212      this.offset = normalizeUpDown(this.offset);
213      this.initialised = false;
214      this.frozen = false;
215    }
216    Headroom.prototype = {
217      constructor: Headroom,
218  
219      /**
220       * Start listening to scrolling
221       * @public
222       */
223      init: function() {
224        if (Headroom.cutsTheMustard && !this.initialised) {
225          this.addClass("initial");
226          this.initialised = true;
227  
228          // defer event registration to handle browser
229          // potentially restoring previous scroll position
230          setTimeout(
231            function(self) {
232              self.scrollTracker = trackScroll(
233                self.scroller,
234                { offset: self.offset, tolerance: self.tolerance },
235                self.update.bind(self)
236              );
237            },
238            100,
239            this
240          );
241        }
242  
243        return this;
244      },
245  
246      /**
247       * Destroy the widget, clearing up after itself
248       * @public
249       */
250      destroy: function() {
251        this.initialised = false;
252        Object.keys(this.classes).forEach(this.removeClass, this);
253        this.scrollTracker.destroy();
254      },
255  
256      /**
257       * Unpin the element
258       * @public
259       */
260      unpin: function() {
261        if (this.hasClass("pinned") || !this.hasClass("unpinned")) {
262          this.addClass("unpinned");
263          this.removeClass("pinned");
264  
265          if (this.onUnpin) {
266            this.onUnpin.call(this);
267          }
268        }
269      },
270  
271      /**
272       * Pin the element
273       * @public
274       */
275      pin: function() {
276        if (this.hasClass("unpinned")) {
277          this.addClass("pinned");
278          this.removeClass("unpinned");
279  
280          if (this.onPin) {
281            this.onPin.call(this);
282          }
283        }
284      },
285  
286      /**
287       * Freezes the current state of the widget
288       * @public
289       */
290      freeze: function() {
291        this.frozen = true;
292        this.addClass("frozen");
293      },
294  
295      /**
296       * Re-enables the default behaviour of the widget
297       * @public
298       */
299      unfreeze: function() {
300        this.frozen = false;
301        this.removeClass("frozen");
302      },
303  
304      top: function() {
305        if (!this.hasClass("top")) {
306          this.addClass("top");
307          this.removeClass("notTop");
308  
309          if (this.onTop) {
310            this.onTop.call(this);
311          }
312        }
313      },
314  
315      notTop: function() {
316        if (!this.hasClass("notTop")) {
317          this.addClass("notTop");
318          this.removeClass("top");
319  
320          if (this.onNotTop) {
321            this.onNotTop.call(this);
322          }
323        }
324      },
325  
326      bottom: function() {
327        if (!this.hasClass("bottom")) {
328          this.addClass("bottom");
329          this.removeClass("notBottom");
330  
331          if (this.onBottom) {
332            this.onBottom.call(this);
333          }
334        }
335      },
336  
337      notBottom: function() {
338        if (!this.hasClass("notBottom")) {
339          this.addClass("notBottom");
340          this.removeClass("bottom");
341  
342          if (this.onNotBottom) {
343            this.onNotBottom.call(this);
344          }
345        }
346      },
347  
348      shouldUnpin: function(details) {
349        var scrollingDown = details.direction === "down";
350  
351        return scrollingDown && !details.top && details.toleranceExceeded;
352      },
353  
354      shouldPin: function(details) {
355        var scrollingUp = details.direction === "up";
356  
357        return (scrollingUp && details.toleranceExceeded) || details.top;
358      },
359  
360      addClass: function(className) {
361        this.elem.classList.add.apply(
362          this.elem.classList,
363          this.classes[className].split(" ")
364        );
365      },
366  
367      removeClass: function(className) {
368        this.elem.classList.remove.apply(
369          this.elem.classList,
370          this.classes[className].split(" ")
371        );
372      },
373  
374      hasClass: function(className) {
375        return this.classes[className].split(" ").every(function(cls) {
376          return this.classList.contains(cls);
377        }, this.elem);
378      },
379  
380      update: function(details) {
381        if (details.isOutOfBounds) {
382          // Ignore bouncy scrolling in OSX
383          return;
384        }
385  
386        if (this.frozen === true) {
387          return;
388        }
389  
390        if (details.top) {
391          this.top();
392        } else {
393          this.notTop();
394        }
395  
396        if (details.bottom) {
397          this.bottom();
398        } else {
399          this.notBottom();
400        }
401  
402        if (this.shouldUnpin(details)) {
403          this.unpin();
404        } else if (this.shouldPin(details)) {
405          this.pin();
406        }
407      }
408    };
409  
410    /**
411     * Default options
412     * @type {Object}
413     */
414    Headroom.options = {
415      tolerance: {
416        up: 0,
417        down: 0
418      },
419      offset: 0,
420      scroller: isBrowser() ? window : null,
421      classes: {
422        frozen: "headroom--frozen",
423        pinned: "headroom--pinned",
424        unpinned: "headroom--unpinned",
425        top: "headroom--top",
426        notTop: "headroom--not-top",
427        bottom: "headroom--bottom",
428        notBottom: "headroom--not-bottom",
429        initial: "headroom"
430      }
431    };
432  
433    Headroom.cutsTheMustard = isSupported();
434  
435    return Headroom;
436  
437  }));
438  

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.