449 lines
17 KiB
JavaScript
449 lines
17 KiB
JavaScript
// Initialize dataLayer for Google Tag Manager
|
|
window.dataLayer = window.dataLayer || [];
|
|
|
|
// Push virtual page view event on page load
|
|
window.dataLayer.push({
|
|
'event': 'virtualPageview',
|
|
'pagePath': window.location.pathname + window.location.search,
|
|
'pageTitle': document.title
|
|
});
|
|
|
|
// --- Product Carousel Logic ---
|
|
document.addEventListener('DOMContentLoaded', function initProductCarousel() {
|
|
const carouselMain = document.querySelector('.carousel-main');
|
|
if (!carouselMain) return;
|
|
|
|
const mainImg = carouselMain.querySelector('img');
|
|
const thumbs = Array.from(document.querySelectorAll('.carousel-thumbnails .product-img-small'));
|
|
const leftArrow = document.querySelector('.carousel-arrow.left');
|
|
const rightArrow = document.querySelector('.carousel-arrow.right');
|
|
|
|
if (!mainImg || thumbs.length === 0) return;
|
|
|
|
let current = thumbs.findIndex(t => t.classList.contains('selected'));
|
|
if (current === -1) current = 0;
|
|
let isAnimating = false;
|
|
|
|
function updateCarousel(idx, smooth = true) {
|
|
if (isAnimating || thumbs.length === 0) return;
|
|
|
|
// Infinite loop logic
|
|
if (idx < 0) idx = thumbs.length - 1;
|
|
if (idx >= thumbs.length) idx = 0;
|
|
|
|
// Animate transition
|
|
if (smooth) {
|
|
isAnimating = true;
|
|
mainImg.style.opacity = '0.5';
|
|
}
|
|
|
|
// Update selected thumbnail
|
|
thumbs.forEach(t => t.classList.remove('selected'));
|
|
thumbs[idx].classList.add('selected');
|
|
|
|
// Update main image
|
|
const newSrc = thumbs[idx].querySelector('img').src;
|
|
|
|
if (smooth) {
|
|
setTimeout(() => {
|
|
mainImg.src = newSrc;
|
|
mainImg.style.opacity = '1';
|
|
isAnimating = false;
|
|
}, 150);
|
|
} else {
|
|
mainImg.src = newSrc;
|
|
}
|
|
|
|
current = idx;
|
|
|
|
// Scroll thumbnail into view (centered)
|
|
const thumbContainer = document.querySelector('.carousel-thumbnails');
|
|
if (thumbContainer) {
|
|
const thumbElement = thumbs[idx];
|
|
const containerRect = thumbContainer.getBoundingClientRect();
|
|
const thumbRect = thumbElement.getBoundingClientRect();
|
|
const scrollLeft = thumbElement.offsetLeft - (containerRect.width / 2) + (thumbRect.width / 2);
|
|
thumbContainer.scrollTo({ left: scrollLeft, behavior: 'smooth' });
|
|
}
|
|
}
|
|
|
|
// Arrow click handlers
|
|
if (leftArrow) {
|
|
leftArrow.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
updateCarousel(current - 1);
|
|
});
|
|
}
|
|
|
|
if (rightArrow) {
|
|
rightArrow.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
updateCarousel(current + 1);
|
|
});
|
|
}
|
|
|
|
// Thumbnail click handlers
|
|
thumbs.forEach((thumb, idx) => {
|
|
thumb.addEventListener('click', () => updateCarousel(idx));
|
|
});
|
|
|
|
// Swipe support for touch devices
|
|
let touchStartX = null;
|
|
|
|
carouselMain.addEventListener('touchstart', (e) => {
|
|
touchStartX = e.touches[0].clientX;
|
|
}, { passive: true });
|
|
|
|
carouselMain.addEventListener('touchend', (e) => {
|
|
if (touchStartX === null) return;
|
|
|
|
const endX = e.changedTouches[0].clientX;
|
|
const diffX = endX - touchStartX;
|
|
|
|
// Require minimum swipe distance
|
|
if (Math.abs(diffX) > 50) {
|
|
if (diffX > 0) {
|
|
updateCarousel(current - 1); // Swipe right = previous
|
|
} else {
|
|
updateCarousel(current + 1); // Swipe left = next
|
|
}
|
|
}
|
|
|
|
touchStartX = null;
|
|
}, { passive: true });
|
|
|
|
// Keyboard navigation
|
|
document.addEventListener('keydown', (e) => {
|
|
// Only if carousel is visible in viewport
|
|
const rect = carouselMain.getBoundingClientRect();
|
|
const inViewport = rect.top < window.innerHeight && rect.bottom > 0;
|
|
|
|
if (!inViewport) return;
|
|
|
|
if (e.key === 'ArrowLeft') {
|
|
e.preventDefault();
|
|
updateCarousel(current - 1);
|
|
} else if (e.key === 'ArrowRight') {
|
|
e.preventDefault();
|
|
updateCarousel(current + 1);
|
|
}
|
|
});
|
|
|
|
// Initialize first thumbnail as selected
|
|
updateCarousel(current, false);
|
|
});
|
|
|
|
// --- Sticky Add to Basket Button ---
|
|
(function handleStickyButton() {
|
|
const btn = document.querySelector('.add-to-basket-sticky');
|
|
if (!btn) return;
|
|
|
|
// Store original position after page load
|
|
let originalBottom = null;
|
|
let isInitialized = false;
|
|
|
|
function initPosition() {
|
|
const rect = btn.getBoundingClientRect();
|
|
originalBottom = window.scrollY + rect.bottom;
|
|
isInitialized = true;
|
|
checkSticky();
|
|
}
|
|
|
|
function checkSticky() {
|
|
if (!isInitialized) return;
|
|
|
|
// On tablet/mobile (992px and below), always keep sticky
|
|
if (window.innerWidth <= 992) {
|
|
btn.classList.add('is-sticky');
|
|
return;
|
|
}
|
|
|
|
// On desktop: sticky while user hasn't scrolled past the button's original position
|
|
const viewportBottom = window.scrollY + window.innerHeight;
|
|
|
|
if (viewportBottom < originalBottom) {
|
|
// User hasn't scrolled enough to see the button naturally
|
|
btn.classList.add('is-sticky');
|
|
} else {
|
|
// User has scrolled past where the button would naturally be
|
|
btn.classList.remove('is-sticky');
|
|
}
|
|
}
|
|
|
|
function handleResize() {
|
|
// Recalculate position on resize
|
|
btn.classList.remove('is-sticky');
|
|
setTimeout(() => {
|
|
initPosition();
|
|
}, 100);
|
|
}
|
|
|
|
// Initialize after DOM is ready and images are loaded
|
|
if (document.readyState === 'complete') {
|
|
initPosition();
|
|
} else {
|
|
window.addEventListener('load', initPosition);
|
|
}
|
|
|
|
window.addEventListener('scroll', checkSticky, { passive: true });
|
|
window.addEventListener('resize', handleResize, { passive: true });
|
|
})();
|
|
if (document.querySelector('.product #product-form')) {
|
|
let updatePrice = () => {
|
|
let price = parseFloat(document.querySelector('.product .price').dataset.price);
|
|
|
|
let rrp = document.querySelector('.product .rrp') ?? 0;
|
|
|
|
if (rrp !=0)
|
|
{
|
|
rrp = parseFloat(document.querySelector('.product .rrp').dataset.rrp) ?? 0;
|
|
}
|
|
|
|
document.querySelectorAll('.product #product-form .option').forEach(e => {
|
|
if (e.value) {
|
|
let optionPrice = e.classList.contains('text') || e.classList.contains('datetime') ? e.dataset.price : 0.00;
|
|
optionPrice = e.classList.contains('select') ? e.options[e.selectedIndex].dataset.price : optionPrice;
|
|
optionPrice = (e.classList.contains('radio') || e.classList.contains('checkbox')) && e.checked ? e.dataset.price : optionPrice;
|
|
price = (e.classList.contains('select') ? e.options[e.selectedIndex].dataset.modifier : e.dataset.modifier) == 1 ? price+parseFloat(optionPrice) : price-parseFloat(optionPrice);
|
|
|
|
let optionRRP = e.classList.contains('text') || e.classList.contains('datetime') ? e.dataset.rrp : 0.00;
|
|
optionRRP = e.classList.contains('select') ? e.options[e.selectedIndex].dataset.rrp : optionRRP;
|
|
optionRRP = (e.classList.contains('radio') || e.classList.contains('checkbox')) && e.checked ? e.dataset.rrp : optionRRP;
|
|
rrp = (e.classList.contains('select') ? e.options[e.selectedIndex].dataset.modifier : e.dataset.modifier) == 1 ? rrp+parseFloat(optionRRP) : rrp-parseFloat(optionRRP);
|
|
|
|
}
|
|
});
|
|
document.querySelector('.product .price').innerHTML = currency_code + (price > 0.00 ? price.toFixed(2) : 0.00);
|
|
if (rrp !=0)
|
|
{
|
|
document.querySelector('.product .rrp').innerHTML = currency_code + (rrp > 0.00 ? rrp.toFixed(2) : 0.00);
|
|
}
|
|
};
|
|
document.querySelectorAll('.product #product-form .option').forEach(ele => ele.onchange = () => updatePrice());
|
|
updatePrice();
|
|
|
|
// Add to cart event
|
|
document.querySelector('.product #product-form').addEventListener('submit', function(e) {
|
|
e.preventDefault(); // Prevent immediate submission
|
|
|
|
let productId = document.querySelector('input[name="product[product]"]').value;
|
|
let quantity = parseInt(document.querySelector('input[name="product[quantity]"]').value);
|
|
let productName = document.querySelector('.product .name').textContent;
|
|
let price = parseFloat(document.querySelector('.product .price').dataset.price);
|
|
|
|
window.dataLayer.push({
|
|
'event': 'addToCart',
|
|
'ecommerce': {
|
|
'add': {
|
|
'products': [{
|
|
'id': productId,
|
|
'name': productName,
|
|
'price': price,
|
|
'quantity': quantity
|
|
}]
|
|
}
|
|
},
|
|
'content_type': 'product',
|
|
'content_ids': [productId],
|
|
'content_name': productName,
|
|
'value': price * quantity,
|
|
'currency': 'EUR'
|
|
});
|
|
|
|
// Submit form after a short delay
|
|
setTimeout(() => {
|
|
e.target.submit();
|
|
}, 100);
|
|
});
|
|
}
|
|
if (document.querySelector('.products-form')) {
|
|
let products_form_submit = () => {
|
|
document.querySelector('.products-form')
|
|
if (rewrite_url) {
|
|
window.location.href = encodeURI(base_url + 'products/' + document.querySelector('.category select').value + '/' + document.querySelector('.sortby select').value);
|
|
} else {
|
|
window.location.href = encodeURI(base_url + 'index.php?page=products&category=' + document.querySelector('.category select').value + '&sort=' + document.querySelector('.sortby select').value);
|
|
}
|
|
};
|
|
document.querySelector('.sortby select').onchange = () => products_form_submit();
|
|
document.querySelector('.category select').onchange = () => products_form_submit();
|
|
}
|
|
if (document.querySelector('.cart .ajax-update')) {
|
|
document.querySelectorAll('.cart .ajax-update').forEach(ele => {
|
|
ele.onchange = () => {
|
|
let formEle = document.querySelector('.cart form');
|
|
let formData = new FormData(formEle);
|
|
formData.append('update', 'Update');
|
|
console.log(formData);
|
|
fetch(formEle.action, {
|
|
method: 'POST',
|
|
body: formData
|
|
}).then(response => response.text()).then(html => {
|
|
let doc = (new DOMParser()).parseFromString(html, 'text/html');
|
|
document.querySelector('.total').innerHTML = doc.querySelector('.total').innerHTML;
|
|
document.querySelectorAll('.product-total').forEach((e,i) => {
|
|
e.innerHTML = doc.querySelectorAll('.product-total')[i].innerHTML;
|
|
});
|
|
|
|
// Push cart update event
|
|
window.dataLayer.push({
|
|
'event': 'updateCart'
|
|
});
|
|
});
|
|
};
|
|
});
|
|
}
|
|
const checkoutHandler = () => {
|
|
if (document.querySelector('.checkout .ajax-update')) {
|
|
document.querySelectorAll('.checkout .ajax-update').forEach(ele => {
|
|
ele.onchange = () => {
|
|
let formEle = document.querySelector('.checkout form');
|
|
let formData = new FormData(formEle);
|
|
formData.append('update', 'Update');
|
|
fetch(formEle.action, {
|
|
method: 'POST',
|
|
body: formData
|
|
}).then(response => response.text()).then(html => {
|
|
let doc = (new DOMParser()).parseFromString(html, 'text/html');
|
|
document.querySelector('.summary').innerHTML = doc.querySelector('.summary').innerHTML;
|
|
document.querySelector('.total').innerHTML = doc.querySelector('.total').innerHTML;
|
|
document.querySelector('.discount-code .result').innerHTML = doc.querySelector('.discount-code .result').innerHTML;
|
|
document.querySelector('.shipping-methods-container').innerHTML = doc.querySelector('.shipping-methods-container').innerHTML;
|
|
|
|
// Push checkout update event
|
|
window.dataLayer.push({
|
|
'event': 'checkoutUpdate'
|
|
});
|
|
|
|
checkoutHandler();
|
|
});
|
|
};
|
|
if (ele.name == 'discount_code') {
|
|
ele.onkeydown = event => {
|
|
if (event.key == 'Enter') {
|
|
event.preventDefault();
|
|
ele.onchange();
|
|
}
|
|
};
|
|
}
|
|
});
|
|
}
|
|
};
|
|
checkoutHandler();
|
|
|
|
function openMenu(div){
|
|
let nav_display = document.querySelector(div).style.display;
|
|
document.querySelector(div).style.display = nav_display == 'block' ? 'none' : 'block';
|
|
}
|
|
|
|
function update(id_large, IMG_large, option_id, price){
|
|
let url_id_a = id_large + 'A';
|
|
let url_id_b = id_large + 'B';
|
|
let url_id_c = id_large + 'C';
|
|
|
|
//change picture
|
|
document.getElementById(id_large).src = IMG_large;
|
|
document.getElementById(url_id_a).href = option_id;
|
|
document.getElementById(url_id_b).href = option_id;
|
|
document.getElementById(url_id_c).innerHTML = price;
|
|
}
|
|
|
|
function updateOption(id_large, IMG_large){
|
|
//change picture
|
|
document.getElementById(id_large).src = IMG_large;
|
|
|
|
// Update the first thumbnail to match the new main image
|
|
let firstThumbnail = document.querySelector('.product-img-small img');
|
|
if (firstThumbnail) {
|
|
firstThumbnail.src = IMG_large;
|
|
firstThumbnail.parentElement.classList.add('selected');
|
|
}
|
|
}
|
|
|
|
|
|
// Function to change the title and flag when a language is selected
|
|
function changeLanguage(language, langCode, flagUrl) {
|
|
const title = document.getElementById("title");
|
|
title.src = flagUrl;
|
|
title.alt = language+" Flag";
|
|
}
|
|
|
|
// Enhanced slider functionality for multiple carousels
|
|
function initializeCarousels() {
|
|
// Handle product sliders (highlightedProducts2)
|
|
const productSliders = document.querySelectorAll('.product-slider');
|
|
|
|
productSliders.forEach((slider) => {
|
|
const carouselId = slider.getAttribute('data-carousel');
|
|
const prevBtn = slider.querySelector('.prev-btn');
|
|
const nextBtn = slider.querySelector('.next-btn');
|
|
const productContainer = slider.querySelector('.product-container-slider');
|
|
const products = slider.querySelectorAll('.product-card-slider');
|
|
|
|
if (!products.length) return;
|
|
|
|
let currentIndex = 0;
|
|
const productsPerView = window.innerWidth < 480 ? 1 :
|
|
window.innerWidth < 768 ? 2 :
|
|
window.innerWidth < 992 ? 3 : 4;
|
|
|
|
function updateSliderPosition() {
|
|
const productWidth = products[0].offsetWidth;
|
|
productContainer.style.transform = `translateX(-${currentIndex * productWidth}px)`;
|
|
}
|
|
|
|
prevBtn.addEventListener('click', () => {
|
|
if (currentIndex > 0) {
|
|
currentIndex--;
|
|
updateSliderPosition();
|
|
}
|
|
});
|
|
|
|
nextBtn.addEventListener('click', () => {
|
|
if (currentIndex < products.length - productsPerView) {
|
|
currentIndex++;
|
|
updateSliderPosition();
|
|
}
|
|
});
|
|
|
|
// Update slider on window resize
|
|
window.addEventListener('resize', () => {
|
|
// Reset position when screen size changes
|
|
currentIndex = 0;
|
|
updateSliderPosition();
|
|
});
|
|
});
|
|
|
|
// Handle sample sliders (getSamples)
|
|
const sampleButtons = document.querySelectorAll('.scrollButton');
|
|
|
|
sampleButtons.forEach((button) => {
|
|
const samplesId = button.getAttribute('data-samples');
|
|
if (!samplesId) return;
|
|
|
|
const samplesContainer = document.getElementById('add_samples_container_' + samplesId);
|
|
if (!samplesContainer) return;
|
|
|
|
const isLeftButton = button.id.includes('slideLeft');
|
|
|
|
button.addEventListener('click', () => {
|
|
const scrollAmount = 200; // Adjust as needed
|
|
const currentScroll = samplesContainer.scrollLeft;
|
|
|
|
if (isLeftButton) {
|
|
samplesContainer.scrollTo({
|
|
left: currentScroll - scrollAmount,
|
|
behavior: 'smooth'
|
|
});
|
|
} else {
|
|
samplesContainer.scrollTo({
|
|
left: currentScroll + scrollAmount,
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Only initialize carousels once DOM is loaded
|
|
// (No duplicate or stray HTML allowed)
|