0

I thought making a simple function where if you click on a button a number will show up inside of a paragraph. And if you continue to click on the button the number inside the paragraph tag will increase. However, I'm getting an error message saying that getElementsByTagName is not a function. Here is the code on jsfiddle, I know there is something simple that I'm doing wrong but I don't know what it is.

HTML

<div class="resist" id="ex1"><h2>Sleep</h2><p></p><button>Resist</button></div>

<div  class="resist" id="ex2"><h2>Eat</h2><p></p><button>Resist</button></div>

Javascript

var count = 0;
var resist = document.getElementsByClassName('resist') ;
for(var i = 0; i < resist.length; i++)
{    var a = resist[i];

    a.querySelector('button').addEventListener('click', function(a){
       count +=1;
        a.getElementsByTagName('p')[0].innerHTML = count;
    });
}
black_yurizan
  • 407
  • 2
  • 7
  • 19

2 Answers2

4

You are overwriting a variable with event object passed into event handler. Change the name to e maybe, or remove it altogether as you are not using it anyway:

a.querySelector('button').addEventListener('click', function(e /* <--- this guy */) {
  count += 1;
  a.getElementsByTagName('p')[0].innerHTML = count;      
});

Another problem you are going to have is classical closure-in-loop issue. One of the solutions would be to use Array.prototype.forEach instead of for loop:

var count = 0;
var resist = Array.prototype.slice.call(document.getElementsByClassName('resist'));
// ES6: var resist = Array.from(document.getElementsByClassName('resist'));

resist.forEach(function(a) {
  a.querySelector('button').addEventListener('click', function(e) {
    count += 1;
    a.getElementsByTagName('p')[0].innerHTML = count;
  });
});
Community
  • 1
  • 1
dfsq
  • 191,768
  • 25
  • 236
  • 258
  • It somewhat works, but now another problem arises. Whenever I click on the two buttons the number only increments in the second .resist area. – black_yurizan May 01 '16 at 19:45
  • I'm not sure what is the expected behaviour. Is it what you want: https://jsfiddle.net/nz1fjf57/2/ ? Or you want separate counters for each .resist? – dfsq May 01 '16 at 19:46
  • I definitely wanted separate counters. Yours works better, but I wanted both of the paragraphs to start at 0. I guess I should just make another counter for each resist div? – black_yurizan May 01 '16 at 19:51
  • Quick question, I don't know if you have time to answer this, but can you give me an explanation as to why you chose to use Array.prototype.slice.call instead of document.getElementsByClassName? I was wondering why you thought that was a better choice – black_yurizan May 01 '16 at 23:52
0

vars in Javascript are function scoped, so you must wrap your event listener binding in a closure function to ensure the variable you're trying to update is correctly set.

(Note: I've renamed a to div in the outer function and removed the arg from the inner click function).

var count = 0;
var resist = document.getElementsByClassName('resist') ;
var div;
for(var i = 0; i < resist.length; i++)
{   
    div = resist[i];
    (function(div){
        div.querySelector('button').addEventListener('click', function(){
            count +=1;
            div.getElementsByTagName('p')[0].innerHTML = count;
        });
    })(div);
}
Blaskovicz
  • 6,122
  • 7
  • 41
  • 50