1class Timer { 2 constructor(element) { 3 this.timerElement = element; 4 this.timezoneInfo = document.querySelector('.timezone-info'); 5 this.init(); 6 } 7 8 init() { 9 const timezoneOffset = parseInt(this.timerElement.dataset.timezone) || 0; 10 const endTimeString = this.timerElement.dataset.endtime; 11 12 this.endTime = this.createDateWithTimezone(endTimeString, timezoneOffset); 13 14 this.animationType = this.timerElement.dataset.animation || 'down'; 15 this.endText = this.timerElement.previousElementSibling.dataset.endtext || 'Time is up!'; 16 17 this.displayTimezoneInfo(timezoneOffset); 18 19 this.daysElement = this.timerElement.querySelector('.days'); 20 this.hoursElement = this.timerElement.querySelector('.hours'); 21 this.minutesElement = this.timerElement.querySelector('.minutes'); 22 this.secondsElement = this.timerElement.querySelector('.seconds'); 23 this.thirdDigitContainer = this.daysElement.querySelector('.third-digit'); 24 25 this.updateTimer(); 26 } 27 28 createDateWithTimezone(dateString, timezoneOffset) { 29 const localDate = new Date(dateString); 30 31 const userTimezoneOffset = localDate.getTimezoneOffset(); 32 33 const targetTimezoneOffset = timezoneOffset * 60; 34 const timezoneDifference = targetTimezoneOffset + userTimezoneOffset; 35 36 const adjustedDate = new Date(localDate.getTime() + timezoneDifference * 60 * 1000); 37 38 return adjustedDate; 39 } 40 41 displayTimezoneInfo(timezoneOffset) { 42 if (!this.timezoneInfo) return; 43 44 const gmtText = timezoneOffset >= 0 ? `GMT+${timezoneOffset}` : `GMT${timezoneOffset}`; 45 46 const localTime = new Date(); 47 const userTimezone = -localTime.getTimezoneOffset() / 60; 48 const userGmtText = userTimezone >= 0 ? `GMT+${userTimezone}` : `GMT${userTimezone}`; 49 50 this.timezoneInfo.textContent = `(Your timezone: ${userGmtText})`; 51 } 52 53 updateDigitGroup(container, newValue, isDays = false) { 54 if (!container) return; 55 56 const digitContainers = Array.from(container.querySelectorAll('.digit-container')).filter((container) => container.style.display !== 'none'); 57 58 const digits = digitContainers.length; 59 const formattedValue = String(newValue).padStart(digits, '0'); 60 61 if (isDays) { 62 const showThirdDigit = newValue > 99; 63 this.thirdDigitContainer.style.display = showThirdDigit ? 'block' : 'none'; 64 65 const updatedContainers = Array.from(container.querySelectorAll('.digit-container')).filter((container) => container.style.display !== 'none'); 66 67 this.updateVisibleDigits(updatedContainers, formattedValue); 68 } else { 69 this.updateVisibleDigits(digitContainers, formattedValue); 70 } 71 } 72 73 updateVisibleDigits(containers, formattedValue) { 74 const valueLength = formattedValue.length; 75 const containersLength = containers.length; 76 77 for (let i = 0; i < containersLength; i++) { 78 const container = containers[i]; 79 const currentDigit = container.querySelector('.digit'); 80 const digitIndex = valueLength - containersLength + i; 81 const newDigitValue = digitIndex >= 0 ? formattedValue[digitIndex] : '0'; 82 83 if (!currentDigit || currentDigit.textContent !== newDigitValue) { 84 this.animateDigit(container, newDigitValue); 85 } 86 } 87 } 88 89 animateDigit(container, newValue) { 90 const currentDigit = container.querySelector('.digit'); 91 if (!currentDigit) return; 92 93 const newDigit = document.createElement('div'); 94 newDigit.className = `digit new ${this.animationType}`; 95 newDigit.textContent = newValue; 96 97 currentDigit.className = `digit old ${this.animationType}`; 98 container.appendChild(newDigit); 99 100 setTimeout(() => { 101 if (currentDigit.parentNode === container) { 102 container.removeChild(currentDigit); 103 newDigit.className = 'digit'; 104 } 105 }, 300); 106 } 107 108 updateTimer() { 109 const now = new Date(); 110 const timeLeft = this.endTime - now; 111 112 if (timeLeft <= 0) { 113 this.timerElement.previousElementSibling.textContent = this.endText; 114 this.timerElement.style.display = 'none'; 115 return; 116 } 117 118 const days = Math.floor(timeLeft / (1000 * 60 * 60 * 24)); 119 const hours = Math.floor((timeLeft % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); 120 const minutes = Math.floor((timeLeft % (1000 * 60 * 60)) / (1000 * 60)); 121 const seconds = Math.floor((timeLeft % (1000 * 60)) / 1000); 122 123 this.updateDigitGroup(this.daysElement, days, true); 124 this.updateDigitGroup(this.hoursElement, hours); 125 this.updateDigitGroup(this.minutesElement, minutes); 126 this.updateDigitGroup(this.secondsElement, seconds); 127 128 setTimeout(() => this.updateTimer(), 1000); 129 } 130} 131 132document.addEventListener('DOMContentLoaded', () => { 133 const timerElement = document.querySelector('.timer'); 134 if (timerElement) { 135 new Timer(timerElement); 136 } 137});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.