PageSourceSearch

https://elitecar.rent/wp-content/themes/meetx/assets/js/scriptsh.js?ver=1791244637

js elitecar.rent collected 2026-10-05 23:57:25 UTC 16,085 bytes, 445 lines download raw bytes

1document.addEventListener("DOMContentLoaded", function () {
2  const ennoBtn = document.getElementById("enno");
3  const closenBtn = document.querySelector(".newfo .closen");
4  const nekk = document.getElementById("nekk");
5  const newfo = document.querySelector(".newfo");
6  const aldesc = document.querySelector(".aldesc");
7
8  /* ennoBtn.addEventListener("click", function () {
9    nekk.style.display = "none";
10	aldesc.style.display = "none";
11    newfo.setAttribute("aria-hidden", "false");
12    newfo.classList.add("slide-in");
13  });
14
15  closenBtn.addEventListener("click", function () {
16    newfo.classList.remove("slide-in");
17    newfo.setAttribute("aria-hidden", "true");
18    setTimeout(() => {
19      nekk.style.display = "flex";
20	 aldesc.style.display = "block";
21    }, 300); // Match the animation duration
22  }); */
23});
24
25
26
27
28document.addEventListener("DOMContentLoaded", () => {
29  const button = document.querySelector('.bitrixx');
30  if (!button) return;
31
32  button.addEventListener('click', function () {
33    const widgetButton = document.querySelector('.b24-widget-button-crmform span');
34    if (widgetButton) widgetButton.click();
35  });
36});
37
38document.addEventListener('DOMContentLoaded', function () {
39  function isMobile() {
40    return ('ontouchstart' in window) || (window.innerWidth <= 900);
41  }
42
43  // Оборачиваем текущих детей car-slider в структуру Swiper
44  function ensureCarGalleryStructure(container, { addPagination = true } = {}) {
45    container.classList.add('swiper');
46
47    let wrapper = container.querySelector('.swiper-wrapper');
48    if (!wrapper) {
49      wrapper = document.createElement('div');
50      wrapper.className = 'swiper-wrapper';
51
52      const children = Array.from(container.children);
53      children.forEach(node => {
54        if (node.classList && node.classList.contains('swiper-wrapper')) return;
55        const slide = document.createElement('div');
56        slide.className = 'swiper-slide';
57        slide.appendChild(node);
58        wrapper.appendChild(slide);
59      });
60      container.appendChild(wrapper);
61    }
62
63    let paginationEl = null;
64    if (addPagination) {
65      paginationEl = container.querySelector('.swiper-pagination');
66      if (!paginationEl) {
67        paginationEl = document.createElement('div');
68        paginationEl.className = 'swiper-pagination';
69        container.appendChild(paginationEl);
70      }
71    }
72    return { wrapper, paginationEl };
73  }
74
75  // Ховер по буллетам
76  function bindBulletHover(swiper) {
77    if (isMobile() || !swiper || !swiper.pagination || !swiper.pagination.bullets) return;
78    swiper.pagination.bullets.forEach((b, i) => {
79      b.onmouseenter = () => {
80        clearTimeout(b.__hoverTimer);
81        b.__hoverTimer = setTimeout(() => {
82          if (!swiper || swiper.destroyed) return;
83          if (swiper.params.loop && swiper.slideToLoop) swiper.slideToLoop(i);
84          else swiper.slideTo(i);
85        }, 80);
86      };
87      b.onmouseleave = () => clearTimeout(b.__hoverTimer);
88    });
89  }
90
91  const carSwiperMap = new WeakMap();
92
93  // Gallery image nodes do not exist in the initial card markup. Build them
94  // only after the visitor hovers, focuses or taps the thumbnail.
95  function createCarGallery(wrapper) {
96    const existing = wrapper.querySelector('.car-slider');
97    if (existing) return existing;
98
99    let gallery;
100    try {
101      gallery = JSON.parse(wrapper.dataset.gallery || '[]');
102    } catch (_) {
103      gallery = [];
104    }
105    if (!Array.isArray(gallery) || gallery.length === 0) return null;
106
107    const slider = document.createElement('div');
108    slider.className = 'car-slider';
109    slider.style.display = 'none';
110
111    gallery.forEach(function (item) {
112      if (!item || !item.src) return;
113
114      const link = document.createElement('a');
115      link.href = wrapper.dataset.galleryLink || '#';
116      link.title = 'аренда ' + (wrapper.dataset.galleryTitle || 'автомобиля');
117
118      const image = document.createElement('img');
119      image.className = 'swiper-lazy';
120      image.dataset.src = item.src;
121      image.alt = item.alt || wrapper.dataset.galleryTitle || '';
122      image.loading = 'lazy';
123      image.decoding = 'async';
124
125      link.appendChild(image);
126      slider.appendChild(link);
127    });
128
129    if (!slider.children.length) return null;
130    const specs = wrapper.querySelector('.anox');
131    wrapper.insertBefore(slider, specs || null);
132    return slider;
133  }
134
135function initSlider(wrapper) {
136  if (wrapper.dataset.swiperInited === '1') return;
137
138  const slider = createCarGallery(wrapper);
139  const thumb  = wrapper.querySelector('.car-thumbnail');
140  if (!slider) return;
141  wrapper.dataset.swiperInited = '1';
142
143  // Показываем слайдер, но миниатюру пока НЕ трогаем
144  slider.style.display = '';
145
146  if (!window.Swiper) {
147    console.error('Swiper не найден. Подключи его до этого скрипта.');
148    const firstImage = slider.querySelector('img[data-src]');
149    if (firstImage) {
150      firstImage.addEventListener('load', function () {
151        if (thumb) thumb.style.display = 'none';
152      }, { once: true });
153      firstImage.src = firstImage.dataset.src;
154    }
155    return;
156  }
157
158  const { paginationEl } = ensureCarGalleryStructure(slider, { addPagination: true });
159
160  let thumbHidden = false; // чтобы не дергать много раз
161
162  const sw = new Swiper(slider, {
163    effect: 'fade',
164    fadeEffect: { crossFade: true },
165    speed: 100,
166    loop: slider.querySelectorAll('.swiper-slide').length > 1,
167    slidesPerView: 1,
168    preloadImages: false,
169    lazy: {
170      checkInView: true,
171      loadOnTransitionStart: true,
172      loadPrevNext: true,
173    },
174    pagination: {
175      el: paginationEl,
176      clickable: true
177    },
178    on: {
179      init(swiper) {
180        bindBulletHover(swiper);
181
182        // сразу просим подгрузить первый слайд
183        if (swiper.lazy && typeof swiper.lazy.load === 'function') {
184          swiper.lazy.load();
185        }
186
187        // на всякий: если lazy отключён или первая картинка уже прогружена
188        const firstImg = slider.querySelector('img.swiper-lazy');
189        if (firstImg && firstImg.complete && firstImg.naturalWidth > 0 && !thumbHidden && thumb) {
190          thumbHidden = true;
191          thumb.style.display = 'none';
192        }
193      },
194
195      // Ключевой момент: миниатюру убираем только когда lazy-картинка ГОТОВА
196      lazyImageReady(swiper, slideEl, imageEl) {
197        if (!thumbHidden && thumb) {
198          thumbHidden = true;
199          thumb.style.display = 'none';
200        }
201      },
202
203      paginationUpdate: bindBulletHover,
204      breakpoint:       bindBulletHover
205    }
206  });
207
208  carSwiperMap.set(wrapper, sw);
209}
210
211  function attachListeners() {
212    document.querySelectorAll('.car-image-wrapper').forEach(function(wrapper){
213      if (wrapper.dataset.listenerAdded) return;
214      wrapper.dataset.listenerAdded = '1';
215
216      const thumb = wrapper.querySelector('.car-thumbnail');
217      if (!thumb || !wrapper.dataset.gallery || wrapper.dataset.gallery === '[]') return;
218      let inited = false;
219
220      function startSlider() {
221        if (inited) return;
222        inited = true;
223        initSlider(wrapper);
224      }
225
226      thumb.addEventListener('mouseenter', startSlider, { once: true });
227      thumb.addEventListener('click', startSlider, { once: true });
228      thumb.addEventListener('focus', startSlider, { once: true });
229      thumb.tabIndex = 0;
230      thumb.setAttribute('role', 'button');
231      thumb.setAttribute('aria-label', 'Открыть фотографии ' + (wrapper.dataset.galleryTitle || 'автомобиля'));
232      thumb.addEventListener('keydown', function (event) {
233        if (event.key === 'Enter' || event.key === ' ') {
234          event.preventDefault();
235          startSlider();
236        }
237      });
238    });
239  }
240
241  attachListeners();
242  window.initCarImageWrappers = attachListeners; // оставляем для AJAX-подгрузок
243});
244
245document.addEventListener('DOMContentLoaded', function() {
246  const bottomNav = document.querySelectorAll('.avto-slider-tabs .tabs-nav li');
247  const bottomPanels = document.querySelectorAll('.avto-slider-tabs .tab-contentt');
248
249  function ensureBessoStructure(container, { addNavigation = true } = {}) {
250    container.classList.add('swiper');
251
252    let wrapper = container.querySelector('.swiper-wrapper');
253    if (!wrapper) {
254      wrapper = document.createElement('div');
255      wrapper.className = 'swiper-wrapper';
256      const children = Array.from(container.children);
257      children.forEach(node => {
258        if (node.classList && node.classList.contains('swiper-wrapper')) return;
259        const slide = document.createElement('div');
260        slide.className = 'swiper-slide';
261        slide.appendChild(node);
262        wrapper.appendChild(slide);
263      });
264      container.appendChild(wrapper);
265    }
266
267    let prevEl = null, nextEl = null;
268    if (addNavigation) {
269      prevEl = container.querySelector('.swiper-button-prev');
270      nextEl = container.querySelector('.swiper-button-next');
271      if (!prevEl) { prevEl = document.createElement('div'); prevEl.className = 'swiper-button-prev'; container.appendChild(prevEl); }
272      if (!nextEl) { nextEl = document.createElement('div'); nextEl.className = 'swiper-button-next'; container.appendChild(nextEl); }
273    }
274    return { wrapper, prevEl, nextEl };
275  }
276
277  function getPanelSwiper(panelEl) {
278    const slider = panelEl.querySelector('.besso');
279    return slider ? slider.__swiperInstance : null;
280  }
281  function setPanelSwiper(panelEl, instance) {
282    const slider = panelEl.querySelector('.besso');
283    if (slider) slider.__swiperInstance = instance;
284  }
285
286function initOrRefreshSlider(panelEl) {
287  const slider = panelEl.querySelector('.besso');
288  if (!slider) return;
289
290  if (panelEl.style.display === 'none') panelEl.style.display = 'flex';
291  if (!window.Swiper) { console.error('Swiper не найден. Подключи его раньше этого скрипта.'); return; }
292
293  const { wrapper, prevEl, nextEl } = ensureBessoStructure(slider, { addNavigation: true });
294
295  // Сколько реально слайдов внутри
296  const slidesCount = wrapper.querySelectorAll(':scope > .swiper-slide').length;
297
298  // Если 0/1 — работаем без инициализации Swiper (статичный режим)
299  if (slidesCount <= 1) {
300    // убираем/прячем навигацию
301    if (prevEl) prevEl.style.display = 'none';
302    if (nextEl) nextEl.style.display = 'none';
303
304    // помечаем классом и выставляем явные размеры
305    slider.classList.add('swiper-single');
306    wrapper.style.display = 'block';
307    const only = wrapper.querySelector('.swiper-slide');
308    if (only) only.style.width = '100%';
309
310    // если раньше был Swiper — корректно убьём
311    let inst = getPanelSwiper(panelEl);
312    if (inst && !inst.destroyed) inst.destroy(true, false);
313    setPanelSwiper(panelEl, null);
314    return;
315  }
316
317  // Для 2+ слайдов — обычная инициализация
318  let sw = getPanelSwiper(panelEl);
319  if (sw && !sw.destroyed) { sw.update(); return; }
320
321  // динамически подстроим конфиг под количество слайдов
322  sw = new Swiper(slider, {
323    speed: 600,
324    loop: false,
325	rewind: true,
326    slidesPerView: 3,
327    slidesPerGroup: Math.min(2, slidesCount),
328    allowTouchMove: slidesCount > 1,
329    watchOverflow: false, // важно: не лочим контейнер
330    navigation: { prevEl, nextEl },
331    breakpoints: {
332      0:    { slidesPerView: 1, slidesPerGroup: 1, allowTouchMove: false },
333	  575:  { slidesPerView: Math.min(2, slidesCount), slidesPerGroup: Math.min(2, slidesCount), allowTouchMove: slidesCount > 1 },
334      769:  { slidesPerView: Math.min(2, slidesCount), slidesPerGroup: Math.min(2, slidesCount), allowTouchMove: slidesCount > 1 },
335      1025: { slidesPerView: Math.min(3, slidesCount), slidesPerGroup: Math.min(2, slidesCount), allowTouchMove: slidesCount > 1 }
336    }
337  });
338
339  setPanelSwiper(panelEl, sw);
340  setTimeout(() => { try { sw.update(); } catch(e) {} }, 0);
341}
342
343  window.initOrRefreshElitecarClassSlider = initOrRefreshSlider;
344
345  function showBottomTab(index) {
346    bottomNav.forEach(b => b.classList.remove('active'));
347    bottomPanels.forEach(p => p.style.display = 'none');
348
349    const btn = bottomNav[index];
350    const panel = bottomPanels[index];
351    if (!btn || !panel) return;
352
353    btn.classList.add('active');
354    panel.style.display = 'flex';
355    initOrRefreshSlider(panel);
356  }
357
358  if (bottomNav.length) {
359    showBottomTab(0);
360    bottomNav.forEach((btn, idx) => btn.addEventListener('click', () => showBottomTab(idx)));
361  }
362
363 
364
365  // ===== СОРТИРОВКА для Swiper (.besso) =====
366  function sortPanel(panelEl, order) {
367    const slider = panelEl.querySelector('.besso');
368    if (!slider) return;
369
370    const wrapper = slider.querySelector('.swiper-wrapper') || (function(){
371      const o = ensureBessoStructure(slider, { addNavigation: true });
372      return o.wrapper;
373    })();
374
375    const slides = Array.from(wrapper.children);
376    slides.sort((a, b) => {
377      const getPrice = (el) => {
378        const ci = el.querySelector('.car-item') || el;
379        return parseFloat(ci.dataset.price) || 0;
380      };
381      const pa = getPrice(a);
382      const pb = getPrice(b);
383      return order === 'asc' ? (pa - pb) : (pb - pa);
384    });
385    slides.forEach(s => wrapper.appendChild(s));
386
387    const sw = getPanelSwiper(panelEl);
388    if (sw && !sw.destroyed) { try { sw.update(); } catch(e) {} }
389  }
390
391  document.querySelectorAll('.avto-slider-tabs .tab-contentt').forEach(panel => {
392    const btn = panel.querySelector('.sort-toggle');
393    if (!btn) return;
394
395    btn.addEventListener('click', () => {
396      const newOrder = (btn.dataset.order === 'desc') ? 'asc' : 'desc';
397      btn.dataset.order = newOrder;
398      btn.dataset.applied = 'true';
399
400      const arrow = btn.querySelector('.arrow');
401      const label = btn.querySelector('.label');
402      if (arrow) arrow.textContent = (newOrder === 'desc') ? '↓' : '↑';
403      if (label) label.textContent =
404        (newOrder === 'desc') ? 'Сначала дороже' : 'Сначала дешевле';
405
406      sortPanel(panel, newOrder);
407      initOrRefreshSlider(panel);
408    });
409  });
410
411  // повторное применение сортировки при возврате к табу
412  const _origShowBottomTab = showBottomTab;
413  showBottomTab = function(index) {
414    _origShowBottomTab(index);
415    const panel = bottomPanels[index];
416    if (!panel) return;
417    const btn = panel.querySelector('.sort-toggle');
418    if (btn && btn.dataset.applied === 'true') {
419      sortPanel(panel, btn.dataset.order || 'desc');
420    }
421  };
422});
423
424window.b24Form7 = null;
425window.b24Form13 = null;
426window.b24Form17 = null;
427
428// слушаем инициализацию CRM-форм
429window.addEventListener('b24:form:init', function (e) {
430    var form = e.detail && e.detail.object;
431    if (!form || !form.identification) return;
432
433    if (form.identification.id == 7) {
434        window.b24Form7 = form;
435        console.log('b24:form:init → сохранили объект формы 7');
436    }
437    if (form.identification.id == 13) {
438        window.b24Form13 = form;
439        console.log('b24:form:init → сохранили объект формы 13');
440    }
441	if (form.identification.id == 17) {
442        window.b24Form17 = form;
443        console.log('b24:form:init → сохранили объект формы 17');
444    }
445});

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.