Im having some problems with .on() and how to use it instead of .bind() in this situation.
What im trying to do here is i click a link and that is supose to bind another click event, but instead it triggers that event right away. I looked in the documentation/jquery.js file and this is how im suppose to do it.
Demo: http://jsfiddle.net/bNaFV/
$('#click_me').on('click', function(){
$('#show_me').addClass('remain');
//this is only suppose to bind that next time i click anywhere on the document it should hide
// not right away
$(document).on('click', 'html', function(){
$('#show_me').hide();
});
});
$("#click_me").hover(
function () {
$('#show_me').show();
},
function () {
if ($('#show_me').hasClass('remain')){
return;
} else {
$('#show_me').hide();
}
}
);
click me<br /><br />
<div id="show_me"></div>
You need to stop the propagation of the event:
$('#click_me').on('click', function(e){
e.stopPropagation(); //Stop the event from bubbling further
$('#show_me').addClass('remain');
$(document).on('click', 'html', function(){
$('#show_me').hide();
});
});
This is because the event has been captured at the #click_me element. You then bind an event handler for that same event type somewhere higher up the DOM tree. The event then continues bubbling up the tree and reaches the document, where it triggers the new event handler.
Here's a working example.
Update (see comments)
As noted by #zerkms in the comments, I think you probably only want to bind the event handler to document once. You could use the one method to do so, which unbinds the event handler after it's been executed once:
$(document).one('click', 'html', function(){
$('#show_me').hide();
});
Related
On the first click myClick() has been called again in itself of myLoad() then at the second click, this myClick() will execute two times
=> The following causes two subsequent execution of
click event of #myBtn by one click
How to avoid or stop this? Please anybody suggest me new logical method or which way to stop this.
$(function() {
myLoad()
})
function myClick() {
$("#myBtn").click(function() {
myLoad(); //load new every click
});
}
function myLoad() {
$("#myCnt").load('ajax.php', {
"data": "some"
}, function() {
myClick() //to live the click event works after ajax load
})
}
Problem with your implementation is that in each call to myClick() an new event handler is attached to button.
You can use .off() to remove existing event handler attached using .on().
function myClick(){
$("#myBtn").off('click').on('click', function(){
myLoad();//load new every click
});
}
A better approach would be to use .on() method with Event Delegation approach, when generating elements dynamically.
General Syntax
$(document).on('event','selector',callback_function)
In place of document you should use closest static container.
The delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, we can use delegated events to bind the click event to dynamically created elements and also to avoid the need to frequently attach and remove event handlers.
A good read Direct and delegated events
Modify you code as
$(function() {
myLoad();
$(document).on("click", "#myBtn", function() {
myLoad(); //load new every click
});
})
function myLoad() {
$("#myCnt").load('ajax.php', { "data": "some"}, function() {
//No need to call my click
})
}
Issues is in the flow of your code
First time when you call myClick() it binds the click event with #myBtn,
On second time it binds that event again , so it will be called twice , remove that event binding from there,
Or else $("#myBtn").click will be bind each time you call the myClick function.
As solution please try this code :
$(function(){
myLoad()
})
$("body").on( "click" , "#myBtn" , function(){
myLoad();//load new every click
});
function myLoad(){
$("#myCnt").load('ajax.php', {"data":"some"}, function(){
$("#myBtn").trigger("click");
})
}
So, i wondered, why this code doesn't work properly, and what can i do, to prevent such a behaviour:
If I would need to prevent event propagation of parent, whilst particular child got clicked, i used method 1, but it seems not to be working, but method 2 is working fine though.
//method 1
$(document).on({
click: function(e) {
console.log('clicked!');
e.preventDefault();
return false;
}
}, '.hax');
//method 2
/*$('.hax').on('click', function(e){
e.preventDefault();
return false;
});*/
//uncommenting will prevent event propagation
.hax {
background-color: whitesmoke;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='wrapper' onclick='alert("hello")'>
<div class='hax'>hax!</div>
</div>
Method 1 Is using event delegation ,so in it event is not directly bind with the element , its bound with the parent ,So in your case the parent is document . in this the case whatever event will be fired for that particular element it will be tracked down from the DOM tree and will execute the parent call before. In your case it will first call the alert from parent .
In method 2 - event is directly bound with the element , The event of parent will still got fired unless you prevent that in the handler but since the handler is bound to the target , you will not face any other action(alert in your case)
Get better Idea of
Event Delegation
You are creating an event delegation by method 1, which can be created the following way too:
$(document).on('click', '.hax', function (e) {
console.log('clicked!');
e.preventDefault();
return false;
});
For clarifying event delegation briefly:
Understanding how events propagate is an important factor in being able to leverage Event Delegation. Any time one of our anchor tags is clicked, a click event is fired for that anchor, and then bubbles up the DOM tree(Up to DOM top), triggering each of its parent click event handlers.
It does not mean you can't achieve your goal here with this method, but in order to make it work, you can create a middle parent for div.hax which is descendant of div.wrapper. I mean:
<div class='wrapper' onclick='alert("hello")'>
<div id="stopHere">
<div class='hax'>hax!</div>
</div>
</div>
Now, we can use method 1, but we only need to stop event propagation / event delegation before it reach div.wrapper. Thus in our newly added div#stopHere:
$("div#stopHere").on('click', '.hax', function (e) {
console.log('clicked!');
e.preventDefault();
return false;
});
I have a piece of JavaScript using jQuery that looks a bit like this:
$('.myclass').on('click', function() {
// Do Stuff
$(document).on('click.mynamespace', function() {
// Do More Stuff
$(document).off('click.mynamespace');
});
});
Upon a click on .myclass, I am expecting it to Do Stuff, then attach a handler to the click event on the document and Do More Stuff on a subsequent click - but it appears that both Stuff and More Stuff happen on the first click.
Is the click event still firing when the second event handler is attached? How do I achieve my desired effect?
Try calling stopPropagation to prevent the event from bubbling out to the document on the first click:
$('.myclass').on('click', function(e) {
e.stopPropagation();
// Do Stuff
$(document).on('click.mynamespace', function() {
// Do More Stuff
$(document).off('click.mynamespace');
});
});
I have the following click event handlers:
$('html').click(function() { do something});
$('#my_div').click(function() { do something});
my_div is a descendant of html.
If I click on my_div, can I control which is called first? Can I depend on the my_div handler always being handled first?
The Child event handler is always called before the parent event handler (event bubbling). So when you click #my_div, its click event handler is called. Here, you have the option to stop the event to bubble up to html click handler by using
event.stopPropagation()
i.e.
$('#my_div').click(function(event) {
event.stopPropagation();
});
Note: when using jQuery, event.stopPropagation() may not work in all browsers. You will have to take event as an argument in your click handler
ie. $('#my_div').click(function(event){ ... });
Say I have an button with an id:
<input id='someButton' />
I want to attach an event listener on this button:
$('#form').on('click', '#someButton', function() {
alert("My listener called");
});
However, unbeknownst to me, someone previously wrote an event listener for this very same button:
$('#form').on('click', '#someButton', function() {
alert("Some other listener called");
});
I encountered some code that effectively does the same thing as above, and it seems like the first listener registered is the one that is used. Am I correct in assuming jQuery will always call the first event listener registered on a specific id (and only that listener)?
Incorrect. jQuery will call ALL event listeners bound to an element, in the order they were bound.
To remove an existing event handler, use .off():
$('#form').off('click'); // click event handler(s) removed
$('#form').off(); // all event handler(s) removed
Be aware that events delegated from ancestor DOM elements won't be removed this way, though.
you could use mousedown:
$('#form').on('mousedown', '#someButton', function() {
alert("My listener called");
});
Hope this help.