PageSourceSearch

https://www.gruener-wald.de/static/template-2189/js/site.js

js gruener-wald.de collected 2026-10-08 20:45:56 UTC 16,514 bytes, 446 lines download raw bytes

1!(function ( $, me ) {
2    "use strict";
3    if ( !$ || !me ) {
4        return;
5    }
6
7    if ( document.location.href.indexOf( '.vioma.de' ) > -1 ) {
8        window.me = me;
9    }
10
11	window["scrolledBannerHeight"] = 100;
12
13    $('#logo img', me.opt.header).on('load').addClass('logo-loaded');
14
15    $(window).ready(function() {
16        me.opt.site.removeClass('no-js');
17		if (document.cookie.indexOf("tracking_consent") > -1) {
18            $("nav.breadcrumb", me.opt.main).addClass("no-animation");
19        }
20
21		if (document.querySelector("video[data-poster]")) {
22			document.querySelectorAll("video[data-poster]").forEach(video => {
23				if (!video.classList.contains("nst21-video-autoplay")) {
24					video.poster = video.dataset.poster;
25				}
26			});
27		}
28    });
29    
30    me.custom_events = function () {
31		var menuPoisLoaded = false;
32
33		if (!menuPoisLoaded) {
34			$('#global-toggle-menu').on('change', function() {
35				$('.nav-poi').addClass('load-image');
36				menuPoisLoaded == true;
37			});
38	
39			$('#nav_menu_button').on('mouseenter', function() {
40				$('.nav-poi').addClass('load-image');
41				menuPoisLoaded == true;
42			});
43		}
44
45        $('.main-menu-item.active .main-menu-toggle').prop('checked', true);
46
47        $('.sub-menu-anchor').on('click', function() {
48            $('.global-toggle').prop('checked', false);
49        });
50
51        if ((!me.opt.touch) && (me.opt.mq.width > 1400)) {
52            var mmTimer;
53            $(".main-menu-link").mouseenter(function () {
54				var item = $(this);
55				var mmToggle = item.parent().prevAll("input.main-menu-toggle");
56				mmTimer = setTimeout(function () {
57					$("input.main-menu-toggle").prop("checked", false);
58					if (mmToggle.length > 0) {
59						mmToggle.prop("checked", true);
60					}
61				}, 180);
62			}).mouseleave(function () {
63				clearTimeout(mmTimer);
64			});
65        }
66
67		$('.purecss-prevnext a, .onepager-item-gallery a[aria-hidden="true"]').on('click', function() {
68            setTimeout(function(){
69                me.opt.uri = location.protocol + '//' + location.host + location.pathname;
70              window.history.pushState({ path: me.opt.uri }, '', me.opt.uri);
71            }, 1);
72        });
73
74		$('a[class*=cta]:not(:has(>span))').each(function() {
75			var ctaInner = $(this).html();
76			$(this).html('<span>' + ctaInner + '</span>');
77		})
78
79		$('.cst-meta-item-tfavail:not([data-counttfs="1"])').on('click', function(e) {
80			e.preventDefault();
81			var tfAvail = $(this);
82			var tfavailClone = $(this).clone().addClass('cst-meta-item-tfavail-clone').removeClass('cst-meta-item-tfavail');
83			if (tfAvail.parent().find($('.cst-meta-item-tfavail-clone')).length > 0) {
84				tfAvail.parent().find('.cst-meta-item-tfavail-clone').remove();
85			}
86			else {
87				tfAvail.parent().append(tfavailClone);
88				tfavailClone.on('click', function(e) {
89					e.preventDefault();
90					$(this).remove();
91				});
92			}
93		});
94
95		$("nav.breadcrumb").on("touchstart mouseenter", function () {
96            $(this).addClass("no-animation");
97        });
98    }
99
100    var bannerdidScroll;
101    var bannerlastScrollTop = 0;
102    var bannerdelta = 50;
103    var bannernavbarHeight = me.opt.banner.outerHeight();
104
105    $(window).scroll(function(event){
106        bannerdidScroll = true;
107    });
108
109    setInterval(function() {
110        if (bannerdidScroll) {
111            hasScrolled();
112            bannerdidScroll = false;
113        }
114    }, 250);
115
116    function hasScrolled() {
117        var bannerSt = $(document).scrollTop();
118        
119        // Make sure they scroll more than delta
120        if(Math.abs(bannerlastScrollTop - bannerSt) <= bannerdelta)
121            return;
122        
123        // If they scrolled down and are past the navbar, add class .nav-up.
124        // This is necessary so you never see what is "behind" the navbar.
125        if (bannerSt > bannerlastScrollTop && bannerSt > bannernavbarHeight){
126            // Scroll Down
127            me.opt.site.removeClass('show-banner');
128        } else if (bannerSt + $(window).height() < $(document).height()) {
129            // Scroll Up
130            me.opt.site.addClass('show-banner');
131        }
132        
133        bannerlastScrollTop = bannerSt;
134	}
135
136    // Widget Flatpickr
137    me.widgetFp = function (clientUrl, hotelId, objPrefix, objId, dateFormat) {
138		var dateFromInit = new Date(document.getElementById( objPrefix + '_date_from' ).dataset.date);
139      	var dateToInit = new Date(document.getElementById( objPrefix + '_date_to' ).dataset.date);
140        me.opt.avail = {};
141		function getAvail(dateFrom, inst) {
142			dateFrom = dateFrom || new Date();
143			var requestFrom = me.date_convert(new Date(dateFrom.getFullYear(), dateFrom.getMonth(), 1), 'Date', 'ymd', 0, true);
144			var requestTo = me.date_convert(new Date(dateFrom.getFullYear(), dateFrom.getMonth() + 2, 1), 'Date', 'ymd');
145			if (me.opt.dev) {
146				console.info('Request: ' + requestFrom + ' -> ' + requestTo);
147			}
148			$.ajax({
149				dataType: 'json',
150				url: clientUrl + 'vsc.php',
151				data: {
152					return_json: true,
153					return_html: false,
154					step: 'calendar_from',
155					date_from: requestFrom,
156					date_to: requestTo,
157					cart_language: me.opt.lang,
158					c: {
159						id_hotel: hotelId
160					}
161				},
162				success: function (d) {
163					if (d.cart) {
164						$.map(d.cart.calendar.date_from.days, function (el, i) {
165							me.opt.avail[i] = el;
166						});
167						if (inst) {
168							inst.redraw();
169						}
170					}
171				}
172			});
173		}
174
175        function updateDate(inst, date) {
176          	date = date || inst.latestSelectedDateObj;
177          	if(!date){ return; }
178          	$(inst.element).siblings('.widget-date-day').text(date.getDate());
179          	$(inst.element).siblings('.widget-date-month').text(inst.l10n.months.shorthand[date.getMonth()]);
180        }
181
182        var fpConfig = {
183          	altInput: true,
184          	altFormat: dateFormat,
185          	locale: me.opt.lang,
186          	disableMobile: true,
187          	minDate: 'today',
188          	onClose: function (selDates, dateStr, inst) {
189            	inst.altInput.blur();
190          	}
191        };
192
193        if ( objId == 'date_from' ) {
194          	$.extend( fpConfig, {
195            	onReady: function ( selDates, dateStr, inst ) {
196              		updateDate(inst, dateFromInit);
197              		inst.set( 'disable', [
198						function ( currentDay ) {
199							var availDay = me.opt.avail[ me.date_convert( currentDay, 'Date', 'ymd' ) ];
200							if ( availDay ) {
201								return !( availDay.type == 2 || availDay.type == 3 );
202							}
203							return true;
204						}
205              		]);
206              		getAvail( dateFromInit, inst );
207            	},
208            	onOpen: function ( selDates, dateStr, inst ) {
209              		inst.fpDateTo = document.getElementById( objPrefix + '_date_to' )._flatpickr;
210                    $(inst.element).parent().addClass('active');
211            	},
212            	onDayCreate: function ( dObj, dStr, inst, dayElem ) {
213              		var span;
214              		var dateIso = me.date_convert( dayElem.dateObj, 'Date', 'ymd' );
215              		if ( !me.opt.avail || !me.opt.avail[dateIso] ) {
216                		return;
217              		}
218              		if ( me.opt.avail[dateIso].type == 2 ) {
219                		span = document.createElement( 'span' );
220                		span.className = 'departure-only';
221                		dayElem.appendChild( span )
222              		}
223            	},
224            	onMonthChange: function ( selDates, dateStr, inst ) {
225              		if ( !me.opt.avail[ me.date_convert( new Date( inst.currentYear, inst.currentMonth + 1, 15 ), 'Date', 'ymd' ) ] ) {
226                		getAvail( new Date( inst.currentYear, inst.currentMonth, 1 ), inst );
227              		}
228            	},
229            	onYearChange: function ( selDates, dateStr, inst ) {
230					if ( !me.opt.avail[ me.date_convert( new Date( inst.currentYear, inst.currentMonth + 1, 15 ), 'Date', 'ymd' ) ] ) {
231                		getAvail( new Date( inst.currentYear, inst.currentMonth, 1 ), inst );
232              		}
233            	},
234            	onChange: function ( selDates, dateStr, inst ) {
235              		if ( inst.latestSelectedDateObj ) {
236                		updateDate(inst);
237                		inst.fpDateTo.clear();
238                		inst.fpDateTo.set( 'minDate', me.date_convert( inst.latestSelectedDateObj, 'Date', 'Date', 1 ) );
239                		inst.fpDateTo.set( 'maxDate', me.date_convert( inst.latestSelectedDateObj, 'Date', 'Date', 28 ) );
240                		inst.fpDateTo.redraw();
241                		inst.fpDateTo.open();
242                        $(inst.element).parent().removeClass('active');
243                		$( 'input.rdfrom1', $( inst.element ).closest( 'form' ) ).val( me.date_convert( inst.latestSelectedDateObj, 'Date', 'dmy' ) );
244                		$('.widget-date-from').addClass('changed');
245              		}
246            	},
247                onClose: function(selDates, dateStr, inst) {
248                    $(inst.element).parent().removeClass('active');
249                }
250          	});
251        }
252        else if (objId === 'date_to') {
253          	$.extend(fpConfig, {
254            	onReady: function (selDates, dateStr, inst) {
255              		updateDate(inst, dateToInit);
256              		inst.set('disable', [
257                		function (currentDay) {
258                  			var availDay = me.opt.avail[me.date_convert(currentDay, 'Date', 'ymd')];
259                  			if (availDay) {
260                    			return availDay.type === -1;
261                  			}
262                  			return true;
263                		}
264              		]);
265              		inst.fpDateFrom = document.getElementById(objPrefix + '_date_from')._flatpickr;
266            	},
267                onOpen: function ( selDates, dateStr, inst ) {
268                    $(inst.element).parent().addClass('active');
269                },
270            	onDayCreate: function (dObj, dStr, inst, dayElem) {
271              		if (!inst.fpDateFrom || !inst.fpDateFrom.latestSelectedDateObj) {
272                		return;
273              		}
274              		var $dayElem = $(dayElem);
275              		var fromDate = me.date_convert(inst.fpDateFrom.latestSelectedDateObj, 'Date', 'ymd');
276              		var toDate = inst.latestSelectedDateObj ? me.date_convert(inst.latestSelectedDateObj, 'Date', 'ymd') : false;
277              		var currentDate = me.date_convert(dayElem.dateObj, 'Date', 'ymd');
278              		$dayElem.toggleClass('arrival-day', currentDate === fromDate)
279						.toggleClass('following-day', currentDate > fromDate)
280						.toggleClass('between-day', currentDate > fromDate && currentDate < toDate)
281						.filter('.following-day:not(.disabled)')
282						.hover(
283							function () {
284								$dayElem.prevAll('.following-day').addBack().addClass('following-day-hover');
285							},
286							function () {
287								$dayElem.prevAll('.following-day').addBack().removeClass('following-day-hover');
288							}
289						);
290            	},
291            	onChange: function (selDates, dateStr, inst) {
292              		if (inst.latestSelectedDateObj) {
293                		updateDate(inst);
294                        $(inst.element).parent().removeClass('active');
295                		$('input.rdto1', $(inst.element).closest('form')).val(me.date_convert(inst.latestSelectedDateObj, 'Date', 'dmy'));
296                		$('.widget-date-to').addClass('changed');
297              		}
298            	},
299                onClose: function(selDates, dateStr, inst) {
300                    $(inst.element).parent().removeClass('active');
301                }
302          	});
303        }
304        $('#' + objPrefix + '_' + objId).flatpickr(fpConfig);
305	};
306
307	if (me.opt.intersectionobserver) {
308		var bgImage = $('img#background-image', me.opt.site);
309		var bgImageTransparency = 0;
310
311		let bgImageobserver = new IntersectionObserver((entries, settings) => { 
312			entries.forEach(entry => {
313				if (entry.target.classList.contains('grp-bg-transparent-hard')) {
314					if ((entry.intersectionRatio > 0) && (entry.intersectionRatio <= 0.2)) {
315						// This allows for a smoother transition, if the element before/after is not that high
316						bgImage.css('opacity', entry.intersectionRatio * 5); // f.e. 0,1 * 100% * 5 to max out at opacity 1;
317					}
318					else if (entry.isIntersecting) {
319						bgImage.css('opacity', 1);
320					}
321					else {
322						bgImage.css('opacity', 0);
323					}
324				}
325				else {
326					bgImageTransparency = Math.round(entry.intersectionRatio * 100);
327					bgImage.css('opacity', bgImageTransparency + '%');
328				}
329			});
330		}, {root: null, rootMargin: "0px", threshold: buildThresholdList()});
331
332		let opacityVisibleObserver = new IntersectionObserver((entries, settings) => { 
333			entries.forEach(entry => {
334				if (entry.isIntersecting) {
335					entry.target.style.opacity = entry.intersectionRatio;
336				}
337			});
338		}, {root: null, rootMargin: "0px", threshold: buildThresholdList()});
339		
340		document.querySelectorAll('section[data-attr-hintergrund="transparent"], footer').forEach(section => { bgImageobserver.observe(section) });
341		document.querySelectorAll('section[data-attr-hintergrund="transparent-hard"]').forEach(section => { bgImageobserver.observe(section) });
342
343		document.querySelectorAll('div.media-display-wide').forEach(section => { opacityVisibleObserver.observe(section) });
344
345		function buildThresholdList() {
346			let thresholds = [];
347			let numSteps = 20;
348			
349			for (let i=1.0; i<=numSteps; i++) {
350				let ratio = i/numSteps;
351				thresholds.push(ratio);
352			}
353			
354			thresholds.push(0);
355			return thresholds;
356		}
357
358		const stickyQuicklinks = document.querySelector('nav.onepager-quicklinks');
359
360		if ((me.opt.mq.width > 960) && (!!stickyQuicklinks)) {
361			const stickyObserver = new IntersectionObserver( 
362				([e]) => e.target.classList.toggle('sticky', e.intersectionRatio < 1),
363				{threshold: [1]}
364			);
365			stickyObserver.observe(stickyQuicklinks);
366
367			var cstUseGroupId = 0;
368			const cstQuicklink = document.querySelectorAll('a.onepager-quicklink');
369			const cstQuicklinkWHeight = window.innerHeight;
370
371			let roomlistObserver = new IntersectionObserver((entries, settings) => {
372				entries.forEach(entry => {
373					if ((entry.intersectionRatio >= 0.6) && (entry.boundingClientRect.top > 0)) {
374						cstUseGroupId = entry.target.dataset.group;
375						cstQuicklink.forEach(link => {
376							if (link.dataset.group == cstUseGroupId) {
377								link.classList.add('active');
378							}
379							else {
380								link.classList.remove('active');
381							}
382						});
383					}
384				});
385			}, {root: null, rootMargin: "0px", threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]});
386
387			document.querySelectorAll('article.onepager-item').forEach(container => {
388				roomlistObserver.observe(container);
389			});
390
391			cstQuicklink.forEach(link => {
392				link.addEventListener('click', function(e) {
393					e.preventDefault();
394					var cstNewScrollToElem = document.getElementById(link.hash.substr(link.hash.indexOf('#') + 1));
395					var cstNewScrollTo = cstNewScrollToElem.getBoundingClientRect().top + window.pageYOffset - 140;
396					window.scrollTo({top: cstNewScrollTo, behavior: 'smooth'});
397				});
398			});
399		}
400
401		document.querySelectorAll('main section[data-attr-hintergrund="transparent-hard"]').forEach(section => {
402			console.log(section);
403			if (!!section.previousSibling) {
404				section.previousSibling.classList.add('transparent-hart-before');
405
406				if (!!section.previousSibling.previousSibling) {
407                    section.previousSibling.previousSibling.classList.add("transparent-hard-z-index");
408                }
409			}
410			if (!!section.nextSibling) {
411                section.nextSibling.classList.add("transparent-hart-after");
412
413				if (!!section.nextSibling.nextSibling) {
414                    section.nextSibling.nextSibling.classList.add("transparent-hard-z-index");
415                }
416            }
417		});
418	}
419
420	$('.grp-mem-57[data-attr-layout="slider"]', me.opt.main).each(function() {
421		if ($(this).parents('section.grp-modules')) {
422			$(this).parents('section.grp-modules').attr('data-attr-layout', 'slider')
423		}
424	});
425
426	document.querySelectorAll('.cst-offer-filter').forEach(label => {
427		var cstOFSpan = document.createElement('span')
428		cstOFSpan.classList.add('cst-offer-filter-inner');
429		cstOFSpan.innerHTML = label.textContent;
430		label.innerHTML = cstOFSpan.outerHTML;
431	});
432
433	window.addEventListener('viomavio', function(e) {
434		if (e.detail.action == 'open') {
435			e.detail.element.querySelectorAll('a[class*=cta]:not(:has(>span))').forEach(link => {
436				var ctaInner = link.innerHTML;
437				var ctaSpan = document.createElement('span');
438				ctaSpan.innerHTML = ctaInner;
439				link.innerHTML = ctaSpan.outerHTML;
440			});
441		}
442	});
443
444    me.init();
445
446})( window.jQuery, window.nst2021 );

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.