PageSourceSearch

https://stsl.ru/bitrix/templates/stsl_new/js/scripts.js?1734097853103505

js stsl.ru collected 2026-10-01 12:00:03 UTC 103,505 bytes, 3,073 lines download raw bytes

1/* vh fix */
2BX.ready(function () {
3
4	window.addEventListener('DOMContentLoaded', utility.setVH());
5	window.addEventListener('resize', utility.debounce(utility.setVH, 250));
6
7
8	/* load assets */
9	if (!disableAnimations) {
10		var imgLoad = imagesLoaded(document.querySelector('.scroll-container'), {
11			background: '.hero__back'
12		});
13		var heroAnimations = HeroAnimations;
14		imgLoad.on('done', function () {
15			/* hero Animations start */
16			heroAnimations.initHero();
17		});
18		imgLoad.on('fail', function () {
19			console.log('FAIL - all images loaded, at least one is broken');
20			/* hero Animations start */
21			heroAnimations.initHero();
22		});
23		imgLoad.on('progress', function (instance) {
24			let currentCount = instance.progressedCount;
25			let totalCount = instance.images.length;
26			let progress = Math.round(currentCount * 100 / totalCount);
27
28			let progressElement = document.querySelector('.slogan__progress');
29			progressElement.innerHTML = `${progress}%`;
30
31			let sloganTextElement = document.querySelector('.slogan__text');
32			sloganTextElement.style.clipPath = `inset(0 ${100 - progress}% 0 0)`;
33
34			let sloganBackElement = document.querySelector('.slogan__back');
35			sloganBackElement.style.clipPath = `inset(0 0 0 ${progress}%)`;
36		});
37	}
38
39
40	/* lang menu */
41	let langMoreTrigger = document.querySelector(".js-lang-more-trigger");
42	if (langMoreTrigger) {
43		langMoreTrigger.addEventListener("click", function (event) {
44			event.preventDefault();
45
46			let langMore = langMoreTrigger.closest(".js-lang-more");
47			if (langMore.classList.contains('menu__item--active')) {
48				langMore.classList.remove('menu__item--active');
49			} else {
50				langMore.classList.add('menu__item--active');
51			}
52
53			return false;
54		});
55
56		document.addEventListener('click', function (event) {
57			let isLangDropdown = false;
58
59			if (event.target.classList.contains('.js-lang-more') || event.target.closest(".js-lang-more")) {
60				isLangDropdown = true;
61			}
62
63			if (!isLangDropdown) {
64				document.querySelector(".js-lang-more").classList.remove('menu__item--active');
65			}
66		});
67	}
68
69
70	/* search */
71	let searchTrigger = document.querySelector(".js-search-trigger");
72	let searchPopup = document.querySelector(".js-search-popup");
73	let searchPopupCloser = searchPopup.querySelector(".js-popup-close");
74	let searchPopupContent = searchPopup.querySelector(".js-popup-content");
75
76	searchTrigger.addEventListener('click', function (event) {
77		event.preventDefault();
78		searchPopup.classList.add("popup--active");
79		utility.disableScroll();
80	});
81
82	searchPopup.addEventListener('click', function (event) {
83		if (!searchPopupContent.contains(event.target)) {
84			searchPopup.classList.remove('popup--active');
85			utility.enableScroll();
86		}
87	});
88
89
90	/* main menu */
91	let mainMenu = document.querySelector('.js-main-menu');
92	let mainMenuItems = [].slice.call(mainMenu.querySelectorAll('.menu__item'));
93	const mainMenuInTime = 100;
94	const mainMenuOutTime = 300;
95	let mainMenuInTimeout = null;
96	let mainMenuOutTimeout = null;
97
98	mainMenuItems.forEach(function (mainMenuItem) {
99		mainMenuItem.addEventListener('touchend', function (event) {
100			let currentMenu = event.target;
101			if (!currentMenu.classList.contains('menu__item')) {
102				currentMenu = event.target.closest('.menu__item');
103			}
104
105			if (currentMenu.classList.contains('menu__item--selected')) {
106				event.stopPropagation();
107				return true;
108			} else {
109				event.stopPropagation();
110				event.preventDefault();
111				mainMenuItems.forEach(function (mainMenuItem) {
112					mainMenuItem.classList.remove('menu__item--selected');
113				});
114
115				currentMenu.classList.add('menu__item--selected');
116
117				let subMenu = currentMenu.querySelector('.menu__item--content');
118				if (subMenu) {
119					let subMenuPosition = subMenu.getBoundingClientRect();
120					subMenu.style.setProperty('--left', `-${subMenuPosition.left}px`);
121					subMenu.style.setProperty('--right', `-${document.body.clientWidth - subMenuPosition.right}px`);
122				}
123			}
124			return false;
125		});
126
127		mainMenuItem.addEventListener('mouseenter', function (event) {
128			clearTimeout(mainMenuInTimeout);
129			clearTimeout(mainMenuOutTimeout);
130			mainMenuInTimeout = setTimeout(function () {
131				mainMenuItems.forEach(function (mainMenuItem) {
132					mainMenuItem.classList.remove('menu__item--selected');
133				});
134
135				let currentMenu = event.target;
136				currentMenu.classList.add('menu__item--selected');
137
138				let subMenu = currentMenu.querySelector('.menu__item--content');
139				if (subMenu) {
140					let subMenuPosition = subMenu.getBoundingClientRect();
141					subMenu.style.setProperty('--left', `-${subMenuPosition.left}px`);
142					subMenu.style.setProperty('--right', `-${document.body.clientWidth - subMenuPosition.right}px`);
143				}
144			}, mainMenuInTime);
145		});
146	});
147
148	mainMenu.addEventListener('mouseleave', function () {
149		clearTimeout(mainMenuInTimeout);
150		clearTimeout(mainMenuOutTimeout);
151		mainMenuOutTimeout = setTimeout(function () {
152			mainMenuItems.forEach(function (mainMenuItem) {
153				mainMenuItem.classList.remove('menu__item--selected');
154			});
155		}, mainMenuOutTime);
156	});
157
158	document.addEventListener('touchend', function (event) {
159		if (!event.target.closest('.js-main-menu') && event.target != mainMenu) {
160			mainMenuItems.forEach(function (mainMenuItem) {
161				mainMenuItem.classList.remove('menu__item--selected');
162			});
163		}
164	});
165
166
167	/* mobile menu */
168	let mobileMenu = document.querySelector(".js-mobile-menu");
169	let mobileMenuTrigger = document.querySelector(".js-mobile-menu-trigger");
170	let mobileMenuCloser = document.querySelector(".js-mobile-menu-close");
171	let mobileMenuFlag = 0;
172	let mobileMenuNavArrows = [].slice.call(document.querySelectorAll('.js-mobile-menu-nav-arrow'));
173	let mobileMenuNavWrapper = document.querySelector(".js-mobile-menu-nav");
174	let mobileMenuNavBg = document.querySelector(".js-mobile-menu-back");
175
176	mobileMenuTrigger.addEventListener('click', function (event) {
177		mobileMenu.classList.add('active');
178		utility.disableScroll();
179	});
180
181	mobileMenuNavBg.addEventListener('click', function () {
182		mobileMenu.classList.remove('active');
183		utility.enableScroll();
184
185		mobileMenuNavArrows.forEach(function (mobileMenuNavArrow) {
186			mobileMenuNavWrapper.classList.remove('hide');
187			let parentLi = mobileMenuNavArrow.parentNode;
188			let parentLiContent = parentLi.getElementsByClassName('menu__item--content section__wrapper')[0];
189			parentLiContent.classList.remove('active');
190		});
191		mobileMenuFlag = 0;
192	});
193
194	mobileMenuCloser.addEventListener('click', function () {
195		if (mobileMenuFlag == 0) {
196			mobileMenu.classList.remove('active');
197			utility.enableScroll();
198		} else {
199			mobileMenuNavArrows.forEach(function (mobileMenuNavArrow) {
200				mobileMenuNavWrapper.classList.remove('hide');
201				let parentLi = mobileMenuNavArrow.parentNode;
202				let parentLiContent = parentLi.getElementsByClassName('menu__item--content section__wrapper')[0];
203				parentLiContent.classList.remove('active');
204			});
205			mobileMenuFlag--;
206		}
207	});
208
209	mobileMenuNavArrows.forEach(function (mobileMenuNavArrow) {
210		mobileMenuNavArrow.addEventListener('click', function () {
211			mobileMenuNavWrapper.classList.add('hide');
212			let parentLi = this.parentNode;
213			let parentLiContent = parentLi.getElementsByClassName('menu__item--content section__wrapper')[0];
214			parentLiContent.classList.add('active');
215			mobileMenuFlag++;
216		});
217	});
218
219
220	/* video */
221	let pageVideos = [].slice.call(document.querySelectorAll('video'));
222	let videoObserver = new IntersectionObserver(videoObserverCallback);
223
224	pageVideos.forEach(function (pageVideo) {
225		videoObserver.observe(pageVideo);
226		let videoSource = pageVideo.querySelector('source');
227		if (!videoSource) {
228			addVideoSource(pageVideo);
229		}
230	});
231
232	function videoObserverCallback (videoEntries) {
233		videoEntries.forEach(function (videoEntry) {
234			let videoElement = videoEntry.target;
235			if (videoEntry.isIntersecting) {
236				if (videoElement.loop || !videoElement.ended) {
237					videoElement.play();
238				}
239			} else {
240				videoElement.pause();
241			}
242		});
243	}
244
245	function addVideoSource (videoElement) {
246		let videoTabletWidth = typeof videoElement.dataset.tablet != 'undefined' ? videoElement.dataset.tablet : null;
247		let videoMobileWidth = typeof videoElement.dataset.mobile != 'undefined' ? videoElement.dataset.mobile : null;
248
249		let videoURL = null;
250		let posterURL = null;
251
252		/* mobile video */
253		if (videoMobileWidth && screen.width <= videoMobileWidth) {
254			videoURL = typeof videoElement.dataset.videoMobile != 'undefined' ? videoElement.dataset.videoMobile : videoURL;
255			posterURL = typeof videoElement.dataset.posterMobile != 'undefined' ? videoElement.dataset.posterMobile : posterURL;
256		}
257
258		/* tablet video */
259		if (!videoURL && videoTabletWidth && screen.width <= videoTabletWidth) {
260			videoURL = typeof videoElement.dataset.videoTablet != 'undefined' ? videoElement.dataset.videoTablet : videoURL;
261		}
262		if (!posterURL && videoTabletWidth && screen.width <= videoTabletWidth) {
263			posterURL = typeof videoElement.dataset.posterTablet != 'undefined' ? videoElement.dataset.posterTablet : posterURL;
264		}
265
266		/* desktop video */
267		if (!videoURL) {
268			videoURL = typeof videoElement.dataset.video != 'undefined' ? videoElement.dataset.video : videoURL;
269		}
270		if (!posterURL) {
271			posterURL = typeof videoElement.dataset.poster != 'undefined' ? videoElement.dataset.poster : posterURL;
272		}
273
274		let videoSources = "";
275		if (videoURL) {
276			videoSources += '<source src="' + videoURL + '" type="video/mp4">';
277		}
278		videoElement.innerHTML = videoSources;
279		if (!videoElement.poster) {
280			videoElement.poster = posterURL;
281		}
282
283		videoElement.parentElement.classList.add('loading');
284		videoElement.addEventListener('playing', function () {
285			videoElement.parentElement.classList.remove('loading');
286		});
287	}
288
289
290	/* 3D hover effect */
291	let hover3dTargets = [].slice.call(document.querySelectorAll('.js-hover-3d'));
292	const motionMatchMedia = window.matchMedia("(prefers-reduced-motion)");
293	const THRESHOLD = 10;
294	const EASING = 0.025;
295
296	if (!utility.isTouchDevice() && !motionMatchMedia.matches) {
297		hover3dTargets.forEach(function (hover3dTarget) {
298			let state = Object.create(null);
299			state.rafId = null;
300			state.rotateX = 0;
301			state.rotateY = 0;
302			state.scale = 1;
303			state.mouseX = hover3dTarget.clientWidth / 2;
304			state.mouseY = hover3dTarget.clientHeight / 2;
305			state.translationX = 0;
306			state.translationY = 0;
307			state.translationScale = 1;
308			state.translationMouseX = 0;
309			state.translationMouseY = 0;
310
311			hover3dTarget.addEventListener("mousemove", function (event) {
312				update(event);
313				state.scale = 1.1;
314
315				if (!state.rafId) {
316					state.rafId = window.requestAnimationFrame(paint);
317				}
318			});
319			hover3dTarget.addEventListener("mouseleave", function (event) {
320				reset(event);
321			});
322
323			function paint () {
324				state.translationX = utility.lerp(state.translationX, state.rotateX, EASING);
325				state.translationY = utility.lerp(state.translationY, state.rotateY, EASING);
326				state.translationScale = utility.lerp(state.translationScale, state.scale, EASING);
327				state.translationMouseX = utility.lerp(state.translationMouseX, utility.lineEq(-20, 20, state.clientWidth, 0, state.mouseX), EASING);
328				state.translationMouseY = utility.lerp(state.translationMouseY, utility.lineEq(-20, 20, state.clientHeight, 0, state.mouseY), EASING);
329
330				gsap.set(hover3dTarget, {
331					x: state.translationMouseX,
332					y: state.translationMouseY,
333					transform: `perspective(${state.clientWidth}px) rotateX(${state.translationY}deg) rotateY(${state.translationX}deg) scale3d(${state.translationScale}, ${state.translationScale}, ${state.translationScale})`
334				});
335
336				state.rafId = window.requestAnimationFrame(paint);
337			}
338
339			function update (event) {
340				let clientX = event.clientX;
341				let clientY = event.clientY;
342				let clientWidth = event.currentTarget.clientWidth;
343				let clientHeight = event.currentTarget.clientHeight;
344				let targetPosition = event.currentTarget.parentElement.getBoundingClientRect();
345				let offsetLeft = targetPosition.left;
346				let offsetTop = targetPosition.top;
347
348				let horizontal = (clientX - offsetLeft) / clientWidth;
349				let vertical = (clientY - offsetTop) / clientHeight;
350				let rotateX = (THRESHOLD / 2 - horizontal * THRESHOLD).toFixed(2);
351				let rotateY = (vertical * THRESHOLD - THRESHOLD / 2).toFixed(2);
352
353				state.clientWidth = clientWidth;
354				state.clientHeight = clientHeight;
355				state.rotateX = rotateX;
356				state.rotateY = rotateY;
357				state.mouseX = clientX - offsetLeft;
358				state.mouseY = clientY - offsetTop;
359			}
360
361			function reset (event) {
362				state.clientWidth = event.currentTarget.clientWidth;
363				state.clientHeight = event.currentTarget.clientHeight;
364				state.rotateX = 0;
365				state.rotateY = 0;
366				state.mouseX = event.currentTarget.clientWidth / 2;
367				state.mouseY = event.currentTarget.clientHeight / 2;
368				state.scale = 1;
369			}
370		});
371	}
372
373
374	/* video mouse follower */
375	let videoCursor = document.querySelector('.js-video-cursor');
376	if (videoCursor && !utility.isTouchDevice()) {
377		let cursorTarget = videoCursor.closest('.banner__video-wrapper');
378		if (cursorTarget) {
379			cursorTarget.addEventListener("mousemove", function (event) {
380				let targetPosition = event.currentTarget.parentElement.getBoundingClientRect();
381				let offsetLeft = targetPosition.left;
382				let offsetTop = targetPosition.top;
383				let mouseX = event.clientX - offsetLeft;
384				let mouseY = event.clientY - offsetTop;
385				videoCursor.style.left = mouseX + "px";
386				videoCursor.style.top = mouseY + "px";
387				videoCursor.classList.add('banner__cursor--visible');
388			});
389
390			cursorTarget.addEventListener("mouseleave", function () {
391				videoCursor.classList.remove('banner__cursor--visible');
392			});
393
394			cursorTarget.addEventListener("click", function () {
395				videoCursor.classList.add('banner__cursor--active');
396
397				setTimeout(function () {
398					videoCursor.classList.remove('banner__cursor--active');
399				}, 500);
400			});
401		}
402	}
403
404
405	/* YouTube video popup */
406	let videoBanner = document.querySelector('.js-video-banner');
407	let videoBannerPopup, videoBannerPopupContact, videoBannerPopupCloser, backgroundVideo, YTScriptTag, firstScriptTag,
408		player, YTVideoId, playerHeight, playerWidth, playerRatio;
409	if (videoBanner) {
410		videoBannerPopup = document.querySelector('.js-video-popup');
411		videoBannerPopupContact = document.querySelector('.js-video-popup-content');
412		videoBannerPopupCloser = document.querySelector('.js-video-popup-close');
413		backgroundVideo = videoBanner.querySelector('.banner__video');
414
415		YTScriptTag = document.createElement('script');
416		YTScriptTag.src = "https://www.youtube.com/iframe_api";
417		firstScriptTag = document.getElementsByTagName('script')[0];
418		firstScriptTag.parentNode.insertBefore(YTScriptTag, firstScriptTag);
419
420		player;
421		YTVideoId = videoBanner.dataset.youtube;
422
423		playerHeight = 0;
424		playerWidth = 0;
425		playerRatio = 16 / 9;
426
427		setSizes(true);
428
429		window.addEventListener('resize', utility.debounce(function () {
430			setSizes(false);
431		}, 250));
432
433		videoBanner.addEventListener('touchend', function (event) {
434			event.preventDefault();
435			event.stopPropagation();
436
437			videoBannerPopup.classList.add('banner__popup--active');
438			utility.disableScroll();
439			backgroundVideo.pause();
440			player.playVideo();
441
442			if (videoCursor && utility.isTouchDevice()) {
443				videoCursor.classList.add('banner__cursor--hidden');
444			}
445
446			return false;
447		});
448
449		videoBanner.addEventListener('click', function (event) {
450			event.preventDefault();
451
452			videoBannerPopup.classList.add('banner__popup--active');
453			utility.disableScroll();
454			backgroundVideo.pause();
455			player.playVideo();
456
457			if (videoCursor && utility.isTouchDevice()) {
458				videoCursor.classList.add('banner__cursor--hidden');
459			}
460
461			return false;
462		});
463
464		videoBannerPopup.addEventListener('touchend', function (event) {
465			event.preventDefault();
466			event.stopPropagation();
467
468			if (event.target == event.currentTarget) {
469				videoBannerPopup.classList.remove('banner__popup--active');
470				utility.enableScroll();
471				backgroundVideo.play();
472				player.pauseVideo();
473
474				if (videoCursor && utility.isTouchDevice()) {
475					videoCursor.classList.remove('banner__cursor--hidden');
476				}
477			}
478
479			return false;
480		});
481
482		videoBannerPopup.addEventListener('click', function (event) {
483			event.preventDefault();
484
485			if (event.target == event.currentTarget) {
486				videoBannerPopup.classList.remove('banner__popup--active');
487				utility.enableScroll();
488				backgroundVideo.play();
489				player.pauseVideo();
490
491				if (videoCursor && utility.isTouchDevice()) {
492					videoCursor.classList.remove('banner__cursor--hidden');
493				}
494			}
495
496			return false;
497		});
498
499		videoBannerPopupCloser.addEventListener('touchend', function (event) {
500			event.preventDefault();
501			event.stopPropagation();
502
503			videoBannerPopup.classList.remove('banner__popup--active');
504			utility.enableScroll();
505			backgroundVideo.play();
506			player.pauseVideo();
507
508			if (videoCursor && utility.isTouchDevice()) {
509				videoCursor.classList.remove('banner__cursor--hidden');
510			}
511
512			return false;
513		});
514
515		videoBannerPopupCloser.addEventListener('click', function (event) {
516			event.preventDefault();
517
518			videoBannerPopup.classList.remove('banner__popup--active');
519			utility.enableScroll();
520			backgroundVideo.play();
521			player.pauseVideo();
522
523			if (videoCursor && utility.isTouchDevice()) {
524				videoCursor.classList.remove('banner__cursor--hidden');
525			}
526
527			return false;
528		});
529
530		function setSizes (initial) {
531			let hRate = 0.8;
532			let wRate = 0.8;
533			let wMargin = 0;
534
535			let windowRatio = window.innerWidth / window.innerHeight
536			if (windowRatio >= playerRatio) {
537				playerHeight = window.innerHeight * hRate;
538				playerWidth = playerHeight * playerRatio;
539			} else {
540				if (window.innerWidth <= 540) {
541					playerWidth = window.innerWidth - wMargin * 2;
542				} else {
543					playerWidth = window.innerWidth * wRate;
544				}
545				playerHeight = playerWidth / playerRatio;
546			}
547
548			if (!initial) {
549				player.setSize(playerWidth, playerHeight);
550			}
551
552			videoBannerPopup.querySelector('.banner__popup-wrapper').style.setProperty('--width', `${playerWidth}px`);
553			videoBannerPopup.querySelector('.banner__popup-wrapper').style.setProperty('--height', `${playerHe
553ight}px`);
554		}
555
556		function onYouTubeIframeAPIReady () {
557			player = new YT.Player(videoBannerPopupContact, {
558				height: playerHeight,
559				width: playerWidth,
560				videoId: YTVideoId,
561				playerVars: {
562					'autoplay': 0,
563					'cc_lang_pref': "ru",
564					'cc_load_policy': 0,
565					'controls': 1,
566					'disablekb': 0,
567					'fs': 1,
568					'hl': "ru",
569					'iv_load_policy': 3,
570					'loop': 0,
571					'modestbranding': 1,
572					'playsinline': 1
573				}
574			});
575		}
576	}
577
578
579	/* question form */
580	let questionForms = [].slice.call(document.querySelectorAll('.js-question-form'));
581	let phoneMask = new Inputmask({
582		mask: "+7 (999) 999-99-99",
583		clearMaskOnLostFocus: true,
584		showMaskOnHover: false,
585		showMaskOnFocus: true,
586		insertMode: false,
587		insertModeVisual: false,
588		undoOnEscape: false,
589		positionCaretOnTab: true,
590		tabThrough: false,
591		shiftPositions: true,
592		positionCaretOnClick: "lvp",
593		inputmode: "tel",
594		oncomplete: function (event) {
595			event.target.classList.add('valid');
596			event.target.classList.remove('error');
597		},
598		onincomplete: function (event) {
599			event.target.classList.remove('valid');
600			event.target.classList.add('error');
601		},
602		oncleared: function (event) {
603			event.target.classList.remove('valid');
604			event.target.classList.remove('error');
605		},
606		onKeyDown: function (event, buffer, caretPos, opts) {
607			if (['ArrowRight', 'ArrowDown', 'ArrowLeft', 'ArrowUp'].includes(event.key)) {
608				return false;
609			}
610		}
611	});
612	questionForms.forEach(function (questionForm) {
613		questionForm.addEventListener('submit', questionFormHandle);
614
615		let questionFormPhone = questionForm.querySelector("INPUT[type='tel']");
616		phoneMask.mask(questionFormPhone);
617	});
618
619	function questionFormHandle (event) {
620		event.preventDefault();
621
622		let form = event.target;
623		let data = new FormData(form);
624		let url = form.action;
625
626		let formPhone = form.querySelector("INPUT[type='tel']");
627		if (formPhone.inputmask && formPhone.inputmask.unmaskedvalue() && !formPhone.inputmask.isComplete()) {
628			formPhone.classList.add('error');
629			return;
630		}
631		if (formPhone.inputmask && !formPhone.inputmask.unmaskedvalue() && data.has(formPhone.name)) {
632			data.set(formPhone.name, "");
633		}
634
635		let formEmail = form.querySelector("INPUT[data-type='email']");
636		if (formEmail) {
637			if (formEmail.value) {
638				let validEmail = "[a-zа-я0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zа-я0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zа-я0-9](?:[a-zа-я0-9-]*[a-zа-я0-9])?\.)+[a-zа-я0-9](?:[a-zа-я0-9-]*[a-zа-я0-9])?";
639				let emailValid = formEmail.value.match(validEmail);
640				if (!emailValid) {
641					formEmail.classList.add("error");
642					return;
643				}
644			} else {
645				formEmail.classList.add("error");
646				return;
647			}
648		}
649
650		let request = new XMLHttpRequest();
651		request.open("POST", url, true);
652		form.classList.add("callback-form--loading");
653		request.onreadystatechange = function () {
654			if (request.readyState == XMLHttpRequest.DONE && request.status == 200) {
655				form.classList.remove("callback-form--loading");
656
657				let parser = new DOMParser();
658				let response = parser.parseFromString(request.responseText, 'text/html');
659
660				let errors = response.querySelector('.js-form-errors');
661				if (errors) {
662					let responseFormContent = response.querySelector('.js-question-form').innerHTML;
663					form.innerHTML = "";
664					let processed = BX.processHTML(responseFormContent, false);
665					form.insertAdjacentHTML("afterBegin", processed.HTML);
666					console.log(processed);
667					BX.ajax.processScripts(processed.SCRIPT);
668
669					let questionFormPhone = form.querySelector("INPUT[type='tel']");
670					phoneMask.mask(questionFormPhone);
671
672					return false;
673				}
674
675				let success = response.querySelector('.js-form-message');
676				if (success) {
677					let responseFormContent = response.querySelector('.js-question-form').innerHTML;
678					form.innerHTML = "";
679					let processed = BX.processHTML(responseFormContent, false);
680					form.insertAdjacentHTML("afterBegin", processed.HTML);
681					BX.ajax.processScripts(processed.SCRIPT);
682					form.style.display = "none";
683
684					let formContent = form.closest('.js-form-content');
685					formContent.prepend(success);
686
687					let formSection = form.closest('.js-question-section');
688					formSection.classList.add('section--callback-form-success');
689					return false;
690				}
691			}
692		}
693		request.send(data);
694
695		return false;
696	}
697
698
699	/* restaurants section */
700	let restaurantItems = [].slice.call(document.querySelectorAll(".js-restaurant-item"));
701	let restaurantBackgrounds = [].slice.call(document.querySelectorAll(".js-restaurant-bg"));
702	restaurantItems.forEach(function (restaurantItem) {
703		let currentItem = restaurantItem;
704
705		currentItem.addEventListener('mouseenter', function () {
706			restaurantItems.forEach(function (restaurantItem) {
707				restaurantItem.classList.remove('focus');
708			});
709			this.classList.add("focus");
710
711			let index = restaurantItems.indexOf(this);
712			restaurantBackgrounds.forEach(function (restaurantBackground) {
713				restaurantBackground.classList.remove('active');
714			});
715			restaurantBackgrounds[index].classList.add("active");
716		});
717
718		currentItem.addEventListener('touchend', function (event) {
719
720
721			if (event.target.closest('.restaurants--item--btn')) {
722				event.stopPropagation();
723				return true;
724			} else if (event.target.closest('.js-restaurant-item')) {
725				event.stopPropagation();
726				event.preventDefault();
727
728				restaurantItems.forEach(function (restaurantItem) {
729					restaurantItem.classList.remove('focus');
730				});
731				this.classList.add("focus");
732
733				let index = restaurantItems.indexOf(this);
734				restaurantBackgrounds.forEach(function (restaurantBackground) {
735					restaurantBackground.classList.remove('active');
736				});
737				restaurantBackgrounds[index].classList.add("active");
738			}
739			return false;
740		});
741	});
742
743
744	/* master classes filter */
745	let filterNavItems = [].slice.call(document.querySelectorAll('.js-filter-nav-item'));
746	let filterItems = [].slice.call(document.querySelectorAll('.js-filter-item'));
747	let filterWrapper = document.querySelector('.js-filter-wrapper');
748	let filterParams = [];
749	let filterList = Object.create(null);
750
751	if (filterWrapper) {
752
753		filterItems.forEach(function (filterItem) {
754			let itemIndex = filterItem.dataset.index;
755			itemIndex = utility.getRandomNumber(0, 9999);
756			filterList[itemIndex] = filterItem.cloneNode(true);
757		});
758
759		filterWrapper.classList.add('masters-products--updating');
760		filterFormatItems(filterWrapper, filterList, filterParams);
761
762		window.addEventListener('resize', function () {
763			filterWrapper.classList.add('masters-products--updating');
764		});
765
766		window.addEventListener('resize', utility.debounce(function () {
767			filterFormatItems(filterWrapper, filterList, filterParams);
768		}, 250));
769
770		filterNavItems.forEach(function (filterNavItem) {
771			filterNavItem.addEventListener('click', function (event) {
772				event.preventDefault();
773
774				let filterParam = event.target.dataset.param;
775				filterParams = [];
776				if (filterParam != "all") {
777					event.target.classList.add('page-filter__item--active');
778					filterParams.push(filterParam);
779				}
780
781				if (!filterParams.length) {
782					filterNavItems.forEach(function (filterNavItem) {
783						if (filterNavItem.dataset.param == "all") {
784							filterNavItem.classList.add('page-filter__item--active');
785						} else {
786							filterNavItem.classList.remove('page-filter__item--active');
787						}
788					});
789				} else {
790					filterNavItems.forEach(function (filterNavItem) {
791						if (filterNavItem.dataset.param == filterParams[0]) {
792							filterNavItem.classList.add('page-filter__item--active');
793						} else {
794							filterNavItem.classList.remove('page-filter__item--active');
795						}
796					});
797				}
798
799				filterWrapper.classList.add('masters-products--updating');
800				filterFormatItems(filterWrapper, filterList, filterParams);
801				return false;
802			});
803		});
804	}
805
806
807	Array.prototype.removeByValue = function () {
808		var what, a = arguments, L = a.length, ax;
809		while (L && this.length) {
810			what = a[--L];
811			while ((ax = this.indexOf(what)) !== -1) {
812				this.splice(ax, 1);
813			}
814		}
815		return this;
816	};
817
818	function filterFormatItems (filterWrapper, filterList, filterParams) {
819
820		// count columns
821		let columnCount = 1;
822		if (window.innerWidth > 600) {
823			columnCount = 2;
824		}
825		if (window.innerWidth > 800) {
826			columnCount = 3;
827		}
828		if (window.innerWidth > 1000) {
829			columnCount = 4;
830		}
831
832		// create columns
833		let columns = Object.create(null);
834		for (i = 0; i < columnCount; i++) {
835			let column = document.createElement('div');
836			column.className = "masters-products__column";
837			column.setAttribute('data-count', i);
838			columns[i] = column;
839		}
840
841		// fill columns
842		let itemNumber = 1;
843		for (itemIndex in filterList) {
844			let item = filterList[itemIndex].cloneNode(true);
845			let hideItem = false;
846			if (filterParams.length) {
847				hideItem = true;
848				filterParams.forEach(function (filterParam) {
849					if (typeof item.dataset[filterParam] != "undefined") {
850						hideItem = false;
851					}
852				});
853			}
854
855			if (hideItem) {
856				continue;
857			}
858
859			if (filterWrapper.classList.contains('masters-products--another')) {
860				let highLightNumber = 2;
861				if (window.innerWidth > 800) {
862					highLightNumber = 3;
863				}
864				if (window.innerWidth > 1000) {
865					highLightNumber = 1;
866				}
867				if (itemNumber == highLightNumber) {
868					item.classList.add('masters-products__item--styled');
869				}
870			} else {
871				if (itemNumber % 5 == 0) {
872					item.classList.add('masters-products__item--styled');
873				}
874			}
875
876
877			columns[(itemNumber - 1) % columnCount].appendChild(item);
878			itemNumber++;
879		}
880
881		// replace filterWrapper with columns
882		while (filterWrapper.firstChild) {
883			filterWrapper.removeChild(filterWrapper.firstChild);
884		}
885		for (columnIndex in columns) {
886			filterWrapper.appendChild(columns[columnIndex]);
887		}
888		filterWrapper.classList.remove('masters-products--updating');
889		filterWrapper.classList.add('masters-products--init');
890	}
891
892
893	/* order form */
894	let orderForm = {
895		wrapper: document.querySelector('.js-order-form'),
896		form: document.querySelector('.js-order-form-popup'),
897		selects: [].slice.call(document.querySelectorAll('.js-order-form-select')),
898		selectItems: [].slice.call(document.querySelectorAll('.js-order-form-select-item')),
899		selectInputs: [].slice.call(document.querySelectorAll('.js-order-form-select-input')),
900		datetime: document.querySelector('.js-order-form-datetime'),
901		dateInput: document.querySelector('.js-order-form-date'),
902		dateValue: document.querySelector('.js-order-form-date-value'),
903		timeTrigger: document.querySelector('.js-order-form-time-trigger'),
904		timeSlider: null,
905		timeItems: [].slice.call(document.querySelectorAll('.js-order-form-time-item')),
906		timeValue: document.querySelector('.js-order-form-time-value'),
907		timeInput: document.querySelector('.js-order-form-time-input'),
908		// payment: document.querySelector('.js-order-form-payment'),
909		// paymentToggle: document.querySelector('.js-order-form-payment-toggle'),
910		serviceToggles: [].slice.call(document.querySelectorAll('.js-order-form-service')),
911		popupTrigger: document.querySelector('.js-order-form-popup-trigger'),
912		popupWrapper: document.querySelector('.js-order-form-popup-wrapper'),
913		popupClosers: [].slice.call(document.querySelectorAll('.js-order-form-popup-close')),
914		totalPrice: document.querySelector('.js-order-form-total'),
915		adultCount: document.querySelector('.js-order-form-adult'),
916		childCount: document.querySelector('.js-order-form-child'),
917		body: document.querySelector('body'),
918		init: function () {
919			this.selectCloseHandler = this.selectCloseHandler.bind(this);
920			this.selectOpenHandler = this.selectOpenHandler.bind(this);
921			this.selectChooseHandler = this.selectChooseHandler.bind(this);
922			this.selectChangeHandler = this.selectChangeHandler.bind(this);
923			this.showDatePicker = this.showDatePicker.bind(this);
924			this.hideDatePicker = this.hideDatePicker.bind(this);
925			// this.changePaymentHandler = this.changePaymentHandler.bind(this);
926			this.timeTriggerClickHandler = this.timeTriggerClickHandler.bind(this);
927			this.timeItemClickHandler = this.timeItemClickHandler.bind(this);
928			this.formClickHandler = this.formClickHandler.bind(this);
929			this.changeServiceHandler = this.changeServiceHandler.bind(this);
930			this.updatePrice = this.updatePrice.bind(this);
931			this.formSubmit = this.formSubmit.bind(this);
932			this.openPopup = this.openPopup.bind(this);
933			this.popupClose = this.popupClose.bind(this);
934			this.clickPopupWrapperHandler = this.clickPopupWrapperHandler.bind(this);
935			this.resizeHandler = this.resizeHandler.bind(this);
936
937			this.initEvents();
938			this.initDatePicker();
939			this.initTimeSelect();
940			this.initPhoneMask();
941			this.updatePrice();
942		},
943		initEvents: function () {
944			let self = this;
945
946			if (this.selects) {
947				this.selects.forEach(function (select) {
948					select.addEventListener('click', self.selectOpenHandler);
949				});
950			}
951
952			if (this.selectItems) {
953				this.selectItems.forEach(function (selectItem) {
954					selectItem.addEventListener('click', self.selectChooseHandler);
955				});
956			}
957
958			if (this.selectInputs) {
959				this.selectInputs.forEach(function (selectInput) {
960					selectInput.addEventListener('change', self.selectChangeHandler);
961				});
962			}
963
964			if (this.timeItems) {
965				this.timeItems.forEach(function (timeItem) {
966					timeItem.addEventListener('click', self.timeItemClickHandler);
967				});
968			}
969
970			if (this.serviceToggles) {
971				this.serviceToggles.forEach(function (serviceToggle) {
972					serviceToggle.addEventListener('change', self.changeServiceHandler);
973				});
974			}
975
976			if (this.timeTrigger) {
977				this.timeTrigger.addEventListener('click', self.timeTriggerClickHandler);
978			}
979
980			// if (this.payment) {
981			//     this.payment.addEventListener('change', self.changePaymentHandler);
982			// }
983
984			if (this.popupTrigger) {
985				this.popupTrigger.addEventListener('click', self.openPopup);
986			}
987
988			if (this.popupWrapper) {
989				this.popupWrapper.addEventListener('click', self.clickPopupWrapperHandler);
990			}
991
992			if (this.popupClosers) {
993				this.popupClosers.forEach(function (popupCloser) {
994					popupCloser.addEventListener('click', self.popupClose);
995				});
996			}
997
998			if (this.form) {
999				this.form.addEventListener('click', self.formClickHandler);
1000				this.form.addEventListener('submit', self.formSubmit);
1001				if (this.form.querySelector("INPUT[name='name']")) {
1002					this.form.querySelector("INPUT[name='name']").addEventListener('change', function () {
1003						if (!this.value) {
1004							this.classList.add("error");
1005							this.classList.remove("valid");
1006						} else {
1007							this.classList.remove("error");
1008							this.classList.add("valid");
1009						}
1010					});
1011				}
1012				if (this.form.querySelector("INPUT[name='email']")) {
1013					this.form.querySelector("INPUT[name='email']").addEventListener('change', function () {
1014						if (this.value) {
1015							let validEmail = "[a-zа-я0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zа-я0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zа-я0-9](?:[a-zа-я0-9-]*[a-zа-я0-9])?\.)+[a-zа-я0-9](?:[a-zа-я0-9-]*[a-zа-я0-9])?";
1016							let emailValid = this.value.match(validEmail);
1017							if (!emailValid) {
1018								this.classList.add("error");
1019								this.classList.remove("valid");
1020							} else {
1021								this.classList.remove("error");
1022								this.classList.add("valid");
1023							}
1024						} else {
1025							this.classList.add("error");
1026							this.classList.remove("valid");
1027						}
1028					});
1029				}
1030			}
1031
1032			this.body.addEventListener('click', self.selectCloseHandler);
1033
1034			window.addEventListener('resize', utility.debounce(this.resizeHandler, 250));
1035		},
1036		resizeHandler: function () {
1037			if (window.innerWidth > 800) {
1038				this.form.style.transition = "";
1039			} else {
1040				this.form.style.transition = "opacity 0.3s ease-in-out, transform 0.3s ease-in-out";
1041			}
1042		},
1043		initDatePicker: function () {
1044			if (!this.dateInput) {
1045				return false;
1046			}
1047			let self = this;
1048			let startDay = new Date(Date.now() + 1000 * 60 * 60 * 24 * 1);
1049			let endDay = new Date(Date.now() + 1000 * 60 * 60 * 24 * 14);
1050			if (self.form.dataset.type == "master-class") {
1051				endDay = null;
1052			}
1053
1054			this.picker = datepicker(this.dateInput, {
1055				onSelect: function (instance, date) {
1056					self.dateValue.innerText = date.toLocaleDateString('ru-RU');
1057
1058					self.form.querySelector(".order-form__datetime-item[data-type='date']").classList.remove("error");
1059
1060					self.updatePrice();
1061				},
1062				onShow: function () {
1063					self.showDatePicker();
1064				},
1065				onHide: function () {
1066					self.hideDatePicker();
1067				},
1068				formatter: function (input, date, instance) {
1069					const value = date.toLocaleDateString('ru-RU');
1070					input.value = value;
1071				},
1072				position: "bl",
1073				startDay: 1,
1074				customDays: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
1075				customMonths: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
1076				defaultView: "calendar",
1077				overlayButton: "Выбрать",
1078				overlayPlaceholder: "Укажите год (4 цифры)",
1079				alwaysShow: false,
1080				minDate: startDay,
1081				maxDate: endDay,
1082				showAllDates: false,
1083				disableMobile: false,
1084				disableYearOverlay: true,
1085				disabledDates: [
1086					new Date(2025, 0, 1) // Январь = 0, так как месяцы в JavaScript начинаются с 0
1087				]
1088			});
1089		},
1090		initTimeSelect: function () {
1091			this.timeSlider = new Swiper('.js-order-form-time-slider', {
1092				direction: 'vertical',
1093				loop: false,
1094				speed: 300,
1095				slidesPerView: 5,
1096				slidesPerGroup: 5,
1097				navigation: {
1098					nextEl: '.js-order-form-time-next',
1099					prevEl: '.js-order-form-time-prev',
1100				}
1101			});
1102		},
1103		initPhoneMask: function () {
1104			let phoneMask = new Inputmask({
1105				mask: "+7 (999) 999-99-99",
1106				clearMaskOnLostFocus: true,
1107				showMaskOnHover: false,
1108				showMaskOnFocus: true,
1109				insertMode: false,
1110				insertModeVisual: false,
1111				undoOnEscape: false,
1112				positionCaretOnTab: true,
1113				tabThrough: false,
1114				shiftPositions: true,
1115				positionCaretOnClick: "lvp",
1116				inputmode: "tel",
1117				oncomplete: function (event) {
1118					event.target.classList.add('valid');
1119					event.target.classList.remove('error');
1120				},
1121				onincomplete: function (event) {
1122					event.target.classList.remove('valid');
1123					event.target.classList.add('error');
1124				},
1125				oncleared: function (event) {
1126					event.target.classList.remove('valid');
1127					event.target.classList.remove('error');
1128				},
1129				onKeyDown: function (event, buffer, caretPos, opts) {
1130					if (['ArrowRight', 'ArrowDown', 'ArrowLeft', 'ArrowUp'].includes(event.key)) {
1131						return false;
1132					}
1133				}
1134			});
1135			let formPhone = this.form.querySelector("INPUT[name='phone']");
1136			if (formPhone) {
1137				phoneMask.mask(formPhone);
1138			}
1139		},
1140		selectOpenHandler: function (event) {
1141			event.preventDefault();
1142
1143			let currentSelect = event.target;
1144			if (!currentSelect.classList.contains('js-order-form-select')) {
1145				currentSelect = currentSelect.closest('.js-order-form-select');
1146			}
1147
1148			if (currentSelect.classList.contains('order-form__count-select--active')) {
1149				return;
1150			}
1151
1152			this.selects.forEach(function (select) {
1153				select.classList.remove('order-form__count-select--active');
1154				let selectIcon = select.querySelector('.js-order-form-select-icon');
1155				let selectInput = select.querySelector('.js-order-form-select-input');
1156				if (selectIcon) {
1157					selectIcon.classList.remove('icon--chevron-up');
1158					if (selectInput && selectInput.value != "0") {
1159						selectIcon.classList.add('icon--chevron-down');
1160					} else {
1161						selectIcon.classList.add('icon--plus');
1162					}
1163				}
1164			});
1165
1166			if (!currentSelect.classList.contains('order-form__count-select--active')) {
1167				currentSelect.classList.add('order-form__count-select--active');
1168				let currentSelectIcon = currentSelect.querySelector('.js-order-form-select-icon');
1169				if (currentSelectIcon) {
1170					currentSelectIcon.classList.remove('icon--chevron-down');
1171					currentSelectIcon.classList.remove('icon--plus');
1172					currentSelectIcon.classList.add('icon--chevron-up');
1173				}
1174			}
1175		},
1176		selectCloseHandler: function (event) {
1177			let select = event.target;
1178			if (select.classList.contains('js-order-form-select-item')) {
1179				select = null;
1180			} else if (!select.classList.contains('js-order-form-select')) {
1181				select = select.closest('.js-order-form-select');
1182			}
1183
1184			if (!select && this.selects) {
1185				this.selects.forEach(function (select) {
1186					select.classList.remove('order-form__count-select--active');
1187					let selectIcon = select.querySelector('.js-order-form-select-icon');
1188					let selectInput = select.querySelector('.js-order-form-select-input');
1189					if (selectIcon) {
1190						selectIcon.classList.remove('icon--chevron-up');
1191						if (selectInput && selectInput.value != "0") {
1192							selectIcon.classList.add('icon--chevron-down');
1193						} else {
1194							selectIcon.classList.add('icon--plus');
1195						}
1196					}
1197				});
1198			}
1199		},
1200		selectChooseHandler: function (event) {
1201			event.preventDefault();
1202
1203			let selectItemValue = parseInt(event.target.innerText);
1204			let select = event.target.closest('.js-order-form-select');
1205			let selectInput = select.querySelector('.js-order-form-select-input');
1206			let selectIcon = select.querySelector('.js-order-form-select-icon');
1207
1208			this.selects.forEach(function (select) {
1209				select.classList.remove("error");
1210			});
1211
1212			select.classList.remove('order-form__count-select--active');
1213			select.classList.add('order-form__count-select--selected');
1214
1215			if (selectInput) {
1216				selectInput.value = selectItemValue;
1217			}
1218
1219			if (selectIcon) {
1220				selectIcon.classList.remove('icon--chevron-up');
1221				selectIcon.classList.add('icon--chevron-down');
1222			}
1223
1224			if (selectItemValue == 0) {
1225				select.classList.remove('order-form__count-select--selected');
1226				selectIcon.classList.remove('icon--chevron-up');
1227				selectIcon.classList.add('icon--plus');
1228			}
1229
1230			this.updatePrice();
1231		},
1232		selectChangeHandler: function (event) {
1233			event.preventDefault();
1234
1235			let input = event.target;
1236			let inputValue = parseInt(event.target.value);
1237			let inputMax = parseInt(event.target.dataset.max);
1238			let select = event.target.closest('.js-order-form-select');
1239			let selectIcon = select.querySelector('.js-order-form-select-icon');
1240
1241			this.selects.forEach(function (select) {
1242				select.classList.remove("error");
1243			});
1244
1245			if (isNaN(inputValue)) {
1246				inputValue = 0;
1247			}
1248
1249			if (!isNaN(inputMax) && inputValue > inputMax) {
1250				inputValue = inputMax;
1251			}
1252
1253			input.value = inputValue;
1254
1255			if (inputValue == 0) {
1256				select.classList.remove('order-form__count-select--selected');
1257				selectIcon.classList.remove('icon--chevron-up');
1258				selectIcon.classList.add('icon--plus');
1259			}
1260
1261			this.updatePrice();
1262		},
1263		showDatePicker: function () {
1264			this.datetime.classList.add('order-form__datetime--active');
1265			this.datetime.classList.add('order-form__datetime--active-date');
1266			this.datetime.classList.remove('order-form__datetime--active-time');
1267		},
1268		hideDatePicker: function () {
1269			this.datetime.classList.remove('order-form__datetime--active');
1270			this.datetime.classList.remove('order-form__datetime--active-date');
1271		},
1272		// changePaymentHandler: function (event) {
1273		//     let paymentCheckbox = event.target;
1274
1275		//     if (!this.paymentToggle) {
1276		//         return;
1277		//     }
1278
1279		//     if (paymentCheckbox.checked) {
1280		//         this.paymentToggle.classList.add('toggle--active');
1281		//     } else {
1282		//         this.paymentToggle.classList.remove('toggle--active');
1283		//     }
1284		// },
1285		timeTriggerClickHandlerORIG: function (event) {
1286			let self = this;
1287
1288			setTimeout(function () {
1289				self.datetime.classList.add('order-form__datetime--active');
1290				self.datetime.classList.add('order-form__datetime--active-time');
1291				self.timeSlider.update();
1292			}, 0);
1293		},
1294		timeTriggerClickHandler: function (event) {
1295			let self = this;
1296
1297			setTimeout(function () {
1298				self.datetime.classList.add('order-form__datetime--active');
1299				self.datetime.classList.add('order-form__datetime--active-time');
1300				self.timeSlider.update();
1301
1302				// Проверяем дату: если 31 декабря 2024, скрываем время после 14:00
1303				if (self.dateInput.value === '31.12.2024') {
1304					self.timeItems.forEach(function (timeItem) {
1305						// Предполагаем, что элементы времени содержат текст вида "14:30", "15:00" и т.д.
1306						let timeValue = timeItem.innerText.trim();
1307						if (timeValue > '14:00') {
1308							// Скрываем элементы, если время позже 14:00
1309							timeItem.style.display = 'none';
1310						} else {
1311							// Убеждаемся, что остальные элементы отображаются
1312							timeItem.style.display = '';
1313						}
1314					});
1315				} else {
1316					// Если дата не 31.12.2024, показываем все элементы времени
1317					self.timeItems.forEach(function (timeItem) {
1318						timeItem.style.display = '';
1319					});
1320				}
1321			}, 0);
1322		},
1323		formClickHandler: function (event) {
1324			let self = this;
1325
1326			let isDateTime = event.target.closest('.js-order-form-datetime');
1327			setTimeout(function () {
1328				if (!isDateTime) {
1329					self.datetime.classList.remove('order-form__datetime--active');
1330					self.datetime.classList.remove('order-form__datetime--active-time');
1331					self.datetime.classList.remove('order-form__datetime--active-date');
1332				}
1333			}, 0);
1334		},
1335		timeItemClickHandler: function (event) {
1336			let self = this;
1337			let item = event.target;
1338
1339			self.form.querySelector(".order-form__datetime-item[data-type='time']").classList.remove("error");
1340
1341			self.datetime.classList.remove('order-form__datetime--active');
1342			self.datetime.classList.remove('order-form__datetime--active-time');
1343			self.datetime.classList.remove('order-form__datetime--active-date');
1344
1345			self.timeValue.innerText = item.innerText;
1346			self.timeInput.value = item.innerText;
1347			self.timeTrigger.classList.add('order-form__datetime-item--active');
1348		},
1349		updatePrice: function () {
1350			let self = this;
1351
1352			// total price
1353			let total = 0;
1354			if (self.selectInputs.length > 1) {
1355				let hasOverflow = false;
1356				self.selectInputs.forEach(function (selectInput) {
1357					let count = parseInt(selectInput.value);
1358					let min = parseInt(selectInput.dataset.min);
1359					if (count >= min) {
1360						hasOverflow = true;
1361						return;
1362					}
1363				});
1364
1365				if (hasOverflow) {
1366					self.selectInputs.forEach(function (selectInput) {
1367						let count = parseInt(selectInput.value);
1368						let price = parseInt(selectInput.dataset.price);
1369						total += price * count;
1370					});
1371				} else {
1372					let adultPrice = parseInt(self.selectInputs[0].dataset.price);
1373					let adultCount = parseInt(self.selectInputs[0].value);
1374					let adultMin = parseInt(self.selectInputs[0].dataset.min);
1375					let childPrice = parseInt(self.selectInputs[1].dataset.price);
1376					let childCount = parseInt(self.selectInputs[1].value);
1377					let minTotal = adultPrice * adultMin;
1378
1379					if (adultCount + childCount <= adultMin) {
1380						adultCount = adultCount + childCount;
1381						childCount = 0;
1382					} else {
1383						childCount = childCount - (adultMin - adultCount);
1384						adultCount = adultMin;
1385					}
1386
1387					total += adultPrice * adultCount + childPrice * childCount;
1388
1389					if (total < minTotal) {
1390						total = minTotal;
1391					}
1392				}
1393			} else {
1394				let minTotal = 0;
1395				self.selectInputs.forEach(function (selectInput) {
1396					let count = parseInt(selectInput.value);
1397					let price = parseInt(selectInput.dataset.price);
1398					let min = parseInt(selectInput.dataset.min);
1399
1400					minTotal = price * min;
1401					total += price * count;
1402				});
1403				if (total < minTotal) {
1404					total = minTotal;
1405				}
1406			}
1407
1408			self.serviceToggles.forEach(function (serviceToggle) {
1409				if (serviceToggle.checked) {
1410					total += parseInt(serviceToggle.dataset.price);
1411				}
1412			});
1413			if (self.totalPrice) {
1414				self.totalPrice.innerText = total + " ₽";
1415			}
1416
1417			// adult & child count
1418			self.selectInputs.forEach(function (selectInput) {
1419				if (selectInput.name == "count[adult]") {
1420					if (self.adultCount) {
1421						if (selectInput.value > 0) {
1422							self.adultCount.closest('.order-form__summary-item').classList.remove('order-form__summary-item--disabled');
1423							self.adultCount.innerText = selectInput.value;
1424						} else {
1425							self.adultCount.closest('.order-form__summary-item').classList.add('order-form__summary-item--disabled');
1426							self.adultCount.innerText = "";
1427						}
1428					}
1429				} else if (selectInput.name == "count[child]") {
1430					if (self.childCount) {
1431						if (selectInput.value > 0) {
1432							self.childCount.closest('.order-form__summary-item').classList.remove('order-form__summary-item--disabled');
1433							self.childCount.innerText = selectInput.value;
1434						} else {
1435							self.childCount.closest('.order-form__summary-item').classList.add('order-form__summary-item--disabled');
1436							self.childCount.innerText = "";
1437						}
1438					}
1439				}
1440			});
1441		},
1442		changeServiceHandler: function () {
1443			this.updatePrice();
1444		},
1445		formSubmit: function (event) {
1446			event.preventDefault();
1447
1448			let self = this;
1449			let form = self.form;
1450			let data = Object.create(null);
1451			let hasErrors = false;
1452
1453			// check can buy
1454			let formCanBuyInput = form.querySelector(".js-order-form-can-buy");
1455			data.can_buy = formCanBuyInput.value;
1456
1457			// check type
1458			let formTypeInput = form.querySelector(".js-order-form-type");
1459			data.type = formTypeInput.value;
1460
1461			// check back url
1462			let formBackUrlInput = form.querySelector(".js-order-form-back-url");
1463			data.back_url = formBackUrlInput.value;
1464
1465			// check title|name
1466			let formTitleInput = form.querySelector(".js-order-form-title");
1467			data.title = formTitleInput.value;
1468
1469			// check counts
1470			data.counts = Object.create(null);
1471			let formAdultCountInput = form.querySelector("INPUT[name='count[adult]']");
1472			let formAdultCount = formAdultCountInput.closest('.order-form__count-select');
1473			let formChildCountInput = form.querySelector("INPUT[name='count[child]']");
1474			let formChildCount = null;
1475
1476			if (formChildCountInput) {
1477				formChildCount = formChildCountInput.closest('.order-form__count-select');
1478				if (!parseInt(formAdultCountInput.value) && !parseInt(formChildCountInput.value)) {
1479					formAdultCount.classList.add("error");
1480					formChildCount.classList.add("error");
1481					hasErrors = true;
1482				} else {
1483					if (parseInt(formAdultCountInput.value)) {
1484						data.counts.adult = Object.create(null);
1485						data.counts.adult.qty = parseInt(formAdultCountInput.value);
1486						data.counts.adult.id = formAdultCountInput.dataset.id;
1487						data.counts.adult.price = parseInt(formAdultCountInput.dataset.price);
1488						data.counts.adult.min = parseInt(formAdultCountInput.dataset.min);
1489					}
1490					if (parseInt(formChildCountInput.value)) {
1491						data.counts.child = Object.create(null);
1492						data.counts.child.qty = parseInt(formChildCountInput.value);
1493						data.counts.child.id = formChildCountInput.dataset.id;
1494						data.counts.child.price = parseInt(formChildCountInput.dataset.price);
1495						data.counts.child.min = parseInt(formChildCountInput.dataset.min);
1496					}
1497				}
1498			} else {
1499				if (!parseInt(formAdultCountInput.value)) {
1500					formAdultCount.classList.add("error");
1501					hasErrors = true;
1502				} else {
1503					data.counts.adult = Object.create(null);
1504					data.counts.adult.qty = parseInt(formAdultCountInput.value);
1505					data.counts.adult.id = formAdultCountInput.dataset.id;
1506					data.counts.adult.price = parseInt(formAdultCountInput.dataset.price);
1507					data.counts.adult.min = parseInt(formAdultCountInput.dataset.min);
1508				}
1509			}
1510
1511			// check service
1512			let formServiceInput = form.querySelector(".js-order-form-service");
1513			if (formServiceInput && formServiceInput.checked) {
1514				data.counts.service = Object.create(null);
1515				data.counts.service.qty = 1;
1516				data.counts.service.id = formServiceInput.dataset.id;
1517			}
1518
1519			// check payment
1520			let formPaymentInput = form.querySelectorAll(".js-order-form-payment");
1521			data.onlinePayment = false;
1522			if (formPaymentInput.length) {
1523				formPaymentInput.forEach(function (input) {
1524					if (input.checked) {
1525						data.onlinePayment = input.value === 'online' ? true : false
1526					}
1527				})
1528			}
1529
1530			// check date
1531			let formDate = form.querySelector(".order-form__datetime-item[data-type='date']");
1532			let formDateInput = form.querySelector(".js-order-form-date");
1533			if (!formDateInput.value) {
1534				formDate.classList.add("error");
1535				hasErrors = true;
1536			} else {
1537				data.date = formDateInput.value;
1538			}
1539
1540			// check time
1541			let formTime = form.querySelector(".order-form__datetime-item[data-type='time']");
1542			let formTimeInput = form.querySelector(".js-order-form-time-input");
1543			if (!formTimeInput.value) {
1544				formTime.classList.add("error");
1545				hasErrors = true;
1546			} else {
1547				data.time = formTimeInput.value;
1548			}
1549
1550			// check name
1551			let formName = form.querySelector("INPUT[name='name']");
1552			if (!formName.value) {
1553				formName.classList.add("error");
1554				hasErrors = true;
1555			} else {
1556				data.name = formName.value;
1557			}
1558
1559			// check email
1560			let formEmail = form.querySelector("INPUT[name='email']");
1561			if (formEmail.value) {
1562				let validEmail = "[a-zа-я0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zа-я0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zа-я0-9](?:[a-zа-я0-9-]*[a-zа-я0-9])?\.)+[a-zа-я0-9](?:[a-zа-я0-9-]*[a-zа-я0-9])?";
1563				let emailValid = formEmail.value.match(validEmail);
1564				if (!emailValid) {
1565					formEmail.classList.add("error");
1566					hasErrors = true;
1567				} else {
1568					data.email = formEmail.value;
1569				}
1570			} else {
1571				formEmail.classList.add("error");
1572				hasErrors = true;
1573			}
1574
1575			// check phone
1576			let formPhone = form.querySelector("INPUT[name='phone']");
1577			if (formPhone.value) {
1578				if (formPhone.inputmask && formPhone.inputmask.unmaskedvalue() && !formPhone.inputmask.isComplete()) {
1579					formPhone.classList.add('error');
1580					hasErrors = true;
1581				} else {
1582					data.phone = formPhone.value;
1583				}
1584			} else {
1585				formPhone.classList.add("error");
1586				hasErrors = true;
1587			}
1588
1589			if (hasErrors) {
1590				return;
1591			}
1592
1593			// send request
1594			form.closest('.order-form').classList.add('order-form--loading');
1595			let request = BX.ajax.runComponentAction('dl:fast.order', 'load', {
1596				mode: 'class',
1597				json: data
1598			});
1599
1600			request.then(function (response) {
1601				form.closest('.order-form').classList.remove('order-form--loading');
1602				if (response.status == "success") {
1603					if (response.data.result == "ok") {
1604						form.closest('.order-form').querySelector(".js-order-form-success-date").innerText = response.data.date;
1605						form.closest('.order-form').querySelector(".js-order-form-success-time").innerText = response.data.time;
1606						form.closest('.order-form').querySelector(".js-order-form-success-id").innerText = response.data.order_id;
1607						if (typeof response.data.pay_html != 'undefined' && response.data.pay_html != "") {
1608							form.closest('.order-form').querySelector(".js-order-form-success-payment").classList.add('order-form__success-payment--active');
1609							form.closest('.order-form').querySelector(".js-order-form-success-payment").innerHTML = response.data.pay_html;
1610							let formAmount = form.closest('.order-form').querySelector(".js-order-form-success-amount");
1611							if (formAmount) {
1612								formAmount.closest("P").style.display = "none";
1613							}
1614						} else {
1615							let formAmount = form.closest('.order-form').querySelector(".js-order-form-success-amount");
1616							if (formAmount && typeof response.data.amount != 'undefined') {
1617								formAmount.innerText = response.data.amount;
1618							}
1619						}
1620						form.closest('.order-form').classList.add('order-form--success');
1621					} else {
1622						console.log('error', response);
1623					}
1624				} else {
1625					console.log('error', response);
1626				}
1627			}, function (response) {
1628				form.closest('.order-form').classList.remove('order-form--loading');
1629				console.log('error', response);
1630			});
1631
1632			return false;
1633		},
1634		openPopup: function () {
1635			this.wrapper.classList.add('order-form--open');
1636			utility.disableScroll();
1637		},
1638		popupClose: function () {
1639			this.wrapper.classList.remove('order-form--open');
1640			this.wrapper.classList.remove('order-form--success');
1641			utility.enableScroll();
1642		},
1643		clickPopupWrapperHandler: function (event) {
1644			if (event.target == this.popupWrapper) {
1645				this.popupClose();
1646			}
1647		}
1648	}
1649
1650	let orderFormElement = document.querySelector('.js-order-form');
1651	if (orderFormElement) {
1652		orderForm.init();
1653	}
1654
1655
1656	/* fslightbox */
1657	let photoGalleryItems = [].slice.call(document.querySelectorAll('.js-photo-gallery-item'));
1658	if (photoGalleryItems.length) {
1659		let lightbox = new FsLightbox();
1660
1661		lightbox.props.type = 'image';
1662		lightbox.props.showThumbsOnMount = true;
1663		lightbox.props.UIFadeOutTime = 30000;
1664
1665		lightbox.props.toolbarButtons.thumbs.title = "Эскизы";
1666		lightbox.props.toolbarButtons.zoomIn.title = "Увеличить";
1667		lightbox.props.toolbarButtons.zoomOut.title = "Уменьшить";
1668		lightbox.props.toolbarButtons.slideshow.start.title = "Включить воспроизведение";
1669		lightbox.props.toolbarButtons.slideshow.pause.title = "Остановить воспроизведение";
1670		lightbox.props.toolbarButtons.fullscreen.enter.title = "Развернуть";
1671		lightbox.props.toolbarButtons.fullscreen.exit.title = "Свернуть";
1672		lightbox.props.toolbarButtons.close.title = "Закрыть";
1673		lightbox.props.slideButtons.previous = {
1674			width: "16px",
1675			height: "32px",
1676			viewBox: "0 0 16 32",
1677			d: "M12.8493 30.4721C13.1409 30.9411 12.997 31.5577 12.5279 31.8493C12.0589 32.1409 11.4423 31.997 11.1507 31.5279L12.8493 30.4721ZM2.67567 16L1.82639 16.5279L1.49821 16L1.82639 15.4721L2.67567 16ZM11.1507 0.472065C11.4423 0.00301931 12.0589 -0.140856 12.5279 0.150715C12.997 0.442286 13.1409 1.05889 12.8493 1.52794L11.1507 0.472065ZM11.1507 31.5279L1.82639 16.5279L3.52496 15.4721L12.8493 30.4721L11.1507 31.5279ZM1.82639 15.4721L11.1507 0.472065L12.8493 1.52794L3.52496 16.5279L1.82639 15.4721Z",
1678			title: "Предыдущая"
1679		};
1680		lightbox.props.slideButtons.next = {
1681			width: "16px",
1682			height: "32px",
1683			viewBox: "0 0 16 32",
1684			d: "M2.15071 30.4721C1.85914 30.9411 2.00302 31.5577 2.47207 31.8493C2.94111 32.1409 3.55772 31.997 3.84929 31.5279L2.15071 30.4721ZM12.3243 16L13.1736 16.5279L13.5018 16L13.1736 15.4721L12.3243 16ZM3.84928 0.472065C3.55771 0.00301931 2.94111 -0.140856 2.47206 0.150715C2.00302 0.442286 1.85914 1.05889 2.15071 1.52794L3.84928 0.472065ZM3.84929 31.5279L13.1736 16.5279L11.475 15.4721L2.15071 30.4721L3.84929 31.5279ZM13.1736 15.4721L3.84928 0.472065L2.15071 1.52794L11.475 16.5279L13.1736 15.4721Z",
1685			title: "Следующая"
1686		};
1687
1688		lightbox.props.sources = jsPhotoGallerySources;
1689		lightbox.props.thumbs = jsPhotoGalleryThumbs;
1690		/* lightbox.props.captions = jsPhotoGalleryCaptions; */
1691
1692		photoGalleryItems.forEach(function (photoGalleryItem) {
1693			let index = parseInt(photoGalleryItem.dataset.index);
1694			photoGalleryItem.addEventListener('click', function () {
1695				lightbox.open(index);
1696			});
1697		});
1698
1699		let orderWrapper = document.querySelector('.js-order-form-popup-wrapper');
1700		let galleryWrapper = document.querySelector('.section--photo-gallery .photo-gallery');
1701		if (orderWrapper && galleryWrapper) {
1702
1703			window.addEventListener('load', function () {
1704				moveGallery(galleryWrapper, orderWrapper);
1705			});
1706
1707			window.addEventListener('resize', utility.debounce(function () {
1708				moveGallery(galleryWrapper, orderWrapper);
1709			}, 250));
1710		}
1711	}
1712
1713	function moveGallery (galleryWrapper, orderWrapper) {
1714		let targetImages = galleryWrapper.querySelector('.photo-gallery__images');
1715		if (!targetImages) {
1716			return;
1717		}
1718
1719		let targetWrapper = orderWrapper.closest('.section.section--master-class');
1720		if (!targetWrapper) {
1721			return;
1722		}
1723
1724		let targetImagesColumns = [].slice.call(galleryWrapper.querySelectorAll('.photo-gallery__column'));
1725		let maxWidth = 0;
1726		let columnWidth = Object.create(null);
1727		let columnIndex = 0;
1728		targetImagesColumns.forEach(function (targetImagesColumn) {
1729			let targetImagesColumnChildren = [].slice.call(targetImagesColumn.querySelectorAll('.photo-gallery__item'));
1730			columnWidth[columnIndex] = 0;
1731			targetImagesColumnChildren.forEach(function (targetImagesColumnChild) {
1732				columnWidth[columnIndex] += targetImagesColumnChild.clientWidth + 10;
1733			});
1734			if (columnWidth[columnIndex] > maxWidth) {
1735				maxWidth = columnWidth[columnIndex];
1736			}
1737			columnIndex++;
1738		});
1739
1740		if (window.innerWidth > 800) {
1741			let orderWrapperPosition = orderWrapper.getBoundingClientRect();
1742			let galleryWrapperPosition = galleryWrapper.getBoundingClientRect();
1743			if (orderWrapperPosition.bottom < galleryWrapperPosition.top) {
1744				if (window.innerWidth > (maxWidth + 40)) {
1745					gsap.set(targetImages, { x: window.innerWidth - galleryWrapperPosition.right - (window.innerWidth - maxWidth + 20) / 2 });
1746					let columnIndex = 0;
1747					targetImagesColumns.forEach(function (targetImagesColumn) {
1748						if (columnWidth[columnIndex] < maxWidth) {
1749							gsap.set(targetImagesColumn, { x: (columnWidth[columnIndex] - maxWidth) / 2 });
1750						}
1751						columnIndex++;
1752					});
1753				} else {
1754					gsap.set(targetImages, { x: window.innerWidth - galleryWrapperPosition.right });
1755					targetImagesColumns.forEach(function (targetImagesColumn) {
1756						gsap.set(targetImagesColumn, { x: 0 });
1757					});
1758				}
1759				targetWrapper.style.overflow = "hidden";
1760			} else {
1761				gsap.set(targetImages, { x: 0 });
1762				targetImagesColumns.forEach(function (targetImagesColumn) {
1763					gsap.set(targetImagesColumn, { x: 0 });
1764				});
1765				targetWrapper.style.overflow = "";
1766			}
1767		} else {
1768			gsap.set(targetImages, { x: 0 });
1769			targetImagesColumns.forEach(function (targetImagesColumn) {
1770				gsap.set(targetImagesColumn, { x: 0 });
1771			});
1772			targetWrapper.style.overflow = "";
1773		}
1774	}
1775
1776	/* chronology__content--page_nav arrow */
1777	let сhronologyNavContent = document.querySelector('.section--сhronology .chronology__content--page_nav');
1778	let сhronologySpoilerTrigger = document.querySelector('.section--сhronology .chronology__content--page_nav__arrow');
1779
1780	if (сhronologySpoilerTrigger) {
1781		сhronologySpoilerTrigger.addEventListener('click', сhronologySpoilerClickHandler);
1782	}
1783
1784	function сhronologySpoilerClickHandler () {
1785		сhronologyNavContent.classList.toggle('show');
1786		сhronologySpoilerTrigger.classList.toggle('active');
1787	};
1788
1789
1790	/* gridify */
1791	window.onload = function () {
1792		gridify.init();
1793	};
1794
1795	window.addEventListener('resize', utility.debounce(function () {
1796		gridify.reInit();
1797	}, 250));
1798
1799
1800	/* worship */
1801	let worship = document.querySelector('.js-worship');
1802	if (worship) {
1803		let worshipItems = [].slice.call(document.querySelectorAll('.js-worship-item'));
1804		worshipItems.forEach(function (worshipItem) {
1805			let itemSaints = worshipItem.querySelector('.js-worship-saints');
1806			if (itemSaints && itemSaints.clientHeight > 60) {
1807				itemSaints.classList.add('worship__item-saints--with-spoiler');
1808			}
1809
1810			worshipItem.addEventListener('touchend', function (event) {
1811				if (event.target.classList.contains('js-worship-link')) {
1812					return true;
1813				}
1814
1815				if (event.target.classList.contains('js-worship-saints') && event.target.classList.contains('worship__item-saints--with-spoiler')) {
1816					event.preventDefault();
1817
1818					let worshipSaints = event.target;
1819					if (worshipSaints.classList.contains('worship__item-saints--active')) {
1820						worshipSaints.classList.remove('worship__item-saints--active');
1821					} else {
1822						worshipSaints.classList.add('worship__item-saints--active');
1823					}
1824				}
1825
1826				return false;
1827			});
1828
1829			worshipItem.addEventListener('click', function (event) {
1830				if (event.target.classList.contains('js-worship-link')) {
1831					return true;
1832				}
1833
1834				if (event.target.classList.contains('js-worship-saints') && event.target.classList.contains('worship__item-saints--with-spoiler')) {
1835					let worshipSaints = event.target;
1836					if (worshipSaints.classList.contains('worship__item-saints--active')) {
1837						worshipSaints.classList.remove('worship__item-saints--active');
1838					} else {
1839						worshipSaints.classList.add('worship__item-saints--active');
1840					}
1841				}
1842
1843				return false;
1844			});
1845		});
1846
1847		let worshipCalendarButton = document.querySelector('.js-worship-calendar-button');
1848		let worshipCalendarWrapper = document.querySelector('.js-worship-calendar-wrapper');
1849		if (worshipCalendarButton && worshipCalendarWrapper) {
1850			worshipCalendarButton.addEventListener('touchend', function (event) {
1851				event.stopPropagation();
1852				event.preventDefault();
1853
1854				showMobileCalendar();
1855
1856				return false;
1857			});
1858
1859			worshipCalendarButton.addEventListener('click', function (event) {
1860				event.preventDefault();
1861
1862				showMobileCalendar();
1863
1864				return false;
1865			});
1866		}
1867
1868		let worshipCalendarClosers = [].slice.call(document.querySelectorAll('.js-worship-calendar-closer'));
1869		worshipCalendarClosers.forEach(function (worshipCalendarCloser) {
1870			worshipCalendarCloser.addEventListener('touchend', function (event) {
1871				event.stopPropagation();
1872				event.preventDefault();
1873
1874				hideMobileCalendar();
1875
1876				return false;
1877			});
1878
1879			worshipCalendarCloser.addEventListener('click', function (event) {
1880				event.preventDefault();
1881
1882				hideMobileCalendar();
1883
1884				return false;
1885			});
1886		});
1887
1888		let showMobileCalendar = function () {
1889			worshipCalendarWrapper.classList.add('worship__calendar-wrapper--active');
1890			utility.disableScroll();
1891		};
1892		let hideMobileCalendar = function () {
1893			worshipCalendarWrapper.classList.remove('worship__calendar-wrapper--active');
1894			utility.enableScroll();
1895		};
1896
1897		let worshipElementsWrapper = document.querySelector('.js-worship-elements');
1898		if (worshipElementsWrapper && worshipCalendarButton) {
1899			let worshipObserverOptions = {
1900				rootMargin: '0px',
1901				threshold: 0.1
1902			}
1903			let worshipObserverCallback = function (entries, observer) {
1904				entries.forEach(function (entry) {
1905					if (entry.isIntersecting) {
1906						worshipCalendarButton.classList.add('worship__calendar-button--visible');
1907					} else {
1908						worshipCalendarButton.classList.remove('worship__calendar-button--visible');
1909					}
1910				});
1911			};
1912			let worshipObserver = new IntersectionObserver(worshipObserverCallback, worshipObserverOptions);
1913			worshipObserver.observe(worshipElementsWrapper);
1914		}
1915
1916		let correctWorshipCalendarCells = function () {
1917			let worshipCalendarCells = [].slice.call(worship.querySelectorAll('.qs-square'));
1918			worshipCalendarCells.forEach(function (worshipCalendarCell) {
1919				if (!worshipCalendarCell.classList.contains('qs-num--hidden') && !worshipCalendarCell.classList.contains('qs-outside-current-month')) {
1920					worshipCalendarCell.style.height = worshipCalendarCell.clientWidth + "px";
1921				}
1922			});
1923		};
1924
1925		let worshipMonthsWrapper = worship.querySelector('.js-worship-months');
1926		let currentDate = null;
1927		if (worshipMonthsWrapper) {
1928			currentDate = worshipMonthsWrapper.dataset.current;
1929		}
1930
1931		let worshipMonths = [].slice.call(worship.querySelectorAll('.js-worship-month'));
1932		worshipMonths.forEach(function (worshipMonth) {
1933			let disabledDates = [];
1934			worshipCalendarDates[worshipMonth.dataset.month].forEach(function (day) {
1935				if (!day.active) {
1936					disabledDates.push(new Date(day.value));
1937				}
1938			});
1939
1940			let highlightedDates = [];
1941			worshipCalendarDates[worshipMonth.dataset.month].forEach(function (day) {
1942				if (day.highlight) {
1943					highlightedDates.push(new Date(day.value));
1944				}
1945			});
1946
1947			let startDayElement = worshipCalendarDates[worshipMonth.dataset.month].shift();
1948			let startDay = new Date(startDayElement.value);
1949			worshipCalendarDates[worshipMonth.dataset.month].unshift(startDayElement);
1950
1951			let endDayElement = worshipCalendarDates[worshipMonth.dataset.month].pop();
1952			let endDay = new Date(endDayElement.value);
1953			worshipCalendarDates[worshipMonth.dataset.month].push(endDayElement);
1954
1955			let monthPicker = datepicker(worshipMonth, {
1956				formatter: function (input, date, instance) {
1957					const value = date.toLocaleDateString('ru-RU');
1958					input.value = value;
1959				},
1960				onSelect: function (instance, date) {
1961					const value = date.toLocaleDateString('ru-RU');
1962					let valueParts;
1963					let url;
1964
1965					if (value.includes("/")) {
1966						valueParts = value.split("/");
1967						url = "/worship/date-" + valueParts[2] + "-" + valueParts[0] + "-" + valueParts[1] + "/";
1968					} else {
1969						valueParts = value.split(".");
1970						url = "/worship/date-" + valueParts[0] + "-" + valueParts[1] + "-" + valueParts[2] + "/";
1971					}
1972
1973					window.location.href = url;
1974				},
1975				onMonthChange: function (instance) {
1976					let target = instance.calendar;
1977					let days = [].slice.call(target.querySelectorAll('.qs-num'));
1978					let calendarDate = instance.el.dataset.date;
1979					let calendarMonth = instance.el.dataset.month;
1980					let calendarActiveDates = [];
1981					worshipCalendarDates[calendarMonth].forEach(function (day) {
1982						calendarActiveDates.push(day.value.replaceAll('-', '.'));
1983					});
1984					days.forEach(function (day) {
1985						let currentDay = day.innerHTML;
1986						while (currentDay.length < 2) currentDay = "0" + currentDay;
1987						let calendarDateValues = calendarDate.split(".");
1988						currentDay = calendarDateValues[0] + "." + calendarDateValues[1] + "." + currentDay;
1989						if (!calendarActiveDates.includes(currentDay)) {
1990							day.classList.add('qs-num--hidden');
1991						}
1992						if (!day.classList.contains('qs-disabled')) {
1993							if (!day.previousSibling || (day.previousSibling && !day.previousSibling.classList.contains('qs-num')) || (day.previousSibling && day.previousSibling.classList.contains('qs-disabled'))) {
1994								day.classList.add('qs-num--first');
1995							}
1996							if (!day.nextSibling || (day.nextSibling && !day.nextSibling.classList.contains('qs-num')) || (day.nextSibling && day.nextSibling.classList.contains('qs-disabled'))) {
1997								day.classList.add('qs-num--last');
1998							}
1999						}
2000					});
2001					correctWorshipCalendarCells();
2002				},
2003				position: "bl",
2004				startDay: 1,
2005				defaultView: "calendar",
2006				alwaysShow: false,
2007				minDate: startDay,
2008				maxDate: endDay,
2009				showAllDates: false,
2010				disabledDates: disabledDates,
2011				events: highlightedDates,
2012				disableMobile: false,
2013				disableYearOverlay: true
2014			});
2015			if (worshipMonth.value) {
2016				let value = worshipMonth.value;
2017				let valueParts;
2018				let date;
2019
2020				if (value.includes("/")) {
2021					valueParts = value.split("/");
2022					date = new Date(Number(valueParts[2]), Number(valueParts[0]) - 1, Number(valueParts[1]));
2023				} else {
2024					valueParts = value.split(".");
2025					if (valueParts[0].length === 4) {
2026						date = new Date(Number(valueParts[0]), Number(valueParts[1]) - 1, Number(valueParts[2]));
2027					} else {
2028						date = new Date(Number(valueParts[2]), Number(valueParts[1]) - 1, Number(valueParts[0]));
2029					}
2030				}
2031
2032				monthPicker.setDate(date);
2033			}
2034			monthPicker.show();
2035			monthPicker.navigate(endDay, true);
2036		});
2037		window.addEventListener('resize', utility.throttle(function () {
2038			correctWorshipCalendarCells();
2039		}, 100));
2040		correctWorshipCalendarCells();
2041
2042		/* correct js-worship-link width */
2043		let worshipLinks = [...document.querySelectorAll('.js-worship-link')];
2044
2045		let worshipDateLinks = [];
2046		worshipLinks.forEach(worshipLink => {
2047			if (worshipLink.classList.contains('worship__item-date') && !worshipLink.closest('.worship__item--active')) {
2048				worshipDateLinks.push(worshipLink);
2049			}
2050		});
2051
2052		let worshipDateLinkWidths = [];
2053		worshipDateLinks.forEach(worshipDateLink => {
2054			worshipDateLinkWidths.push(worshipDateLink.getBoundingClientRect().width);
2055		});
2056
2057		let worshipDateLinkMaxWidth = Math.ceil(Math.max.apply(null, worshipDateLinkWidths));
2058		worshipDateLinks.forEach(worshipDateLink => {
2059			worshipDateLink.style.width = worshipDateLinkMaxWidth + "px";
2060		});
2061	}
2062
2063
2064	/* news calendar */
2065	let chronologySelectDay = document.querySelector('.js-chrono-select-day');
2066	let newsCalendar = document.querySelector('.js-news-calendar');
2067	let newsCalendarClosers = [].slice.call(document.querySelectorAll('.js-news-calendar-closer'));
2068	if (chronologySelectDay && newsCalendar) {
2069		chronologySelectDay.addEventListener('touchend', chronologySelectDayTouchHandler);
2070		chronologySelectDay.addEventListener('click', chronologySelectDayClickHandler);
2071		newsCalendarClosers.forEach(function (newsCalendarCloser) {
2072			newsCalendarCloser.addEventListener('touchend', chronologyCloserTouchHandler);
2073			newsCalendarCloser.addEventListener('click', chronologyCloserClickHandler);
2074		});
2075
2076		let newsCalendarInput = document.querySelector('.js-news-calendar-input');
2077		if (newsCalendarInput) {
2078			let enableDates = [];
2079			for (item in newsCalendarDates) {
2080				enableDates.push(newsCalendarDates[item]);
2081			}
2082
2083			let newsCalendarPicker = datepicker(newsCalendarInput, {
2084				formatter: function (input, date, instance) {
2085					const value = date.toLocaleDateString('ru-RU');
2086					input.value = value;
2087				},
2088				onSelect: function (instance, date) {
2089					const value = date.toLocaleDateString('ru-RU');
2090					let valueParts;
2091					let url;
2092
2093					if (value.includes("/")) {
2094						valueParts = value.split("/");
2095						url = "/lavra-news/date-" + valueParts[2] + "-" + valueParts[0] + "-" + valueParts[1] + "/";
2096					} else {
2097						valueParts = value.split(".");
2098						url = "/lavra-news/date-" + valueParts[0] + "-" + valueParts[1] + "-" + valueParts[2] + "/";
2099					}
2100
2101					window.location.href = url;
2102				},
2103				onMonthChange: function (instance) {
2104					initNewsCalendar(instance);
2105				},
2106				onShow: function (instance) {
2107					initNewsCalendar(instance);
2108				},
2109				disabler: function (date) {
2110					const value = date.toLocaleDateString('ru-RU');
2111					let values = value.split(".");
2112					let dateValue = values[2] + "-" + values[1] + "-" + values[0];
2113					return !enableDates.includes(dateValue);
2114				},
2115				position: "bl",
2116				startDay: 1,
2117				defaultView: "calendar",
2118				alwaysShow: true,
2119				showAllDates: false,
2120				disableMobile: false,
2121				disableYearOverlay: false,
2122				customDays: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
2123				customMonths: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
2124				overlayButton: "Выбрать",
2125				overlayPlaceholder: "Укажите год (4 цифры)"
2126			});
2127
2128			if (newsCalendarInput.value) {
2129				let value = newsCalendarInput.value;
2130				let valueParts;
2131				let date;
2132
2133				if (value.includes("/")) {
2134					valueParts = value.split("/");
2135					date = new Date(Number(valueParts[2]), Number(valueParts[0]) - 1, Number(valueParts[1]));
2136				} else {
2137					valueParts = value.split(".");
2138					if (valueParts[0].length === 4) {
2139						date = new Date(Number(valueParts[0]), Number(valueParts[1]) - 1, Number(valueParts[2]));
2140					} else {
2141						date = new Date(Number(valueParts[2]), Number(valueParts[1]) - 1, Number(valueParts[0]));
2142					}
2143				}
2144
2145				newsCalendarPicker.setDate(date);
2146				newsCalendarPicker.navigate(date, true);
2147			} else {
2148				newsCalendarPicker.show();
2149			}
2150		}
2151	}
2152
2153	function chronologySelectDayTouchHandler (event) {
2154		event.stopPropagation();
2155		event.preventDefault();
2156
2157		if (newsCalendar.classList.contains('news-calendar--active')) {
2158			chronologyHideCalendar();
2159		} else {
2160			chronologyShowCalendar();
2161		}
2162
2163		return false;
2164	}
2165
2166	function chronologySelectDayClickHandler (event) {
2167		event.preventDefault();
2168
2169		if (newsCalendar.classList.contains('news-calendar--active')) {
2170			chronologyHideCalendar();
2171		} else {
2172			chronologyShowCalendar();
2173		}
2174
2175		return false;
2176	}
2177
2178	function chronologyCloserTouchHandler (event) {
2179		event.stopPropagation();
2180		event.preventDefault();
2181
2182		chronologyHideCalendar();
2183
2184		return false;
2185	}
2186
2187	function chronologyCloserClickHandler (event) {
2188		event.preventDefault();
2189
2190		chronologyHideCalendar();
2191
2192		return false;
2193	}
2194
2195	function chronologyShowCalendar () {
2196		newsCalendar.classList.add('news-calendar--active');
2197		utility.disableScroll();
2198	}
2199
2200	function chronologyHideCalendar () {
2201		newsCalendar.classList.remove('news-calendar--active');
2202		utility.enableScroll();
2203	}
2204
2205	function initNewsCalendar (instance) {
2206		let target = instance.calendar;
2207		let days = [].slice.call(target.querySelectorAll('.qs-num'));
2208		days.forEach(function (day) {
2209			if (!day.classList.contains('qs-disabled')) {
2210				if (!day.previousSibling || (day.previousSibling && !day.previousSibling.classList.contains('qs-num')) || (day.previousSibling && day.previousSibling.classList.contains('qs-disabled'))) {
2211					day.classList.add('qs-num--first');
2212				}
2213				if (!day.nextSibling || (day.nextSibling && !day.nextSibling.classList.contains('qs-num')) || (day.nextSibling && day.nextSibling.classList.contains('qs-disabled'))) {
2214					day.classList.add('qs-num--last');
2215				}
2216			}
2217		});
2218
2219		correctNewsCalendarCells(instance);
2220	}
2221
2222	function correctNewsCalendarCells (instance) {
2223		let target = instance.calendar;
2224		let days = [].slice.call(target.querySelectorAll('.qs-num'));
2225
2226		days.forEach(function (day) {
2227			let rect = day.getBoundingClientRect();
2228			day.style.height = rect.width + "px";
2229		});
2230	};
2231
2232
2233	if (document.getElementById('inline-picker')) {
2234		const picker = datepicker('#inline-picker', {
2235			customDays: ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'],
2236			customMonths: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
2237			defaultView: "calendar",
2238			overlayButton: "Выбрать",
2239			overlayPlaceholder: "Укажите год (4 цифры)",
2240			alwaysShow: true,
2241		})
2242	}
2243
2244
2245	let calendarPopUp = document.getElementById('calendar-popup')
2246	if (calendarPopUp) {
2247		let calendarPopupOpen = document.querySelectorAll('.calendar-popup__open')
2248		let calendarPopupClose = document.querySelectorAll('.calendar-popup__close')
2249
2250		calendarPopupOpen.forEach(el => el.addEventListener('click', function () {
2251			calendarPopUp.classList.add('active')
2252		}))
2253
2254		calendarPopupClose.forEach(el => el.addEventListener('click', function () {
2255			el.closest('.calendar-popup').classList.remove('active')
2256		}))
2257
2258		calendarPopUp.addEventListener('mouseup', function (e) {
2259			if (!e.target.closest('.calendar-popup__wrap')) {
2260				this.closest('.calendar-popup').classList.remove('active')
2261			}
2262		})
2263	}
2264
2265	/* chronology photo grid */
2266	(() => {
2267		console.log('-1-')
2268		window.addEventListener('DOMContentLoaded', () => {
2269			console.log('-2-')
2270			const galleryRows = [...document.querySelectorAll('.js-chrono-photo-row')];
2271			const showMoreButton = document.getElementById('loadmore');
2272			const contentWrapper = document.querySelector('.news-page__detail__left');
2273			const pageWrapper = document.querySelector('.js-photo-gallery-wrapper');
2274			const relatedWrapper = document.querySelector('.section--photo-gallery.section--photo-gallery--albumPage');
2275
2276			window.addEventListener('resize', utility.debounce(function () {
2277				gallerySetSizes();
2278				if (relatedWrapper && contentWrapper && pageWrapper) {
2279					moveGalleryRelated();
2280				}
2281			}, 250));
2282			gallerySetSizes();
2283			if (relatedWrapper && contentWrapper && pageWrapper) {
2284				moveGalleryRelated();
2285			}
2286
2287			if (showMoreButton) {
2288				showMoreButton.addEventListener('click', galleryShowMore);
2289			}
2290
2291			function gallerySetSizes () {
2292				galleryRows.forEach(function (galleryRow) {
2293					if (galleryRow.closest('.photo-gallery__row').dataset.visible === 'false') {
2294						return;
2295					}
2296					let galleryRowRatios = [];
2297					let galleryRowMaxHeight = null;
2298					let galleryRowWidth = 0;
2299					let galleryImages = [...galleryRow.querySelectorAll('.js-chrono-photo-image')];
2300
2301					if (galleryRow.closest('.photo-gallery__row')) {
2302						galleryRowWidth = galleryRow.closest('.photo-gallery__row').clientWidth - (10 * (galleryImages.length - 1));
2303					}
2304
2305					let rowIndex = Number(galleryRow.closest('.photo-gallery__row').dataset.row);
2306					if (rowIndex == galleryRows.length) {
2307						let rowLimit = Number(galleryRow.dataset.limit);
2308						if (galleryImages.length < rowLimit) {
2309							for (let i = 0; i < rowLimit - galleryImages.length; i++) {
2310								let placeholder = document.createElement('div');
2311								let placeholderInner = document.createElement('div');
2312								let placeholderImage = document.createElement('div');
2313
2314								placeholder.className = "photo-gallery__item";
2315								placeholderInner.className = "photo-gallery__item-link";
2316								placeholderImage.classList.add("photo-item--placeholder", "js-chrono-photo-image");
2317
2318								placeholderInner.appendChild(placeholderImage);
2319								placeholder.appendChild(placeholderInner);
2320								galleryRow.appendChild(placeholder);
2321							}
2322						}
2323					}
2324
2325					galleryImages = [...galleryRow.querySelectorAll('.js-chrono-photo-image')];
2326
2327					let imageRatio;
2328					galleryImages.forEach(function (galleryImage) {
2329						if (!galleryImage.classList.contains('photo-item--placeholder')) {
2330							imageRatio = parseInt(galleryImage.getAttribute('width')) / parseInt(galleryImage.getAttribute('height'));
2331						}
2332
2333						galleryRowRatios.push(imageRatio);
2334						if (galleryRowMaxHeight == null || parseInt(galleryImage.getAttribute('height')) < galleryRowMaxHeight) {
2335							galleryRowMaxHeight = parseInt(galleryImage.getAttribute('height'));
2336						}
2337					});
2338
2339					let targetHeight = galleryRowMaxHeight;
2340					let testWidth = checkRowWidth(galleryRowRatios, targetHeight);
2341					if (testWidth >= galleryRowWidth) {
2342						while (checkRowWidth(galleryRowRatios, targetHeight) >= galleryRowWidth) {
2343							targetHeight--;
2344						}
2345					} else {
2346						while (checkRowWidth(galleryRowRatios, targetHeight) < galleryRowWidth) {
2347							targetHeight++;
2348						}
2349					}
2350
2351					let itemWidth = 0;
2352					galleryImages.forEach(function (galleryImage) {
2353						if (!galleryImage.classList.contains('photo-item--placeholder')) {
2354							let imageRatio = parseInt(galleryImage.getAttribute('width')) / parseInt(galleryImage.getAttribute('height'));
2355							galleryRowRatios.push(imageRatio);
2356							itemWidth = imageRatio * targetHeight;
2357						}
2358						galleryImage.style.setProperty('--item-width', `${itemWidth}px`);
2359					});
2360
2361					let rowHeight = targetHeight + 10;
2362					galleryRow.closest('.photo-gallery__row').style.setProperty('--row-height', `${rowHeight}px`);
2363				});
2364			}
2365
2366			function checkRowWidth (ratios, height) {
2367				let width = 0;
2368
2369				ratios.forEach(function (ratio) {
2370					width += height * ratio;
2371				});
2372
2373				return Math.round(width);
2374			}
2375
2376			function galleryShowMore () {
2377				let rowCount = 0;
2378				galleryRows.forEach(galleryRow => {
2379					if (galleryRow.closest('.photo-gallery__row').dataset.visible === 'true') {
2380						return;
2381					}
2382					if (++rowCount <= 14) {
2383						galleryRow.closest('.photo-gallery__row').dataset.visible = "true";
2384					}
2385				});
2386
2387				if (rowCount <= 14) {
2388					showMoreButton.removeEventListener('click', galleryShowMore);
2389					showMoreButton.remove();
2390				}
2391
2392				gallerySetSizes();
2393			}
2394
2395			function moveGalleryRelated () {
2396				if (window.innerWidth > 800) {
2397					pageWrapper.appendChild(relatedWrapper);
2398				} else {
2399					contentWrapper.appendChild(relatedWrapper);
2400				}
2401			}
2402		});
2403	})();
2404
2405	/* chronology main nav toggle */
2406	(() => {
2407		window.addEventListener('DOMContentLoaded', () => {
2408			const chronologyNavToggler = document.querySelector('.js-chronology-nav-toggler');
2409			const chronologyNav = document.querySelector('.chronology-news__links');
2410
2411			if (chronologyNavToggler && chronologyNav) {
2412				chronologyNavToggler.addEventListener('click', event => {
2413					event.preventDefault();
2414
2415					let togglerText = chronologyNavToggler.querySelector('.text');
2416					let togglerIcon = chronologyNavToggler.querySelector('.icon');
2417
2418					if (chronologyNav.classList.contains('chronology-news__links--open')) {
2419						chronologyNav.classList.remove('chronology-news__links--open');
2420						togglerText.textContent = chronologyNavToggler.dataset.textOpen;
2421						togglerIcon.classList.remove('icon--chevron-up');
2422						togglerIcon.classList.add('icon--chevron-down');
2423					} else {
2424						chronologyNav.classList.add('chronology-news__links--open');
2425						togglerText.textContent = chronologyNavToggler.dataset.textClose;
2426						togglerIcon.classList.add('icon--chevron-up');
2427						togglerIcon.classList.remove('icon--chevron-down');
2428					}
2429
2430					return false;
2431				})
2432			}
2433		});
2434	})();
2435
2436	/* info blocks */
2437	(() => {
2438		let infoBlocksOldWidth;
2439		let infoBlocksNewWidth;
2440		let infoBlocks;
2441		let infoBlocksItems = Object.create(null);
2442
2443		window.addEventListener('DOMContentLoaded', () => {
2444			infoBlocks = document.querySelector('.js-info-blocks');
2445
2446			if (infoBlocks && typeof infoBlocksConfig !== 'undefined') {
2447				infoBlocksOldWidth = window.innerWidth;
2448
2449				getInfoBlocksItems();
2450
2451				window.addEventListener('resize', utility.debounce(function () {
2452					checkRenderInfoBlocks(false);
2453				}, 250));
2454
2455				checkRenderInfoBlocks(true);
2456			}
2457		});
2458
2459		function checkRenderInfoBlocks (force) {
2460			infoBlocksNewWidth = window.innerWidth;
2461
2462			let infoBlocksOldLayout = null;
2463			let infoBlocksNewLayout = null;
2464
2465			for (let layout in infoBlocksConfig) {
2466				if (infoBlocksOldWidth >= infoBlocksConfig[layout].dimensions.min && infoBlocksOldWidth <= infoBlocksConfig[layout].dimensions.max) {
2467					infoBlocksOldLayout = layout;
2468				}
2469
2470				if (infoBlocksNewWidth >= infoBlocksConfig[layout].dimensions.min && infoBlocksNewWidth <= infoBlocksConfig[layout].dimensions.max) {
2471					infoBlocksNewLayout = layout;
2472				}
2473			}
2474
2475			if (infoBlocksOldLayout !== infoBlocksNewLayout || force) {
2476				renderInfoBlocks(infoBlocksNewLayout);
2477			}
2478
2479			infoBlocksOldWidth = infoBlocksNewWidth;
2480		}
2481
2482		function renderInfoBlocks (layout) {
2483			infoBlocks.innerHTML = "";
2484
2485			let columns = ['left', 'center', 'right'];
2486			for (let columnType of columns) {
2487				if (!infoBlocksConfig[layout].items.hasOwnProperty(columnType)) {
2488					continue;
2489				}
2490
2491				let column = document.createElement('div');
2492				column.classList.add('info-blocks__column', 'info-blocks__column--' + columnType);
2493
2494				for (let itemType of infoBlocksConfig[layout].items[columnType]) {
2495					let item = infoBlocksItems[itemType].cloneNode(true);
2496					column.appendChild(item);
2497				}
2498
2499				infoBlocks.appendChild(column);
2500			}
2501		}
2502
2503		function getInfoBlocksItems () {
2504			let items = [...document.querySelectorAll('.js-info-block')];
2505			items.map(item => {
2506				infoBlocksItems[item.dataset.type] = item;
2507			});
2508		}
2509	})();
2510
2511	/* home page */
2512	(() => {
2513		const tabletWidth = 600;
2514		const desktopWidth = 1000;
2515
2516		let homepageOldWidth;
2517		let homepageNewWidth;
2518		let homepageOldLayout = 'mobile';
2519		let homepageNewLayout;
2520
2521		let homepage = document.querySelector('HTML.page--main');
2522
2523		if (homepage) {
2524			window.addEventListener('DOMContentLoaded', () => {
2525				homepageOldWidth = window.innerWidth;
2526
2527				window.addEventListener('resize', utility.debounce(function () {
2528					checkRenderHomepage();
2529				}, 250));
2530
2531				checkRenderHomepage();
2532			});
2533		}
2534
2535		function moveGalleryRelated () {
2536			if (window.innerWidth > 800) {
2537				pageWrapper.appendChild(relatedWrapper);
2538			} else {
2539				contentWrapper.appendChild(relatedWrapper);
2540			}
2541		}
2542
2543		function checkRenderHomepage () {
2544			homepageNewWidth = window.innerWidth;
2545
2546			homepageNewLayout = 'mobile';
2547			if (homepageNewWidth > tabletWidth) {
2548				homepageNewLayout = 'tablet';
2549			}
2550			if (homepageNewWidth > desktopWidth) {
2551				homepageNewLayout = 'desktop';
2552			}
2553
2554			if (homepageOldLayout !== homepageNewLayout) {
2555				renderHomepage(homepageNewLayout);
2556			}
2557
2558			homepageOldLayout = homepageNewLayout;
2559			homepageOldWidth = homepageNewWidth;
2560		}
2561
2562		function renderHomepage (layout) {
2563			console.log('hp render')
2564			let homeHeroWrapper = document.querySelector('.js-home-hero-wrapper');
2565			let homeNewsListWrapper = document.querySelector('.js-home-news-list-wrapper');
2566			let homePhotoWrapper = document.querySelector('.js-home-photo-wrapper');
2567			let homeVideoListWrapper = document.querySelector('.js-home-video-list-wrapper');
2568			let homeBannersWrapper = document.querySelector('.js-home-banners-wrapper');
2569			let homeMobileWrapper = document.querySelector('.js-home-mobile-wrapper');
2570
2571			let homeItemMainNew = document.querySelector('.js-home-item-main-new');
2572			let homeItemNewsList = document.querySelector('.js-home-item-news-list');
2573			let homeItemPhoto = document.querySelector('.js-home-item-photo');
2574			let homeItemShop = document.querySelector('.js-home-item-shop');
2575
2576			switch (layout) {
2577				case "mobile":
2578					homeHeroWrapper.appendChild(homeItemMainNew);
2579					homeMobileWrapper.appendChild(homeItemNewsList);
2580					homeMobileWrapper.appendChild(homeItemPhoto);
2581					break;
2582				case "tablet":
2583					homeHeroWrapper.appendChild(homeItemMainNew);
2584					homeNewsListWrapper.appendChild(homeItemNewsList);
2585					homePhotoWrapper.appendChild(homeItemPhoto);
2586					homeBannersWrapper.appendChild(homeItemShop);
2587					break;
2588				case "desktop":
2589					homeHeroWrapper.appendChild(homeItemMainNew);
2590					homeNewsListWrapper.appendChild(homeItemNewsList);
2591					homeVideoListWrapper.appendChild(homeItemShop);
2592					homeVideoListWrapper.insertBefore(homeItemShop, homeVideoListWrapper.firstChild);
2593					homePhotoWrapper.appendChild(homeItemPhoto);
2594					break;
2595			}
2596
2597			// init custom event
2598			const homepageRenderEvent = new CustomEvent('homepage.render', { detail: layout });
2599			let mainColumns = document.querySelector(".js-home-columns");
2600			if (mainColumns) {
2601				mainColumns.dispatchEvent(homepageRenderEvent);
2602			}
2603		}
2604	})();
2605
2606	/* body color */
2607	(() => {
2608		let homepageOldWidth;
2609		let homepageNewWidth;
2610		let mainColumns;
2611
2612		window.addEventListener('DOMContentLoaded', () => {
2613			mainColumns = document.querySelector(".js-home-columns");
2614
2615			if (mainColumns) {
2616				homepageOldWidth = window.innerWidth;
2617
2618				window.addEventListener('resize', utility.debounce(function () {
2619					checkBodyColor();
2620				}, 100));
2621
2622				window.addEventListener('load', checkBodyColor);
2623				mainColumns.addEventListener('homepage.render', checkBodyColor);
2624			}
2625		});
2626
2627		function checkBodyColor () {
2628			homepageNewWidth = window.innerWidth;
2629
2630			if ((homepageOldWidth <= 1000 && homepageNewWidth > 1000) || (homepageOldWidth == homepageNewWidth && homepageNewWidth > 1000)) {
2631				initBodyColor();
2632			} else if (homepageNewWidth <= 1000 && homepageOldWidth > 1000) {
2633				clearBodyColor();
2634			} else {
2635				if (homepageNewWidth > 1000) {
2636					clearBodyColor();
2637					initBodyColor();
2638				}
2639			}
2640
2641			homepageOldWidth = homepageNewWidth;
2642		}
2643
2644		function initBodyColor () {
2645			let triggerOffset = Math.max(0.4 * window.innerHeight, mainColumns.getBoundingClientRect().top + window.pageYOffset - 0.4 * window.innerHeight);
2646			ScrollTrigger.create({
2647				id: "homepageBodyColor",
2648				toggleClass: {
2649					targets: "BODY",
2650					className: "light-bg"
2651				},
2652				start: triggerOffset,
2653				end: 20000
2654			});
2655		}
2656
2657		function clearBodyColor () {
2658			let triggers = ScrollTrigger.getAll();
2659			triggers.forEach(trigger => {
2660				if (trigger.id == "clearBodyColor") {
2661					trigger.kill();
2662				}
2663			});
2664		}
2665	})();
2666
2667	/* column scroll */
2668	(() => {
2669		let homepageOldWidth;
2670		let homepageNewWidth;
2671
2672		let homepage = document.querySelector('HTML.page--main');
2673
2674		if (homepage) {
2675
2676			let mainColumns = document.querySelector(".js-home-columns");
2677			let targetColumn = mainColumns.querySelector(".js-home-column-1");
2678			let photoColumn = mainColumns.querySelector(".js-home-column-2");
2679			let bannerColumn = mainColumns.querySelector(".js-home-column-3");
2680			let imagesColumn = mainColumns.querySelector(".js-home-column-l");
2681			let videoColumn = mainColumns.querySelector(".js-home-column-r");
2682			let photoColumnOffset;
2683			let bannerColumnOffset;
2684			let imagesColumnOffset;
2685			let videoColumnOffset;
2686
2687			window.addEventListener('DOMContentLoaded', () => {
2688				homepageOldWidth = window.innerWidth;
2689
2690				window.addEventListener('resize', utility.debounce(function () {
2691					checkScroll();
2692				}, 100));
2693
2694				window.addEventListener('load', checkScroll);
2695
2696				if (mainColumns) {
2697					mainColumns.addEventListener('homepage.render', checkScroll);
2698				}
2699			});
2700
2701			function checkScroll () {
2702				homepageNewWidth = window.innerWidth;
2703
2704				if ((homepageOldWidth <= 1000 && homepageNewWidth > 1000) || (homepageOldWidth == homepageNewWidth && homepageNewWidth > 1000)) {
2705					initScroll();
2706				} else if (homepageNewWidth <= 1000 && homepageOldWidth > 1000) {
2707					clearScroll();
2708				} else {
2709					if (homepageNewWidth > 1000) {
2710						clearScroll();
2711						initScroll();
2712					}
2713				}
2714
2715				if (homepageNewWidth > 600 && homepageNewWidth <= 1000) {
2716					setColumnOffset();
2717				} else {
2718					resetColumnOffset();
2719				}
2720
2721				homepageOldWidth = homepageNewWidth;
2722			}
2723
2724			function initScroll () {
2725				if (targetColumn) {
2726					if (photoColumn) {
2727						photoColumnOffset = targetColumn.getBoundingClientRect().bottom - 50 - photoColumn.getBoundingClientRect().bottom;
2728					}
2729					if (bannerColumn) {
2730						bannerColumnOffset = targetColumn.getBoundingClientRect().bottom - 50 - bannerColumn.getBoundingClientRect().bottom;
2731					}
2732					if (imagesColumn) {
2733						imagesColumnOffset = targetColumn.getBoundingClientRect().bottom - 50 - imagesColumn.getBoundingClientRect().bottom;
2734					}
2735					if (videoColumn) {
2736						videoColumnOffset = targetColumn.getBoundingClientRect().bottom - 50 - videoColumn.getBoundingClientRect().bottom;
2737					}
2738
2739					let targetColumnHeight = targetColumn.getBoundingClientRect().height;
2740					mainColumns.style.height = targetColumnHeight + 134 + "px";
2741				}
2742
2743				// photo column scroll
2744				if (photoColumn && photoColumnOffset) {
2745					gsap.to(photoColumn, {
2746						y: () => photoColumnOffset,
2747						ease: "none",
2748						scrollTrigger: {
2749							id: "homepagePhotoColumn",
2750							trigger: mainColumns,
2751							start: "top center",
2752							end: "bottom center",
2753							scrub: 0,
2754							invalidateOnRefresh: true
2755						}
2756					});
2757				}
2758
2759				// banner column scroll
2760				if (bannerColumn && bannerColumnOffset) {
2761					gsap.to(bannerColumn, {
2762						y: () => bannerColumnOffset,
2763						ease: "none",
2764						scrollTrigger: {
2765							id: "homepageBannerColumn",
2766							trigger: mainColumns,
2767							start: "top center",
2768							end: "bottom center",
2769							scrub: 0,
2770							invalidateOnRefresh: true
2771						}
2772					});
2773				}
2774
2775				// images column scroll
2776				if (imagesColumn && imagesColumnOffset) {
2777					gsap.to(imagesColumn, {
2778						y: () => imagesColumnOffset,
2779						ease: "none",
2780						scrollTrigger: {
2781							id: "homepageImagesColumn",
2782							trigger: mainColumns,
2783							start: "top center",
2784							end: "bottom center",
2785							scrub: 0,
2786							invalidateOnRefresh: true
2787						}
2788					});
2789				}
2790
2791				// video column scroll
2792				if (videoColumn && videoColumnOffset) {
2793					gsap.to(videoColumn, {
2794						y: () => videoColumnOffset,
2795						ease: "none",
2796						scrollTrigger: {
2797							id: "homepageVideoColumn",
2798							trigger: mainColumns,
2799							start: "top center",
2800							end: "bottom center",
2801							scrub: 0,
2802							invalidateOnRefresh: true
2803						}
2804					});
2805				}
2806			}
2807
2808			function clearScroll () {
2809				mainColumns.style.height = "";
2810
2811				let triggers = ScrollTrigger.getAll();
2812				let targetTriggers = ["homepageVideoColumn", "homepageImagesColumn", "homepageBannerColumn", "homepagePhotoColumn"];
2813				triggers.forEach(trigger => {
2814					if (targetTriggers.includes(trigger.id)) {
2815						trigger.kill();
2816					}
2817				});
2818			}
2819
2820			function setColumnOffset () {
2821				let exampleElement = document.querySelector('.js-home-item-main-new');
2822				let targetElement = document.querySelector('.js-home-column-3');
2823				targetElement.style.marginTop = -(exampleElement.getBoundingClientRect().height + 32) + "px";
2824			}
2825
2826			function resetColumnOffset () {
2827				let targetElement = document.querySelector('.js-home-column-3');
2828				targetElement.style.marginTop = "";
2829			}
2830		}
2831	})();
2832
2833	/* reverend hover */
2834	(() => {
2835		let container;
2836		let containerSize;
2837		let mousePos;
2838		let shadows;
2839
2840		window.addEventListener('DOMContentLoaded', () => {
2841			container = document.querySelector('.js-reverend-hover');
2842
2843			if (container) {
2844				shadows = [...document.querySelectorAll('.js-reverend-shadow')];
2845				container.addEventListener('mouseleave', mouseLeaveHandler);
2846				container.addEventListener('mousemove', mouseMoveHandler);
2847
2848				window.addEventListener('resize', calcContainerSize);
2849				window.addEventListener('load', () => {
2850					calcContainerSize();
2851					render();
2852				});
2853
2854				calcContainerSize();
2855
2856				mousePos = {
2857					x: containerSize.width / 2,
2858					y: containerSize.height / 2
2859				};
2860			}
2861		});
2862
2863		function calcContainerSize () {
2864			containerSize = {
2865				width: container.getBoundingClientRect().width,
2866				height: container.getBoundingClientRect().height
2867			};
2868		}
2869
2870		function getMousePos (event) {
2871			let posX = 0;
2872			let posY = 0;
2873			if (!event) {
2874				event = window.event;
2875			}
2876			if (event.pageX || event.pageY) {
2877				posX = event.pageX - container.offsetLeft;
2878				posY = event.pageY - container.offsetTop;
2879			}
2880			return { x: posX, y: posY };
2881		}
2882
2883		function mouseLeaveHandler () {
2884			mousePos = {
2885				x: containerSize.width / 2,
2886				y: containerSize.height / 2
2887			};
2888		}
2889
2890		function mouseMoveHandler (event) {
2891			mousePos = getMousePos(event);
2892		}
2893
2894		function render () {
2895			let mouseMoveValues = {
2896				translationX: 0,
2897				translationY: 0
2898			};
2899
2900			const raf = () => {
2901				mouseMoveValues.translationX = utility.lerp(
2902					mouseMoveValues.translationX,
2903					utility.lineEq(-10, 10, containerSize.width, 0, mousePos.x),
2904					0.025
2905				);
2906				mouseMoveValues.translationX = Math.round(mouseMoveValues.translationX * 1000) / 1000;
2907				mouseMoveValues.translationY = utility.lerp(
2908					mouseMoveValues.translationY,
2909					utility.lineEq(-5, 5, containerSize.height, 0, mousePos.y),
2910					0.025
2911				);
2912				mouseMoveValues.translationY = Math.round(mouseMoveValues.translationY * 1000) / 1000;
2913
2914				shadows.forEach(shadow => {
2915					gsap.set(shadow, {
2916						x: mouseMoveValues.translationX * parseInt(shadow.dataset.depth),
2917						y: mouseMoveValues.translationY * parseInt(shadow.dataset.depth)
2918					});
2919				});
2920
2921				requestAnimationFrame(raf);
2922			}
2923
2924			requestAnimationFrame(raf);
2925		}
2926
2927		utility
2928	})();
2929
2930	/* news page galley */
2931	(() => {
2932		let newsGallery = null;
2933		let newsGalleryRows = null;
2934		let newsGalleryRowImages = null;
2935
2936		window.addEventListener('DOMContentLoaded', () => {
2937			newsGallery = document.querySelector('.js-news-gallery');
2938
2939			if (newsGallery) {
2940				correctImagesHeight();
2941
2942				window.addEventListener('resize', correctImagesHeight);
2943			}
2944		});
2945
2946		function correctImagesHeight () {
2947			newsGalleryRows = [...document.querySelectorAll('.js-news-gallery-row')];
2948			let rowNumber = 1;
2949
2950			newsGalleryRows.forEach(newsGalleryRow => {
2951				newsGalleryRowImages = [...newsGalleryRow.querySelectorAll('.js-photo-gallery-item')];
2952
2953				if (window.innerWidth <= 1000) {
2954					newsGalleryRowImages.forEach((newsGalleryRowImage, index) => {
2955						if (newsGalleryRowImage.closest('.news-page__photo__box')) {
2956							newsGalleryRowImages.splice(index, 1);
2957						}
2958					});
2959				}
2960
2961				let newsGalleryRowWidth = 0;
2962				let newsGalleryRowRatios = [];
2963				let newsGalleryRowMaxHeight = null;
2964
2965				newsGalleryRowWidth = newsGalleryRow.clientWidth - (newsGalleryRowImages.length - 1) * 10;
2966
2967				newsGalleryRowImages.forEach(function (newsGalleryRowImage) {
2968					let image = newsGalleryRowImage.querySelector('IMG');
2969					let imageRatio = parseInt(image.getAttribute('width')) / parseInt(image.getAttribute('height'));
2970					newsGalleryRowRatios.push(imageRatio);
2971					if (newsGalleryRowMaxHeight == null || parseInt(image.getAttribute('height')) < newsGalleryRowMaxHeight) {
2972						newsGalleryRowMaxHeight = parseInt(image.getAttribute('height'));
2973					}
2974				});
2975
2976				let targetHeight = newsGalleryRowMaxHeight;
2977
2978				if (rowNumber == 2) {
2979					while (checkRowWidth(newsGalleryRowRatios, targetHeight) >= newsGalleryRowWidth) {
2980						targetHeight = targetHeight - 0.5;
2981					}
2982
2983					newsGalleryRowImages.forEach(function (newsGalleryRowImage) {
2984						let image = newsGalleryRowImage.querySelector('IMG');
2985						let imageRatio = parseInt(image.getAttribute('width')) / parseInt(image.getAttribute('height'));
2986						let itemWidth = imageRatio * targetHeight;
2987						image.style.setProperty('--item-width', `${itemWidth}px`);
2988					});
2989				} else {
2990					let rowFactors = null;
2991					if (rowNumber == 1) {
2992						switch (newsGalleryRowImages.length) {
2993							case 1:
2994								rowFactors = [1];
2995							case 2:
2996								rowFactors = [0.85, 1];
2997							case 3:
2998								rowFactors = [0.85, 1, 0.7];
2999								break;
3000						}
3001					} else if (rowNumber == 3) {
3002						switch (newsGalleryRowImages.length) {
3003							case 1:
3004								rowFactors = [1];
3005							case 2:
3006								rowFactors = [1, 0.85];
3007							case 3:
3008								rowFactors = [0.7, 1, 0.85];
3009								break;
3010						}
3011					}
3012
3013					while (checkRowWidthVariable(newsGalleryRowRatios, rowFactors, targetHeight) >= newsGalleryRowWidth) {
3014						targetHeight = targetHeight - 0.5;
3015					}
3016
3017					newsGalleryRowImages.forEach(function (newsGalleryRowImage, index) {
3018						let image = newsGalleryRowImage.querySelector('IMG');
3019						let imageRatio = parseInt(image.getAttribute('width')) / parseInt(image.getAttribute('height'));
3020						let itemWidth = imageRatio * targetHeight * rowFactors[index];
3021						image.style.setProperty('--item-width', `${itemWidth}px`);
3022					});
3023				}
3024
3025				rowNumber++;
3026			});
3027		}
3028
3029		function checkRowWidth (ratios, height) {
3030			let width = 0;
3031
3032			ratios.forEach(function (ratio) {
3033				width += height * ratio;
3034			});
3035
3036			return Math.round(width);
3037		}
3038
3039		function checkRowWidthVariable (ratios, factors, height) {
3040			let width = 0;
3041
3042			ratios.forEach(function (ratio, index) {
3043				width += height * ratio * factors[index];
3044			});
3045
3046			return Math.round(width);
3047		}
3048	})();
3049
3050	(() => {
3051		let interval = setStepAnimation()
3052
3053		function setStepAnimation (step = 3) {
3054			let count = 0
3055			let calendarBtn = document.querySelector('.js-worship-calendar-button');
3056
3057			if (calendarBtn) {
3058				return setInterval(function () {
3059					if (count === step) {
3060						calendarBtn.classList.add('animation')
3061						clearInterval(interval)
3062
3063						setTimeout(function () {
3064							calendarBtn.classList.remove('animation')
3065							interval = setStepAnimation()
3066						}, step * 1000)
3067					}
3068					count++
3069				}, 1000)
3070			}
3071		}
3072	})();
3073});

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.