PageSourceSearch

https://www.kindermann-textilpflege.de/js/custom.231025091910.js

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