Zoker
Zoker

Reputation: 2059

`.one` function is attached multiple times

I have a function, that binds a function via .one('click' to an element:

function apply() {
    jQuery('.delete-item').one('click', function() {
        jQuery('body').LoadingOverlay('show');
        var id = jQuery(this).closest('.item').data('item-id');
        delete_item(this, id);
    });
}

Then the apply function is called multiple times (because there are new elements in the dom). But although I use the .one instead of .on, the click function gets attached three times: enter image description here

When I remove the listeners manually in chrome, it works fine.

Why is the listener applied multiple times?

Upvotes: 0

Views: 47

Answers (1)

Daniel Beck
Daniel Beck

Reputation: 21485

.one() doesn't guarantee that only one event handler will be called for a particular event; it guarantees that this particular event handler will only run once.

In the sample below if you click the "apply" button four times, you will call apply() four times, which will attach four .one('click') handlers to the other button. If you click that button, you'll see it runs four times. If you click it again, it will run zero times (because each of the four events expired after its first use.)

function apply() {
  console.log("Calling apply");
  $('.foo').one('click', function() {
    console.log("CLICKED");
  });
  
}

$('.apply').on('click', apply);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="foo">Click me to trigger .one</button>

<button class="apply">Click me to apply()</button>

Instead of running your apply() function which attaches event handlers to every .delete-item on the page every time you add stuff to the DOM, you could attach single event handlers only to the newly-added item.

But what would probably be easiest is to, at document ready, attach a single delegated event to the body or a convenient parent element that will handle the event for any child .delete-item (even if that item didn't exist when the delegated event was created):

$('body').on('click', '.delete-item', function() {
  // ...
  var id = $(this).closest('.item').data('item-id');
  // delete_item(this, id);
  console.log("Clicked ", id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item" data-item-id="1"><button class="delete-item">delete</button></div>
<div class="item" data-item-id="2"><button class="delete-item">delete</button></div>
<div class="item" data-item-id="3"><button class="delete-item">delete</button></div>

Upvotes: 2

Related Questions