Search code examples
javascriptvariablessetintervallocalgreasemonkey

Struggling to use variables in a repeating timer to merely change time remaining on a webpage


Using a greasemonkey fork called Violetmonkey to try to make a dynamic timer on a retro website https://riseoftyrants.com/age2/

I don't know if you need an account to see the event timer. But events happen for 15 minutes out of at most every 20 minutes, so when you visit you may see what I'm trying to edit.

const tables = document.querySelectorAll("div.d1l");
  alert(tables[2].innerText);
bling = tables[2].innerText.match(/(\d\d):(\d\d)/i); //" (\d\d):(\d\d)/i"); //Ends: 01:58  first capture group $1 is minutes and $2 is seconds
min = bling[1];
sec = bling[2];
//alert(min + "..." + sec);
console.log("Alpha");

setInterval(function (){
  tables[2].innerText=Brick(min,sec);
  console.log("Beta");
},1000);

function Brick(min,sec) {
  console.log("Gamma");
  sec = sec-1;
  if (sec<0){
    min=min-1;
    sec=59;
  }
  return "Ends: " + min + ":" + sec;
}

The timer updates as I'd expect. Well, I still have to do some manipulating for a leading zero on the seconds component. But it only updates one time. The console log shows me that the functions keep running because Beta and Gamma keep populating in the log. But how am I supposed to let the function update min and sec, or at least pass those values onto the next call?

I suppose I can just repeat grabbing the variables off the webpage after the script updates them, but that seems atrocious.

Any previous answers on this tell me functions use local variables and if you need a global variable to define it outside of the function. Did I not do that? What is wrong?


Solution

  • I suppose I can just repeat grabbing the variables off the webpage after the script updates them, but that seems atrocious.

    Any previous answers on this tell me functions use local variables and if you need a global variable to define it outside of the function. Did I not do that? What is wrong?

    You are on the right tracks in your thinking. Ultimately, it only updates once as every time the interval is called you are passing the same min and sec to Brick every time since those are fetched at the top of file from the DOM, and never updated again. They are stored outside the scope of the interval.

    The reason it doesn't update those top variables is that inside Brick, as you have it now, you define min and sec again, but this time as function parameters. These local variables with the same name (best to avoid using same name) will take precedence over that global one. You might think passing the top level ones as parameters is the same, but it isn't because primitives like numbers are copied when you pass them into params.

    What you could do is alter Brick such that it is changing those stored global variables, rather than locals one. That means each time it runs, its running on top of the newest modified value from the last run.

    const tables = document.querySelectorAll("div.d1l");
      alert(tables[2].innerText);
    bling = tables[2].innerText.match(/(\d\d):(\d\d)/i); //" (\d\d):(\d\d)/i"); //Ends: 01:58  first capture group $1 is minutes and $2 is seconds
    min = bling[1];
    sec = bling[2];
    //alert(min + "..." + sec);
    console.log("Alpha");
    
    setInterval(function (){
      tables[2].innerText=Brick();
      console.log("Beta");
    },1000);
    
    function Brick() {
      console.log("Gamma");
      sec = sec-1; // Since these aren't passed to the function, we are now directly modifying the min and set vars set near the top
      if (sec<0){
        min=min-1;
        sec=59;
      }
      return "Ends: " + min + ":" + sec;
    }