0

I want to create javascript function adds an event listener to a div such that when the div is clicked, it runs a function, and ensures that the div can only be clicked once. My function looks like this right now:

function clickOnce(divID,func){
  var args = Array.prototype.slice.call(arguments,2);
  functionToRun=partial(func,args);
  thisDiv=document.getElementById(divID);
  thisDiv.addEventListener("click",function(e){
    e.target.removeEventListener(e.type, arguments.callee);
    functionToRun();
  });
}

I have a working example in jsfiddle: https://jsfiddle.net/qtzLhgr4/1/ In the JSfiddle, when I click button 1 it says "button #2 clicked".

duplode
  • 33,731
  • 7
  • 79
  • 150
user1763510
  • 1,070
  • 1
  • 15
  • 28

2 Answers2

3

You didn’t declare functionToRun, so it’s implicitly global. Declare it and thisDiv:

var functionToRun=partial(func,args);
var thisDiv=document.getElementById(divID);

Then start working in strict mode, which will prevent these kinds of problems as well as stop you from using arguments.callee, which is the Wrong Way To Do Things:

thisDiv.addEventListener("click", function listener(e) {
    thisDiv.removeEventListener("click", listener);
    functionToRun();
});

(e.target was also incorrect; this would have been better.)

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • Good catch with `e.target`. `this` is the best solution, but one could also use `e.currentTarget`. `e.target` will break as soon as the element contains other elements. – Felix Kling Aug 12 '16 at 00:15
2

functionToRun (and thisDiv, but that's not related to the problem) is global. The second call to clickOnce overwrites functionToRun, so both event handlers execute the same function.

Always declare your variables. Also note that arguments.callee is deprecated. You can use a named function expression instead.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143