0

I am sorry that my origin description is not clear. I have revised my question:

I am using jQuery, as shown in the attached picture, each time I attach an event listener (e.g. click) to an element, it will fire twice. It looks like this problem is due to the jQuery debugger.

I would like to ask if there is any approach other than adding unbind() or off() before the listener to solve the problem, I have tried these approaches but it removes the listeners already attached to the elements (e.g. I have #element1 which is created in html, then use jQuery to append two elements #element2 and #element3 to #element1, if I use

    $('#element1').off('click').on('click', '#element2', function(){
       //implementation
    }    
    $('#element1').off('click').on('click', '#element3', function(){
       //implementation
    }

the click event of #element2 will no longer work because the click listener attached on it is removed in this situation. So I am asking if there is a better way to do it?

By the way, I am wondering where is the VM 7188 listener comes from (it looks like from jQuery debugger) and if there is anyway to remove this listener so that I no longer need to use off() every time when I write a listener, thanks.

Attached picture for duplicated listeners

enter image description here

Jason
  • 11
  • 2
  • 1
    if you are going to use the `unbind(eventName)` please use the eventName with it like: `unbind('click')` try this. – vikscool May 15 '18 at 08:50
  • 1
    Also note that `unbind()` was deprecated a while ago. You should be using `off()` instead – Rory McCrossan May 15 '18 at 08:54
  • Isn't this because his event is triggered on a child descendant and therefore the event bubbles? Why don't you use event.stopPropagation() within your handler? – ibrahim tanyalcin May 15 '18 at 08:57
  • Thanks for reminding, I have revised my code using off() – Jason May 15 '18 at 11:35
  • The problem is due to accidentally includes the same javascript twice so that the listener attached twice, the VM prefix of js in Chrome debugger is used by Chrome to distinguish the files (refers to: https://stackoverflow.com/questions/17367560/chrome-development-tool-vm-file-from-javascript/18621472#18621472) – Jason Mar 18 '20 at 15:23

3 Answers3

1

It's unclear why you'd need to remove and attach a handler to #element1 just because #element2 is removed and dynamically created; you're using delegated syntax, so it's totally fine that #element2 is dynamically created. You only need to set that handler once, regardless. Example:

// Note this continues to work even as we remove and recreate #element2
$("#element1").on("click", "#element2", function() {
  console.log("Got the click on #element2");
});

function tick() {
  $("#element1").append("<span id='element2'>Click me</span>");
  setTimeout(function() {
    $("#element2").remove();
    setTimeout(tick, 500);
  }, 1500);
}

tick();
<div id="element1"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

But to target specific handlers, you can use event namespaces, e.g.:

$('#element1').off("click.my-namespace").on('click.my-namespace', '#element2', function(){
   //implementation
});

For more, see "Event names and namespaces" in the documentation.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

I'm not a jquery person, but it seems to me that you are adding the handler to a child descendant and therefore the event bubbles. Instead of adding/removing listeners like this, when adding the handler to children, consider adding event.stopPropagation()

$('#element1').unbind().on('click', '#element2', function(e){
   e.stopPropagation();//#element1 won't receive this anymore
   //implementation
}
ibrahim tanyalcin
  • 5,643
  • 3
  • 16
  • 22
  • Thanks for your help, I tried to use e.stopPropagation(), it does not work, it looks like the button firing twice is because the VM 7188 (I guess is jQuery listener) automatically attach the existing listener again to the same button. – Jason May 15 '18 at 11:39
  • I cannot be sure based on no fiddle. Assuming what you say is true, the jquery must be attaching the listener on the parent and fires if event.target matches the selector you specified. Then the solution is to NOT attach the listener on the parent, but the descendant directly and then call stopPropagation. – ibrahim tanyalcin May 15 '18 at 11:43
-1
  1. You can call inline function, add attr to your element

    onclick="handler"

  2. Remove old handler before bind new

    $("#element1").off("click", "#element2", handler); $("#element1").on("click", "#element2", handler);

Valera Checha
  • 294
  • 4
  • 16