|
@@ -754,7 +754,7 @@ $fmtDate = function ($v) {
|
|
|
countdownEls.forEach(countdownEl => createCountdown(countdownEl))
|
|
countdownEls.forEach(countdownEl => createCountdown(countdownEl))
|
|
|
|
|
|
|
|
function createCountdown(countdownEl) {
|
|
function createCountdown(countdownEl) {
|
|
|
- const target = new Date(countdownEl.dataset.targetDate);
|
|
|
|
|
|
|
+ const target = new Date((countdownEl.dataset.targetDate || '').trim());
|
|
|
const parts = {
|
|
const parts = {
|
|
|
days: {
|
|
days: {
|
|
|
text: ["days", "day"],
|
|
text: ["days", "day"],
|
|
@@ -799,40 +799,42 @@ $fmtDate = function ($v) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function getRemainingTime(target, parts, first = true) {
|
|
function getRemainingTime(target, parts, first = true) {
|
|
|
- const now = new Date()
|
|
|
|
|
- if (first) console.log({
|
|
|
|
|
- target,
|
|
|
|
|
- now
|
|
|
|
|
- })
|
|
|
|
|
- const remaining = {}
|
|
|
|
|
- let seconds = Math.floor((target - (now)) / 1000);
|
|
|
|
|
|
|
+ const now = new Date();
|
|
|
|
|
+ const diff = target - now;
|
|
|
|
|
+
|
|
|
|
|
+ // Past or invalid date — freeze at all zeros
|
|
|
|
|
+ if (isNaN(diff) || diff <= 0) {
|
|
|
|
|
+ Object.entries(parts).forEach(([key, value]) => {
|
|
|
|
|
+ value.element.querySelector(".number").innerText = 0;
|
|
|
|
|
+ value.element.querySelector(".text").innerText = value.text[0];
|
|
|
|
|
+ value.element.querySelectorAll(".dot").forEach(dot => {
|
|
|
|
|
+ dot.dataset.active = false;
|
|
|
|
|
+ dot.dataset.lastactive = false;
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let seconds = Math.floor(diff / 1000);
|
|
|
let minutes = Math.floor(seconds / 60);
|
|
let minutes = Math.floor(seconds / 60);
|
|
|
- let hours = Math.floor(minutes / 60);
|
|
|
|
|
- let days = Math.floor(hours / 24);
|
|
|
|
|
- hours = hours - (days * 24);
|
|
|
|
|
- minutes = minutes - (days * 24 * 60) - (hours * 60);
|
|
|
|
|
|
|
+ let hours = Math.floor(minutes / 60);
|
|
|
|
|
+ let days = Math.floor(hours / 24);
|
|
|
|
|
+ hours = hours - (days * 24);
|
|
|
|
|
+ minutes = minutes - (days * 24 * 60) - (hours * 60);
|
|
|
seconds = seconds - (days * 24 * 60 * 60) - (hours * 60 * 60) - (minutes * 60);
|
|
seconds = seconds - (days * 24 * 60 * 60) - (hours * 60 * 60) - (minutes * 60);
|
|
|
- Object.entries({
|
|
|
|
|
- days,
|
|
|
|
|
- hours,
|
|
|
|
|
- minutes,
|
|
|
|
|
- seconds
|
|
|
|
|
- }).forEach(([key, value]) => {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ Object.entries({ days, hours, minutes, seconds }).forEach(([key, value]) => {
|
|
|
const remaining = parts[key].element.querySelector(".number");
|
|
const remaining = parts[key].element.querySelector(".number");
|
|
|
- const text = parts[key].element.querySelector(".text");
|
|
|
|
|
|
|
+ const text = parts[key].element.querySelector(".text");
|
|
|
remaining.innerText = value;
|
|
remaining.innerText = value;
|
|
|
- text.innerText = parts[key].text[Number(value == 1)]
|
|
|
|
|
- const dots = parts[key].element.querySelectorAll(".dot")
|
|
|
|
|
- dots.forEach((dot, idx) => {
|
|
|
|
|
- dot.dataset.active = idx <= value;
|
|
|
|
|
- dot.dataset.lastactive = idx == value;
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- if (now <= target) {
|
|
|
|
|
- window.requestAnimationFrame(() => {
|
|
|
|
|
- getRemainingTime(target, parts, false)
|
|
|
|
|
|
|
+ text.innerText = parts[key].text[Number(value === 1)];
|
|
|
|
|
+ parts[key].element.querySelectorAll(".dot").forEach((dot, idx) => {
|
|
|
|
|
+ dot.dataset.active = idx <= value;
|
|
|
|
|
+ dot.dataset.lastactive = idx === value;
|
|
|
});
|
|
});
|
|
|
- }
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ window.requestAnimationFrame(() => getRemainingTime(target, parts, false));
|
|
|
}
|
|
}
|
|
|
document.getElementById('tryParse')?.addEventListener('click', function(e) {
|
|
document.getElementById('tryParse')?.addEventListener('click', function(e) {
|
|
|
e.preventDefault();
|
|
e.preventDefault();
|