PageSourceSearch

https://xn--80aal0a.xn--80asehdb/templates/Cursor/js/cursor-navigation.js?v=7

js xn--80aal0a.xn--80asehdb collected 2026-10-02 16:41:31 UTC 22,000 bytes, 515 lines download raw bytes

1(function () {
2	'use strict';
3
4	var nav = document.getElementById('cur-nav');
5	var script = document.currentScript;
6	if (!nav || !script) return;
7	var imageBase = script.getAttribute('data-model-images');
8	var menu = nav.querySelector('.cur-menu');
9	var shopItem = nav.querySelector('.cur-menu__item--shop');
10	var catalogItem = nav.querySelector('.cur-menu__item--catalog');
11	var header = nav.closest('.cur-header');
12	var burger = document.getElementById('cur-burger');
13	if (!imageBase || !menu || !shopItem || !catalogItem || !header || !burger) return;
14
15	var mobile = window.matchMedia('(max-width: 1099px)');
16	var body = document.body;
17	var desktopPanels = [];
18	var desktopButtons = [];
19	var activeDesktop = -1;
20	var mobileSections = [];
21	var isolated = [];
22	var modelImages = [
23		['vesta', 'Vesta', 'ladavesta-2.webp'],
24		['xray', 'XRAY', 'ladaxray-2.webp'],
25		['granta', 'Granta', 'ladagranta-2.webp'],
26		['largus', 'Largus', 'ladalargus-2.webp'],
27		['legend|4x4', 'Niva Legend / 4x4', 'lada4x4-2.webp'],
28		['travel|chevrolet|Шеви', 'Niva Travel', 'ladaniva-2.webp'],
29		['kalina', 'Kalina', 'ladakalina.webp'],
30		['priora', 'Priora', 'ladapriora.webp'],
31		['iskra', 'Iskra', 'ladaiskra.webp'],
32		['azimut', 'Azimut', 'ladaazimut.webp'],
33		['xcite|skm', 'XCITE, SKM и др.', 'xcite2.webp']
34	];
35	var icons = {
36		grid: 'M3 3h7v7H3z M14 3h7v7h-7z M3 14h7v7H3z M14 14h7v7h-7z',
37		news: 'M5 3h14v18H5z M8 7h8 M8 11h8 M8 15h3 M14 15h2 M8 18h8',
38		tag: 'M3 3h8l10 10-8 8L3 11z M7 7h.01',
39		book: 'M12 5C8 2 4 3 2 4v16c4-2 7-1 10 1 3-2 6-3 10-1V4c-4-2-7-1-10 1z M12 5v16',
40		car: 'M4 9l2-6h12l2 6 M3 9h18v10H3z M6 19v2 M18 19v2 M6 13h2 M16 13h2',
41		wrench: 'M14 3l-4 4 3 3 4-4c2 5-2 9-6 8L5 21l-3-3 7-7C8 7 10 3 14 3z',
42		chat: 'M3 3h18v14H8l-5 4z M7 7h10 M7 11h7',
43		cart: 'M2 3h3l3 12h11l3-9H6 M9 20h.01 M18 20h.01',
44		heart: 'M12 21L3 12C-2 5 6 0 12 6c6-6 14-1 9 6z',
45		arrow: 'M9 5l7 7-7 7'
46	};
47	var sectionIcons = ['cart', 'grid', 'news', 'tag', 'book', 'car', 'wrench', 'book', 'car', 'chat'];
48
49	function element(tag, className, text) {
50		var node = document.createElement(tag);
51		if (className) node.className = className;
52		if (text) node.textContent = text;
53		return node;
54	}
55
56	function icon(name) {
57		var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
58		svg.setAttribute('viewBox', '0 0 24 24');
59		svg.setAttribute('width', '20');
60		svg.setAttribute('height', '20');
61		svg.setAttribute('fill', 'none');
62		svg.setAttribute('stroke', 'currentColor');
63		svg.setAttribute('stroke-width', '1.6');
64		svg.setAttribute('stroke-linecap', 'round');
65		svg.setAttribute('stroke-linejoin', 'round');
66		svg.setAttribute('aria-hidden', 'true');
67		svg.setAttribute('focusable', 'false');
68		var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
69		path.setAttribute('d', icons[name] || icons.grid);
70		svg.appendChild(path);
71		return svg;
72	}
73
74	function copyLink(source, className, label) {
75		var link = source.cloneNode(false);
76		['id', 'role', 'aria-expanded', 'aria-controls', 'tabindex'].forEach(function (name) {
77			link.removeAttribute(name);
78		});
79		link.className = className || '';
80		link.textContent = label || source.textContent.trim();
81		return link;
82	}
83
84	function button(label, className) {
85		var node = element('button', className, label);
86		node.type = 'button';
87		return node;
88	}
89
90	function modelFor(link) {
91		return modelImages.find(function (model) {
92			return new RegExp(model[0], 'i').test(link.textContent);
93		});
94	}
95
96	function setupTabs(buttons, activate, vertical) {
97		buttons.forEach(function (tab, index) {
98			tab.setAttribute('role', 'tab');
99			tab.addEventListener('click', function () { activate(index); });
100			tab.addEventListener('keydown', function (event) {
101				var previous = vertical ? 'ArrowUp' : 'ArrowLeft';
102				var next = vertical ? 'ArrowDown' : 'ArrowRight';
103				var target = index;
104				if (event.key === previous) target = (index + buttons.length - 1) % buttons.length;
105				else if (event.key === next) target = (index + 1) % buttons.length;
106				else if (event.key === 'Home') target = 0;
107				else if (event.key === 'End') target = buttons.length - 1;
108				else return;
109				event.preventDefault();
110				activate(target);
111				buttons[target].focus();
112			});
113		});
114	}
115
116	function selectTabs(buttons, selected) {
117		buttons.forEach(function (tab, index) {
118			tab.setAttribute('aria-selected', index === selected ? 'true' : 'false');
119			tab.tabIndex = index === selected ? 0 : -1;
120		});
121	}
122
123	var shopRows = Array.from(shopItem.querySelectorAll('.cur-menu__row'));
124	var services = Array.from(shopItem.querySelectorAll('.cur-menu__sub > li:not(.cur-menu__row) a'));
125	var catalogLinks = Array.from(catalogItem.querySelectorAll('.cur-menu__sub a'));
126	if (shopRows.length < 2) return;
127	var shopHome = shopRows[0].querySelector('a');
128	var popularHome = shopRows[0].querySelector('.cur-menu__pop');
129	if (!shopHome || !popularHome) return;
130
131	function shop(mode, onActivate) {
132		var prefix = 'cur-' + mode + '-shop';
133		var panel = element('section', 'cur-shop');
134		var aside = element('div', 'cur-shop__aside');
135		aside.appendChild(element('h2', 'cur-shop__name', 'Магазин LADA'));
136		aside.appendChild(element('p', 'cur-shop__hint', 'Начните с вашей модели'));
137		var switches = element('div', 'cur-shop__switches');
138		switches.setAttribute('role', 'tablist');
139		switches.setAttribute('aria-label', 'Раздел магазина');
140		switches.setAttribute('aria-orientation', mode === 'desktop' ? 'vertical' : 'horizontal');
141		var modes = ['Все товары', 'Популярное', 'Каталог деталей'];
142		var buttons = modes.map(function (label, index) {
143			var tab = button('', 'cur-shop__switch');
144			tab.id = prefix + '-tab-' + index;
145			tab.append(icon(['grid', 'heart', 'grid'][index]), element('span', '', label), icon('arrow'));
146			switches.appendChild(tab);
147			return tab;
148		});
149		aside.appendChild(switches);
150		var links = element('div', 'cur-shop__services');
151		var serviceLinks = mode === 'desktop' ? ['/oplata-dostavka.html', '/vozvrat.html', '/about-shop.html'].map(function (path) {
152			return services.find(function (source) { return source.pathname === path; });
153		}) : services;
154		serviceLinks.filter(Boolean).forEach(function (source) {
155			links.appendChild(copyLink(source, 'cur-shop__service'));
156		});
157		if (mode === 'desktop') {
158			var reviewSource = services.find(function (source) { return source.textContent.trim() === 'Отзывы клиентов'; });
159			var reviewLink = reviewSource ? copyLink(reviewSource, 'cur-shop__service') : element('a', 'cur-shop__service', 'Отзывы клиентов');
160			if (!reviewSource) {
161				reviewLink.href = 'https://webmaster.yandex.ru/siteinfo/?site=xn--80aal0a.xn--80asehdb&page=1&ranking=by_time';
162				reviewLink.rel = 'nofollow';
163			}
164			links.appendChild(reviewLink);
165		}
166		aside.appendChild(links);
167		var main = element('div', 'cur-shop__main');
168		var panels = modes.map(function (label, index) {
169			var content = element('div', 'cur-shop__models');
170			content.id = prefix + '-models-' + index;
171			content.setAttribute('role', 'tabpanel');
172			content.setAttribute('aria-labelledby', buttons[index].id);
173			content.tabIndex = 0;
174			buttons[index].setAttribute('aria-controls', content.id);
175			var heading = element('div', 'cur-shop__heading');
176			heading.appendChild(element('h2', '', ['Выберите автомобиль', 'Популярное по моделям', 'Каталог деталей'][index]));
177			var items = index === 2 ? catalogLinks : shopRows.slice(1).map(function (row) {
178				return row.querySelector(index === 1 ? '.cur-menu__pop' : 'a');
179			});
180			heading.appendChild(element('span', 'cur-shop__count', String(items.length)));
181			content.appendChild(heading);
182			var grid = element('div', 'cur-shop__grid');
183			items.forEach(function (source, itemIndex) {
184				var modelSource = index === 1 ? shopRows[itemIndex + 1].querySelector('a') : source;
185				var model = modelFor(modelSource);
186				var label = model ? model[1] : modelSource.textContent.trim();
187				if (index === 2 && /xcite/i.test(label)) label = modelSource.textContent.trim();
188				var card = copyLink(source, 'cur-model', label);
189				var labelNode = element('span', 'cur-model__label', card.textContent);
190				card.textContent = '';
191				if (model) {
192					var image = element('img', 'cur-model__image');
193					image.src = imageBase + model[2];
194					image.alt = '';
195					image.width = 180;
196					image.height = 90;
197					image.loading = 'lazy';
198					image.decoding = 'async';
199					card.appendChild(image);
200				}
201				card.appendChild(labelNode);
202				grid.appendChild(card);
203			});
204			if (index !== 2) {
205				var all = copyLink(index === 1 ? popularHome : shopHome, 'cur-model cur-model--all',
206					index === 1 ? 'Все популярные товары' : 'Все товары');
207				all.prepend(icon('grid'));
208				if (index === 0) all.appendChild(element('span', 'cur-model__caption', 'Главная магазина →'));
209				grid.appendChild(all);
210			}
211			content.appendChild(grid);
212			main.appendChild(content);
213			return content;
214		});
215		function activate(index) {
216			selectTabs(buttons, index);
217			panels.forEach(function (content, position) { content.hidden = position !== index; });
218			if (mode === 'mobile') panel.scrollTop = 0;
219			if (onActivate) onActivate(index);
220		}
221		setupTabs(buttons, activate, mode === 'desktop');
222		activate(0);
223		if (mode === 'desktop') {
224			var footer = element('div', 'cur-shop__footer');
225			footer.appendChild(element('span', 'cur-shop__footer-hint', 'Не знаете артикул?'));
226			services.forEach(function (source) {
227				var href = source.getAttribute('href');
228				if (/13006/.test(href)) {
229					footer.appendChild(copyLink(source, 'cur-shop__footer-find', 'Как найти деталь →'));
230				} else if (/do-order/.test(href)) {
231					footer.appendChild(copyLink(source, 'cur-shop__footer-order', 'Как оформить заказ →'));
232				}
233			});
234			main.appendChild(footer);
235		}
236		if (mode === 'mobile') panel.append(main, aside);
237		else panel.append(aside, main);
238		return panel;
239	}
240
241	function editorial(item, prefix) {
242		var trigger = item.querySelector('.cur-menu__link');
243		var panel = element('section', 'cur-editorial');
244		var heading = element('div', 'cur-editorial__heading');
245		var title = element('h2', '', trigger.textContent.trim());
246		title.id = prefix + '-title';
247		panel.setAttribute('aria-labelledby', title.id);
248		heading.appendChild(title);
249		if (trigger.hasAttribute('href')) {
250			heading.appendChild(copyLink(trigger, 'cur-editorial__all', trigger.textContent.trim() === 'Новости' ? 'Все новости →' : 'Перейти в раздел →'));
251		}
252		panel.append(heading, element('p', 'cur-editorial__hint', 'Выберите модель или тему'));
253		var columns = element('div', 'cur-editorial__columns');
254		var models = element('div', 'cur-editorial__models');
255		var topics = element('div', 'cur-editorial__topics');
256		models.appendChild(element('h3', '', 'По модели'));
257		topics.appendChild(element('h3', '', 'Темы'));
258		var modelList = element('div', 'cur-editorial__links');
259		var topicList = element('div', 'cur-editorial__links');
260		Array.from(item.querySelectorAll('.cur-menu__sub a')).forEach(function (source) {
261			var model = modelFor(source);
262			var isModel = model || /^Lada /i.test(source.textContent);
263			var text = source.textContent.trim().replace(/^Lada /, '').replace(' (Шеви)', '').replace('Niva Legend (4x4)', 'Niva Legend / 4x4');
264			(isModel ? modelList : topicList).appendChild(copyLink(source, 'cur-editorial__link', text));
265		});
266		models.appendChild(modelList);
267		topics.appendChild(topicList);
268		if (modelList.children.length) columns.appendChild(models);
269		if (topicList.children.length) columns.appendChild(topics);
270		if (!topicList.children.length) columns.classList.add('cur-editorial__columns--models');
271		panel.appendChild(columns);
272		return panel;
273	}
274
275	function isSimple(item) {
276		return item !== shopItem && item !== catalogItem &&
277			item.querySelector('.cur-menu__link').getAttribute('href') !== '/auto-news/';
278	}
279
280	function mobileList(item) {
281		var list = item.querySelector('.cur-menu__sub').cloneNode(true);
282		list.removeAttribute('id');
283		list.className = 'cur-simple cur-simple--mobile';
284		return list;
285	}
286
287	function closeDesktop(restore) {
288		var previous = activeDesktop;
289		desktopPanels.forEach(function (panel, index) {
290			panel.hidden = true;
291			desktopButtons[index].setAttribute('aria-expanded', 'false');
292		});
293		activeDesktop = -1;
294		if (restore && previous >= 0) desktopButtons[previous].focus();
295	}
296
297	function positionPanels() {
298		var bar = header.querySelector('.cur-header__bar').getBoundingClientRect();
299		nav.style.setProperty('--cur-navigation-top', Math.max(0, bar.bottom) + 'px');
300		if (activeDesktop >= 0 && !mobile.matches) {
301			var panel = desktopPanels[activeDesktop];
302			if (!panel.classList.contains('cur-mega')) return;
303			var width = Math.min(activeDesktop === 0 ? 1180 : 820, window.innerWidth - 32);
304			var left = activeDesktop === 0 ? (window.innerWidth - width) / 2 : Math.min(
305				Math.max(16, desktopButtons[activeDesktop].getBoundingClientRect().left - 24),
306				window.innerWidth - width - 16
307			);
308			panel.style.left = left + 'px';
309		}
310	}
311
312	Array.from(menu.children).forEach(function (item, index) {
313		var trigger = item.querySelector('.cur-menu__link');
314		var simple = isSimple(item);
315		var panel = simple ? item.querySelector('.cur-menu__sub') :
316			(item === shopItem ? shop('desktop') : editorial(item, 'cur-desktop-' + index));
317		if (simple) panel.classList.add('cur-simple', 'cur-simple--desktop');
318		else panel.classList.add('cur-mega');
319		panel.id = 'cur-mega-' + index;
320		panel.hidden = true;
321		item.appendChild(panel);
322		trigger.setAttribute('aria-expanded', 'false');
323		trigger.setAttribute('aria-controls', panel.id);
324		if (!trigger.hasAttribute('href')) {
325			trigger.setAttribute('role', 'button');
326			trigger.tabIndex = 0;
327		}
328		desktopPanels.push(panel);
329		desktopButtons.push(trigger);
330		function open(focus, toggle) {
331			var wasOpen = activeDesktop === index;
332			closeDesktop(false);
333			if (wasOpen && toggle) return;
334			nav.dispatchEvent(new CustomEvent('cur:panel-open'));
335			activeDesktop = index;
336			panel.hidden = false;
337			trigger.setAttribute('aria-expanded', 'true');
338			positionPanels();
339			if (focus) panel.querySelector('a, button, [tabindex="0"]').focus();
340		}
341		trigger.addEventListener('click', function (event) {
342			if (mobile.matches || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return;
343			event.preventDefault();
344			open(false, true);
345		});
346		trigger.addEventListener('keydown', function (event) {
347			if (mobile.matches) return;
348			if (event.key === 'ArrowDown') {
349				event.preventDefault();
350				open(true);
351			} else if (event.key === ' ' || (event.key === 'Enter' && !trigger.hasAttribute('href'))) {
352				event.preventDefault();
353				open(false, true);
354			}
355		});
356	});
357
358	var mobileUI = element('div', 'cur-mobile');
359	var tablist = element('div', 'cur-mobile__tabs');
360	tablist.setAttribute('role', 'tablist');
361	tablist.setAttribute('aria-label', 'Навигация сайта и магазина');
362	var tabs = ['Сайт', 'Магазин'].map(function (label, index) {
363		var tab = button(label, 'cur-mobile__tab');
364		tab.id = 'cur-mobile-tab-' + index;
365		tab.setAttribute('aria-controls', 'cur-mobile-view-' + index);
366		tablist.appendChild(tab);
367		return tab;
368	});
369	var views = ['site', 'shop'].map(function (name, index) {
370		var view = element('div', 'cur-mobile__view cur-mobile__view--' + name);
371		view.id = 'cur-mobile-view-' + index;
372		view.setAttribute('role', 'tabpanel');
373		view.setAttribute('aria-labelledby', tabs[index].id);
374		return view;
375	});
376	var siteList = element('div', 'cur-mobile__sections');
377	var siteItems = Array.from(menu.children).slice(1);
378	var catalog = siteItems.shift();
379	siteItems.splice(6, 0, catalog);
380	siteItems.forEach(function (item) {
381		var index = Array.from(menu.children).indexOf(item);
382		var source = item.querySelector('.cur-menu__link');
383		var row = element('div', 'cur-mobile__section');
384		var trigger = button('', 'cur-mobile__section-toggle');
385		trigger.append(icon(sectionIcons[index]), element('span', '', source.textContent.trim()), icon('arrow'));
386		var panel = isSimple(item) || item === catalogItem ? mobileList(item) : editorial(item, 'cur-mobile-section-' + index);
387		panel.id = 'cur-mobile-section-' + index;
388		panel.hidden = true;
389		trigger.setAttribute('aria-expanded', 'false');
390		trigger.setAttribute('aria-controls', panel.id);
391		trigger.addEventListener('click', function () {
392			var open = panel.hidden;
393			mobileSections.forEach(function (section) {
394				section.panel.hidden = true;
395				section.trigger.setAttribute('aria-expanded', 'false');
396			});
397			panel.hidden = !open;
398			trigger.setAttribute('aria-expanded', String(open));
399		});
400		mobileSections.push({ panel: panel, trigger: trigger });
401		row.append(trigger, panel);
402		siteList.appendChild(row);
403	});
404	var shopCTA = button('', 'cur-mobile__shop-cta');
405	shopCTA.append(icon('cart'), element('strong', '', 'Перейти в магазин'), element('span', '', 'Запчасти и аксессуары по моделям'));
406	var siteFooter = element('div', 'cur-mobile__footer');
407	[['/about.html', 'О проекте'], ['/index.php?do=feedback', 'Контакты']].forEac
407h(function (data) {
408		var link = element('a', '', data[1]);
409		link.href = data[0];
410		siteFooter.appendChild(link);
411	});
412	views[0].append(siteList, shopCTA, siteFooter);
413	var shopTitle = element('h2', 'cur-mobile__shop-title', 'Детали для вашей LADA');
414	var shopFooter = element('div', 'cur-mobile__shop-footer');
415	shopFooter.append(copyLink(shopHome, 'cur-mobile__all', 'Все товары магазина →'));
416	var mobileShop = shop('mobile', function (index) {
417		shopFooter.hidden = index !== 0;
418	});
419	views[1].append(shopTitle, mobileShop, shopFooter);
420	mobileUI.append(tablist, views[0], views[1]);
421	nav.appendChild(mobileUI);
422
423	function selectView(index) {
424		selectTabs(tabs, index);
425		views.forEach(function (view, position) { view.hidden = position !== index; });
426		mobileUI.classList.toggle('cur-mobile--shop', index === 1);
427	}
428	setupTabs(tabs, selectView, false);
429	selectView(0);
430	shopCTA.addEventListener('click', function () {
431		selectView(1);
432		tabs[1].focus();
433	});
434
435	function isolatePage(open) {
436		if (open && !isolated.length) {
437			Array.from(body.children).forEach(function (node) {
438				if (node === header || node.contains(header) || node.id === 'cur-overlay' || /^(SCRIPT|STYLE|LINK)$/.test(node.tagName)) return;
439				isolated.push({ node: node, inert: node.inert });
440				node.inert = true;
441			});
442		} else if (!open) {
443			isolated.forEach(function (entry) { entry.node.inert = entry.inert; });
444			isolated = [];
445		}
446	}
447
448	function closeMobile(restore) {
449		body.classList.remove('cur-navigation-open', 'cur-menu-open');
450		burger.setAttribute('aria-expanded', 'false');
451		burger.setAttribute('aria-label', 'Меню');
452		isolatePage(false);
453		if (restore) burger.focus();
454	}
455
456	nav.addEventListener('cur:menu-toggle', function (event) {
457		if (!mobile.matches) return;
458		if (!event.detail.open) {
459			closeMobile(true);
460			return;
461		}
462		closeDesktop(false);
463		positionPanels();
464		selectView(0);
465		mobileShop.querySelector('[role="tab"]').click();
466		mobileSections.forEach(function (section) {
467			section.panel.hidden = true;
468			section.trigger.setAttribute('aria-expanded', 'false');
469		});
470		body.classList.add('cur-navigation-open');
471		burger.setAttribute('aria-label', 'Закрыть меню');
472		isolatePage(true);
473		tabs[0].focus();
474	});
475	nav.addEventListener('cur:menu-close', function () {
476		var restore = nav.contains(document.activeElement);
477		closeDesktop(restore && !mobile.matches);
478		closeMobile(restore && mobile.matches);
479	});
480	document.addEventListener('click', function (event) {
481		if (!nav.contains(event.target)) closeDesktop(false);
482		if (mobile.matches && event.target.closest('.cur-minicart, .cur-logo__link')) closeMobile(false);
483	});
484	document.addEventListener('focusin', function (event) {
485		if (!mobile.matches && !nav.contains(event.target)) closeDesktop(false);
486	});
487	document.addEventListener('keydown', function (event) {
488		if (event.key !== 'Tab' || !mobile.matches || !body.classList.contains('cur-navigation-open')) return;
489		var focusable = Array.from(header.querySelectorAll('a[href], button, input, [tabindex="0"]')).filter(function (node) {
490			return !node.disabled && !node.closest('[hidden], [inert]') && node.getClientRects().length;
491		});
492		var first = focusable[0];
493		var last = focusable[focusable.length - 1];
494		if (!first || !last) return;
495		if (event.shiftKey && document.activeElement === first) {
496			event.preventDefault();
497			last.focus();
498		} else if (!event.shiftKey && document.activeElement === last) {
499			event.preventDefault();
500			first.focus();
501		}
502	});
503	mobile.addEventListener('change', function () {
504		var focusInside = nav.contains(document.activeElement);
505		closeDesktop(false);
506		closeMobile(false);
507		if (focusInside) (mobile.matches ? burger : desktopButtons[0]).focus();
508		positionPanels();
509	});
510	window.addEventListener('resize', positionPanels);
511	window.addEventListener('scroll', positionPanels, { passive: true });
512	if (window.ResizeObserver) new ResizeObserver(positionPanels).observe(header);
513	nav.classList.add('cur-nav--enhanced');
514	positionPanels();
515})();

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.