Tips for maintaining my Countdown timer even after a page refresh

I'm currently tackling JS and I've hit a roadblock. I have successfully created a countdown timer, but now I want it to continue running even after the page is reloaded. I decided to use sessionStorage to store the countdown value and check if there's an existing sessionStorage on page load. The issue I'm facing is figuring out how to keep the countdown going with the stored values in sessionStorage.

Any assistance would be greatly appreciated!

class Timer {

    constructor(secondes, minutes) {
        this.secondes = secondes;
        this.minutes = minutes;
        this.button = document.getElementById("button");
        this.counter = document.getElementById("counter");
        this.storageCheck();
    }

    countdown(minutes) {
        var seconds = this.secondes;
        var mins = this.minutes; 
        var myCounter = this.counter; 
        function tick() {
            var current_minutes = mins-1;
            seconds--;
            myCounter.innerHTML = current_minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
            var duration = sessionStorage.setItem("timer", myCounter.innerHTML);

        if( seconds > 0 ) {
                setTimeout(tick, 1000);
            } else {
                if(mins > 1){
                    countdown(mins-1);           
                }
            }
        }
      tick();
    }

    buttonClick() {
        button.addEventListener("click", () => {
            this.countdown(this.minutes);
        })
    }

    storageCheck() {
        if (sessionStorage.getItem("timer")) {
            // Determine how to maintain the countdown
        }
    }
}

let newTimer = new Timer(60, 20);
newTimer.buttonClick();
<!DOCTYPE html>
<html>
<head>
<title>Test Countdown</title>
</head>
<body>

<div id="counter"></div>
<button id="button">Run</button>

<script type="text/javascript" src="countdown.js"></script>

</body>
</html>

Answer №1

Ensure that before initializing the seconds and minutes in the constructor, you check if they are already stored in the storage. If they do not exist in the storage, then only assign the values passed in the constructor to this.seconds = seconds and this.minutes = minutes;

   constructor(seconds, minutes) {
        this.button = document.getElementById("button");
        this.counter = document.getElementById("counter");
        if(!this.storageCheck()){ // check if seconds and minutes are stored in the storage
            this.seconds = seconds; // if not, set the minutes and seconds to the values passed in the constructor
            this.minutes = minutes;
        }
        else {
          this.countdown(this.minutes);
        }
    }

The function storageCheck() should verify if the values exist in storage. If they do, retrieve the values and assign them to this.seconds and this.minutes, then return true, otherwise return false.

  storageCheck() {
        // check if both minutes and seconds exist
        if (sessionStorage.getItem("mins") && sessionStorage.getItem("secs")) {
            // keep the countdown running
            this.minutes = parseInt(sessionStorage.getItem("mins")); // get minutes
            this.seconds = parseInt(sessionStorage.getItem("secs")); // get seconds
            return true;
        }
        else {
          return false;
        }
    }

In the countdown() function, save the current values to storage:

sessionStorage.setItem("mins", vm.minutes); // set current minutes
sessionStorage.setItem("secs", vm.seconds); // set current seconds

Test this implementation here: https://jsbin.com/bavexigute/1/edit?html,js,console,output

class Timer {

    constructor(seconds, minutes) {
      this.button = document.getElementById("button");
      this.counter = document.getElementById("counter");
      if (!this.storageCheck()) { // check if seconds and minutes are stored in the storage
        this.seconds = seconds; // if not, set the minutes and seconds to the values passed in the constructor
        this.minutes = minutes;
       }
       else {
          this.countdown();
       }
    }

     countdown() {
       debugger;
       var vm=this;
        if(!(this.minutes-1<0))
           this.minutes--;
       
       let tick = function() {
           vm.seconds--
           if(vm.seconds == 0){
              vm.seconds = 59;
              vm.minutes--;
           }
           vm.counter.innerHTML =  vm.minutes + ":" + (vm.seconds < 10 ? "0" : "") + vm.seconds;
           if(vm.minutes == 0 && vm.seconds - 1 == 0){
            vm.seconds--; 
            vm.counter.innerHTML =  vm.minutes + ":" + vm.seconds-1;
            }    
           else{
             setTimeout(tick, 1000);
           }
           sessionStorage.setItem("mins", vm.minutes); // set current minutes
           sessionStorage.setItem("secs", vm.seconds); // set current seconds
         }
        setTimeout(tick, 1000);
     }    

    buttonClick() {
        button.addEventListener("click", () => {
            this.countdown();
        })
    }

    storageCheck() {
        // check if both minutes and seconds exist
        if (sessionStorage.getItem("mins") && sessionStorage.getItem("secs")) {
            // keep the countdown running
            this.minutes = parseInt(sessionStorage.getItem("mins")); // get minutes
            this.seconds = parseInt(sessionStorage.getItem("secs")); // get seconds
            return true;
        }
        else {
          return false;
        }
    }

}

let newTimer = new Timer(60, 20);
newTimer.buttonClick();

Answer №2

To modify the minutes and seconds arguments, you can utilize your storage check function to override them if it is available.

constructor(mins, secs) {
  this.mins = mins
  this.secs = secs
  this.checkStorage = this.checkStorage.bind(this)
  this.checkStorage(mins, secs)
}
checkStorage(mins, secs) {
  if(window.storage) { // or any other condition
    this.secs = window.storage.secs
    this.mins = window.storage.mins
  }
}

You can implement a similar approach where the setStorage function updates the values initialized in the constructor.

Answer №3

Here's a handy trick you can try out:

window.onload = function() {
  let mins = localStorage.getItem("mins")
  let secs = localStorage.getItem("secs")
  let timer = new Timer(secs, mins);
};

Instead of storing the entire innerHtml in sessionStorage, consider saving just the minutes and seconds to see if that resolves your issue.

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

Group Hover by StyleX

I recently experimented with the innovative StyleX library and encountered a particular challenge. Can a group hover effect be achieved for a component solely using this library? For instance, let's assume we have the following component in Tailwind ...

Guide on navigating to a different page following a successful Google Sign In within React18

I'm facing an issue with redirection after signing in with Google on my React 18 project. Despite successfully logging in, the page does not redirect as expected. Below is a snippet of my Login.jsx file where the Google login functionality is implemen ...

Execute a specialized function with imported modules and specified parameters

Within an npm project, I am looking to execute a custom function with arguments, or ideally provide it as a script in the package.json file like this: npm run custom-function "Hello, World". Currently, I have a file called src/myFunction.ts: import * as e ...

Activate automatic selection when the input field is disabled

How can I enable auto-select for text in an input field even when it is disabled? Currently, the auto select feature doesn't work when the field is disabled. Here is my HTML: <input type="text" class="form-control" ng-model="gameId" select-on-cli ...

How does the keyof operator fetch non-enumerable inherited properties from an object literal type?

Take a look at this TypeScript code: 'use strict'; type Value = 1 | 2 ; type Owner = 'ownerA' | 'ownerB'; type ItemType = 'itemTypeA' | 'itemTypeB'; type Item = { type: ItemType; owner: Owner; value: ...

Looking for a way to locate the point where objects intersect in three.js?

My goal is to load 20 objects with random positions in a way that they do not intersect. How can I detect and check for intersections between these objects? for (var i = 0; i < 20; i++) { // Create a material var textureLoader = new ...

JavaScript Stopwatch Break

Below is the code snippet. How can a button be implemented to pause the timer and then resume it when the resume button is pressed? The // marks indicate where I plan to add my pause and resume functionality. Thank you in advance for your assistance! &l ...

The output of JSON.stringify() when given a single value as input

The JSON.stringify() function is designed to convert a JavaScript value into JSON format. console.log(JSON.stringify('a')); //output: "a" console.log(JSON.stringify(1)); //output: 1 console.log(JSON.stringify(true)); //output: true However, tec ...

Click event dynamically bound to list items

I have a web application built with Durandal and Knockout. Here is the HTML code snippet: <ul id="header"> </ul> In a JavaScript function, I am dynamically adding a list item as follows: $("#header).append('<li id="btn"><a hre ...

Access various results from a jQuery function

Is there a way to efficiently extract the values of petKeys and employeeKey using the jQuery functions provided below? var whenSelectDateFromCalendar = function () { initKeyValues(); petKeys = ? employeeKey = ? }; var initKeyValues = function ...

Adding a character at the current cursor position in VUE JS

My quest for inserting emojis in a textarea at the exact cursor position has led me to an extensive search on Vue JS techniques. However, most resources available online provide solutions using plain Javascript. Here is the code snippet I am working with: ...

Algorithm for encryption and decryption using symmetric keys

Can anyone recommend a reliable symmetric-key encryption algorithm that works seamlessly with both JavaScript and Java programming languages? I attempted to implement one myself, but encountered some complications related to encoding. ...

Encountering a Javascript error while trying to optimize bundling operations

After bundling my JavaScript with the .net setting BundleTable.EnableOptimizations = true;, I've encountered a peculiar issue. Here's the snippet of the generated code causing the error (simplified): var somVar = new b({ searchUrl: "/so ...

Is it feasible to choose the component generated by this element?

My current dilemma involves a component that renders a form, however, it also has its own form "catcher". var FormUpload = React.createClass({ submit : function(){ var formdata =new FormData(); ...

Implementing JavaScript logic to proceed to the following array within a 3D array once a specific condition is met

I'm currently tackling a challenge that requires me to obtain a specific number using a given 3D array. This array consists of 2D arrays, each containing the same number repeated x times. The parent array is sorted from largest to smallest. Here&apos ...

What is the best way to retrieve the innerHTML content of an anchor tag with Cheerio?

Looking to extract data from an HTML page, a simplified example is provided below. Upon running the code, I anticipate the output to be [ "foo", "baz", "quux", ] but instead encounter an error message stating "TypeError: anch ...

Updating the query parameters/URL in Node.js's request module

In my Express.js application, I am utilizing the npm request module to interact with an internal API. The options passed to the request function are as follows: requestOptions = { url : http://whatever.com/locations/ method : "GET", json : {}, qs : { ...

AngularJS not displaying loader during AJAX request

While utilizing ajax requests with $http, there seems to be a delay due to the server operation taking longer than expected. I have implemented a loader to display while processing the request, but unfortunately it is not showing up on the page. Even after ...

How can I clear my object so that new Dates() can be added to my calendar?

I am working on updating my program to seamlessly replace old JSON data from a holidays API with new data as soon as it is received. Initially, I attempted to declare the array as empty at the start, but this approach did not yield the desired results. Si ...

Unraveling the Mystery of Passing Props in React.js

Currently taking an online course to learn React, I encountered a unique scenario where one property is attached to another property in this manner: this.props.property01(this.props.property02) The tutor briefly touched on this code line, leaving me quit ...