简体   繁体   中英

Display of Multiple JavaScript Countdowns

I found a way to display multiple countdowns, using javascript. Having multiple countdown timer events intervals in javascript

I am trying to create a "warmer" display, in a grid. I opted for an HTML table. I have a draft here

I can't get the countdowns to display in the table cells, with separated time components. I just have the entire SPAN tag in the "Days" column.

I'd take a different approach. First of all, instead of creating the table in your HTML, I would store the data about the countdown timers in an array of objects in your JavaScript code and generate the table using JS. Doing this will make it cleaner and more maintainable; to add new items you can just add an object to the array instead of mucking about with HTML.

Secondly, instead of starting an interval for each timer, I would create a single interval that updates all of the timers. Using a single interval means your DOM updates will be batched together and will minimize page reflow .

This code also recalculates the time left each time it updates. If you calculate it once and then just subtract each round, it could introduce drift into your counter. This is because setInterval only guarantees that it will wait at least as many milliseconds as you specify in the delay parameter, it could be more . It probably wouldn't matter much unless your timer was running continuously for a very long time, but over time it would be come inaccurate.

 // data is an array of objects, each representing one of your categories. // Each category has a .title to store its title and a .counters that // stores an object for each counter in that category. var data = [ { title: 'ASTRONOMY', counters: [ // Each counter has a .title and a .date that is parsed by new Date() { title: 'Total Solar Eclipse - (NE US)', date: 'August 21, 2017' }, { title: 'Next Supermoon - Full', date: 'December 3, 2017' } ] }, { title: 'POLITICS', counters: [ { title: 'Next Presidential Election', date: 'November 3, 2020' } ] }, { title: 'TEST', counters: [ { title: '30 seconds from page load', date: (new Date()).getTime() + (30 * 1000) }, { title: 'Unix Epoch', date: 'January 1, 1970' } ] } ]; // this reduce generates the table let table = data.reduce((acc, category, categoryIndex) => { return acc + `<tr><td colspan="6" class="category">${category.title}</td></tr>` + category.counters.reduce((acc, counter, index) => { return acc + `<tr id="counter-${categoryIndex}-${index}"> <td>${counter.title}</td> <td>${counter.date}</td> <td class="days"></td> <td class="hours"></td> <td class="minutes"></td> <td class="seconds"></td> </tr>`; }, ''); }, '<table class="countdown"><tr><th>Event</th><th>Date</th><th>Days</th><th>Hours</th><th>Minutes</th><th>Seconds</th></tr>'); table += '</table>'; // insert the table after the noscript tag document.getElementById('countdown').insertAdjacentHTML('afterend', table); // generate a flat list of counters let counters = data.reduce((acc, category, categoryIndex) => { return acc.concat(category.counters.reduce((counterAcc, counter, index) => { return counterAcc.concat([{ // counters will be an array of the objects we generate here. // node contains a reference to the tr element for this counter node: document.getElementById(`counter-${categoryIndex}-${index}`), // date is the date for this counter parsed by Date and then converted // into a timestamp date: (new Date(counter.date)).getTime() }]); }, [])); }, []); const msSecond = 1000, msMinute = msSecond * 60, msHour = msMinute * 60, msDay = msHour * 24; let intervalId; function updateCounters () { counters.forEach((counter, counterIndex) => { let remaining = counter.date - Date.now(), node = counter.node; let setText = (selector, text) => node.querySelector(selector).textContent = text; if (remaining > 0) { setText('.days', Math.floor(remaining / msDay)); remaining %= msDay; setText('.hours', Math.floor(remaining / msHour)); remaining %= msHour; setText('.minutes', Math.floor(remaining / msMinute)); remaining %= msMinute; setText('.seconds', Math.floor(remaining / msSecond)); } else { // make sure we don't accidentally display negative numbers if a timer // firing late returns a past timestamp (or the data contains a past date) setText('.days', 0); setText('.hours', 0); setText('.minutes', 0); setText('.seconds', 0); // This countdown has reached 0 seconds, stop updating it. counters.splice(counterIndex, 1); // no more counters? Stop the timer if (counters.length === 0) { clearInterval(intervalId); } } }); } // display counters right away without waiting a second updateCounters(); intervalId = setInterval(updateCounters, 1000); 
  table { border-collapse: collapse; } tr:nth-child(even) { background-color: #edf; } .category { font-weight: bold; } td, th { padding: .5em; } .days, .hours, .minutes, .seconds { text-align: right; } 
  <noscript id="countdown">Sorry, you need JavaScript enabled to view the count downs</noscript> 

More Reading

If you are ok to use any javascript library why not check FlipClock.js out.

As per the text provided on their site, the following are the logical requirements that were considered when creating the API.

  • Use as a clock
  • Use as a timer
  • Use as a countdown
  • Themeable using pure CSS
  • Clean & Dry Syntax
  • Abstract everything into reusable objects
  • Full-Featured Developer API to create custom “Clock Faces”

And if you are not ok to use any library here is what you can learn from about how to create a countdown timer using javascript

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM