PageSourceSearch

https://www.denkmalschutz.de/_assets/d74c55fa1039d323b05304b931d8ea62/Js/n4_input_reset.js?1782207863

js denkmalschutz.de collected 2026-09-24 09:43:32 UTC 28,900 bytes, 815 lines download raw bytes

1function norm4_InputReset(obj) {
2	this.obj = obj;
3	this.position = 0;
4	this.default = '';
5	this.type = '';
6	this.followUpClickSuppressor = null;
7
8	this.blockClearEvent = function(event) {
9		if (!event) return false;
10		event.preventDefault();
11		event.stopPropagation();
12		if (event.stopImmediatePropagation) event.stopImmediatePropagation();
13		return false;
14	}
15
16	this.suppressFollowUpClick = function() {
17		var that = this;
18		var suppress = function(event) {
19			that.blockClearEvent(event);
20			document.removeEventListener("click", suppress, true);
21			that.followUpClickSuppressor = null;
22		};
23
24		if (this.followUpClickSuppressor) {
25			document.removeEventListener("click", this.followUpClickSuppressor, true);
26		}
27
28		this.followUpClickSuppressor = suppress;
29		document.addEventListener("click", suppress, true);
30		setTimeout(function() {
31			if (that.followUpClickSuppressor === suppress) {
32				document.removeEventListener("click", suppress, true);
33				that.followUpClickSuppressor = null;
34			}
35		}, 500);
36	}
37
38	this.activate = function() {
39		var that = this;
40		if (this.obj.parent().find(".deactivate_inputreset").length > 0) return;
41		this.obj.parent().append('<span class="deactivate_inputreset position' + this.position + ' form-control-clear"></span>');
42		this.obj.parent().find(".deactivate_inputreset")
43			.on("pointerdown touchstart mousedown", function(event) {
44				return that.blockClearEvent(event);
45			})
46			.on("pointerup touchend click", function(event) {
47				that.blockClearEvent(event);
48				if (that.clearHandledAt && Date.now() - that.clearHandledAt < 500) return false;
49				that.clearHandledAt = Date.now();
50				if (event.type !== "click") that.suppressFollowUpClick();
51				that.deactivate();
52				$('#currentPage').val(1);
53				return false;
54			});
55		this.obj.parent().addClass("has-clear");
56		if (this.type == 'selectpicker') {
57			this.obj.selectpicker('refresh');
58		}
59
60	}
61	this.deactivate = function() {
62
63		this.obj.closest(".has-clear").find(".deactivate_inputreset").remove();
64		this.obj.closest(".has-clear").removeClass("has-clear");
65		var bugfix = $(window).scrollTop();//unerklärliches scrolling at monuments
66
67		this.setDefault();
68		if (this.type == 'selectpicker') this.obj.trigger("changed.bs.select");
69		if (this.type != 'input') this.obj.trigger("change");
70		if (this.type == 'input') this.obj.keyup();
71		if (this.obj.closest(".tx-nc-monuments")) $(window).scrollTop(bugfix);
72	}
73
74	this.reset = function() {
75
76		this.obj.closest(".has-clear").find(".deactivate_inputreset").remove();
77		this.obj.closest(".has-clear").removeClass("has-clear");
78		var bugfix = $(window).scrollTop();//unerklärliches scrolling at monuments
79		this.setDefault();
80		if (this.obj.closest(".tx-nc-monuments")) $(window).scrollTop(bugfix);
81	}
82
83	this.update = function() {
84		if (this.default != this.getValue()) this.activate();
85		else {
86			this.obj.closest(".has-clear").find(".deactivate_inputreset").remove();
87			this.obj.closest(".has-clear").removeClass("has-clear");
88			if (this.type == 'selectpicker') {
89				this.obj.selectpicker('refresh');
90			}
91		}
92	}
93
94	this.normalizeValue = function(value) {
95		if (Array.isArray(value)) {
96			return value.map(function(v) { return String(v).trim(); }).sort().join(",");
97		}
98		if (value === null || typeof value === "undefined") return "";
99		return String(value).trim();
100	}
101
102
103	this.setDefault = function() {
104		if (this.obj.data("inputreset-clear")) {
105			eval(this.obj.data("inputreset-clear"));
106			return;
107		}
108
109		switch (this.type) {
110			case 'input':
111				this.obj.val(this.default); break;
112			case 'easepick':
113				eval(this.obj.data("inputreset-clear"));
114				break;
115			case 'selectpicker':
116				var values = this.default === "" ? [] : String(this.default).split(",");
117				if (this.default === "" && this.obj.prop("multiple") && this.obj.find("option").length > 0) {
118					var firstOption = this.obj.find("option").first();
119					var firstValue = String(firstOption.val()).trim();
120					var firstText = String(firstOption.text()).trim();
121					if (/^Alle\b/.test(firstText) || ["", "0", "-1"].indexOf(firstValue) >= 0) {
122						values = [firstValue];
123					}
124				}
125				this.obj.selectpicker('val', this.obj.prop("multiple") ? values : this.default);
126				this.obj.selectpicker('refresh');
127				break;
128			case 'select':
129				this.obj.prop("selectedIndex", this.default); break;
130
131		}
132
133	}
134
135	this.getValue = function() {
136
137		switch (this.type) {
138			case 'input':
139			case 'easepick':
140				return this.obj.val();
141			case 'selectpicker':
142				return this.normalizeValue(this.obj.val() || []);
143			case 'select':
144				return this.obj.prop("selectedIndex");
145
146		}
147
148
149	}
150
151
152	this.setType = function() {
153		if (this.obj.is('input')) {
154			if (this.obj.attr("id") == 'easepick' || this.obj.hasClass("easepick"))
155				this.type = 'easepick';
156			else this.type = 'input';
157
158		} else if (this.obj.is('select')) {
159			if (this.obj.hasClass("selectpicker"))
160				this.type = 'selectpicker';
161			else this.type = 'select';
162		}
163	}
164
165
166	this.setChange = function() {
167		var that = this;
168		switch (this.type) {
169			case 'input':
170				this.obj.keyup(function() {
171					if (that.getValue() != that.default) { that.activate(); } else { that.reset();}
172				});
173				break;
174			case 'selectpicker':
175			case 'select':
176			case 'selectpicker':
177				this.obj.change(function() {
178					if (that.getValue() != that.default) { that.activate(); } else { that.reset(); }
179				}); break;
180			case 'easepick':
181				this.obj.change(function() {
182					if (that.getValue() != that.default) { that.activate(); } else { that.reset(); }
183				}); break;
184
185		}
186
187	}
188
189	this.init = function() {
190		var existing = this.obj.data("norm4InputReset");
191		if (existing && typeof existing.update === "function") {
192			existing.update();
193			return;
194		}
195
196		this.position = this.obj.data("inputreset");
197		this.setType();
198		if (undefined !== this.obj.attr("data-default"))
199			this.default = this.obj.data("default");
200		else this.default = this.getValue();
201
202		this.setChange();
203		this.obj.data("norm4InputReset", this);
204		this.update();
205
206
207	}
208	this.init();
209}
210
211$(document).ready(function() {
212
213	function getSelectpickerValues($select) {
214		var values = ($.fn.selectpicker && $select.data("selectpicker")) ? $select.selectpicker("val") : $select.val();
215		if (!Array.isArray(values)) values = values || values === 0 ? [values] : [];
216		return values.map(function(value) { return String(value).trim(); });
217	}
218
219	function getAllOptionInfo($select) {
220		var $firstOption = $select.find("option").first();
221		if ($firstOption.length === 0) return null;
222
223		var text = String($firstOption.text() || "").trim();
224		if (!/^Alle\b/i.test(text)) return null;
225
226		return {
227			index: $select.find("option").index($firstOption),
228			value: String($firstOption.val()).trim()
229		};
230	}
231
232	function closeSelectpickerDropdown($select) {
233		var $wrapper = $select.closest(".bootstrap-select");
234		var $button = $wrapper.children("button.dropdown-toggle");
235
236		if ($.fn.dropdown && $button.length > 0) {
237			$button.dropdown("hide");
238			return;
239		}
240
241		$wrapper.removeClass("show");
242		$wrapper.children(".dropdown-menu").removeClass("show");
243		$button.attr("aria-expanded", "false");
244	}
245
246	function getVisibleHeight(selector) {
247		var element = document.querySelector(selector);
248		if (!element) return 0;
249
250		var style = window.getComputedStyle(element);
251		if (style.display === "none" || style.visibility === "hidden") return 0;
252
253		var rect = element.getBoundingClientRect();
254		return Math.max(0, Math.ceil(rect.height));
255	}
256
257	function getVisibleViewportBottom(selector) {
258		var element = document.querySelector(selector);
259		if (!element) return 0;
260
261		var style = window.getComputedStyle(element);
262		if (style.display === "none" || style.visibility === "hidden") return 0;
263
264		var rect = element.getBoundingClientRect();
265		if (rect.bottom <= 0 || rect.top >= window.innerHeight) return 0;
266
267		return Math.max(0, Math.ceil(Math.min(window.innerHeight, rect.bottom)));
268	}
269
270	function getSelectpickerHeaderOffset() {
271		var rootStyle = getComputedStyle(document.documentElement);
272		var headerOffset = parseFloat(rootStyle.getPropertyValue("--sticky-header-height")) || 75;
273		var extraOffset = parseFloat(rootStyle.getPropertyValue("--sticky-filter-extra-offset")) || 0;
274		headerOffset = Math.max(
275			headerOffset,
276			getVisibleHeight(".sticky-header.smaller"),
277			getVisibleViewportBottom("header .sticky-header")
278		);
279
280		if (extraOffset === 0 && window.innerWidth < 769) {
281			var helper = document.querySelector(".menu-sidebar-helper.d-md-none");
282			if (helper) {
283				var helperStyle = window.getComputedStyle(helper);
284				if (helperStyle.display !== "none" && helperStyle.visibility !== "hidden") {
285					var helperRect = helper.getBoundingClientRect();
286					extraOffset = helperRect.height > 0 ? Math.max(0, Math.ceil(helperRect.bottom - headerOffset)) : 0;
287				}
288			}
289		}
290
291		return headerOffset + extraOffset;
292	}
293
294	function getSelectpickerWindowPadding() {
295		var topPadding = Math.ceil(getSelectpickerHeaderOffset() + 44);
296		return [topPadding, 8, 16, 8];
297	}
298
299	function updateSelectpickerMenuSize($select) {
300		if (!$.fn.selectpicker || !$select.data("selectpicker")) return;
301
302		var selectpicker = $select.data("selectpicker");
303		selectpicker.options.windowPadding = getSelectpickerWindowPadding();
304
305		if (typeof selectpicker.setSize === "function") {
306			selectpicker.setSize(true);
307		} else if (typeof selectpicker.setMenuSize === "function") {
308			selectpicker.setMenuSize();
309		}
310
311		restoreSelectpickerAllOption($select);
312	}
313
314	function restoreSelectpickerAllOption($select) {
315		if (!$.fn.selectpicker || !$select.data("selectpicker")) return;
316
317		var firstOption = getAllOptionInfo($select);
318		if (!firstOption) return;
319
320		var selectpicker = $select.data("selectpicker");
321		var firstData = selectpicker.selectpicker && selectpicker.selectpicker.main && selectpicker.selectpicker.main.data && selectpicker.selectpicker.main.data[firstOption.index];
322		var firstElement = firstData && firstData.element;
323		var menuInner = selectpicker.$menuInner && selectpicker.$menuInner.get(0);
324		var list = menuInner && menuInner.querySelector("ul.dropdown-menu");
325
326		if (!firstElement || !list) return;
327
328		var firstRenderedItem = list.querySelector("li");
329		var firstRenderedText = firstRenderedItem ? String(firstRenderedItem.innerText || firstRenderedItem.textContent || "").trim() : "";
330		var firstOptionText = String($select.find("option").eq(firstOption.index).text() || "").trim();
331		if (firstRenderedText === firstOptionText) return;
332
333		list.insertBefore(firstElement, list.firstElementChild);
334	}
335
336	function clampSelectpickerMenuToViewport($select) {
337		if (!$.fn.selectpicker || !$select.data("selectpicker")) return;
338
339		var selectpicker = $select.data("selectpicker");
340		if (!selectpicker.$menu || !selectpicker.$menuInner) return;
341
342		var menu = selectpicker.$menu.get(0);
343		var inner = selectpicker.$menuInner.get(0);
344		if (!menu || !inner || !selectpicker.$menu.hasClass("show")) return;
345
346		var safeTop = Math.ceil(getSelectpickerHeaderOffset() + 12);
347		var safeBottom = Math.floor(window.innerHeight - 16);
348		var menuRect = menu.getBoundingClientRect();
349		var innerRect = inner.getBoundingClientRect();
350		var overflowTop = Math.ceil(safeTop - menuRect.top);
351		var overflowBottom = Math.ceil(menuRect.bottom - safeBottom);
352		var reduction = Math.max(overflowTop, overflowBottom, 0);
353
354		if (reduction <= 0) return;
355
356		var menuMaxHeight = parseFloat(menu.style.maxHeight) || menuRect.height;
357		var innerMaxHeight = parseFloat(inner.style.maxHeight) || innerRect.height;
358		var minMenuHeight = Math.min(140, Math.max(80, safeBottom - safeTop));
359
360		selectpicker.$menu.css("max-height", Math.max(minMenuHeight, menuMaxHeight - reduction) + "px");
361		selectpicker.$menuInner.css("max-height", Math.max(1, innerMaxHeight - reduction) + "px");
362
363		if (selectpicker.dropdown && selectpicker.dropdown._popper && typeof selectpicker.dropdown._popper.update === "function") {
364			selectpicker.dropdown._popper.update();
365		}
366	}
367
368	function scheduleSelectpickerMenuSizeUpdate($select) {
369		updateSelectpickerMenuSize($select);
370		clampSelectpickerMenuToViewport($select);
371
372		if (window.requestAnimationFrame) {
373			window.requestAnimationFrame(function() {
374				updateSelectpickerMenuSize($select);
375				clampSelectpickerMenuToViewport($select);
376				window.requestAnimationFrame(function() {
377					clampSelectpickerMenuToViewport($select);
378				});
379			});
380		}
381	}
382
383	function updateOpenSelectpickerMenus() {
384		$("select.selectpicker").each(function() {
385			var $select = $(this);
386			var $wrapper = $select.closest(".bootstrap-select");
387			var selectpicker = $select.data("selectpicker");
388			var hasOpenMenu = selectpicker && selectpicker.$menu && selectpicker.$menu.hasClass("show");
389			if (!$wrapper.hasClass("show") && !$wrapper.children(".dropdown-menu").hasClass("show") && !hasOpenMenu) return;
390
391			updateSelectpickerMenuSize($select);
392			clampSelectpickerMenuToViewport($select);
393		});
394	}
395
396	var selectpickerMenuSizeFrame = null;
397
398	function scheduleOpenSelectpickerMenuSizeUpdate() {
399		if (selectpickerMenuSizeFrame !== null) return;
400
401		if (window.requestAnimationFrame) {
402			selectpickerMenuSizeFrame = window.requestAnimationFrame(function() {
403				selectpickerMenuSizeFrame = null;
404				updateOpenSelectpickerMenus();
405			});
406			return;
407		}
408
409		selectpickerMenuSizeFrame = window.setTimeout(function() {
410			selectpickerMenuSizeFrame = null;
411			updateOpenSelectpickerMenus();
412		}, 0);
413	}
414
415	$(document).on("changed.bs.select", "select.selectpicker[multiple]", function() {
416		var $select = $(this);
417		if (!$.fn.selectpicker || !$select.data("selectpicker")) return;
418
419		var allOption = getAllOptionInfo($select);
420		if (!allOption) return;
421
422		setTimeout(function() {
423			var values = getSelectpickerValues($select);
424			if (values.length !== 1 || values[0] !== allOption.value) return;
425			closeSelectpickerDropdown($select);
426		}, 0);
427	});
428
429	$(document).on("show.bs.select shown.bs.select", "select.selectpicker", function() {
430		var $selectpicker = $(this).closest(".bootstrap-select");
431		$selectpicker.addClass("selectpicker-open");
432		$selectpicker.closest(".sticky-filter-wrapper").addClass("filter-dropdown-open");
433		scheduleSelectpickerMenuSizeUpdate($(this));
434	});
435
436		$(document).on("hide.bs.select hidden.bs.select", "select.selectpicker", function() {
437			var $selectpicker = $(this).closest(".bootstrap-select");
438			var $filterWrapper = $selectpicker.closest(".sticky-filter-wrapper");
439			$selectpicker.removeClass("selectpicker-open");
440			if ($filterWrapper.find(".bootstrap-select.selectpicker-open").length === 0) {
441				$filterWrapper.removeClass("filter-dropdown-open");
442			}
443		});
444
445		$(window).on("resize orientationchange scroll", scheduleOpenSelectpickerMenuSizeUpdate);
446
447		function initMobileRevealStickyFilters() {
448			var maxMobileWidth = 768;
449			var revealDelta = 50;
450			var hideDelta = 50;
451			var protectionReserve = 32;
452			var $filters = $(".sticky-filter-wrapper");
453			var lastScrollY = Math.max(0, Math.round(window.scrollY || window.pageYOffset || 0));
454			var lastDirection = 0;
455			var directionDelta = 0;
456			var ticking = false;
457			var resizeFrame = null;
458			var touchStartY = null;
459
460			function isMobileFilterViewport() {
461				return window.matchMedia && window.matchMedia("(max-width: " + maxMobileWidth + "px)").matches;
462			}
463
464			function isMobileStickyFilterEnabled() {
465				var root = document.documentElement;
466				var body = document.body;
467
468				// Customer switch: set window.norm4DisableMobileStickyFilter = true to disable mobile filter reveal.
469				return window.norm4MobileStickyFilterEnabled !== false
470					&& window.norm4DisableMobileStickyFilter !== true
471					&& (!root || root.getAttribute("data-mobile-sticky-filter") !== "0")
472					&& (!body || body.getAttribute("data-mobile-sticky-filter") !== "0");
473			}
474
475			function getScrollY() {
476				return Math.max(0, Math.round(window.scrollY || window.pageYOffset || 0));
477			}
478
479			function refreshFilters() {
480				$filters = $(".sticky-filter-wrapper");
481				if (!isMobileStickyFilterEnabled()) {
482					resetFilters();
483					return;
484				}
485				$filters.addClass("mobile-filter-scroll-ready");
486				updateFilters(true);
487			}
488
489			function resetFilters() {
490				$filters.removeClass("mobile-filter-scroll-ready mobile-filter-sticky mobile-filter-control-active mobile-filter-slide-in mobile-filter-slide-out mobile-filter-shadow mobile-filter-force-relative");
491			}
492
493			function releaseMobileStickyFilters(scope) {
494				if (!isMobileFilterViewport()) return;
495				var $targetFilters = scope ? $(scope).closest(".sticky-filter-wrapper") : $filters;
496				if (scope && $targetFilters.length === 0) $targetFilters = $(scope).find(".sticky-filter-wrapper");
497				if ($targetFilters.length === 0) return;
498
499				$targetFilters.each(function() {
500					if (this.contains(document.activeElement) && document.activeElement && typeof document.activeElement.blur === "function") {
501						document.activeElement.blur();
502					}
503					clearSlideOutTimer(this);
504					this.classList.add("mobile-filter-force-relative");
505					this.classList.remove("mobile-filter-sticky");
506					this.classList.remove("mobile-filter-control-active");
507					this.classList.remove("mobile-filter-slide-in");
508					this.classList.remove("mobile-filter-slide-out");
509					this.classList.remove("mobile-filter-shadow");
510					this.classList.remove("filter-dropdown-open");
511					$(this).find(".selectpicker-open").removeClass("selectpicker-open");
512					this.mobileFilterReturnZoneReached = false;
513					updateNaturalFilterPosition(this, getScrollY());
514				});
515
516				lastScrollY = getScrollY();
517				lastDirection = 0;
518				directionDelta = 0;
519			}
520
521			function clearControlActiveFilters() {
522				$filters.removeClass("mobile-filter-control-active");
523			}
524
525			function clearSlideOutTimer(element) {
526				if (!element.mobileFilterSlideOutTimer) return;
527				window.clearTimeout(element.mobileFilterSlideOutTimer);
528				element.mobileFilterSlideOutTimer = null;
529			}
530
531			function finishSlideOut(element) {
532				clearSlideOutTimer(element);
533				element.classList.remove("mobile-filter-sticky");
534				element.classList.remove("mobile-filter-slide-in");
535				element.classList.remove("mobile-filter-slide-out");
536				element.classList.remove("mobile-filter-shadow");
537				element.mobileFilterReturnZoneReached = false;
538			}
539
540			function startSlideOut(element) {
541				if (!element.classList.contains("mobile-filter-sticky")) {
542					finishSlideOut(element);
543					return;
544				}
545
546				if (element.classList.contains("mobile-filter-slide-out")) return;
547
548				element.classList.remove("mobile-filter-slide-in");
549				element.classList.add("mobile-filter-slide-out");
550				clearSlideOutTimer(element);
551				element.mobileFilterSlideOutTimer = window.setTimeout(function() {
552					if (element.classList.contains("mobile-filter-slide-out")) finishSlideOut(element);
553				}, 560);
554			}
555
556			function cancelSlideOut(element) {
557				clearSlideOutTimer(element);
558				element.classList.remove("mobile-filter-slide-out");
559			}
560
561			function hasOpenDropdown(element) {
562				return element.classList.contains("filter-dropdown-open")
563					|| element.querySelector(".selectpicker-open")
564					|| element.querySelector(".bootstrap-select.show")
565					|| element.querySelector(".bootstrap-select.dropup.show")
566					|| element.querySelector(".bootstrap-select > .dropdown-menu.show");
567			}
568
569			function hasFocusedControl(element) {
570				return element.contains(document.activeElement);
571			}
572
573			function hasActiveFilters(element) {
574				var activeFilter = element.querySelector(".filter.has-active-filters");
575				var resetButton = element.querySelector(".filter-reset-button");
576				return !!activeFilter || !!(resetButton && resetButton.getAttribute("aria-disabled") === "fal
576se");
577			}
578
579			function updateNaturalFilterPosition(element, scrollY) {
580				if (element.classList.contains("mobile-filter-sticky") || element.classList.contains("mobile-filter-slide-in") || element.classList.contains("mobile-filter-slide-out")) return;
581				var rect = element.getBoundingClientRect();
582				element.mobileFilterNaturalTopY = rect.top + scrollY;
583				element.mobileFilterNaturalBottomY = rect.bottom + scrollY;
584			}
585
586			function updateStickyShadow(element, scrollY) {
587				if (!element.classList.contains("mobile-filter-sticky")) {
588					element.classList.remove("mobile-filter-shadow");
589					return;
590				}
591
592				if (typeof element.mobileFilterNaturalBottomY === "undefined") {
593					element.classList.add("mobile-filter-shadow");
594					return;
595				}
596
597				var shadowEndY = Math.max(0, Math.ceil(element.mobileFilterNaturalBottomY - getSelectpickerHeaderOffset()));
598				element.classList.toggle("mobile-filter-shadow", scrollY > shadowEndY);
599			}
600
601			function hasReachedNaturalFilterArea(element, scrollY) {
602				if (typeof element.mobileFilterNaturalBottomY === "undefined") return false;
603				return element.mobileFilterNaturalBottomY - scrollY > getSelectpickerHeaderOffset();
604			}
605
606			function isPastFilterRevealDistance(element, scrollY) {
607				updateNaturalFilterPosition(element, scrollY);
608				var rect = element.getBoundingClientRect();
609				var filterBottomY = typeof element.mobileFilterNaturalBottomY === "undefined" ? rect.bottom + scrollY : element.mobileFilterNaturalBottomY;
610				var revealDistance = Math.max(0, Math.ceil(rect.height * 2));
611				var headerOffset = getSelectpickerHeaderOffset();
612				return scrollY >= Math.ceil(filterBottomY + revealDistance + headerOffset);
613			}
614
615			function getFilterProtectionZone(element) {
616				var rect = element.getBoundingClientRect();
617				return Math.ceil(rect.height + getSelectpickerHeaderOffset() + protectionReserve);
618			}
619
620			function getRevealThreshold(element) {
621				return Math.max(revealDelta, getFilterProtectionZone(element));
622			}
623
624			function getHideThreshold(element) {
625				return Math.max(hideDelta, getFilterProtectionZone(element));
626			}
627
628			function updateFilters(force) {
629				ticking = false;
630				if ($filters.length === 0) return;
631
632				if (!isMobileStickyFilterEnabled() || !isMobileFilterViewport()) {
633					resetFilters();
634					return;
635				}
636
637				var scrollY = getScrollY();
638				var scrollDiff = scrollY - lastScrollY;
639				var direction = scrollDiff > 0 ? 1 : (scrollDiff < 0 ? -1 : lastDirection);
640
641				if (direction !== 0) {
642					if (direction !== lastDirection) {
643						directionDelta = Math.abs(scrollDiff);
644						lastDirection = direction;
645					} else {
646						directionDelta += Math.abs(scrollDiff);
647					}
648				}
649				lastScrollY = scrollY;
650
651				$filters.each(function() {
652					var element = this;
653					element.classList.add("mobile-filter-scroll-ready");
654					updateNaturalFilterPosition(element, scrollY);
655
656					if (scrollY <= 0) {
657						clearSlideOutTimer(element);
658						element.classList.remove("mobile-filter-sticky");
659						element.classList.remove("mobile-filter-control-active");
660						element.classList.remove("mobile-filter-slide-in");
661						element.classList.remove("mobile-filter-slide-out");
662						element.classList.remove("mobile-filter-shadow");
663						element.classList.remove("mobile-filter-force-relative");
664						element.mobileFilterReturnZoneReached = false;
665						return;
666					}
667
668					if (element.classList.contains("mobile-filter-force-relative")) {
669						if (direction > 0 && isPastFilterRevealDistance(element, scrollY)) {
670							element.classList.remove("mobile-filter-force-relative");
671						} else {
672							clearSlideOutTimer(element);
673							element.classList.remove("mobile-filter-sticky");
674							element.classList.remove("mobile-filter-control-active");
675							element.classList.remove("mobile-filter-slide-in");
676							element.classList.remove("mobile-filter-slide-out");
677							element.classList.remove("mobile-filter-shadow");
678							return;
679						}
680					}
681
682					if (!force && direction > 0 && element.classList.contains("mobile-filter-sticky") && element.mobileFilterReturnZoneReached && !hasOpenDropdown(element) && !hasFocusedControl(element)) {
683						finishSlideOut(element);
684						return;
685					}
686
687					if (!force && direction > 0 && directionDelta >= getHideThreshold(element) && isPastFilterRevealDistance(element, scrollY) && !hasOpenDropdown(element) && !hasFocusedControl(element)) {
688						if (element.classList.contains("mobile-filter-control-active")) {
689							cancelSlideOut(element);
690							element.classList.add("mobile-filter-sticky");
691							updateStickyShadow(element, scrollY);
692							return;
693						}
694						startSlideOut(element);
695						updateStickyShadow(element, scrollY);
696						return;
697					}
698
699					if (element.classList.contains("mobile-filter-control-active") || hasOpenDropdown(element) || hasFocusedControl(element)) {
700						cancelSlideOut(element);
701						element.classList.add("mobile-filter-sticky");
702						element.classList.remove("mobile-filter-slide-in");
703						updateStickyShadow(element, scrollY);
704						return;
705					}
706
707					if (!force && direction < 0 && directionDelta >= getRevealThreshold(element)) {
708						if (element.classList.contains("mobile-filter-sticky")) {
709							if (hasReachedNaturalFilterArea(element, scrollY)) element.mobileFilterReturnZoneReached = true;
710							cancelSlideOut(element);
711							updateStickyShadow(element, scrollY);
712							return;
713						}
714
715						if (!hasActiveFilters(element)) {
716							element.classList.remove("mobile-filter-slide-in");
717							element.classList.remove("mobile-filter-slide-out");
718							element.classList.remove("mobile-filter-shadow");
719							return;
720						}
721
722						if (!isPastFilterRevealDistance(element, scrollY)) {
723							element.classList.remove("mobile-filter-slide-in");
724							element.classList.remove("mobile-filter-slide-out");
725							element.classList.remove("mobile-filter-shadow");
726							return;
727						}
728
729						cancelSlideOut(element);
730						element.classList.remove("mobile-filter-slide-in");
731						void element.offsetWidth;
732						element.classList.add("mobile-filter-slide-in");
733						element.classList.add("mobile-filter-sticky");
734						element.mobileFilterReturnZoneReached = false;
735						updateStickyShadow(element, scrollY);
736					}
737
738					if (!force && direction > 0 && directionDelta >= getHideThreshold(element) && isPastFilterRevealDistance(element, scrollY)) {
739						startSlideOut(element);
740						updateStickyShadow(element, scrollY);
741					}
742				});
743			}
744
745			function requestUpdate() {
746				if (ticking) return;
747				ticking = true;
748				if (window.requestAnimationFrame) {
749					window.requestAnimationFrame(function() {
750						updateFilters(false);
751					});
752					return;
753				}
754				window.setTimeout(function() {
755					updateFilters(false);
756				}, 0);
757			}
758
759			function requestRefresh() {
760				if (resizeFrame !== null) return;
761				var callback = function() {
762					resizeFrame = null;
763					refreshFilters();
764				};
765				if (window.requestAnimationFrame) {
766					resizeFrame = window.requestAnimationFrame(callback);
767					return;
768				}
769				resizeFrame = window.setTimeout(callback, 0);
770			}
771
772			if ($filters.length === 0) return;
773			window.norm4ReleaseMobileStickyFilters = releaseMobileStickyFilters;
774			refreshFilters();
775			window.addEventListener("scroll", requestUpdate, { passive: true });
776			window.addEventListener("resize", requestRefresh);
777			window.addEventListener("orientationchange", requestRefresh);
778			$(document).on("animationend", ".sticky-filter-wrapper.mobile-filter-slide-in, .sticky-filter-wrapper.mobile-filter-slide-out", function(event) {
779				if (event.originalEvent && event.originalEvent.animationName === "mobileFilterSlideOut") {
780					finishSlideOut(this);
781					return;
782				}
783				this.classList.remove("mobile-filter-slide-in");
784			});
785			window.addEventListener("touchstart", function(event) {
786				if (!isMobileStickyFilterEnabled() || !isMobileFilterViewport() || !event.touches || event.touches.length === 0) return;
787				touchStartY = event.touches[0].clientY;
788			}, { passive: true });
789			window.addEventListener("touchmove", function(event) {
790				if (!isMobileStickyFilterEnabled() || !isMobileFilterViewport() || touchStartY === null || !event.touches || event.touches.length === 0) return;
791				var currentY = event.touches[0].clientY;
792				if (touchStartY - currentY > 8) clearControlActiveFilters();
793				touchStartY = currentY;
794			}, { passive: true });
795			window.addEventListener("wheel", function(event) {
796				if (isMobileStickyFilterEnabled() && isMobileFilterViewport() && event.deltaY > 0) clearControlActiveFilters();
797			}, { passive: true });
798			$(document).on("shown.bs.select hidden.bs.select", ".sticky-filter-wrapper select.selectpicker", requestUpdate);
799			$(document).on("change keyup", ".sticky-filter-wrapper select, .sticky-filter-wrapper input", function() {
800				var $filterWrapper = $(this).closest(".sticky-filter-wrapper");
801				if (isMobileStickyFilterEnabled() && isMobileFilterViewport() && getScrollY() > 0 && !$filterWrapper.hasClass("mobile-filter-force-relative")) {
802					$filterWrapper.addClass("mobile-filter-sticky mobile-filter-control-active");
803				}
804			});
805		}
806
807		initMobileRevealStickyFilters();
808
809		$.each($("select[data-inputreset],input[data-inputreset]"), function(index, value) {
810			new norm4_InputReset($(value));
811		});
812
813	
814
815});

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.