PageSourceSearch

https://hallenboccia.de/js/custom.251028102152.js

js hallenboccia.de collected 2026-10-03 18:41:20 UTC 10,798 bytes, 380 lines download raw bytes

1/* JS for preset "Menu V2" */
2(function() {
3	$(function() {
4		$('.menu-wrapper').each(function() {
5			initMenu($(this))
6		});
7	});
8
9	// Make :active pseudo classes work on iOS
10	document.addEventListener("touchstart", function() {}, false);
11
12	const initMenu = function($menuWrapper) {
13		const $body = $('body');
14		const $menu = $('.ed-menu', $menuWrapper);
15		const $menuLinks = $('a', $menu);
16		const $menuTrigger = $('.menu-trigger', $menuWrapper);
17		const $banner = $('.banner').first();
18
19		const smoothScrollOffset = 20;
20		
21		// Set aria attributes
22		$menuTrigger.attr({
23				'aria-expanded': 'false',
24				'aria-controls': $menu.attr('id'),
25		});
26
27		toggleClassOnClick($body.add($menu), $menuTrigger, null, 'open open-menu'); // Keep open on $menu for backward compatibility
28		activateSmoothScroll($menuLinks.add($('.scroll a')), smoothScrollOffset);
29		addClassOnVisibleLinkTargets($menuLinks, 'active', 2 / 3);
30		handleSticky($menuWrapper, 'sticky', $banner);
31	};
32
33	/**
34	 * Observe element's height changes and reload the initMenu() function
35	 *
36	 * @param {HTMLElement} elm Element to observe
37	 * @param {function} callback to call when elmement's height changed
38	 */
39	const observeHeightChange = function(elm, callback) {
40		if (!('ResizeObserver' in window) || elm == null) return;
41
42		const ro = new ResizeObserver(callback);
43		ro.observe(elm);
44	}
45
46	/**
47	 * Toggles class on a target when a trigger is clicked
48	 * 
49	 * @param {jQuery} $target The target to apply the CSS class to
50	 * @param {jQuery} $trigger The Trigger
51	 * @param {jQuery} $closeTrigger Optional close trigger
52	 * @param {string} cssClass CSS Class to toggle on the target
53	 */
54	const toggleClassOnClick = function($target, $trigger, $closeTrigger, cssClass) {
55
56		// Reset in case class "open" was saved accidentally
57		$target.removeClass(cssClass);
58		$trigger.removeClass(cssClass).attr('aria-expanded', 'false');
59
60		// Click on trigger toggles class "open"
61		$trigger.off('.toggle').on('click.toggle', function() {
62			const isExpanded = $(this).attr('aria-expanded') === 'true';
63			$(this).toggleClass(cssClass).attr('aria-expanded', !isExpanded);
64			$target.toggleClass(cssClass);
65		});
66
67		// Close target when link inside is clicked
68		$target.find('a').click(function() {
69			$target.removeClass(cssClass);
70			$trigger.removeClass(cssClass).attr('aria-expanded', 'false');
71		});
72
73		if (!$closeTrigger || !$closeTrigger.length) {
74			return;
75		}
76
77		$closeTrigger.click(function() {
78			$target.removeClass(cssClass);
79			$trigger.removeClass(cssClass).attr('aria-expanded', 'false');
80		});
81	};
82
83	/**
84	 * Smooth scroll to link targets
85	 * 
86	 * @param {jQuery} $scrollLinks The links
87	 * @param {jQuery} scrollOffset Offset to subtract from the scroll target position (e.g. for fixed positioned elements like a menu)
88	 */
89	const activateSmoothScroll = function($scrollLinks, scrollOffset) {
90		if (typeof scrollOffset === 'undefined') {
91			scrollOffset = 0;
92		}
93
94		const determineTarget = function($trigger, hash) {
95			if (hash == '#!next') {
96				return $trigger.closest('.ed-element').next();
97			}
98
99			return $(hash);
100		}
101
102		$scrollLinks.click(function(e) {
103			const $target = determineTarget($(this), this.hash);
104			if (!$target.length) return;
105			e.preventDefault();
106
107			viewport.scrollTo($target, 'top', 500, 0);
108
109		});
110	};
111
112	/**
113	 * We are using the fill property on an element to pass user's choices from CSS to JavaScript
114	 * 
115	 * @param {jQuery} $element
116	 */
117	const getStickyMode = function($element) {
118		const fillValue = getComputedStyle($element[0]).fill;
119
120		return fillValue === 'rgb(255, 0, 0)' ?
121			'sticky_banner' :
122			fillValue === 'rgb(0, 255, 0)' ?
123			'sticky_menu' :
124			fillValue === 'rgb(0, 0, 255)' ?
125			'sticky_instant' :
126			fillValue === 'rgb(255, 255, 255)' ?
127			'sticky_reverse' :
128			'sticky_none';
129	};
130
131	/**
132	 * Adds a class to an element when not currently visible
133	 * 
134	 * @param {jQuery} $element The element to handle stickyness for
135	 * @param {string} cssClass The actual CSS class to be applied to the element when it's above a certain scroll position
136	 * @param {jQuery} $banner A banner to reference the scroll position to
137	 */
138	const handleSticky = function($element, cssClass, $banner) {
139		let triggerPos = 0,
140			offset = 0;
141		let menuWrapperHeight = $element.outerHeight();
142		let mode;
143		let prevScroll = 0;
144		$element.removeClass(cssClass);
145		
146		const toggleSpacer = function(toggle) {
147			document.body.style.setProperty('--spacer-height', toggle ? menuWrapperHeight + 'px' : '');
148		};
149
150		const handleScroll = function() {
151			if (!$element.length || mode === 'sticky_none') return;
152			//if (!$element.length || mode === 'sticky_none' || mode === 'sticky_instant') return;
153
154			const isReverse = mode === 'sticky_reverse',
155				curScroll = viewport.getScrollTop();
156
157			if (triggerPos <= curScroll && (!isReverse || prevScroll > curScroll)) {
158				$element.addClass(cssClass);
159				toggleSpacer(true);
160			} else {
161				$element.removeClass(cssClass);
162				toggleSpacer(false);
163			}
164
165			prevScroll = curScroll;
166		};
167		
168		const updateOffset = function() {
169			mode = getStickyMode($element);
170			menuWrapperHeight = $element.outerHeight();
171			if (!$element.hasClass(cssClass)) {
172				offset = $element.offset().top;
173			}
174			if (mode === 'sticky_banner' && !$banner.length) {
175				mode = 'sticky_menu';
176			}
177			if (mode === 'sticky_banner') {
178				triggerPos = $banner.offset().top + ($banner.length ? $banner.outerHeight() : $element.outerHeight());
179			}
180			if (mode === 'sticky_menu' || mode === 'sticky_reverse') {
181				triggerPos = offset + $element.outerHeight();
182			}
183			if (mode === 'sticky_instant') {
184				triggerPos = offset;
185			}
186			
187			handleScroll();
188		}
189		
190		viewport.observe('resize', updateOffset);
191		viewport.observe('animation.end', updateOffset);
192		observeHeightChange($element[0], updateOffset);
193		updateOffset();
194		
195		viewport.observe('scroll', handleScroll);
196		handleScroll();
197	};
198
199	/**
200	 * Adds a class to links whose target is currently inside the viewport
201	 * 
202	 * @param {jQuery} $links Link(s) to be observed
203	 * @param {string} cssClass CSS Class to be applied
204	 * @param {float} sectionViewportRatio Ratio by which the target should be within the viewport
205	 */
206	const addClassOnVisibleLinkTargets = function($links, cssClass, sectionViewportRatio) {
207		if (typeof sectionViewportRatio === 'undefined') {
208			sectionViewportRatio = 1 / 2;
209		}
210
211		const menuTargets = [];
212		const activeLink = $links.filter('.active');
213
214		const links = $links.filter(function() {
215			const $target = $(this.hash);
216			if (!$target.length) {
217				return false;
218			}
219
220			// Cache offset position to improve performance (update on resize)		
221			const updateOffset = function() {
222				$target.data('offset', $target.offset().top);
223			};
224
225			viewport.observe('resize', updateOffset);
226			viewport.observe('animation.end', updateOffset);
227			updateOffset();
228
229			menuTargets.push($target);
230			return true;
231		});
232
233		// No hash links found, so don't handle it at all
234		if (!links.length) {
235			return;
236		}
237
238		const checkVisibility = function() {
239			$links.removeClass('active');
240
241			// Check section position reversely
242			for (let i = menuTargets.length - 1; i >= 0; i--) {
243				const desiredScrollPosition = menuTargets[i].data('offset') - viewport.getHeight() * (1 - sectionViewportRatio);
244				if (viewport.getScrollTop() >= desiredScrollPosition && menuTargets[i][0].offsetParent !== null) {
245					links.eq(i).addClass(cssClass);
246					return;
247				}
248			}
249
250			// Fallback to originally active item
251			activeLink.addClass(cssClass);
252		};
253
254		viewport.observe('scroll', checkVisibility);
255		checkVisibility();
256	};
257})();
258/* End JS for preset "Menu V2" */
259
260/* JS for preset "Counter V2" */
261$(function() {
262	EasingFunctions = {
263		// no easing, no acceleration
264		linear: function(t) {
265			return t
266		},
267		// accelerating from zero velocity
268		easeInQuad: function(t) {
269			return t * t
270		},
271		// decelerating to zero velocity
272		easeOutQuad: function(t) {
273			return t * (2 - t)
274		},
275		// acceleration until halfway, then deceleration
276		easeInOutQuad: function(t) {
277			return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t
278		},
279		// accelerating from zero velocity 
280		easeInCubic: function(t) {
281			return t * t * t
282		},
283		// decelerating to zero velocity 
284		easeOutCubic: function(t) {
285			return (--t) * t * t + 1
286		},
287		// acceleration until halfway, then deceleration 
288		easeInOutCubic: function(t) {
289			return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
290		},
291		// accelerating from zero velocity 
292		easeInQuart: function(t) {
293			return t * t * t * t
294		},
295		// decelerating to zero velocity 
296		easeOutQuart: function(t) {
297			return 1 - (--t) * t * t * t
298		},
299		// acceleration until halfway, then deceleration
300		easeInOutQuart: function(t) {
301			return t < .5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t
302		},
303		// accelerating from zero velocity
304		easeInQuint: function(t) {
305			return t * t * t * t * t
306		},
307		// decelerating to zero velocity
308		easeOutQuint: function(t) {
309			return 1 + (--t) * t * t * t * t
310		},
311		// acceleration until halfway, then deceleration 
312		easeInOutQuint: function(t) {
313			return t < .5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t
314		}
315	}
316    
317	$('[data-count]').each(function() {
318		var $target = $(this);
319		var offset = 0;
320		
321		var duration = 2000;
322		var interval = Math.floor(duration / 60);
323		var steps = Math.ceil(duration / interval);
324		var max = $target.data('count');
325		
326		var run = false, handle;
327		
328		// Cache offset position to improve performance (update on resize)		
329		var updateOffset = function() {
330			offset = $target.offset().top + $target.height()/2;
331		};
332		viewport.observe('resize', updateOffset);
333		viewport.observe('animation.end', updateOffset);
334		updateOffset();
335		
336		var resetCounter = function() {
337		    $target.html('0');
338		    run = false;
339		};
340		
341		var finishCounter = function() {
342		    $target.html(max);
343			window.clearInterval(handle);
344		};
345
346		var startCounter = function() {
347			if (run) return;
348
349			run = true;
350			var i = 0;
351			handle = window.setInterval(function() {
352                var newCount = Math.round(max * EasingFunctions.easeOutCubic(++i / steps));
353                if (newCount >= max) {
354                    return finishCounter();
355                }
356				$target.html(newCount);
357			}, interval);
358		};
359		
360		var checkVisiblity = function() {
361		    var t = viewport.getScrollTop();
362		    var h = viewport.getHeight();
363		    if (t < offset && offset < t+h) {
364				!run && startCounter();
365			} else {
366			    run && resetCounter();
367			}
368		};
369		
370		viewport.observe('scroll', checkVisiblity);
371		checkVisiblity();
372	});
373});
374/* End JS for preset "Counter V2" */
375
376/* JS for preset "Marquee V2" */
377$(function() {
378   $('.marquee-wrap').attr('data-items', $('.marquee-wrap > .inner').children().length);
379});
380/* End JS for preset "Marquee V2" */

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.