0

I am trying to build a reset function for a timer. I do understand how to reset the value of one button, but I cannot figure out how I can assign the same function to different buttons with each their own timer.

Currently I use the code below, but it specifically targets one element, while it should work on different ones.

<html>
<head>
    <script>
    function resettimer() {
        var x = document.getElementsByClassName("timer");
        x[0].innerHTML = "Hello World!";
    }
    </script>
</head>
<body>
    <table> 
        <tr>
            <p class="timer">Timer 1</p>
            <button onclick="resettimer()">Reset timer 1</button>
        </tr>
        <tr>
            <p class="timer">Timer 2</p>
            <button onclick="resettimer()">Reset timer 2</button>
        </tr>
        <tr>
            <p class="timer">Timer 3</p>
            <button onclick="resettimer()">Reset timer 3</button>
        </tr>
        <tr>
            <p class="timer">Timer 4</p>
            <button onclick="resettimer()">Reset timer 4</button>
        </tr>
    <table>
</body>
</html>
Ignacio Ara
  • 2,476
  • 2
  • 26
  • 37
  • 1
    This won't work in the long term. You need some way to distuinguish the timers states and you have to bind the DOM handlers /elements to that state. Otherwise it will just be a big mess. – Jonas Wilms Apr 19 '18 at 15:23
  • I've edited the post and fix the head and body tag errors – Ignacio Ara Apr 19 '18 at 15:24

2 Answers2

2

One solution is to use this keyword

 <html>
     <head>
        <script>
          function resettimer(btn) {
             btn.previousSibling.innerHTML = "Hello World!";
          }
        </script>
    </head>
    <body>
    <table>
       <tr>
            <p class="timer">Timer 1</p>
            <button onclick="resettimer(this)">Reset timer 1</button>
       </tr>
       <tr>
           <p class="timer">Timer 2</p>
           <button onclick="resettimer(this)">Reset timer 2</button>
       </tr>
       <tr>
           <p class="timer">Timer 3</p>
           <button onclick="resettimer(this)">Reset timer 3</button>
       </tr>
       <tr>
           <p class="timer">Timer 4</p>
           <button onclick="resettimer(this)">Reset timer 4</button>
       </tr>
   <table>
   </body>
 </html>
2

By placing all the buttons into an array and all the timers into an "array-like" object, you can simply set the timer who's index matches the index of the button that was clicked (for example, if button 0 is clicked, update timer 0).

Next, you need to move your script so that it is just prior to the closing body tag so that by the time is is encountered, all the HTML will have been read into memory and you can successfully access the elements.

You should also not be using inline HTML event handling attributes (i.e. onclick) as this is a 20+ year old technique that has many reasons to not use them. Instead separate your JavaScript from your HTML completely.

Also, you have some HTML validity issues (no closing table tag).

Lastly, don't use .innerHTML when the value you are setting/getting does not contain any HTML - that's a waste of processing. Use .textContent when there is no HTML to set/get.

<!doctype html>
<html>
<head></head>
<body>
<table>
  <tr>
    <p class="timer">Timer 1</p>
    <button class="reset">Reset timer 1</button>
  </tr>

  <tr>
    <p class="timer">Timer 2</p>
    <button class="reset">Reset timer 2</button>
  </tr>

  <tr>
    <p class="timer">Timer 3</p>
    <button class="reset">Reset timer 3</button>
  </tr>

  <tr>
    <p class="timer">Timer 4</p>
    <button class="reset">Reset timer 4</button>
  </tr>

</table>
  <script>
    // Get all the buttons into an array and loop through the array
    var btns = Array.prototype.slice.call(document.querySelectorAll("button.reset"));
    btns.forEach(function(btn){
      btn.addEventListener("click", resettimer);
    });
    
    // Get all the timer elements into a collection
    var timers = document.querySelectorAll("p.timer");
  
    function resettimer() {
      // Access the timer with the same index as the index of the button that was clicked
      timers[btns.indexOf(this)].textContent = "Hello World!";
    }
  </script>
</body>
</html>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71