first commit
This commit is contained in:
117
views/js/front.js
Normal file
117
views/js/front.js
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Product Discount Countdown Module
|
||||
*
|
||||
* This script initializes countdown timers on the product page.
|
||||
* It handles the initial page load and the dynamic updates that occur
|
||||
* when a customer changes a product combination (attribute).
|
||||
*/
|
||||
|
||||
// A global array to keep track of our active timer intervals.
|
||||
// This is crucial for cleanup when the product block is updated via AJAX.
|
||||
let productCountdownIntervals = [];
|
||||
|
||||
/**
|
||||
* Scans the DOM for countdown containers and initializes them.
|
||||
* This function is designed to be called on page load and after AJAX updates.
|
||||
*/
|
||||
function initializeProductCountdowns() {
|
||||
// 1. Clear any previously running timers.
|
||||
// This prevents multiple timers from running after a product combination change.
|
||||
productCountdownIntervals.forEach(intervalId => clearInterval(intervalId));
|
||||
productCountdownIntervals = [];
|
||||
|
||||
// 2. Find all countdown containers on the page that need to be processed.
|
||||
const countdownContainers = document.querySelectorAll('.product-countdown-container');
|
||||
|
||||
countdownContainers.forEach(container => {
|
||||
// Check if this specific container has already been initialized to avoid race conditions.
|
||||
if (container.dataset.initialized === 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
const timerElement = container.querySelector('.countdown-timer');
|
||||
if (!timerElement) return;
|
||||
|
||||
// Mark as initialized
|
||||
container.dataset.initialized = 'true';
|
||||
|
||||
const targetTimestamp = parseInt(container.dataset.timestamp, 10);
|
||||
const onExpireAction = container.dataset.onExpire;
|
||||
const expiredText = container.dataset.expiredText;
|
||||
|
||||
// Get translated units from hidden spans
|
||||
const units = {
|
||||
day: container.querySelector('[data-unit="day"]').textContent,
|
||||
days: container.querySelector('[data-unit="days"]').textContent,
|
||||
hr: container.querySelector('[data-unit="hr"]').textContent,
|
||||
min: container.querySelector('[data-unit="min"]').textContent,
|
||||
sec: container.querySelector('[data-unit="sec"]').textContent
|
||||
};
|
||||
|
||||
function updateTimer() {
|
||||
const now = Math.floor(new Date().getTime() / 1000);
|
||||
const diff = targetTimestamp - now;
|
||||
|
||||
if (diff <= 0) {
|
||||
clearInterval(interval);
|
||||
handleExpiry();
|
||||
return;
|
||||
}
|
||||
|
||||
const d = Math.floor(diff / (60 * 60 * 24));
|
||||
const h = Math.floor((diff % (60 * 60 * 24)) / (60 * 60));
|
||||
const m = Math.floor((diff % (60 * 60)) / 60);
|
||||
const s = Math.floor(diff % 60);
|
||||
|
||||
const parts = [];
|
||||
if (d > 0) {
|
||||
parts.push(`${d} ${d > 1 ? units.days : units.day}`);
|
||||
}
|
||||
// Always show hours, minutes, and seconds for a better countdown experience
|
||||
parts.push(`${String(h).padStart(2, '0')}${units.hr}`);
|
||||
parts.push(`${String(m).padStart(2, '0')}${units.min}`);
|
||||
parts.push(`${String(s).padStart(2, '0')}${units.sec}`);
|
||||
|
||||
timerElement.textContent = parts.join(' ');
|
||||
}
|
||||
|
||||
function handleExpiry() {
|
||||
switch (onExpireAction) {
|
||||
case 'reload':
|
||||
location.reload();
|
||||
break;
|
||||
case 'message':
|
||||
container.querySelector('.countdown-wrapper').innerHTML = `<span class="badge badge-secondary">${expiredText}</span>`;
|
||||
break;
|
||||
case 'hide':
|
||||
default:
|
||||
container.style.display = 'none';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const interval = setInterval(updateTimer, 1000);
|
||||
// Add the new interval ID to our global array for tracking.
|
||||
productCountdownIntervals.push(interval);
|
||||
updateTimer(); // Initial call to display the timer immediately
|
||||
});
|
||||
}
|
||||
|
||||
// --- Event Listeners ---
|
||||
|
||||
// 1. Run the initializer on the initial page load.
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initializeProductCountdowns();
|
||||
});
|
||||
|
||||
// 2. Run the initializer whenever PrestaShop updates the product block via AJAX.
|
||||
// The `prestashop` object is globally available in modern themes.
|
||||
if (typeof prestashop !== 'undefined') {
|
||||
prestashop.on('updateProduct', (data) => {
|
||||
// We use a small timeout to ensure the DOM has been fully updated by PrestaShop's scripts
|
||||
// before our script runs and looks for the new container. 100ms is usually safe.
|
||||
setTimeout(() => {
|
||||
initializeProductCountdowns();
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user