PageSourceSearch

https://restaurant-ofenloch.at/site/templates/scripts/main.js

js restaurant-ofenloch.at collected 2026-10-08 08:40:39 UTC 8,853 bytes, 279 lines download raw bytes

1
2$(function() {
3
4	function isMobile() {
5		return /Mobi|Android/i.test(navigator.userAgent);
6	}
7
8	$('.scroll').on('click', function(e) {
9		e.preventDefault();
10
11		var navbar = $('.fixed-top').height() || 0;
12		var subnav = $('.sticky-top').height() || 0;
13		var offset = navbar + subnav + 30;
14		var target = this.hash;
15
16		if ($(this).data('offset') !== undefined) {
17			offset = $(this).data('offset');
18		}
19
20		if ($(target).length) {
21			$('html, body').stop().animate({
22				'scrollTop': $(target).offset().top - offset
23			}, 300, 'swing');
24		}
25	});
26
27	$(window).on('load', function() {
28		if (window.location.hash) {
29			var target = window.location.hash;
30			var $link = $('.scroll[href="' + target + '"]').first();
31
32			if ($link.length) {
33				if (isMobile()) {
34					// ➔ Mobile: Verzögerung einbauen
35					setTimeout(function() {
36						$link.trigger('click');
37					}, 600);
38				} else {
39					// ➔ Desktop: sofort klicken
40					$link.trigger('click');
41				}
42			}
43		}
44	});
45
46});
47
48
49
50$(document).ready(function(){
51
52	//$('#popup').fancybox().trigger('click');
53	$('#popup').fancybox({
54		transitionIn: 'fade',
55		transitionOut: 'fade',
56		speedIn: 200, 
57		speedOut: 200, 
58		overlayColor: '#000', 
59		overlayOpacity: 0.7,
60		padding: 30,
61		margin: 30,
62		width: 600,
63		helpers: {
64			overlay: {
65				closeClick: false  // Klick aufs Overlay schließt NICHT
66			}
67		},
68		afterShow: function() {
69			// Links klickbar machen - stopPropagation verhindert fancybox close
70			$('.fancybox-inner a').off('click touchstart touchend').on('click touchstart touchend', function(e) {
71				e.stopPropagation();
72				// Link normal funktionieren lassen (href wird automatisch ausgeführt)
73			});
74		}
75	}).trigger('click'); 
76	
77	$(window).scroll(function(){
78  		var section = $('section:first');
79  		var sheight = section.height();
80  		var scroll = $(window).scrollTop();
81  		if (scroll > sheight - 100) {
82			$("nav.navbar").addClass('scrolled');
83  		}
84		
85  		else{
86	  		$("nav.navbar").removeClass('scrolled');  	
87  		}
88	})
89
90	$('#gallery a').simpleLightbox({loadingCaption: '...'});
91  
92});
93
94
95/*
96	$("#popup").fancybox({
97	  'transitionIn'	:	'fade',
98	  'transitionOut'	:	'fade',
99	  'speedIn'		:	200, 
100	  'speedOut'		:	200, 
101	  'overlayColor'	:	'#000', 
102	  'overlayOpacity':	0.7, 
103	  'opacity'		:	true, 
104	  'changeFade'	:	'fast', 
105	  'overlayShow'	:	true,
106	  'padding'	:	30,
107	  'margin'	:	30,
108	  'width'			:  600
109  });
110*/  
111
112  
113  
114/**
115 * A lightweight youtube embed. Still should feel the same to the user, just MUCH faster to initialize and paint.
116 *
117 * Thx to these as the inspiration
118 *   https://storage.googleapis.com/amp-vs-non-amp/youtube-lazy.html
119 *   https://autoplay-youtube-player.glitch.me/
120 *
121 * Once built it, I also found these:
122 *   https://github.com/ampproject/amphtml/blob/master/extensions/amp-youtube (👍👍)
123 *   https://github.com/Daugilas/lazyYT
124 *   https://github.com/vb/lazyframe
125 */
126class LiteYTEmbed extends HTMLElement {
127	connectedCallback() {
128		this.videoId = this.getAttribute('videoid');
129
130		let playBtnEl = this.querySelector('.lty-playbtn');
131		// A label for the button takes priority over a [playlabel] attribute on the custom-element
132		this.playLabel = (playBtnEl && playBtnEl.textContent.trim()) || this.getAttribute('playlabel') || 'Play';
133
134		/**
135		 * Lo, the youtube placeholder image!  (aka the thumbnail, poster image, etc)
136		 *
137		 * See https://github.com/paulirish/lite-youtube-embed/blob/master/youtube-thumbnail-urls.md
138		 *
139		 * TODO: Do the sddefault->hqdefault fallback
140		 *       - When doing this, apply referrerpolicy (https://github.com/ampproject/amphtml/pull/3940)
141		 * TODO: Consider using webp if supported, falling back to jpg
142		 */
143		if (!this.style.backgroundImage) {
144		  this.style.backgroundImage = `url("https://i.ytimg.com/vi/${this.videoId}/hqdefault.jpg")`;
145		}
146
147		// Set up play button, and its visually hidden label
148		if (!playBtnEl) {
149			playBtnEl = document.createElement('button');
150			playBtnEl.type = 'button';
151			playBtnEl.classList.add('lty-playbtn');
152			this.append(playBtnEl);
153		}
154		if (!playBtnEl.textContent) {
155			const playBtnLabelEl = document.createElement('span');
156			playBtnLabelEl.className = 'lyt-visually-hidden';
157			playBtnLabelEl.textContent = this.playLabel;
158			playBtnEl.append(playBtnLabelEl);
159		}
160		playBtnEl.removeAttribute('href');
161
162		// On hover (or tap), warm up the TCP connections we're (likely) about to use.
163		this.addEventListener('pointerover', LiteYTEmbed.warmConnections, {once: true});
164
165		// Once the user clicks, add the real iframe and drop our play button
166		// TODO: In the future we could be like amp-youtube and silently swap in the iframe during idle time
167		//   We'd want to only do this for in-viewport or near-viewport ones: https://github.com/ampproject/amphtml/pull/5003
168		this.addEventListener('click', this.addIframe);
169
170		// Chrome & Edge desktop have no problem with the basic YouTube Embed with ?autoplay=1
171		// However Safari desktop and most/all mobile browsers do not successfully track the user gesture of clicking through the creation/loading of the iframe,
172		// so they don't autoplay automatically. Instead we must load an additional 2 sequential JS f
172iles (1KB + 165KB) (un-br) for the YT Player API
173		// TODO: Try loading the the YT API in parallel with our iframe and then attaching/playing it. #82
174		this.needsYTApiForAutoplay = navigator.vendor.includes('Apple') || navigator.userAgent.includes('Mobi');
175	}
176
177	/**
178	 * Add a <link rel={preload | preconnect} ...> to the head
179	 */
180	static addPrefetch(kind, url, as) {
181		const linkEl = document.createElement('link');
182		linkEl.rel = kind;
183		linkEl.href = url;
184		if (as) {
185			linkEl.as = as;
186		}
187		document.head.append(linkEl);
188	}
189
190	/**
191	 * Begin pre-connecting to warm up the iframe load
192	 * Since the embed's network requests load within its iframe,
193	 *   preload/prefetch'ing them outside the iframe will only cause double-downloads.
194	 * So, the best we can do is warm up a few connections to origins that are in the critical path.
195	 *
196	 * Maybe `<link rel=preload as=document>` would work, but it's unsupported: http://crbug.com/593267
197	 * But TBH, I don't think it'll happen soon with Site Isolation and split caches adding serious complexity.
198	 */
199	static warmConnections() {
200		if (LiteYTEmbed.preconnected) return;
201
202		// The iframe document and most of its subresources come right off youtube.com
203		LiteYTEmbed.addPrefetch('preconnect', 'https://www.youtube-nocookie.com');
204		// The botguard script is fetched off from google.com
205		LiteYTEmbed.addPrefetch('preconnect', 'https://www.google.com');
206
207		// Not certain if these ad related domains are in the critical path. Could verify with domain-specific throttling.
208		LiteYTEmbed.addPrefetch('preconnect', 'https://googleads.g.doubleclick.net');
209		LiteYTEmbed.addPrefetch('preconnect', 'https://static.doubleclick.net');
210
211		LiteYTEmbed.preconnected = true;
212	}
213
214	fetchYTPlayerApi() {
215		if (window.YT || (window.YT && window.YT.Player)) return;
216
217		this.ytApiPromise = new Promise((res, rej) => {
218			var el = document.createElement('script');
219			el.src = 'https://www.youtube.com/iframe_api';
220			el.async = true;
221			el.onload = _ => {
222				YT.ready(res);
223			};
224			el.onerror = rej;
225			this.append(el);
226		});
227	}
228
229	async addYTPlayerIframe(params) {
230		this.fetchYTPlayerApi();
231		await this.ytApiPromise;
232
233		const videoPlaceholderEl = document.createElement('div')
234		this.append(videoPlaceholderEl);
235
236		const paramsObj = Object.fromEntries(params.entries());
237
238		new YT.Player(videoPlaceholderEl, {
239			width: '100%',
240			videoId: this.videoId,
241			playerVars: paramsObj,
242			events: {
243				'onReady': event => {
244					event.target.playVideo();
245				}
246			}
247		});
248	}
249
250	async addIframe(){
251		if (this.classList.contains('lyt-activated')) return;
252		this.classList.add('lyt-activated');
253
254		const params = new URLSearchParams(this.getAttribute('params') || []);
255		params.append('autoplay', '1');
256		params.append('playsinline', '1');
257
258		if (this.needsYTApiForAutoplay) {
259			return this.addYTPlayerIframe(params);
260		}
261
262		const iframeEl = document.createElement('iframe');
263		iframeEl.width = 560;
264		iframeEl.height = 315;
265		// No encoding necessary as [title] is safe. https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#:~:text=Safe%20HTML%20Attributes%20include
266		iframeEl.title = this.playLabel;
267		iframeEl.allow = 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture';
268		iframeEl.allowFullscreen = true;
269		// AFAIK, the encoding here isn't necessary for XSS, but we'll do it only because this is a URL
270		// https://stackoverflow.com/q/64959723/89484
271		iframeEl.src = `https://www.youtube-nocookie.com/embed/${encodeURIComponent(this.videoId)}?${params.toString()}`;
272		this.append(iframeEl);
273
274		// Set focus for a11y
275		iframeEl.focus();
276	}
277}
278// Register custom element
279customElements.define('lite-youtube', LiteYTEmbed);

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.