lunes, 24 de mayo de 2010

Cuenta regresiva (Countdown) ó tiempo restante (time remaining) con JavaScript + PHP

Tuve la necesidad de incluir un contador regresivo para decirle al usuario en cuánto tiempo se termina su sesión dentro de una aplicación Web. Buscando por la red, me encontré con un script muy bueno que deseo compartir con ustedes.

Este primer ejemplo lo pongo tal cual (copy-paste) lo encontré en la página origen: http://www.yaldex.com/FSDateAndTime/TimeRemaining.htm la cual se basa en la fecha y hora de la computadora cliente. En el segundo ejemplo, viene la integración con PHP.

Muy importante: este código debe estar dentro de la etiqueta < BODY >


<script language="javascript" type="text/javascript">
/* Visit http://www.yaldex.com/ for full source code
and get more free JavaScript, CSS and DHTML scripts! */
<!-- Begin
function getTime() {
now = new Date();
y2k = new Date("Jan 1 2055 14:00:00");
days = (y2k - now) / 1000 / 60 / 60 / 24;
daysRound = Math.floor(days);
hours = (y2k - now) / 1000 / 60 / 60 - (24 * daysRound);
hoursRound = Math.floor(hours);
minutes = (y2k - now) / 1000 /60 - (24 * 60 * daysRound) - (60 * hoursRound);
minutesRound = Math.floor(minutes);
seconds = (y2k - now) / 1000 - (24 * 60 * 60 * daysRound) - (60 * 60 * hoursRound) - (60 * minutesRound);
secondsRound = Math.round(seconds);
sec = (secondsRound == 1) ? " second." : " seconds.";
min = (minutesRound == 1) ? " minute" : " minutes, ";
hr = (hoursRound == 1) ? " hour" : " hours, ";
dy = (daysRound == 1)  ? " day" : " days, "
document.timeForm.input1.value = "Time remaining: " + daysRound  + dy + hoursRound + hr + minutesRound + min + secondsRound + sec;
newtime = window.setTimeout("getTime();", 1000);
}
window.onload=getTime;
//  End -->
</script>
Date:  Jan 1, 2055 2:00:00 p.m.
<form name=timeForm>
<input type=text name=input1 size=70 border-style="none" style="border-bottom: 0px solid; border-left: 0px solid;border-right: 0px solid;border-top: 0px solid;font:14px arial, helvetica,sans-serif">
</form>


En este segundo ejemplo, tomo como referencias las fechas del servidor web de mi aplicación, esto obedece a no tener fallas por tomar la hora de la computadora cliente, que como saben se puede manipular y dar al traste con la funcionalidad esperada del contador regresivo. Este ejemplo está hecho con PHP, pero la lógica es la misma para ASP o JSP.

Muy importante: este código debe estar dentro de la etiqueta < BODY >

<div id="div_session_timeout" class="ui-state-highlight" style="float: left; width: 30%;  font-size: .8em; text-align: center;">
   <script language="javascript" type="text/javascript">
      /* Visit http://www.yaldex.com/ for full source code and get more free JavaScript, CSS and DHTML scripts! */
      var dateStamp = new Date("<?php echo date('D M j Y H:i:s'); ?>"); // Obtener la fecha y hora actual del servidor en este formato: Sun May 23 2010 20:14:11
      var intStamp = Number(dateStamp); // Convertir a timestamp la fecha y hora actual del servidor
      <!-- Begin
      function getTime() {
         now = new Date(intStamp); // Trabajar con el formato timestamp
         // Obtener la fecha y hora en la que deberá terminar la sessión
         // en mi caso, la sesión la tengo establecida a 3600 segundos
         y2k = new Date("<?php echo date('M j Y H:i:s', time() + 3600); ?>");
         days = (y2k - now) / 1000 / 60 / 60 / 24;
         daysRound = Math.floor(days);
         hours = (y2k - now) / 1000 / 60 / 60 - (24 * daysRound);
         hoursRound = Math.floor(hours);
         minutes = (y2k - now) / 1000 /60 - (24 * 60 * daysRound) - (60 * hoursRound);
         minutesRound = Math.floor(minutes);
         seconds = (y2k - now) / 1000 - (24 * 60 * 60 * daysRound) - (60 * 60 * hoursRound) - (60 * minutesRound);
         secondsRound = Math.round(seconds);
         sec = (secondsRound == 1) ? " segundo" : " segundos";
         min = (minutesRound == 1) ? " minuto, " : " minutos, ";
         hr = (hoursRound == 1) ? " hora, " : " horas, ";
         dy = (daysRound == 1)  ? " d\355a, " : " d\355as, "
         //document.timeForm.input1.value = "Time remaining: " + daysRound  + dy + hoursRound + hr + minutesRound + min + secondsRound + sec;
         if (daysRound+hoursRound+minutesRound+secondsRound == '0000'){
            document.getElementById("session_timeout").innerHTML = '<span style="color: red;">La sesi\363n ha expirado.</span><br />' + hoursRound + hr + minutesRound + min + secondsRound + sec;
         } else {
            document.getElementById("session_timeout").innerHTML = "Tiempo restante de esta sesi\363n: <br />" + hoursRound + hr + minutesRound + min + secondsRound + sec;
            newtime = window.setTimeout("getTime();", 1000);
            intStamp = intStamp + 1000; // Para avanzar un segundo en cada iteracion a partir de la fecha y hora actual obtenida desde el servidor
         } // endif
      } // end function
      window.onload=getTime;
      //  End -->
   </script>
   <span id="session_timeout"></span>
</div>

7 comentarios:

  1. copio y pego el codigo y me sale:

    Tiempo restante de esta sesión:
    NaN horas, NaN minutos, NaN segundos

    que estoy haciendo mal????

    ResponderEliminar
    Respuestas
    1. Tienes que guardar el archivo donde pusiste este codigo en formato php ya que si lo guardas como html no te toma los <?php echo date ... que estan escritos.

      Saludos.

      Eliminar
    2. Es correcto tu comentario, este script funciona para páginas dinámicas, que no sean html, pueden ser para asp, php, etc. pues necesitamos interpretar la hora del servidor y NO depender de la hora del cliente (la computadora del usuario que está navegando)

      Eliminar
  2. Muy buen aporte Ultiminio y muchas gracias por compartir, pero tengo una duda ¿como lo puedo hacer para que no refresque el tiempo cada vez que cambie de pagina dentro de la sesión?, ojala me pudieras ayudar con esta duda y nuevamente gracias.

    ResponderEliminar
  3. Hola, muy buen aporte, y por el problema que comentan al inicio hay un error es porque los meses son en ingles, me explico

    Fecha: Jan 1, 2055 2:00:00 p.m.
    donde
    Jan == Enero
    Jun == Junio

    para que funcione y no les vote

    Tiempo restante de esta sesión: NaN horas, NaN minutos, NaN segundos

    ResponderEliminar
    Respuestas
    1. yo tambien tube un problema como ese al obtener una fecha de mi tabla mysql, lo solucione con un array y un explode.

      $mes = array(1=>"Ene", 2=>"Feb", 3=>"Mar", 4=>"Abr", 5=>"May", 6=>"Jun", 7=>"Jul", 8=>"Ago", 9=>"Set", 10=>"Oct", 11=>"Nov", 12=>"Dic");

      //Guarde los datos de la fecha como $datos['fecha']. //probeniente de mi tabla mysql

      //Formateamos la fecha:

      $date = date("y-n-d",strtotime($datos['fecha']));
      $fecha = explode("-",$date); //aqui se guardan "y" "n" "d" comenzando en 0
      $day = $fecha[2];
      $month = $fecha[1];
      $year = $fecha[0];

      //Y la imprimimos:

      echo $day." ".$mes[$month]." de ".$year ; //aqui lo armas como mas te guste

      Impreso quedaria algo asi: "9 Feb de 2015"

      Eliminar
  4. Realmente muy bueno, pero tengo un problema:
    Yo traigo el tiempo de mi base de datos y tengo varios registros y los quiero listar (while) (cada uno con su propio cronometro), pero al aplicar el codigo solo me imprime el cronometro al primer dato de la lista. (todo los demas datos imprime perfecto,solo el cronometro me da problemas).

    ResponderEliminar

Datos personales

Mi foto
Podrás encontrar códigos recursos y artículos sobre PHP, JavaScript, jQuery, MooTools, Ajax, CSS, HTML, UML, RUP, AUP, XP (eXtreme Programming), Six-Sigma, CMMI, FrameWorks, Zend Framework, Magento, CodeIgniter, CakePHP, Joomla 1.5, Doctrine, Active Record, ORM, POO, MVC, MySql, PostgreSql. Este espacio está destinado a ayudar y compartir un poco de lo mucho que he recibido de la comunidad en la Red.