Simple JavaScript timer with loop and pause

Having trouble with a countdown script and encountering multiple issues.

  1. The script does not run smoothly
  2. Difficult to make it repeat (closure)
  3. Struggling with delaying the start and repeat (closure)

Seeking assistance in fixing this code which should ideally work but is not functioning correctly.

I require the following functionality:

a. The counter starts after a delay number of seconds once the page loads,
b. When the counter reaches 0, it restarts after another delay number of seconds

Here is my Fiddle

Specific Issues:

  1. Counter seems to wait an extra second before counting down
  2. No pause functionality
  3. Repeat starts after the counter has already been running

.

// For a more accurate timer - reference: https://gist.github.com/1185904
function interval(duration, fn){
  this.baseline = undefined

  this.run = function(){
    if(this.baseline === undefined){
      this.baseline = new Date().getTime()
    }
    fn()
    var end = new Date().getTime()
    this.baseline += duration

    var nextTick = duration - (end - this.baseline)
    if(nextTick<0){
      nextTick = 0
    }
    (function(i){
        i.timer = setTimeout(function(){
        i.run(end)
      }, nextTick)
    }(this))
  }

  this.stop = function(){
   clearTimeout(this.timer)
  }
}
window.onload=function() {
  var cnt1 = 10;
  var delay1 = 5;
  var timer1 = new interval(1000, function(){
    document.getElementById('out1').innerHTML=cnt1--
    if (cnt1 <= 0) { // trying to reset
      timer1.stop(); // does not work
      cnt1 = 10;
      setTimeout(function() { timer1.run()},delay1*1000)
    }
  })
  setTimeout(function() { timer1.run()},delay1*1000)
}  

Answer №1

I have revamped the code to achieve the desired outcomes. The initial code you provided was not very efficient. Take a look at my script comments for guidance on how to use it.

Check it out on Fiddle: http://jsfiddle.net/RVBDQ/1/

/*
  @name  countdownTimer
  @param number startFrom     Starting number for countdown
  @param number delay         Time in seconds before each countdown
  @param number intervalDelay Milliseconds between count updates
  @param number runTimes      Optional; Number of countdown iterations. Stops after reaching this limit. Default is 1 (one countdown)
  @param Boolean noFirstRun   Optional; If false, countdown begins immediately. Default is false
*/

function countdownTimer(startFrom, delay, intervalDelay, runTimes, noFirstRun){
    if(typeof runTimes == "undefined") runTimes = 1;
    if(runTimes-- < 0) return;
    setTimeout(function(){
        var counter = startFrom;
        var timer1 = window.setInterval(function(){
            document.getElementById('out1').innerHTML = counter--;
            if(counter <= 0){
                clearInterval(timer1);
                countdownTimer(startFrom, delay, intervalDelay, runTimes, true);
            }

        }, intervalDelay);
    }, noFirstRun ? delay*1000 : 0);
}
window.onload=function() {
    countdownTimer(10, 5, 1000, 2);
    //Executes two times, starting from 10 and counting down to 1 with a 5-second delay between counts.
}  

Answer №2

Class with methods start([delay]) and stop().

Visit this link for a demonstration.

function timedOperation(duration, callback, delay){
    this.timer = null;
    this.duration = duration;
    this.callback = callback;

    this.start(delay);
}
timedOperation.prototype.start = function(delay){
    if (this.timer) {return;}
    var self=this;
    this.timer = setTimeout(function(){ self.run(); }, delay||0);
};
timedOperation.prototype.run = function(called){
    var self = this,
        nextTick = called ? this.duration - (new Date - called) : 0;

    this.timer = setTimeout(function(){
        self.callback();
        self.run(new Date);
    }, nextTick<0 ? 0 : nextTick);
};
timedOperation.prototype.stop = function(){
    clearTimeout(this.timer);
    this.timer = null;
};

window.onload = function() {
    var counter = 10;
    var initialDelay = 5;
    window.operation1 = new timedOperation(1000, function(){
        document.getElementById('output1').innerHTML=counter;
        counter = counter === 1 ? 10 : counter-1;
    }, initialDelay*1000);
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to disable 'rtl' using {flip: false}?

I am attempting to replicate the behavior demonstrated in the MUI docs at this link. When switching from 'ltr' to 'rtl', the 'Affected' content flips sides while the 'Unaffected' remains unaffected. To illustrate th ...

An alternative to passing AngularJS expressions to PHP or Ajax

Within my PHP/HTML file, I have an AngularJS expression that looks like this: {{data.po_id}} This expression is included as <td>{{data.po_id}}</td> within a table row. I am trying to use this expression as a parameter for a PHP function in t ...

What is the best way to fetch the id of the option that has been chosen from a bootstrap drop-down menu?

I recently created a basic drop-down list like this: https://i.sstatic.net/4Tlxx.png Here is the HTML code for it: <select class="form-control" id='0' (change)="retrieveValue($event.target)"> <option id='0'>{{ g ...

JQuery computes the grand total without displaying it on the screen

I have been working on creating a small e-commerce website, and recently integrated a jQuery program to calculate items in the shopping cart. I wanted to display the total amount of these items next to the cart, but despite seeing that the calculation was ...

Create a jQuery URL within the $.ajax function

Attempting to execute a $.ajax call and send data to a php file. The php file is situated in a component's directory, while the js file is located in the webroot directory. How can the url section of the $.ajax be configured correctly to point to the ...

Utilizing JSON format for processing HTTP requests in JavaScript with Node.js

I'm working with a snippet that retrieves data in JSON format, but I'm interested in manipulating the data instead of just outputting it to the console. var request = require('request'); var headers = { 'Connection': ' ...

Identifying changes in value in any scenario, jQuery

When I click on a button and change the input value, I want an alert to display 'Ok Done', but it's not working as expected. The input value may contain both numbers and letters. $("#myTextBox").bind("change paste keyup", function() { ...

Using Jquery's append() method to dynamically alter the HTML content

I am attempting to create a table with rows that are added dynamically. The challenge I am encountering is that each row consists of form elements, including multiple inputs. I have a PHP function that generates the correct row, and I have been able to sen ...

The functionalities of $scope and this in AngularJS

Currently, I am developing a small application using angularjs. In this project, I am trying to implement a feature that involves deleting a contact. The functionality itself works perfectly fine, however, I am encountering an issue where the 'this.op ...

Guidelines for incorporating JS in Framework7

I am developing an application using the framework7. I am facing a challenge where I need to execute some javascript in my page-content, but it is not running as expected. <div class="pages"> <div class="page close-panel" data-page="item"> ...

ajax modal form editing

Encountered an issue with editing a form using modal ajax, where the edit form pops up but the data remains empty. The code snippet for my controller: public function edit() { $id=$this->uri->segment(3); $data=array( 'project' => $th ...

Unexpectedly, Internet Explorer 11 is causing the "input" event to fire prematurely

While troubleshooting a JavaScript issue, I came across what seems to be a bug in Internet Explorer 11. I am reaching out here on StackOverflow for validation and to see if anyone else using IE11 can replicate this problem. The problem arises when the val ...

Unable to locate FFmpeg on the root server for Discord JS v13

After setting up my DiscordJS Bot on a new rootserver, I transferred all the files and launched the bot. Everything seemed to be working fine until I tried to run a command that involved the bot joining a voice channel and playing audio. At this point, an ...

Utilizing JavaScript to verify the presence of a div element within dynamically injected HTML code

While working on a website, I have implemented an embed function which involves calling a javascript from my server to inject HTML on another remote server. To ensure that these embeds also benefit from Google ranking, I have included a piece of HTML in t ...

Alter the color of the text within the `<li>` element when it is clicked on

Here is a list of variables and functions: <ul id="list"> <li id="g_commondata" value="g_commondata.html"> <a onclick="setPictureFileName(document.getElementById('g_commondata').getAttribute('value'))">Variable : ...

Is there a method to display a loading animation while the micro apps are being loaded in a single spa project?

Currently, I am working on a project using single spa and I need to implement a loader while my micro app is being loaded. Additionally, I also need the loader to be displayed when switching between these micro apps. Are there any methods to accomplish t ...

Clever method for enabling image uploads upon image selection without needing to click an upload button using JQuery

Is there a way to automatically upload the file without having to click the upload button? Detail : The code below shows an input field for uploading an image, where you have to select the file and then click the "Upload" button to actually upload it: & ...

The module 'react/jsx-runtime' could not be located within the path relative to '@mui/styled-engine/StyledEngineProvider/StyledEngineProvider.js'

I encountered this issue when attempting to create a new React project using MUI. I followed this code example from the documentation, which functions correctly in their live Codesandbox but not on my local setup. Here is the complete error message: Module ...

Interactive pop-up window featuring conversational chat boxes

Trying to create a comment box within a Modal dialog box that is half of the width. The comments in this box should be read-only and created using div tags. Attempted reducing the width and using col-xs-6, but ending up with columns spanning the entire w ...

Make sure to include all enum type values within the function's body to ensure comprehensive coverage

I am defining an enumeration called ApiFunctions with values like "HIDE", "SET_READ_ONLY", and "DESCRIPTION". Also, I have a type ValueOfApiFunction that should include all values of ApiFunctions. Additionally, I have a logic that listens for messages on ...