简体   繁体   中英

setTimeout of a forEach loop with datetime countdown?

I'm trying to create a script that loops through an array of html elements, and creates a countdown for each of them, using a setTimeout . I don't really know why this does not work, but here is my code, and the console.log it gives me. Console log >

-1481055605166  testing.html:61:5
End  testing.html:64:5
days-> -17142-hours->-21-minutes->-21-second->-6  testing.html:75:5
NaN  testing.html:61:5
days-> NaN-hours->NaN-minutes->NaN-second->NaN  testing.html:75:5
NaN  testing.html:61:5
days-> NaN-hours->NaN-minutes->NaN-second->NaN*

Here is the code >

  var productos = document.querySelectorAll(".producto.med"); function recorrido() { productos.forEach(function(item) { var hora = item.querySelector("#hasta"); cdtd(hora); }); } var timer = setTimeout(recorrido, 2000); function cdtd(dia) { var xmas = new Date(dia); var now = new Date(); var timeDiff = xmas.getTime() - now.getTime(); console.log(timeDiff); if (timeDiff <= 0) { clearTimeout(timer); console.log("End"); // Run any code needed for countdown completion here } var seconds = Math.floor(timeDiff / 1000); var minutes = Math.floor(seconds / 60); var hours = Math.floor(minutes / 60); var days = Math.floor(hours / 24); hours %= 24; minutes %= 60; seconds %= 60; var total = 'days-> ' + days + '-hours->' + hours + '-minutes->' + minutes + '-second->' + seconds; console.log(total); } 
 <article class="producto med" id='{{$producto->id}}'> <h4>uno</h4> <div class="img-producto"> <img src="{{$producto->ruta_imagen}}" alt="producto"> </div> <div class="datos-producto"> <ul class="tiempo"> <li>desde: <span>{{$producto->fecha_inicio}}</span> </li> <li>hasta: <span id="hasta1">2016-12-12 15:45:00</span> </li> </ul> <p class="restante">tiempo restante:</p> <p class="tiempo">12hs 43m 03s</p>//JS PARA COUNTDOWNL </div> <a href="" class="ofertar">Ofertar ahora</a> </article> <article class="producto med" id='{{$producto->id}}'> <h4>dos</h4> <div class="img-producto"> <img src="{{$producto->ruta_imagen}}" alt="producto"> </div> <div class="datos-producto"> <ul class="tiempo"> <li>desde: <span>{{$producto->fecha_inicio}}</span> </li> <li>hasta: <span id="hasta">2017-12-12 15:45:00</span> </li> </ul> <p class="restante">tiempo restante:</p> <p class="tiempo">12hs 43m 03s</p>//JS PARA COUNTDOWNL </div> <a href="" class="ofertar">Ofertar ahora</a> </article> <article class="producto med" id='{{$producto->id}}'> <h4>tres</h4> <div class="img-producto"> <img src="{{$producto->ruta_imagen}}" alt="producto"> </div> <div class="datos-producto"> <ul class="tiempo"> <li>desde: <span>{{$producto->fecha_inicio}}</span> </li> <li>hasta: <span id="hasta">2016-12-12 15:45:00</span> </li> </ul> <p class="restante">tiempo restante:</p> <p class="tiempo">12hs 43m 03s</p>//JS PARA COUNTDOWNL </div> <a href="" class="ofertar">Ofertar ahora</a> </article> 

  1. The first product has a "hasta1" for id value. This should be " hasta "

  2. HTML elements should have unique ids.
    This can be achieved by

a) Using "data-id" attributes instead of "id" attributes, changing all

    <span id="hasta">

into

    <span data-id="hasta">

b) Make the selector find these elements by changing

       var hora = item.querySelector("#hasta");

to

       var hora = item.querySelector("[data-id=hasta]");
  1. The Nan values indicate the data value used for Date is invalid: this is because an HTMLSpan element is being passed to cdtd , not a string. One way to fix this is to add a statement at the beginning of cdtd

      function cdtd(dia) { // get text before creating date dia = dia.textContent || dia.innerText; var xmas = new Date(dia); // ... and continue 
  2. Changing setTimeout to setInterval , as in

     var timer = setInterval(recorrido, 2000); 

should repeatedly call recorrido until the timer is stopped in cdtd (not tested). Stopping the timer can use clearInterval for clarity, although calling clearTimeout does the same thing as clearInterval .


Update: Warning: avoid using class selectors to find elements if the class name is also used for styling. Use of data attributes provide an alternative.

In this example, both <ul class="tiempo"> and <p class="tiempo"> match a selector for .tiempo . If elements with this class name have their content set to show the time remaining, the list element will be updated first and destroy the child element with the data-id="hasta" attribute. This produces a dia value of null .

It appears you are looking for something listed in the page: http://www.htmlgoodies.com/html5/javascript/calculating-the-difference-between-two-dates-in-javascript.html#fbid=S_-Ojf9buFk

As long as you can calculate the number of milliseconds in an interval, you can come up with a number by dividing the total number of milliseconds by the number of milliseconds in the desired interval. What's more, we can apply the modulus (%) operator to strip out that value to determine the next larger interval. The key is to always go from the smallest interval - milliseconds - to the largest - days:

Date.daysBetween = function( date1, date2 ) {
  //Get 1 day in milliseconds
  var one_day=1000*60*60*24;

  // Convert both dates to milliseconds
  var date1_ms = date1.getTime();
  var date2_ms = date2.getTime();

  // Calculate the difference in milliseconds
  var difference_ms = date2_ms - date1_ms;
  //take out milliseconds
  difference_ms = difference_ms/1000;
  var seconds = Math.floor(difference_ms % 60);
  difference_ms = difference_ms/60; 
  var minutes = Math.floor(difference_ms % 60);
  difference_ms = difference_ms/60; 
  var hours = Math.floor(difference_ms % 24);  
  var days = Math.floor(difference_ms/24);

  return days + ' days, ' + hours + ' hours, ' + minutes + ' minutes, and ' + seconds + ' seconds';
}

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