PageSourceSearch

https://svblada.ru/bitrix/templates/svblada/js/main.js

js svblada.ru collected 2026-10-09 03:41:28 UTC 11,209 bytes, 347 lines download raw bytes

1// Определяем переменную для экономии памяти.
2var doc = $(document),
3	menuTimer,
4	touchStartPos;
5
6doc
7	.on('click keypress', '.search-button', function(e) {
8		if (e.type == 'keypress' && e.which != 13) {
9			return;
10		}
11		if(e.type == 'keypress' && e.which == 13) {
12			$('.container-search').find('.search-input').addClass('tabindex');
13		}
14		// Обработка нажатия на кнопку поиска
15		$('.container-search').addClass('opened').find('.search-input').focus();
16		var $hamburger = $('.hamburger');
17		if ($hamburger.hasClass('active')) {
18			$hamburger.trigger('click');
19		}
20	})
21	.on('click', '.search-close-button', function() {
22		// Обработка нажатия на кнопку закрытия поиска
23		$('.container-search').removeClass('opened');
24	})
25	.on('blur', '.search-input.tabindex', function() {
26		if ($(this).val() === '') {
27			$(this).closest('.container-search').removeClass('opened');
28			$('.search-button').focus();
29		}
30	})
31	.on('input', '.search-input', function() {
32		/**
33		 * @todo Этот код необходимо удалить, он тут только для демонстрации поведения поиска
34		 */
35		if ($(this).val() !== '') {
36			$('.search-suggestions').slideDown(500);
37		} else {
38			$('.search-suggestions').slideUp(300);
39		}
40	})
41	.on('click touchend', '.top-nav-block .parent > a, .top-header-nav .parent > a', function(e) {
42		// Обработка клика и тача по родительским пунктам верхнего меню
43		if (e.type == 'touchend') {
44			$(this).off('click');
45			var $this = $(this),
46				$parent = $this.closest('.parent');
47			if ($parent.hasClass('active')) {
48				$parent.removeClass('active').siblings();
49			} else {
50				$parent.addClass('active').siblings().removeClass('active');
51			}
52
53			return false;
54		}
55	})
56	.on('touchstart', '.mobile-nav li.parent > a', function (e) {
57		e.preventDefault();
58		touchStartPos = getTopElementPostition(this);
59	})
60	.on('click touchend', '.mobile-nav li.parent > a', function (e) {
61		if (e.type == 'touchend') {
62			$(this).off('click');
63			// Сворачиваем/разворачиваем пункты меню на мобильном с учётом свайпов.
64			var distance = touchStartPos - getTopElementPostition(this);
65			if (isNotSwiped(distance)) {
66				var $this = $(this),
67					$parent = $this.closest('.parent');
68				if ($parent.hasClass('active')) {
69					$parent.removeClass('active');
70				}
71				else {
72					$parent.addClass('active');
73				}
74			}
75		}
76		return false;
77	})
78	.on('input keyup', '.jq-selectbox__search input', function() {
79		$(this).closest('ul').perfectScrollbar('update');
80
81	})
82	.on('click', '.toggle-next', function(e) {
83		// Сворачивание/разворачивание следующего за текущим элемента
84		e.preventDefault();
85		$(this).toggleClass('opened').next().slideToggle(500);
86	})
87	.on('touchend', '.footer-menu-content ul .h4', function() {
88		// Сворачиваем/разворачиваем меню в футере сайта только на тач-устройствах	
89		$(this).toggleClass('opened').next().slideToggle(500);
90	})
91	.on('click', '.sidebar-nav .parent > a', function(e) {
92		// Меню в сайдбаре
93		e.preventDefault();
94		var $parent = $(this).parent();
95
96		if ($parent.hasClass('current')) {
97			$parent.removeClass('current');
98		} else {
99			$('.sidebar-nav .parent').removeClass('current');
100			$parent.addClass('current');
101		}
102		return false;
103	})
104	// При первом наведении на блок с меню делаем задержку для предотвращения случайного показа пунктов
105	.on('mouseenter', '.top-nav-block', function() {
106		var $this = $(this);
107		if (menuTimer) {
108			clearTimeout(menuTimer);
109			menuTimer = null;
110		}
111		menuTimer = setTimeout(function () {
112			$this.addClass('hovered');
113		}, 400);
114	})
115	.on('mouseleave', '.top-nav-block', function() {
116		if (menuTimer) {
117			clearTimeout(menuTimer);
118			menuTimer = null;
119		}
120		$(this).removeClass('hovered').find('.parent').removeClass('active');
121		$(':focus').blur();
122	})
123	.on('mouseenter', '.top-header-nav-ul, .top-nav-block', function() {
124		$('.top-header-nav-ul, .top-nav-block').find('.parent').removeClass('active');
125		$(':focus').blur();
126	})
127	.on('mouseenter focusin touchend', '.container-top-navigation .parent > a', function(e) {
128		// Обработка выпадающего меню в шапке
129		var $this = $(this),
130			$parent = $this.closest('li'),
131			$second = $this.next('.second-level');
132
133		if (e.type == 'focusin') {
134			$('.top-nav-block').addClass('hovered');
135			// Убираем у внутренних ссылок в меню tabindex
136			$('.container-top-navigation .second-level a').prop('tabindex', false);
137			// Добавляем tabindex для внутренних ссылок в текущем пункте меню
138			$second.find('a').prop('tabindex', 1);
139
140			if ($parent.hasClass('active')) {
141				$parent.removeClass('active');
142			} else {
143				$parent.addClass('active').siblings().removeClass('active');
144			}
145		}
146
147		if ($second.length) {
148			$second.css('top', $parent.height() + $parent.position().top);
149		}
150	})
151	.on('focusin', '.top-nav-block > ul > li > a', function() {
152		var $this = $(this),
153			$parent = $this.closest('li');
154		if (!$parent.hasClass('parent')) {
155
156			$('.top-nav-block .parent').removeClass('active');
157			$parent.addClass('active');
158			$('.top-nav-block .second-level a').prop('tabindex', false);
159		}
160	})
161	.on('focusin', '.top-header-nav-ul .parent > a', function(e) {
162		var $this = $(this),
163			$parent = $this.closest('.parent'),
164			$a = $parent.find('ul a');
165
166		if (e.type == 'focusin') {
167			// Убираем у внутренних ссылок в меню tabindex
168			$('.top-header-nav-ul .parent ul a').prop('tabindex', false);
169			// Добавляем tabindex для внутренних ссылок в текущем пункте меню
170			$a.prop('tabindex', 1);
171		}
172
173		if ($parent.hasClass('active')) {
174			$parent.removeClass('active');
175		} else {
176			$parent.addClass('active').siblings().removeClass('active');
177		}
178	})
179	.on('blur', '.top-header-nav-ul .parent ul li:last a', function() {
180		$('.top-header-nav-ul  .parent').removeClass('active');
181	})
182	.on('refresh', '.styler', function() {
183		// При пересчёте стилизации селектов необходимо выполнить то, 
184		// что по-хорошему должно выполниться по умолчанию в плагине.
185		stylerRefresh();
186	});
187
188if (window.frameCacheVars !== undefined) {
189	// Композит
190	BX.addCustomEvent('onFrameDataReceived', mainJsFile);
191} else {
192	// Обычный режим
193	$(mainJsFile);
194}
195
196// Основной js-код, выполняемый при загрузке страницы
197function mainJsFile() {
198	// Строим мобильную навигацию
199	$.simpleMobileNav({
200		navBlock: '.top-nav-block > ul',
201		navContainer: '.mobile-nav',
202		navWrapper: '.mobile-nav-wrapper',
203		beforeNavOpen: function () {
204			var $searchCloseButton = $('.search-close-button');
205			if ($searchCloseButton.is(':visible')) {
206				$searchCloseButton.trigger('click');
207			}
208		}
209	});
210
211	// Табы с селектами
212	// Этот код должен быть выше плагина styler 
213	// для автоматической стилизации селектов, которые он создаёт.
214	var $firstSelect;
215
216	$.tabsToSelect({
217		selectCalss: 'styler',
218		selectAppendTo: '.tts-tabs-switchers-wrapper',
219		onInit: function () {
220			// Запоминаем первый селект
221			$firstSelect = $('.tts-tabs-select:first');
222		},
223		onResized: function () {
224			// Обновляем стилизацию селекта, если он становится видимым при ресайзе страницы
225			if ($firstSelect.is(':visible') && !$firstSelect.hasClass('refreshed')) {
226				$('.tts-tabs-select').addClass('refreshed').trigger('refresh');
227			}
228		},
229		beforeTabSwich: function (e) {
230			// Если у переключателя таба, по которому кликаем, есть data-атрибут - значит перейдём по ссылке в нём.
231			var link = $(e.currentTarget).find('.tts-tabs-switcher').eq(e.tab).data('targetSelf');
232
233			if (link) {
234				location.href = link;
235				return false;
236			}
237			return true;
238		}
239	});
240
241	// Слайдер на главной странице
242	var $bigSlider = $('.big-slider'),
243		$bigSliderParams = $bigSlider.data() || {};
244
245	$bigSlider.owlCarousel({
246		items: 1,
247		loop: ($bigSliderParams.owlLoop == 'y') ? true : false,
248		autoplay: ($bigSliderParams.owlAutoplay == 'y') ? true : false,
249		autoplayTimeout: $bigSliderParams.owlAutoplayTimeout * 1000,
250		autoplayHoverPause: true,
251		navContainer: '.big-slider-nav',
252		navText: ['', ''],
253		responsive: {
254			0: {
255				nav: false,
256				dots: true
257			},
258			768: {
259				nav: true,
260				dots: false
261			}
262		}
263	});
264
265	// Стилизация селектов
266	$('.styler').styler({
267		selectSearch: true,
268		selectSearchLimit: 20,
269		onSelectOpened: function() {
270			// к открытому применяем плагин стилизации скроллбара
271			$(this).find('ul').perfectScrollbar();
272		},
273		onFormStyled: function () {
274			$('.jq-selectbox').addClass('opacity-one');
275		}
276	});
277
278	// Одинаковая высота блоков
279	$('.equal').matchHeight();
280
281}
282
283/**
284 * Определяем в какой позиции пользователь тапнул по экрану телефона
285 */
286function getTopElementPostition(element) {
287	return $(element).position().top || $(element).offset().top || $(window).scrollTop();
288}
289/**
290 * Определяем сдвинул ли пользователь экран.
291 */
292function isNotSwiped(distance) {
293	if (distance > 20 || distance < -20) {
294		return false;
295	}
296	return true;
297}
298/**
299 * Обновляем стилизацию селектов
300 */
301function stylerRefresh() {
302	$('.jq-selectbox').addClass('opacity-one');
303}
304
305
306// Функции для реализации адаптивности таблицы
307function splitTable(original) {
308	original.wrap('<div class="table-wrapper" />');
309
310	var copy = original.clone();
311	copy.find('td:not(:first-child), th:not(:first-child)').css('display', 'none');
312	copy.removeClass('table-responsive');
313
314	original.closest('.table-wrapper').append(copy);
315	copy.wrap('<div class="pinned" />');
316	original.wrap('<div class="scrollable" />');
317
318	setCellHeights(original, copy);
319}
320
321function unsplitTable(original) {
322	original.closest('.table-wrapper').find('.pinned').remove();
323	original.unwrap();
324	original.unwrap();
325}
326
327function setCellHeights(original, copy) {
328	var tr = original.find('tr'),
329		tr_copy = copy.find('tr'),
330		heights = [];
331
332	tr.each(function (index) {
333		var self = $(this),
334			tx = self.find('th, td');
335
336		tx.each(function () {
337			var height = $(this).outerHeight(true);
338			heights[index] = heights[index] || 0;
339			if (height > heights[index]) heights[index] = height;
340		});
341
342	});
343
344	tr_copy.each(function (index) {
345		$(this).height(heights[index]);
346	});
347}

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.