1document.addEventListener('DOMContentLoaded', function () { 2 'use strict'; 3 4 var countdowns = document.querySelectorAll( 5 '.rolling-countdown' 6 ); 7 8 countdowns.forEach(function (countdown) { 9 var targetDateString = countdown.getAttribute( 10 'data-countdown-date' 11 ); 12 13 if (!targetDateString) { 14 return; 15 } 16 17 var targetDate = new Date(targetDateString).getTime(); 18 19 if (Number.isNaN(targetDate)) { 20 console.error( 21 'Neispravan countdown datum:', 22 targetDateString 23 ); 24 25 return; 26 } 27 28 var units = { 29 weeks: countdown.querySelector( 30 '[data-unit="weeks"]' 31 ), 32 days: countdown.querySelector( 33 '[data-unit="days"]' 34 ), 35 hours: countdown.querySelector( 36 '[data-unit="hours"]' 37 ), 38 minutes: countdown.querySelector( 39 '[data-unit="minutes"]' 40 ), 41 seconds: countdown.querySelector( 42 '[data-unit="seconds"]' 43 ) 44 }; 45 46 var previousValues = {}; 47 var interval = null; 48 49 function padNumber(value, minimumLength) { 50 return String(value).padStart(minimumLength, '0'); 51 } 52 53 function createValueElement(value) { 54 var valueElement = document.createElement('span'); 55 56 valueElement.className = 57 'rolling-countdown__digit-value'; 58 59 valueElement.textContent = value; 60 61 return valueElement; 62 } 63 64 function createDigitElement(value) { 65 var digit = document.createElement('span'); 66 var track = document.createElement('span'); 67 68 digit.className = 'rolling-countdown__digit'; 69 track.className = 70 'rolling-countdown__digit-track'; 71 72 track.appendChild(createValueElement(value)); 73 digit.appendChild(track); 74 75 digit.setAttribute('data-value', value); 76 77 return digit; 78 } 79 80 function renderInitialValue(element, value) { 81 if (!element) { 82 return; 83 } 84 85 element.innerHTML = ''; 86 87 value.split('').forEach(function (digitValue) { 88 element.appendChild( 89 createDigitElement(digitValue) 90 ); 91 }); 92 } 93 94 function finishDigitAnimation( 95 digitElement, 96 track, 97 newDigit 98 ) { 99 digitElement.classList.remove('is-animating'); 100 101 track.style.transition = 'none'; 102 track.style.transform = 103 'translate3d(0, 0, 0)'; 104 105 track.innerHTML = ''; 106 track.appendChild(createValueElement(newDigit)); 107 108 digitElement.setAttribute( 109 'data-value', 110 newDigit 111 ); 112 113 /* 114 * Forsira browser da registruje zavrÅ¡no stanje 115 * pre vraÄanja CSS tranzicije. 116 */ 117 void track.offsetHeight; 118 119 track.style.transition = ''; 120 track.style.transform = ''; 121 } 122 123 function animateDigit( 124 digitElement, 125 oldDigit, 126 newDigit 127 ) { 128 if (!digitElement || oldDigit === newDigit) { 129 return; 130 } 131 132 var track = digitElement.querySelector( 133 '.rolling-countdown__digit-track' 134 ); 135 136 if (!track) { 137 return; 138 } 139 140 /* 141 * Prekidamo eventualnu prethodnu animaciju. 142 */ 143 digitElement.classList.remove('is-animating'); 144 145 track.style.transition = 'none'; 146 track.style.transform = 147 'translate3d(0, 0, 0)'; 148 149 track.innerHTML = ''; 150 track.appendChild(createValueElement(oldDigit)); 151 track.appendChild(createValueElement(newDigit)); 152 153 /* 154 * Browser mora prvo da iscrta poÄetno stanje, 155 * pa tek onda pokreÄemo tranziciju. 156 */ 157 void track.offsetHeight; 158 159 track.style.transition = ''; 160 track.style.transform = ''; 161 162 var animationFinished = false;
163 164 function handleTransitionEnd(event) { 165 if ( 166 event.target !== track || 167 event.propertyName !== 'transform' || 168 animationFinished 169 ) { 170 return; 171 } 172 173 animationFinished = true; 174 175 track.removeEventListener( 176 'transitionend', 177 handleTransitionEnd 178 ); 179 180 finishDigitAnimation( 181 digitElement, 182 track, 183 newDigit 184 ); 185 } 186 187 track.addEventListener( 188 'transitionend', 189 handleTransitionEnd 190 ); 191 192 requestAnimationFrame(function () { 193 requestAnimationFrame(function () { 194 digitElement.classList.add( 195 'is-animating' 196 ); 197 }); 198 }); 199 200 /* 201 * Rezervni zavrÅ¡etak u sluÄaju da transitionend 202 * ne bude aktiviran zbog promene taba ili browsera. 203 */ 204 window.setTimeout(function () { 205 if (animationFinished) { 206 return; 207 } 208 209 animationFinished = true; 210 211 track.removeEventListener( 212 'transitionend', 213 handleTransitionEnd 214 ); 215 216 finishDigitAnimation( 217 digitElement, 218 track, 219 newDigit 220 ); 221 }, 500); 222 } 223 224 function animateValue(element, oldValue, newValue) { 225 if (!element) { 226 return; 227 } 228 229 if ( 230 oldValue === undefined || 231 oldValue.length !== newValue.length 232 ) { 233 renderInitialValue(element, newValue); 234 return; 235 } 236 237 var digitElements = element.querySelectorAll( 238 '.rolling-countdown__digit' 239 ); 240 241 newValue.split('').forEach(function ( 242 newDigit, 243 index 244 ) { 245 var oldDigit = oldValue.charAt(index); 246 var digitElement = digitElements[index]; 247 248 animateDigit( 249 digitElement, 250 oldDigit, 251 newDigit 252 ); 253 }); 254 } 255 256 function updateUnit( 257 unitName, 258 value, 259 minimumLength 260 ) { 261 var formattedValue = padNumber( 262 value, 263 minimumLength 264 ); 265 266 var previousValue = previousValues[unitName]; 267 268 animateValue( 269 units[unitName], 270 previousValue, 271 formattedValue 272 ); 273 274 previousValues[unitName] = formattedValue; 275 } 276 277 function updateCountdown() { 278 var now = Date.now(); 279 var distance = Math.max( 280 0, 281 targetDate - now 282 ); 283 284 var totalSeconds = Math.floor( 285 distance / 1000 286 ); 287 288 var weeks = Math.floor( 289 totalSeconds / 604800 290 ); 291 292 var days = Math.floor( 293 (totalSeconds % 604800) / 86400 294 ); 295 296 var hours = Math.floor( 297 (totalSeconds % 86400) / 3600 298 ); 299 300 var minutes = Math.floor( 301 (totalSeconds % 3600) / 60 302 ); 303 304 var seconds = totalSeconds % 60; 305 306 updateUnit('weeks', weeks, 2); 307 updateUnit('days', days, 2); 308 updateUnit('hours', hours, 2); 309 updateUnit('minutes', minutes, 2); 310 updateUnit('seconds', seconds, 2); 311 312 if (distance <= 0) { 313 countdown.classList.add('is-finished'); 314 315 if (interval) { 316 window.clearInterval(interval); 317 } 318 } 319 } 320 321 updateCountdown(); 322 323 interval = window.setInterval( 324 updateCountdown, 325 1000 326 ); 327 328 /* 329 * Kada se korisnik vrati na tab, countdown se odmah 330 * sinhronizuje sa stvarnim vremenom. 331 */ 332 document.addEventListener( 333 'visibilitychange', 334 function () { 335 if (!document.hidden) { 336 updateCountdown(); 337 } 338 } 339 ); 340 }); 341});
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.