script.js — ванільний JavaScript
script.js — ванільний JavaScript
Основні правила
- ✅ Тільки vanilla JS — без jQuery, Swiper, Slick, будь-яких CDN бібліотек
- ✅ IIFE обгортка щоб не забруднювати глобальний scope
- ✅ Guard від подвійної ініціалізації (
if (el.dataset.init) return) - ✅ Відносна навігація через
el.querySelector(), неdocument.getElementById() - ❌ Не використовувати id-атрибути для пошуку — секція може бути кілька разів на сторінці
Базовий паттерн
(function () {
document.querySelectorAll('.cms-section-countdown').forEach(function (el) {
if (el.dataset.init) return; // guard: ще раз не ініціалізувати
el.dataset.init = '1';
// навігація лише всередині поточного el
var timerEl = el.querySelector('.countdown__timer');
var totalSec = parseInt(el.dataset.seconds || '3600', 10);
// ... логіка
});
})();
Countdown timer
(function () {
document.querySelectorAll('.cms-section-countdown').forEach(function (el) {
if (el.dataset.init) return;
el.dataset.init = '1';
var timerEl = el.querySelector('.countdown__timer');
var totalSec = parseInt(el.dataset.seconds || '3600', 10);
function pad(n) { return n < 10 ? '0' + n : '' + n; }
function render(s) {
var h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60), sec = s % 60;
timerEl.innerHTML =
'<span class="js-cd-h">' + pad(h) + '</span>:' +
'<span class="js-cd-m">' + pad(m) + '</span>:' +
'<span class="js-cd-s">' + pad(sec) + '</span>';
}
render(totalSec);
setInterval(function () { if (totalSec > 0) { totalSec--; render(totalSec); } }, 1000);
});
})();
HTML для даних: <div class="countdown__timer" data-seconds="{{TIMER_SECONDS}}"></div>
Vanilla slider (Swiper-сумісна розмітка)
(function () {
document.querySelectorAll('.cms-section-testimonials .swiper-reviews').forEach(function (swiper) {
if (swiper.dataset.init) return;
swiper.dataset.init = '1';
var wrapper = swiper.querySelector('.swiper-wrapper');
var slides = swiper.querySelectorAll('.swiper-slide');
var total = slides.length, current = 0;
var pagination = swiper.querySelector('.swiper-pagination');
var bullets = [];
for (var i = 0; i < total; i++) {
var b = document.createElement('span');
b.className = 'swiper-pagination-bullet' + (i === 0 ? ' swiper-pagination-bullet-active' : '');
(function(idx) { b.addEventListener('click', function() { go(idx); }); })(i);
pagination.appendChild(b); bullets.push(b);
}
function go(idx) {
current = (idx + total) % total;
wrapper.style.transform = 'translateX(-' + (current * 100) + '%)';
bullets.forEach(function(b, i) {
b.className = 'swiper-pagination-bullet' + (i === current ? ' swiper-pagination-bullet-active' : '');
});
}
var nextBtn = swiper.querySelector('.swiper-button-next');
var prevBtn = swiper.querySelector('.swiper-button-prev');
if (nextBtn) nextBtn.addEventListener('click', function() { go(current + 1); });
if (prevBtn) prevBtn.addEventListener('click', function() { go(current - 1); });
// Touch support
var startX = 0;
wrapper.addEventListener('touchstart', function(e) { startX = e.touches[0].clientX; }, {passive:true});
wrapper.addEventListener('touchend', function(e) {
if (Math.abs(e.changedTouches[0].clientX - startX) > 40)
go(e.changedTouches[0].clientX < startX ? current + 1 : current - 1);
});
});
})();
Маска телефону (Україна +380)
(function () {
document.querySelectorAll('.cms-section-order-form input[name="phone"]').forEach(function(input) {
if (input.dataset.masked) return;
input.dataset.masked = '1';
input.addEventListener('input', function() {
var raw = this.value.replace(/\D/g, '');
if (raw.startsWith('380')) raw = raw.slice(3);
else if (raw.startsWith('0')) raw = raw.slice(1);
raw = raw.slice(0, 9);
var out = '+380';
if (raw.length > 0) out += ' ' + raw.slice(0, 2);
if (raw.length > 2) out += ' ' + raw.slice(2, 5);
if (raw.length > 5) out += '-' + raw.slice(5, 7);
if (raw.length > 7) out += '-' + raw.slice(7, 9);
this.value = out;
});
input.addEventListener('focus', function() { if (!this.value) this.value = '+380 '; });
});
})();
Відправка форми в Telegram
(function () {
document.querySelectorAll('.cms-section-order-form .m1-form').forEach(function(form) {
if (form.dataset.init) return;
form.dataset.init = '1';
form.addEventListener('submit', function(e) {
e.preventDefault();
var token = this.dataset.tgToken || '';
var chatId = this.dataset.tgChat || '';
var data = Object.fromEntries(new FormData(this));
var text = Object.entries(data)
.filter(([k]) => !k.startsWith('_'))
.map(([k, v]) => '*' + k + ':* ' + v).join('\n');
fetch('https://api.telegram.org/bot' + token + '/sendMessage', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ chat_id: chatId, text: text, parse_mode: 'Markdown' })
}).then(function() {
form.style.display = 'none';
form.closest('.cms-section-order-form').querySelector('.form-success').style.display = 'block';
});
});
});
})();
Оновлено: 26.10.2026 22:43
👁 22
Інші сторінки в категорії «Для розробників»