最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Multiple countdown timers on one page - Stack Overflow

programmeradmin2浏览0评论

Currently working on a project that requires two timers on one page. The timers need to have a start button and both have different timings (i.e. timer1 lasts 10 secs and timer2 lasts 20). Here's the script I'm using, but I don't know how to duplicate the timer and let each timer work independently.

Is there anyone who can easily change this script to a functioning one for two timers?

<html>
<head>
<script language="JavaScript" type="text/javascript">
    var interval;
    var minutes = 0;
    var seconds = 10;

    function countdown(element) {
        interval = setInterval(function(timer) {
            var el = document.getElementById(element);
            if(seconds == 0) {
                if(minutes == 0) {
                    (el.innerHTML = "STOP!");     

                    clearInterval(interval);
                    return;
                } else {
                    minutes--;
                    seconds = 60;
                }
            }
            if(minutes > 0) {
                var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
            } else {
                var minute_text = '';
            }
            var second_text = seconds > 1 ? '' : '';
            el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + '';
            seconds--;
        }, 1000);
    }
var start = document.getElementById('start');

start.onclick = function(timer) {
    if (!interval) {
        countdown('countdown');
    }
}

</script>
</head>

<body>
<div id='countdown'></div>
<input type="button" onclick="countdown('countdown');this.disabled = true;" value="Start" />
</body>
</html>

Currently working on a project that requires two timers on one page. The timers need to have a start button and both have different timings (i.e. timer1 lasts 10 secs and timer2 lasts 20). Here's the script I'm using, but I don't know how to duplicate the timer and let each timer work independently.

Is there anyone who can easily change this script to a functioning one for two timers?

<html>
<head>
<script language="JavaScript" type="text/javascript">
    var interval;
    var minutes = 0;
    var seconds = 10;

    function countdown(element) {
        interval = setInterval(function(timer) {
            var el = document.getElementById(element);
            if(seconds == 0) {
                if(minutes == 0) {
                    (el.innerHTML = "STOP!");     

                    clearInterval(interval);
                    return;
                } else {
                    minutes--;
                    seconds = 60;
                }
            }
            if(minutes > 0) {
                var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
            } else {
                var minute_text = '';
            }
            var second_text = seconds > 1 ? '' : '';
            el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + '';
            seconds--;
        }, 1000);
    }
var start = document.getElementById('start');

start.onclick = function(timer) {
    if (!interval) {
        countdown('countdown');
    }
}

</script>
</head>

<body>
<div id='countdown'></div>
<input type="button" onclick="countdown('countdown');this.disabled = true;" value="Start" />
</body>
</html>
Share Improve this question asked Apr 1, 2014 at 20:51 user3486844user3486844 611 gold badge1 silver badge2 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 10

There are few things you're doing that prevent you from expanding the code. If you want a reusable timer, you can't hard set the variables it will use. So first thing is to get rid of the three variables at the top and recreate them WITHIN the scope of the function.

That way, every time the function is called, a new set of variables is created for its execution.

The minutes and seconds are probably best passed as parameters and interval should be defined within the scope of function.

Secondly you are setting the click handler BOTH inline and within the script. Get rid of one of them (preferably get rid of the inline version).

Then, you have a timer variable as a parameter for the click handler and setInterval but never used. That variable will be set to the click event on the event handler (and again, is not being used) and will be undefined on setInterval. So they really shouldn't be there.

A performance issue, you may want to know about is that you are doing a DOM lookup for the counters EVERY second. You should get it once per function call at the beginning and cache it.

At that point, you function would look more or less like this

function countdown(element, minutes, seconds) {
    // Fetch the display element
    var el = document.getElementById(element);

    // Set the timer
    var interval = setInterval(function() {
        if(seconds == 0) {
            if(minutes == 0) {
                (el.innerHTML = "STOP!");     

                clearInterval(interval);
                return;
            } else {
                minutes--;
                seconds = 60;
            }
        }

        if(minutes > 0) {
            var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
        } else {
            var minute_text = '';
        }

        var second_text = seconds > 1 ? '' : '';
        el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + '';
        seconds--;
    }, 1000);
}

And your setup more or less like this

//Start as many timers as you want

var start1 = document.getElementById('timer1');
var start2 = document.getElementById('timer2');

start1.onclick = function() {
    countdown('countdown1', 0, 15);
}

start2.onclick = function() {
    countdown('countdown2', 0, 10);
}

Of course, you need the extra button and counter

<div id='countdown1'></div>
<div id='countdown2'></div>
<input id="timer1" type="button" value="Start timer 1" />
<input id="timer2" type="button" value="Start timer 2" />

Working example: http://codepen.io/anon/pen/Jmpcq/?editors=101

-- Note: for precise timers, setInterval() may not be a good option because the precise interval is not guaranteed and time tracked by it may be delayed after a while. For applications where precise time is critical, there are other methods (e.g. https://sitepoint.com/creating-accurate-timers-in-javascript & https://html5rocks.com/en/tutorials/webperformance/usertimin), thanks @KaiKarver for pointing out in the comments.

Long but it works

let d = document,
    id = 'getElementById',
    time = {
//Multiple Timers
//[current time, time setting, (pause/running), HTML section#timer]
      timer1: ['0:10', '0:10', 0, d[id]('timer1')],
      timer2: ['2:30', '2:30', 0, d[id]('timer2')],
      timer3: ['5:00', '5:00', 0, d[id]('timer3')],


//Manage Timer Functions
      reset: function(t) {time[t][0] = time[t][1];},
      pause: function(t) {time[t][2] = 0;time.state(t,'pause');time.button(t,'resume');},
      resume: function(t) {time[t][2] = 1;time.state(t,'running');time.button(t,'pause');},
      set: function(t,s) {time[t][0] = s; time[t][1] = s;},
      state: function(t,s) {time[t][3].setAttribute('state',s);},
      button: function(t,s) {time[t][3].querySelector('div').innerHTML = s;},
      cancel: function(t) {time[t][2] = 0;time.reset(t);time.state(t,'');time.button(t,'start');time.setTimer(t);},
      start: function(t) {time.reset(t);time[t][2] = 1;time.state(t,'running');time.button(t,'pause');},
      getTimers: function() {return Object.keys(time).filter(function (n) {return n.indexOf("ti")==0;});},
      setTimer: function(t) {time[t][3].querySelector('span').innerHTML = time[t][0]},
      setTimers: function(x) {
        let times = time.getTimers();
        for (var i=0,t;i<times.length;i++) {t=times[i];
              if(time[t][2]||x){time[t][3].querySelector('span').innerHTML = time[t][0]}
        }
  },
};

//handle seconds passed
function convertSeconds(s=0) {return new Date(s*1000).toISOString().substr(11,8).replace(/^(00:0(?=[1-9])|00:|0)/gm, '')}
function toSeconds(t) {t=t.split(':').reverse();return (t[2]*3600||0)+(t[1]*60||0)+t[0]*1||0;}

//set HTML times onLoad
time.setTimers(1)


function runTimer(times){times = time.getTimers();time.setTimers();
    function run(t,s,l){if(t&&t[2]){s=toSeconds(t[0]);t[0]=s?convertSeconds(s-1):'00:00'&&(time.cancel(l));}}
    for (var i=0,t;i<times.length;i++) {run(time[times[i]],'',times[i])}
}

//run timer every second reguardless of whether timer is paused or running
setInterval(runTimer, 1000)
body {
  background: #e6e9f0;
  user-select: none;
  font-family: "SF Pro Display", Helvetica Neue, Arial, Helvetica, Geneva, sans-serif;
  font-size: 14px;
}
div, span {display: inline-block;}
span {min-width: 60px;}
#time > section {
  padding: 10px 20px;
  background: white;
  margin: 10px;
  border-radius: 4px;
  transition: .15s ease-in-out 0s;
  text-transform: capitalize;
}
#time > section:hover {box-shadow: 0px 0px 0px 2px #A8D1FD;}
#time > section > div{text-shadow: 0 1px 1px rgba(0,0,0,0.3);transition: .1s ease-in-out 0s;}
#time > section > div:nth-of-type(2){background: #cfd3dd;opacity: 1;}
#time > section[state=""] > div:nth-of-type(2) {opacity: 0;}
#time > section > div{
  background: #368ad2;
  color: white;
  padding: 6px 10px;
  margin: 0 5px;
  min-width: 50px;
  text-align: center;
  border-radius: 4px;
}
<section id="time">
  <section id="timer1" state="">
    <span>0:00</span>
    <div onClick="time[this.innerHTML]('timer1')">start</div>
    <div onClick="time.cancel('timer1')">cancel</div>
  </section>
  <section id="timer2" state="">
    <span>0:00</span>
    <div onClick="time[this.innerHTML]('timer2')">start</div>
    <div onClick="time.cancel('timer2')">cancel</div>
  </section>
  <section id="timer3" state="">
    <span>0:00</span>
    <div onClick="time[this.innerHTML]('timer3')">start</div>
    <div onClick="time.cancel('timer3')">cancel</div>
  </section>
</section>

var interval;

var countdown1 = {
    minutes:0,
    seconds: 10
};

var countdown2 = {
    minutes:0,
    seconds: 2
}

function countdown(element) {
    alert(element);
    var cd;
    element === 'countdown1' ? cd = countdown1 : cd = countdown2;
    interval = setInterval(function(timer) {
        var el = document.getElementById(element);
        if(cd.seconds == 0) {
            if(cd.minutes == 0) {
                (el.innerHTML = "STOP!");     

                clearInterval(interval);
                return;
            } else {
                cd.minutes--;
                cd.seconds = 60;
            }
        }
        if(cd.minutes > 0) {
            var minute_text = cd.minutes + (cd.minutes > 1 ? ' minutes' : ' minute');
        } else {
            var minute_text = '';
        }
        var second_text = seconds > 1 ? '' : '';
        el.innerHTML = minute_text + ' ' + cd.seconds + ' ' + second_text + '';
        cd.seconds--;
    }, 1000);
}
var start = document.getElementById('start');


 <div id='countdown'></div>
 <input type="button" onclick="countdown('countdown1');this.disabled = true;" value="Start" />
 <div id="countdown1"></div>

 <input type="button" onclick="countdown('countdown2');this.disabled = true;" value="Start" />
 <div id="countdown2"></div>

fiddle: http://jsfiddle.net/dn3hJ/

let d = document,
    id = 'getElementById',
    time = {
//Multiple Timers
//[current time, time setting, (pause/running), HTML section#timer]
      timer1: ['0:10', '0:10', 0, d[id]('timer1')],
      timer2: ['2:30', '2:30', 0, d[id]('timer2')],
      timer3: ['5:00', '5:00', 0, d[id]('timer3')],


//Manage Timer Functions
      reset: function(t) {time[t][0] = time[t][1];},
      pause: function(t) {time[t][2] = 0;time.state(t,'pause');time.button(t,'resume');},
      resume: function(t) {time[t][2] = 1;time.state(t,'running');time.button(t,'pause');},
      set: function(t,s) {time[t][0] = s; time[t][1] = s;},
      state: function(t,s) {time[t][3].setAttribute('state',s);},
      button: function(t,s) {time[t][3].querySelector('div').innerHTML = s;},
      cancel: function(t) {time[t][2] = 0;time.reset(t);time.state(t,'');time.button(t,'start');time.setTimer(t);},
      start: function(t) {time.reset(t);time[t][2] = 1;time.state(t,'running');time.button(t,'pause');},
      getTimers: function() {return Object.keys(time).filter(function (n) {return n.indexOf("ti")==0;});},
      setTimer: function(t) {time[t][3].querySelector('span').innerHTML = time[t][0]},
      setTimers: function(x) {
        let times = time.getTimers();
        for (var i=0,t;i<times.length;i++) {t=times[i];
              if(time[t][2]||x){time[t][3].querySelector('span').innerHTML = time[t][0]}
        }
  },
};

//handle seconds passed
function convertSeconds(s=0) {return new Date(s*1000).toISOString().substr(11,8).replace(/^(00:0(?=[1-9])|00:|0)/gm, '')}
function toSeconds(t) {t=t.split(':').reverse();return (t[2]*3600||0)+(t[1]*60||0)+t[0]*1||0;}

//set HTML times onLoad
time.setTimers(1)


function runTimer(times){times = time.getTimers();time.setTimers();
    function run(t,s,l){if(t&&t[2]){s=toSeconds(t[0]);t[0]=s?convertSeconds(s-1):'00:00'&&(time.cancel(l));}}
    for (var i=0,t;i<times.length;i++) {run(time[times[i]],'',times[i])}
}

//run timer every second reguardless of whether timer is paused or running
setInterval(runTimer, 1000)
body {
  background: #e6e9f0;
  user-select: none;
  font-family: "SF Pro Display", Helvetica Neue, Arial, Helvetica, Geneva, sans-serif;
  font-size: 14px;
}
div, span {display: inline-block;}
span {min-width: 60px;}
#time > section {
  padding: 10px 20px;
  background: white;
  margin: 10px;
  border-radius: 4px;
  transition: .15s ease-in-out 0s;
  text-transform: capitalize;
}
#time > section:hover {box-shadow: 0px 0px 0px 2px #A8D1FD;}
#time > section > div{text-shadow: 0 1px 1px rgba(0,0,0,0.3);transition: .1s ease-in-out 0s;}
#time > section > div:nth-of-type(2){background: #cfd3dd;opacity: 1;}
#time > section[state=""] > div:nth-of-type(2) {opacity: 0;}
#time > section > div{
  background: #368ad2;
  color: white;
  padding: 6px 10px;
  margin: 0 5px;
  min-width: 50px;
  text-align: center;
  border-radius: 4px;
}
<section id="time">
  <section id="timer1" state="">
    <span>0:00</span>
    <div onClick="time[this.innerHTML]('timer1')">start</div>
    <div onClick="time.cancel('timer1')">cancel</div>
  </section>
  <section id="timer2" state="">
    <span>0:00</span>
    <div onClick="time[this.innerHTML]('timer2')">start</div>
    <div onClick="time.cancel('timer2')">cancel</div>
  </section>
  <section id="timer3" state="">
    <span>0:00</span>
    <div onClick="time[this.innerHTML]('timer3')">start</div>
    <div onClick="time.cancel('timer3')">cancel</div>
  </section>
</section>

发布评论

评论列表(0)

  1. 暂无评论