Search code examples
javascriptjquerycookiestimercountdown

"Tick" issue while using cookies to maintain a persistent countdown timer


The following question requires a look into the following external resources:

No, this isn't one of the other "Cookie Timer not working" questions here on SO. ;)

I have crafted a persistent countdown timer that uses cookies to save a particular user's countdown state regardless of browser reloads or reboots. Everything is working great, except for when I use jQuery Countdown's "ticks" to create callbacks…

Actually, the callbacks do work if I let the timer run without reloading the page. But as soon as the page reloads, one of the callbacks doesn't work — and one of them does.

The callback that works regardless is the one that checks for the end of the timer. The one that doesn't work (after reload) is the one that checks for the "halfway" point.

Here's the code…

$(document).ready(function()
{
   if (!Cookies.get('cdTime'))
   {
      var now = $.now(); // First time on page
      var timerSet = 30; // Amout of time (sec)
      var halfway = timerSet / 2;
      Cookies.set('firstTime', now,
      {
         expires: 7,
         path: '/'
      });
      Cookies.set('cdTime', timerSet,
      {
         expires: 7,
         path: '/'
      });
      var runTimer = Cookies.get('cdTime');
   }
   else
   {
      var currentTime = $.now();
      var usedTime = (currentTime - Cookies.get('firstTime')) / 1000; // Calculate and convert to sec
      var runTimer = Cookies.get('cdTime') - usedTime;
   }
   $('#cd').countdown({
      until: runTimer,
      compact: true,
      onExpiry: endCountdown,
      onTick: callBacks,
      layout: '{sn} seconds left...'
   });

   function callBacks(periods)
   {
      if ($.countdown.periodsToSeconds(periods) <= halfway)
      {
         $('#cd').addClass('halfway');
      }
      else if ($.countdown.periodsToSeconds(periods) === 0)
      {
         endCountdown();
      }
   }

   function endCountdown()
   {
      $('#cd').removeClass('halfway').addClass('ended');
      $('#cd').html('&#9829;');
   }
});
body {
    margin: 1em;
    font: 2em/1.4em 'Helvetica Neue', 'Helvetica','Arial', sans-serif;
    color: #333;
}
#cd {
    margin-top: 2em;
   font-family: 'Source Code Pro','Andale Mono',Monaco,'Courier New',monospace;
   font-size: 30px;
    font-weight: 100;
}
.halfway {
    color: #0000ff;
}
.ended {
    color: #ff0000;
   font-size: 125% !important;
   line-height: 0;
}
header, footer
{
   width:66%;
   font-size: 18px;
    line-height: 1.4em;
}
footer
{
   position: absolute;
   bottom: 0;
   margin-bottom: 1.5em;
   font-style: italic;
   color:  #ffa500;
}
.highlight
{
   background: #FFFBCC;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-countdown/2.0.2/jquery.plugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-countdown/2.0.2/jquery.countdown.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.1.3/js.cookie.min.js"></script>
<header>This countdown timer uses <a href="http://keith-wood.name/countdown.html">jQuery Countdown</a>, by Keith Wood, and <a href="https://github.com/js-cookie/js-cookie">JavaScript Cookie</a> to work &#8212; it will continue itsa countdown regardless of browser reloads or reboots (really, try it!). <span class="highlight">Oh, and it works on mobile too</span>.</header>
<div id="cd"></div>
<footer>(Clear the “firstTime” and “cdTime" Cookies and then reload the page to start the timer over.)</footer>

A working example can be found here:

http://codepen.io/ProfessorSamoff/pen/xqXrgx

Watch it through once without reloading the page and then follow the onscreen instructions in order to start the timer again and play around with reloading.

Any ideas about why this might be happening?

Thank you!

Tim


Solution

  • I'm not 100%, but I think halfway is undefined. It only gets sets when the page is loaded for the first time.

    Instead of if ($.countdown.periodsToSeconds(periods) <= halfway) try just if ($.countdown.periodsToSeconds(periods) <= halftime)

    At the top, instead of var timerSet = 30; before the first if statement put totalTime = 30; and also halftime = Math.floor(totalTime / 2)