0

Issue: Each time div.a is clicked, the number of callbacks when div.b is clicked,accumulates by 1.

var $=jQuery;
$(function(){
   $("div.a").click(function(){cbf(trgmsg);});
});
function trgmsg(){
   alert($.now());
}
function cbf(cb){
   $("div.b").click(function(){cb()});
}

Result:
click div.a once and click div.b => alert() pops-up;
if i click div.a again and click div.b => alert() pops-up twice consecutively;
if i click div.a another time and click div.b => alert() pops-up three times consecutively;
..and so on

I have No idea what the cause of the problem is or if its simply my misunderstanding/misuse of callback functions in JS. Any insights and/or advice will be greatly appreciated. thanks

4 Answers4

1

Quickest fix for your code without a refactor is to just unbind and re-bind.

var $=jQuery;
$(function(){
   $("div.a").click(function(){cbf(trgmsg);});
});
function trgmsg(){
   alert($.now());
}
function cbf(cb){
   $("div.b").off('click').click(function(){cb()});
}
AlienWebguy
  • 76,997
  • 17
  • 122
  • 145
0

What you have now (refactored) looks like:

(function($){
  $(function(){
    function trgmsg(){
      alert($.now());
    }
    $('div.a').click(function(){
      // every time `div.a` is clicked a new click event is
      // attached to `div.b`.
      $('div.b').click(function(){ // maybe use `.one()` instead of `.click()`?
        cb();
      });
    });
  });
})(jQuery);

You may want to use .one() so after it binds it's only executed once. Or else you need to elaborate on what the actual goal is and see if that can be solves differently.

Brad Christie
  • 100,477
  • 16
  • 156
  • 200
  • That will unbind the listener on `div.b` so it'll only work once. It's not a "if it's bound, just use the existing listener" solution. – AlienWebguy Sep 10 '13 at 17:43
  • WOW,just tried .one() and worked perfectly. My goal was to have a confirm dialogue (yes/no) and execute functions depending on the selection. I was having a problem bc everytime i selected a yes/no the # of executions that followed started duplicating. Thank you! – user2530844 Sep 10 '13 at 17:44
  • 1
    What happens on the 2nd alert dialog though? – AlienWebguy Sep 10 '13 at 17:45
  • i put the div.a click & alert to simplify my question as much as possible(so that ppl didnt have to read a bunch of code). In reality i have a function that calls a confirm dialogue, which waits for a response and then executes accordingly. – user2530844 Sep 10 '13 at 17:52
0

If you just want to call the supplied function against div.b, when div.a is clicked, this might work for you

var $=jQuery;
$(function(){
   $("div.a").click(function(){cbf(trgmsg);});
});
function trgmsg(){
   alert($.now());
}
function cbf(cb){
   $("div.b")[0].apply(cb);
}
Robert Byrne
  • 562
  • 2
  • 13
0

You are attaching multiple click events onto div.b. So every time you click on div.a it is attaching another click event onto div.b so when div.b is clicked each of it's click events are fired. You can try setting a flag that says a click has already been registered.

var $=jQuery;
var flag = 0;
$(function(){
   $("div.a").click(function(){cbf(trgmsg);});
});
function trgmsg(){
   alert($.now());
}
function cbf(cb){
   if (!flag) {
       flag = 1;
       $("div.b").click(function(){cb()});
   }
}

Although I'm not quite sure what your using this for so that may not be your desired functionality.

hyphrend
  • 11
  • 2
  • Thank you for the response. Your explanation was quite helpful in understanding the mechanincs of what im doing wrong. Is there a way to 'clear'/'reset' attached multiple events? or a way to count the # of events attached? – user2530844 Sep 10 '13 at 18:06
  • If you remove the if statement for the flag and turn the flag variable into a counter you can just flag++ every time instead. This would count every time the event was attached. To remove them all you could just call $("div.b").off('click'); and that will remove all the click events for those elements. – hyphrend Sep 10 '13 at 18:22