PageSourceSearch

https://marcovermeulen.eu/lib/js/functions.js?v=c82

js marcovermeulen.eu collected 2026-10-04 08:52:59 UTC 6,016 bytes, 273 lines download raw bytes

1const init = () => {
2	ini_nav();
3	ini_hero();
4	lazyload();
5	ini_fx();
6	ini_tc();
7	ini_swiper();
8	ini_slideshow();
9	ini_Ukiyo();
10	ini_Isotope();
11	ini_search();
12};
13
14const ini_nav = () => {
15	let cs,
16		ls = 0;
17
18	window.addEventListener('scroll', function(e) {
19		cs = window.scrollY;
20		$('header').classList.toggle('slideup', ls < cs);
21		$('header').classList.toggle('compact', ls < 100);
22		ls = cs;
23	});
24
25	$('.burger').onclick = () => {
26		$('body').classList.toggle('nav-active');
27	};
28};
29
30const ini_tc = () => {
31	let tcs = $$('.tc .t');
32	tcs.forEach((entry, index) => {
33		entry.onclick = e => {
34			elm = $('a', entry);
35			entry.parentNode.classList.toggle('active');
36		};
37	});
38};
39
40const ini_slideshow = nslide => {
41	const entry = $$('.slideshow-container');
42	if (!entry.length) return;
43	let slideIndex = 0;
44	const slides = document.querySelectorAll('.slide');
45
46	function showSlides() {
47		for (let i = 0; i < slides.length; i++) {
48			slides[i].classList.remove('active');
49		}
50
51		slideIndex++;
52		if (slideIndex > slides.length) {
53			slideIndex = 1;
54		}
55
56		slides[slideIndex - 1].classList.add('active');
57		setTimeout(showSlides, 5000); // Change image every 5 seconds
58	}
59	showSlides();
60};
61
62const ini_Ukiyo = () => {
63	const sections = document.querySelectorAll('.ukiyo');
64	if (sections.length < 1) return;
65	sections.forEach(section => {
66		new Ukiyo(section, {
67			speed: 2,
68			scale: 1.25,
69		});
70	});
71};
72
73const ini_fx = () => {
74	const observed = $$('.fx');
75	if (observed.length) {
76		const io = new IntersectionObserver(
77			(entries, observer) => {
78				entries.forEach(entry => {
79					entry.target.classList.toggle('active', entry.intersectionRatio > 0.25);
80				});
81			},
82			{
83				root: null,
84				rootMargin: '0px 0px 30px 0px',
85				threshold: new Array(101).fill(0).map((zero, index) => {
86					return index * 0.01;
87				}),
88			}
89		);
90		observed.forEach(el => {
91			io.observe(el);
92		});
93	}
94};
95
96const ini_hero = () => {
97	const observed = $('.hero');
98	if (!observed) return;
99	const observer = new IntersectionObserver(
100		(entries, observer) => {
101			$('body').classList.toggle('hero', entries[0].intersectionRatio > 0.1);
102		},
103		{
104			root: null,
105			rootMargin: '0px 0px 30px 0px',
106			threshold: new Array(101).fill(0).map((zero, index) => {
107				return index * 0.01;
108			}),
109		}
110	);
111	observer.observe(observed);
112};
113
114const lazyload = () => {
115	const observed = $$('.lazy');
116	const observer = new IntersectionObserver(
117		(entries, observer) => {
118			entries.forEach(entry => {
119				if (Math.round(entry.intersectionRatio > 0.1)) {
120					img = $('img', entry.target);
121					isz = Math.max(entry.target.offsetWidth, entry.target.offsetHeight);
122					if (img && isz > 512) {
123						img.src = img.src.replace('/files/t', '/files/' + (isz > 1024 ? 'h' : 'm'));
124					}
125					observer.unobserve(entry.target);
126					entry.target.classList.add('loaded');
127				}
128			});
129		},
130		{
131			root: null,
132			rootMargin: '0px 0px 30px 0px',
133			threshold: new Array(101).fill(0).map((zero, index) => {
134				return index * 0.01;
135			}),
136		}
137	);
138
139	observed.forEach(el => {
140		observer.observe(el);
141		el.onclick = () => {
142			popup_slider(observed, el);
143		};
144	});
145};
146
147const popup_slider = (observed, clicked) => {
148	var lightbox = $('.lightbox');
149	var close = $('.swiper-close');
150	var swiper = $('.swiper-wrapper');
151	var initiated = lightbox.classList.contains('initiated');
152	var nslide = 0;
153
154	if (!initiated) {
155		observed.forEach((el, i) => {
156			if (el == clicked) nslide = i;
157			img = $('img', el);
158			if (img) {
159				src = img.src;
160				fnm = src.replace(/^.*[\\/]/, '');
161				obj = document.createElement('div');
162				obj.classList.add('swiper-slide');
163				img = document.createElement('img');
164				img.src = '/files/h/' + fnm;
165				obj.append(img);
166				swiper.append(obj);
167			}
168		});
169		close.onclick = () => {
170			lightbox.classList.remove('active');
171		};
172		lightbox.classList.add('initiated');
173	} else {
174		observed.forEach((el, i) => {
175			if (el == clicked) nslide = i;
176		});
177	}
178
179	ini_swiper(nslide);
180	lightbox.classList.add('active');
181};
182
183const ini_swiper = nslide => {
184	const entries = $$('.swiper');
185	const ns = nslide || 0;
186	entries.forEach(entry => {
187		slides = $$('.swiper-slide', entry);
188		if (slides.length > 0) {
189			nn = is_mobile() ? 1 : entry.dataset.nn;
190			var swiper = new Swiper(entry, {
191				slidesPerView: nn,
192				spaceBetween: 16,
193				initialSlide: ns,
194				navigation: {
195					nextEl: '.swiper-button-next',
196					prevEl: '.swiper-button-prev',
197				},
198			});
199			swiper.slideTo(ns);
200		}
201	});
202};
203
204const ini_Isotope = () => {
205	const gallery = $('.gallery');
206	const entries = $$('.isotope .grid-item');
207	if (entries.length > 0) {
208		const idx = $('.filter-index');
209		const cts = $$('.filter-categories li');
210		const ffs = $$('.filters li .trigger');
211
212		var $grid = new Isotope('.isotope', {
213			itemSelector: '.grid-item',
214		});
215
216		cts.forEach((el, i) => {
217			el.onclick = e => {
218				idx.classList.toggle('on', i);
219			};
220		});
221
222		ffs.forEach((el, index) => {
223			el.onclick = e => {
224				el.parentNode.classList.toggle('active');
225				ffs.forEach(instance => {
226					if (instance != el) instance.parentNode.classList.remove('active');
227				});
228				ff = el.parentNode.classList.contains('active') ? '.' + el.parentNode.id : '';
229				$grid.arrange({ filter: ff });
230			};
231		});
232	}
233};
234
235const ini_search = () => {
236	const sf = $('#search'),
237		ip = $('header #search input');
238
239	sf.onclick = () => {
240		sf.classList.add('active');
241		ip.focus();
242	};
243
244	ip.onkeyup = e => {
245		var formData = new FormData();
246		formData.set('do', 'search');
247		formData.set('q', ip.value);
248
249		fetch('/lib/xhr/search.php', {
250			method: 'POST',
251			body: formData,
252		})
253			.then(response => response.json())
254			.then(data => {
255				if (data.success) {
256					$('#search-result').innerHTML = data.message;
257				}
258			});
259	};
260};
261
262const is_mobile = () => {
263	return window.matchMedia('(pointer: coarse)').matches;
264};
265
266const $ = (s, p) => {
267	return (p ? p : document).querySelector(s);
268};
269
270const $$ = (s, p) => {
271	return (p ? p : document).querySelectorAll(s);
272};
273document.addEventListener('DOMContentLoaded', init);

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.