<script>
// ================================================================
// copilp/ru СЛАЙДЕР ДЛЯ БЛОКА «КОМАНДА» (TM102)
//
// Превращает сетку карточек Tilda в слайдер Swiper:
// бесконечная прокрутка, стрелки, точки-буллеты, авто-прокрутка.
//
// МЕНЯТЬ НУЖНО ТОЛЬКО ОБЪЕКТ SLIDER_SETTINGS НИЖЕ.
// Контейнер всегда остаётся по центру страницы.
// Вставляется вместо старого <script> И старого <style> этого блока.
// ================================================================
(function () {
'use strict';
// ------------------------------- НАСТРОЙКИ -------------------------------
var SLIDER_SETTINGS = {
blockSelector: '.uc-custom-team', // класс блока (доп. класс блока «Команда» в Тильде)
width: 1440, // ШИРИНА контейнера слайдера, px (вместе с боковыми отступами)
sidePadding: 20, // БОКОВЫЕ ОТСТУПЫ внутри контейнера, px (слева и справа)
spaceBetween: 10, // расстояние между карточками, px
loop: true, // бесконечная прокрутка (по кругу)
autoplayDelay: 10000, // авто-прокрутка, мс (10000 = 10 секунд), 0 — выключить
pauseOnHover: true, // пауза авто-прокрутки при наведении мыши
slidesDesktop: 4, // карточек в ряд: экраны >= 1024px
slidesLaptop: 3, // 768–1023px
slidesTablet: 2, // 480–767px
slidesMobile: 1 // < 480px
};
// Версия Swiper зафиксирована намеренно. В CDN-адресе без версии сейчас
// отдаётся Swiper 14.x, где при 8 карточках и 5 в ряд режим loop ломается:
// навигация «залипает», точки расходятся с карточками. 8.4.7 проверена.
var SWIPER_VERSION = '8.4.7';
var SWIPER_CSS = 'https://unpkg.com/swiper@' + SWIPER_VERSION + '/swiper-bundle.min.css';
var SWIPER_JS = 'https://unpkg.com/swiper@' + SWIPER_VERSION + '/swiper-bundle.min.js';
var NS = SLIDER_SETTINGS.blockSelector; // короткий псевдоним для селекторов в CSS
// -------------------- 1. ПОДКЛЮЧЕНИЕ СТИЛЕЙ SWIPER --------------------
if (!document.querySelector('link[href*="swiper@' + SWIPER_VERSION + '"]')) {
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = SWIPER_CSS;
document.head.appendChild(link);
}
// -------------------- 2. ЗАГРУЗКА JS SWIPER (один раз на страницу) --------------------
function loadSwiper(callback) {
if (window.__sliderSwiperReady) {
callback();
return;
}
var script = document.createElement('script');
script.src = SWIPER_JS;
script.onload = function () {
window.__sliderSwiperReady = true;
callback();
};
document.head.appendChild(script);
}
loadSwiper(function () {
// -------------------- 3. СТИЛИ СЛАЙДЕРА --------------------
// Вставляем ПОСЛЕ CSS Swiper, чтобы наши правила выигрывали при равной
// специфичности.
var style = document.createElement('style');
style.textContent = `
/* Переменные геометрии. Значения приходят из JS-настроек выше. */
${NS} {
--sb-width: 1440px;
--sb-pad: 20px;
}
/* --- Контейнер с шириной и отступами, всегда по центру страницы --- */
${NS} .sb-viewport {
width: 100%;
max-width: var(--sb-width);
margin-left: auto;
margin-right: auto;
padding-left: var(--sb-pad);
padding-right: var(--sb-pad);
box-sizing: border-box;
}
/* --- Сам слайдер: занимает всю ширину обёртки, лишнее прячем --- */
${NS} .t537__container.swiper {
display: block !important;
flex-wrap: nowrap !important;
width: 100% !important;
max-width: none !important;
min-width: 0 !important;
margin: 0 !important;
padding: 0 !important;
float: none !important;
overflow: hidden;
box-sizing: border-box;
}
/* Ширину слайда считает Swiper, поэтому width здесь НЕ переопределяем.
margin-right тоже не трогаем — это и есть зазор spaceBetween. */
${NS} .t537__container.swiper .t537__col,
${NS} .swiper-wrapper .t537__col,
${NS} .swiper-slide {
margin-top: 0 !important;
margin-bottom: 0 !important;
margin-left: 0 !important;
padding-top: 0 !important;
padding-bottom: 0 !important;
float: none !important;
clear: none !important;
max-width: none !important;
min-width: 0 !important;
width: auto;
display: flex;
flex-direction: column;
flex-shrink: 0;
box-sizing: border-box;
}
/* Внутренняя обёртка карточки — на всю ширину слайда */
${NS} .t537__itemwrapper,
${NS} [class*="t537__itemwrapper"] {
max-width: none !important;
width: 100% !important;
flex: 1;
display: flex;
flex-direction: column;
}
/* Псевдоэлементы старой сетки Tilda убираем */
${NS} .t537__col::before,
${NS} .t537__col::after {
content: none !important;
display: none !important;
}
/* Одинаковая высота карточек */
${NS} .swiper-wrapper { align-items: stretch; }
${NS} .swiper-slide { height: auto; }
/* Картинка и текст внутри карточки */
${NS} .t537__blockimg img { width: 100%; height: auto; display: block; }
${NS} .t537__textwrapper { flex: 1; }
/* --- Стрелки --- */
/* Мобильные и планшеты: две стрелки рядом по центру над слайдером */
${NS} .sb-nav {
width: 100%;
max-width: var(--sb-width);
margin: 0 auto 16px;
padding-left: var(--sb-pad);
padding-right: var(--sb-pad);
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
gap: 12px;
user-select: none;
}
${NS} .sb-prev,
${NS} .sb-next {
width: 36px;
height: 38px;
border-radius: 50%;
border: 1px solid #d5d5d5;
background: #fff;
font-size: 16px;
line-height: 1;
color: #333;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s, border-color 0.2s, color 0.2s;
-webkit-tap-highlight-color: transparent;
}
${NS} .sb-prev:hover,
${NS} .sb-next:hover {
background: #77ED6C;
border-color: #77ED6C;
color: #000;
}
/* Неактивная стрелка (если прокрутка не по кругу) */
${NS} .sb-prev.swiper-button-disabled,
${NS} .sb-next.swiper-button-disabled {
opacity: 0.3;
pointer-events: none;
}
/* Широкие экраны: стрелки разносим по краям контейнера.
padding у .sb-nav такой же, как у .sb-viewport, поэтому стрелки
встают ровно по краям карточек. */
@media (min-width: 1125px) {
${NS} .sb-nav {
justify-content: space-between;
gap: 0;
height: 40px;
margin-bottom: 16px;
}
${NS} .sb-prev,
${NS} .sb-next {
width: 34px;
height: 40px;
font-size: 18px;
}
}
/* --- Точки-буллеты --- */
${NS} .sb-pagination {
width: 100%;
max-width: var(--sb-width);
margin: 16px auto 0;
padding-left: var(--sb-pad);
padding-right: var(--sb-pad);
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
}
${NS} .sb-pagination .swiper-pagination-bullet {
width: 8px;
height: 8px;
margin: 0 !important; /* расстояние задаёт gap, а не margin Swiper */
border-radius: 50%;
background: #d5d5d5;
opacity: 1;
transition: background 0.3s, transform 0.3s;
}
${NS} .sb-pagination .swiper-pagination-bullet-active {
background: #333;
transform: scale(1.3);
}
/* --- Гасим ограничения сетки Tilda, мешающие слайдеру --- */
${NS} .t-col,
${NS} .t-col_3,
${NS} .t537__col {
max-width: none !important;
margin-left: 0 !important;
padding-left: 0 !important;
padding-right: 0 !important;
float: none !important;
}
/* Ширину контейнера карточек задаёт .sb-viewport */
${NS} .t-container,
${NS} .t537__container {
max-width: none !important;
width: 100% !important;
margin-left: 0 !important;
margin-right: 0 !important;
}
/* Мобильная сетка Tilda: второй столбец без верхнего отступа */
@media screen and (max-width: 1000px) {
${NS} .t537 .t537__container:not(.t-list__container_inrow1)
.t-list__item:nth-child(2) {
margin-top: 0px !important;
}
}
`;
document.head.appendChild(style);
// -------------------- 4. ИНИЦИАЛИЗАЦИЯ КАЖДОГО БЛОКА «КОМАНДА» --------------------
document.querySelectorAll(NS + ' .t537__container').forEach(function (container) {
// Защита от повторного запуска
if (container.classList.contains('sb-initialized')) return;
container.classList.add('sb-initialized', 'swiper');
var block = container.closest(NS) || container.parentNode;
// 4.1 Обёртка с шириной и отступами — контейнер карточек переезжает внутрь
var viewport = container.closest('.sb-viewport');
if (!viewport) {
viewport = document.createElement('div');
viewport.className = 'sb-viewport';
container.parentNode.insertBefore(viewport, container);
viewport.appendChild(container);
}
// 4.2 Карточки: сбрасываем инлайновые стили Tilda и переносим в .swiper-wrapper
var wrapper = container.querySelector('.swiper-wrapper');
if (!wrapper) {
wrapper = document.createElement('div');
wrapper.className = 'swiper-wrapper';
}
Array.prototype.slice.call(container.querySelectorAll('.t537__col')).forEach(function (card) {
card.style.marginTop = '';
card.style.marginBottom = '';
card.style.marginLeft = '';
card.style.paddingTop = '';
card.style.paddingBottom = '';
card.style.float = '';
card.style.clear = '';
card.style.width = '';
card.style.height = '';
card.style.minWidth = '';
card.style.maxWidth = '';
var itemwrapper = card.querySelector('.t537__itemwrapper');
if (itemwrapper) {
itemwrapper.style.maxWidth = '';
itemwrapper.style.width = '';
}
card.classList.add('swiper-slide');
wrapper.appendChild(card);
});
if (!wrapper.parentNode) container.appendChild(wrapper);
// 4.3 Стрелки и точки — соседи обёртки, в том месте, где стоял контейнер.
// Вставляем относительно фактического родителя (иначе insertBefore падает).
var host = viewport.parentNode;
var nav = block.querySelector('.sb-nav');
if (!nav) {
nav = document.createElement('div');
nav.className = 'sb-nav';
nav.innerHTML = '<button type="button" class="sb-prev" aria-label="Назад">❮</button>' +
'<button type="button" class="sb-next" aria-label="Вперёд">❯</button>';
host.insertBefore(nav, viewport);
}
var pagination = block.querySelector('.sb-pagination');
if (!pagination) {
pagination = document.createElement('div');
pagination.className = 'sb-pagination';
host.insertBefore(pagination, viewport.nextSibling);
}
// 4.4 Геометрия из настроек -> CSS-переменные блока
block.style.setProperty('--sb-width', SLIDER_SETTINGS.width + 'px');
block.style.setProperty('--sb-pad', SLIDER_SETTINGS.sidePadding + 'px');
// 4.5 Запуск Swiper
var gap = SLIDER_SETTINGS.spaceBetween;
new Swiper(container, {
loop: SLIDER_SETTINGS.loop,
slidesPerView: SLIDER_SETTINGS.slidesDesktop,
spaceBetween: gap,
speed: 500,
autoHeight: false,
watchOverflow: false,
autoplay: SLIDER_SETTINGS.autoplayDelay > 0 ? {
delay: SLIDER_SETTINGS.autoplayDelay,
disableOnInteraction: false,
pauseOnMouseEnter: SLIDER_SETTINGS.pauseOnHover
} : false,
navigation: {
nextEl: nav.querySelector('.sb-next'),
prevEl: nav.querySelector('.sb-prev')
},
pagination: {
el: pagination,
clickable: true,
dynamicBullets: false
},
breakpoints: {
0: { slidesPerView: SLIDER_SETTINGS.slidesMobile, spaceBetween: gap },
480: { slidesPerView: SLIDER_SETTINGS.slidesTablet, spaceBetween: gap },
768: { slidesPerView: SLIDER_SETTINGS.slidesLaptop, spaceBetween: gap },
1024: { slidesPerView: SLIDER_SETTINGS.slidesDesktop, spaceBetween: gap }
},
simulateTouch: true,
grabCursor: true,
resistanceRatio: 0.85
});
});
});
})();
</script>