0

Basically if I click on a checkbox, I want the name of the checkbox to be displayed on the console.

Here is the relevant javascript function and HTML.

javascript:

var list = [];

function test(){
      var checkBoxes = document.querySelectorAll('input[type=checkbox]')
    for(var i = 0; i < checkBoxes.length; i++) {
      checkBoxes[i].addEventListener('change',function(){
        if(this.checked){
          console.log(this.value)
          }
      });
  }
}

HTML:

<label><input type = "checkbox" onclick= "test()" name ="one" value ="one">test<br></label>
<label><input type = "checkbox" onclick= "test()" name ="two" value ="two" > test 1<br></label>
<label><input type = "checkbox" onclick= "test()" name ="three" value ="three" >test 2<br></label>
<label><input type = "checkbox" onclick= "test()" name ="four" value ="four" >test 3<br></label>
<label><input type = "checkbox" onclick= "test()" name ="five" value ="five" >test 4<br></label>
<label><input type = "checkbox" onclick= "test()" name ="six" value ="six" >Test 5<br></label>

If I click on the checkbox it is supposed to show in the console the name of the checked box.

However, something really strange happens and I don’t understand why it is. I have a vague inkling as to why it's happening but it's not quite clear.

When I click on the first check box for example. I click on the checkbox named "one". The console displays:
one (as required)

But if I click on the next check box (for example I clicked on the checkbox named "four"). In the console it displays:
four
four

And the next checkbox clicked (if it's the one named "five") The console shows:
five
five
five

and so on....(incrementally repeating the checkbox name displayed on the console each time I click on another checkbox)

Why is it repeating ? When I click on the checkbox there should be technically one onclick event. How come it's counting all the other ones and repeating the console.log(this.value) bit?

Thanks in advance for any who may be able to give some idea as to why this is happening.

chu8
  • 105
  • 1
  • 1
  • 10

3 Answers3

2

The problem is that you have inline click event handlers already set up and then when you click a checkbox, you programmatically set up a second one for the change event with .addEventListener(). So EVERY time you click a checkbox, you add yet another change event handler - - if a checkbox value gets changed, EACH AND EVERY handler associated with the change event will run. The more you click a checkbox, the more change events you set up.

Now, in order to change a checkbox, you need to click it. So, a future click will cause both the click and the change events to fire. Because of this way that change works with checkboxes and radio buttons, it's not usually used and instead click handlers typically do the job.

Inline event handlers should not be used, they are a 20+ year old technique that has many faults.

Also, you don't need to loop through the checkboxes in the handler. You'd use a loop to set up the handlers.

// Get all the checkboxes into an Array
var checkBoxes = Array.prototype.slice.call(document.querySelectorAll('input[type=checkbox]'));

// Loop over the array only to set up event handlers on them
checkBoxes.forEach(function(cb) {
  // Set up an event handler
  cb.addEventListener('change',function(){
    // You don't need to loop again, just use the value of "this"
    if(this.checked){
      console.log(this.value);
    }
  });
});
<label><input type = "checkbox" name ="one" value ="one">test<br></label>
<label><input type = "checkbox" name ="two" value ="two" > test 1<br></label>
<label><input type = "checkbox" name ="three" value ="three" >test 2<br></label>
<label><input type = "checkbox" name ="four" value ="four" >test 3<br></label>
<label><input type = "checkbox" name ="five" value ="five" >test 4<br></label>
<label><input type = "checkbox" name ="six" value ="six" >Test 5<br></label>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
1

The problem is that you keep adding event listeners to every checkbox whenever you click on one. This means that every time you click on a checkbox, more handlers are present that log to the console.

The sequence of events decoded:

  • Your page is loaded, nothing has been done so far.
  • Click on a check box => onclick is fired.
  • test() is invoked, an event listener for change is attached to each checkbox.
  • The onchange event fires and reaches the installed handler.
  • The event is logged to the console.
  • Click on another checkbox => onclick is fired.
  • test() is invoked, another event listener for changeis attached to each checkbox.
  • The onchange event fires and reaches the first instance of the installed handler.
  • The event is logged to the console.
  • The onchange event reaches the second instance of the handler.
  • The event is logged to the console again.
  • and so on...

If you want to keep track of everything, I'd suggest the following JS to eliminate this problem (this doesn't need the onclick attribute at all):

document.addEventListener('DOMContentLoaded', function (p_event) {
var l_checkboxes = document.querySelectorAll('input[type="checkbox"]');
var l_item;

  for(l_item of l_checkboxes)
    {
    l_item.addEventListener('change', function (p_event) {
      if(p_event.target.checked)
        console.log(p_event.target.value);
      }, false);
    }
  }, false);
Robidu
  • 576
  • 3
  • 17
  • *Your page is loaded, nothing has been done so far.* Not true. The inline `click` event handlers have now been registered. – Scott Marcus Aug 27 '18 at 18:07
  • My statement related to the JS that you are using, because as long as you don't do anything, nothing is explicitly done by the JS. – Robidu Aug 27 '18 at 18:09
  • But that's not true. During the parsing of the HTML, the JS runtime will set up `click` event handlers for each and every checkbox. It's true that those handlers haven't been run yet, but it is wrong to say that the JS runtime hasn't done anything, especially with this particular issue. – Scott Marcus Aug 27 '18 at 18:12
  • As you have said it: The **(X)HTML parser** is setting these up (so it's an implicit assignment). No JS is involved, because the only script that I see is the snippet containing `function test()` - and that needs to be called to do anything. As long as there's no _explicit_ invocation of `test()` your JS engine merelys records this function and otherwise sits idle until the very first `onclick` event is fired. – Robidu Aug 27 '18 at 18:30
  • There is a difference between ***"doing nothing"*** and ***"invocation"***. Up until now, you've been saying "doing nothing", which is not true. Registering the handler is "something" and is essential to understanding why this code is doing what it does. Also, there is no such thing as an (X)HTML parser in standard browsers. There is only an HTML parser. Browsers don't understand XHTML. – Scott Marcus Aug 27 '18 at 18:34
  • Also, I did not say that the HTML Parser was setting up the event handlers, I said *"the **JS runtime** will set up click event handlers for each and every checkbox".* – Scott Marcus Aug 27 '18 at 18:44
  • You like playing the nitpicking card, don't you? I know what I have written and what point I was trying to convey, and that just doesn't change because you obviously intend to twist and misinterpret my words by taking everything literally. Furthermore you have merely opened a secondary theater of war that distracts from the original question (it does absolutely **nothing** to find a solution, instead it leads to even more confusion), and finally **you** don't have to lecture me on what the OP has written. As far as this discussion is concerned, I'm out, because it's absolutely fruitless. – Robidu Aug 28 '18 at 06:05
  • Ok, wow. Clearly you have misinterpreted quite a bit here. It boils down simply to this, you wrote *The sequence of events decoded:* followed by a lengthy list of things. This clearly conveys that you intended to be as precise as possible. Since your first bullet point was incorrect (and relevant to the entire point of the question), I pointed that out. You could have responded with "Oh, right. Let me update my answer.". But, instead you continued to argue your incorrect statement. Who benefits from that? – Scott Marcus Aug 28 '18 at 11:48
  • @Robidu Thanks for your response. It has helped my understanding of this problem. To clarify: as per your explanation: Everytime I click on a checkbox, multiple event listeners are being added to the checkboxes. Thus when for e.g. the second checkbox is ticked, there are two event listeners on the checkboxes and therefore when it is clicked, it will run test() twice and therefore logs onto the console twice? Again thanks for your detailed explanation. – chu8 Aug 28 '18 at 16:15
  • @chu8: No, since you are only assigning the onclick event once, it gets triggered just once when you click on the checkbox. However, since the function `test()` assigns an event listener for the `change` event (they are the ones that actually do the logging, your `test()` isn't involved in this) every time that you click on a checkbox, they stack up over time, and since each instance of that handler gets invoked when `change` fires, you will get a number of log entries that matches the number of instances of listeners waiting on the `change` event. – Robidu Aug 28 '18 at 17:57
-1

You are getting all the checkboxes on the page with document.querySelectorAll. Then you are looping through the list of all checkboxes in a for loop.

You can get the ID of the element clicked with

var checkBox = event.target.id;

then just display the name with console.log(document.getElementById(checkBox).value)

Some_Dude
  • 309
  • 5
  • 21