Reputation:
My Jquery one()
function dies after second click instead of first click. Here is my HTML
<div class="box">
<div class="call" data-tai="5">CLICK</div>
</div>
and heres my Jquery
$('body div').one('click', '.call', function() {
var mother = $(this).parent();
if(mother.css('position') === 'static')
mother.css('position', 'relative');
var tai = $(this).data('tai');
$.ajax({
method: 'GET',
url: '/bootstrap/call.php',
data: 'tai='+tai,
dataType: 'html',
success: function(ret) {
mother.append(ret);
},
});
return false;
});
Interesting thing is, if i don't use return false;
, it dies after first click. However bubbling
occurs and it appends 2 html tags instead of 1, inside box
element. Thanks for help
Upvotes: 0
Views: 1416
Reputation: 144689
That's because event handlers bound by using .one
will be fired once for each element in the jQuery collection. Since the return false
stops the propagation of the event, if you click on the .call
element, click handler of the parent element is not executed but the parent element still has an active click handler. You should use a more specific selector for selecting the target element. If the click handler should be bound to the div.call
elements:
$('.box div.call').one(...);
Now, if .box
elements have 9 div.call
descendants then you have 9 click handlers! After clicking on each element jQuery unbinds the handler for that specific element.
It's not once for all elements, it's once for each element.
If the handler should be called once for all the matching elements you can use the delegation version of the .one
method:
$(document).one('click', '.box div.call', function() {
// ...
});
And if you want to delegate the event and have the handler working once for dynamically generated elements you can use the .on
method and :not
selector:
$(document).on('click', '.box .call:not(.clicked)', function() {
$(this).addClass('clicked');
// ...
});
Now the handler is called once for each .call
element. Since :not
excludes the elements that have .clicked
class the selector doesn't match the already-clicked elements.
Upvotes: 1
Reputation: 3207
Events bubble in JavaScript. Your code
$('body div').one('click', '.call', function() {
}
wires up on both
<div class="box"> <!-- This -->
<div class="call" data-tai="5">CLICK</div> <!-- And this -->
</div>
You need a more specific selector. If this div is a parent element in the body like this:
<body>
<div class="box">
<div class="call" data-tai="5">CLICK</div>
</div>
<div class="box">
<div class="call" data-tai="5">CLICK</div>
</div>
</body>
then you can use a selector like this:
$('body > div').one('click', '.call', function() {
}
The question is - where do you expect your click event to be placed? Perhaps the div with the box class?
$('div.box').one('click', '.call', function() {
}
This assumes that the .call divs are being added dynamically to the .box div.
P.S. - if you want to stop the bubbling, I suggest you pass in the event object to your click event and call stopPropagation()
$('div.box').one('click', '.call', function(evt) {
evt.stopPropagation(); // no bubbling
}
Upvotes: 0
Reputation: 2165
$('body div')
would select both the divs and attach click handlers to both of them. When you click on the nested div then, both clicks will be fired. Use a specific selector to avoid this.
$('.call')
could perhaps achieve this.
Upvotes: 2