This is more a learning piece for me around how event listeners bound to jQuery selectors are handled.
So say I have the following code:
<html>
<div class = "one">one</div>
<div class = "two">two</div>
</html>
<script>
$(".one").click(function() {
$(this).removeClass("one").addClass("two");
console.log("one");
})
$(".two").click(function() {
console.log("two");
})
</script>
On the first click of one, the selector is no longer valid (as the class is now two instead of one). However the event is still bound to this element. This element will also not fire the ".two" handler as this has already been bound.
What would be the easiest way to unbind a handler with the initial click and then rebind afterwards?
Bind the events on the document, no need to unbind and rebind the events.
$(document).on("click", ".one", function() {
$(this).removeClass("one").addClass("two");
console.log("one");
});
$(document).on("click", ".two", function() {
console.log("two");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="one">one</div>
<div class="two">two</div>
$(".one").unbind("click");
$(".one").bind("click", fn);
You can use unbind() to remove an event added with bind() (or binded like above)
https://jsfiddle.net/7yn7apte/ No re-binding
https://jsfiddle.net/7yn7apte/1/ Re-binding
Well, this answer your question. But, you'd better use on() and off() as bind() calls on() and unbind() calls off().
You can find a more exhaustive explanation here https://stackoverflow.com/a/9113835/6341631
Related
I found a code as shown below.
Html code:
<div id="myButton">Click Here</div>
JQuery Code:
$("#myButton").unbind("click").bind("click",function(){
alert("Working")
});
What is the need of unbind("click") before binding the element?
It is also working if unbind is not used. like shown below
$("#myButton").bind("click",function(){
alert("Working")
});
Which one is best? what is the difference?
This only makes sure, that there is no other click event listener attached. So your handler will be the only handler acting upon clicking the #myButton
Edit: as #T.J. Crowder noted in the comments, unbind() will not affect handlers attached in different way than by calling bind().
It is also worth noting, that:
as of jQuery 1.7, the .on() and .off() methods are preferred to attach and remove event handlers on elements
(excerpt from the jQuery.unbind() doc). In fact, unbind() is implemented internally by the off() method).
Consider:
$("#myButton").bind('click', function () {
console.log('click 1');
});
$("#myButton").unbind('click').bind('click', function () {
console.log('click 2');
});
// When clicked, prints "click 2"
Versus:
$("#myButton").bind('click', function () {
console.log('click 1');
});
// note: no unbind here
$("#myButton").bind('click', function () {
console.log('click 2');
});
// When clicked, prints "clicked 1" followed by "clicked 2"
By unbinding "click" event on an element, you are actually removing all the onclick events associated with that element. i.e. if your html form's input field has an onclick event and it calls a function, it will be unbound. After an unbind, you are binding another click event which will call your function onclick of that element.
$("#myButton").unbind("click").bind("click",function(){
alert("Working")
});
jQuery bind() function is used to attach an event handler to elements, while the unbind() is used to detached an existing event handler from elements. please see a demo http://www.mkyong.com/wp-content/uploads/jQuery/jQuery-bind-unbind-example.html
Without url of this html code , i'm not sure that #myButtonelement whether has other click handler attached ,but what is certain is unbind method remove all the handler on this element , i think the author only want to trigger one click event.
Also, you can see if there is other event handler on debug inspector of browser.
Hope this will help you.
I doing this way:
$.each($('img'), function () {
this.unbind('onmouseover');
});
This does not work. Why?
Try like below,
$('img').unbind('mouseover');
No need for looping.. and also it should be mouseover not onmouseover
Assumptions: You are using .bind to bind the mouseover handler
I'm not using bind. some images have onmouseover attribute and I want to delete them. I tries $('img').removeAttr('onmouseover') but it still does not work
Using inline event handler is not a standard.
Since you are using jQuery, you should bind handler like below.
Code:
$('img').on('mouseover', function () {
//Your code
});
And later can unbind them by using .off ->
$('img').off('mouseover');
A work around for what you have (not preferred), (Reference)
$.each($('img'), function () {
$(this).removeAttr('onmouseover');
});
No need for $.each() when a jQuery element collection already has an internal each().
Also, you can "daisy chain" remove handlers methods in jQuery since each function returns the same collection. Each attach method has it's own remove method pair, so use accordingly.
on() => off()
bind() => unbind()
live() => die()
Lastly, to remove the handlers on the DOM elements (the inline event handlers), replace it with null or a function that does return false;
Here's the concept code:
$('img')
.unbind('mouseover') //remove events attached with bind
.off('mouseover') //remove events attached with on
.die('mouseover'); //remove events attached with live
.each(function(i,el){ //and for each element
el.onmouseover = null //replace the onmouseover event
});
Say I have this code in my page:
<script language="javascript">
$(document).ready(function() {
$(".test").click(function() {
alert('Hello');
});
});
</script>
Why doesn't the previous code apply to elements with the class "test" which I add later to the document like this for example:
$('body').append('<p class="test">Test</p>');
Because what happens is that when I click the previous <p> tag nothing happens.
Also, if I have this:
<div id="first">Edit me.<div id="second">Save me.</div></div>
Can I do what the text describes? that is, controlling the content of the #first div without affecting the content of the #second div?
Thank you.
The problem is that .click() does only apply a listener for elements that are available in the DOM when the method is executed. You should take a look at .on() instead.
With .on() you can delegate the event, like this for instance:
$("body").on("click", ".test", function() {
alert('Hello');
});
Now any element (current and future) with the class test available within your body will have a click-event listener.
live is deprecated as of 1.7, use on
http://api.jquery.com/on/
try using on() listener:
$(document).on("click",".test", function() {
alert('Hello');
});
When you bind events to elements they only bind to those elements that have already been created. So you need to run the 'bind' command again on the new elements.
Alternatively, you can use on('click') which will bind the event to existing and all future elements.
Because at the time you attach your event handler the object doesnt exist yet. You cant subscribe to elements that dont exist. You can use the Live method for this.
http://api.jquery.com/live/
It seems those are deprecated (thanks #Anthony Grist). Use On, or delegate() instead.
http://api.jquery.com/on/
http://api.jquery.com/delegate/
$('div').on('click', function()
{
//Do something
});
you should use "on" to bind events with the elements that are added after the script is interpreted.
$(document).on("click", selector, function(e){
//do something
});
If you need to apply the click to later added tags, you should use live on
$(document).on('click','.test',function() { });
EDIT: #Anthony your're right. live is deprecated. Updated the code
I would like to delegate the event one for the click. Does anyone know if it is possible to do it?
I'm going to assume that you want the event to fire only once PER matched element rather than unbind entirely on the first click.
I'd implement it like so:
$('#container').delegate('.children', 'click', function() {
if($(this).data('clicked')) {
return;
}
// ... your code here ...
$(this).data('clicked', true);
});
This will fire only once per element. Technically, it fires everytime but is flagged the first time it is clicked so the code will not execute again.
The inherent problem of simulating a .one() handler w/ delegate is that using .one() each element that was matched in the selector is bound its own event handler. So when it is fired for the first time it unbinds/removes the handler from that element. You can't do that with .delegate() because only a SINGLE handler is being used for ALL the matched elements.
While the code above simulates it perfectly, it is still somewhat hackish because it doesn't literally do the same thing that .one() does (unbinding an event handler).
Since this post is a few years old, I just wanted to provide a complete updated example for more contemporary readers (2015). The logic is no different from the other answers here, but jQuery's methods have evolved since 2011. Specifically:
As of jQuery 1.7, .delegate() has been superseded by the .on() method.
jQuery delegate()
// define output element
var $output = $('div#output');
// attach delegated click handler
$(document).on('click', 'button', function() {
// define clicked element
var $this=$(this);
// if this element has already been clicked, abort
if ($this.data('clicked')) {
return false;
}
// perform click actions
$output.append("clicked " + $this.html() + "<br />");
// mark this element as clicked
$this.data('clicked',true);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>One</button>
<button>Two</button>
<button>Three</button>
<div id="output"></div>
I'm sure there is a neat way of doing it, but a simple way to do it would be something like this:
<script>
$(document).ready(function(){
$("#container").delegate('.clickers', 'click', function(){
if($(this).data("clicked")==null){
$(this).data("clicked", "true");
$("#container").append($(this).html());
}
});
});
</script>
<div class="clickers" clicked="false"></div>
<div class="clickers" clicked="false"></div>
EDIT: Thanks to the comments below I decided to use data, now this doesn't screw the DOM all up for w3c standards.
How do I unbind "hover" in jQuery?
This does not work:
$(this).unbind('hover');
$(this).unbind('mouseenter').unbind('mouseleave')
or more succinctly (thanks #Chad Grant):
$(this).unbind('mouseenter mouseleave')
Actually, the jQuery documentation has a more simple approach than the chained examples shown above (although they'll work just fine):
$("#myElement").unbind('mouseenter mouseleave');
As of jQuery 1.7, you are also able use $.on() and $.off() for event binding, so to unbind the hover event, you would use the simpler and tidier:
$('#myElement').off('hover');
The pseudo-event-name "hover" is used as a shorthand for "mouseenter mouseleave" but was handled differently in earlier jQuery versions; requiring you to expressly remove each of the literal event names. Using $.off() now allows you to drop both mouse events using the same shorthand.
Edit 2016:
Still a popular question so it's worth drawing attention to #Dennis98's point in the comments below that in jQuery 1.9+, the "hover" event was deprecated in favour of the standard "mouseenter mouseleave" calls. So your event binding declaration should now look like this:
$('#myElement').off('mouseenter mouseleave');
Unbind the mouseenter and mouseleave events individually or unbind all events on the element(s).
$(this).unbind('mouseenter').unbind('mouseleave');
or
$(this).unbind(); // assuming you have no other handlers you want to keep
unbind() doesn't work with hardcoded inline events.
So, for example, if you want to unbind the mouseover event from
<div id="some_div" onmouseover="do_something();">, I found that $('#some_div').attr('onmouseover','') is a quick and dirty way to achieve it.
Another solution is .die() for events who that attached with .live().
Ex.:
// attach click event for <a> tags
$('a').live('click', function(){});
// deattach click event from <a> tags
$('a').die('click');
You can find a good refference here: Exploring jQuery .live() and .die()
( Sorry for my english :"> )
All hover is doing behind the scenes is binding to the mouseover and mouseout property. I would bind and unbind your functions from those events individually.
For example, say you have the following html:
Link
then your jQuery would be:
$(document).ready(function() {
function mouseOver()
{
$(this).css('color', 'red');
}
function mouseOut()
{
$(this).css('color', 'blue');
}
// either of these might work
$('.myLink').hover(mouseOver, mouseOut);
$('.myLink').mouseover(mouseOver).mouseout(mouseOut);
// otherwise use this
$('.myLink').bind('mouseover', mouseOver).bind('mouseout', mouseOut);
// then to unbind
$('.myLink').click(function(e) {
e.preventDefault();
$('.myLink').unbind('mouseover', mouseOver).unbind('mouseout', mouseOut);
});
});
You can remove a specific event handler that was attached by on, using off
$("#ID").on ("eventName", additionalCss, handlerFunction);
// to remove the specific handler
$("#ID").off ("eventName", additionalCss, handlerFunction);
Using this, you will remove only handlerFunction
Another good practice, is to set a nameSpace for multiple attached events
$("#ID").on ("eventName1.nameSpace", additionalCss, handlerFunction1);
$("#ID").on ("eventName2.nameSpace", additionalCss, handlerFunction2);
// ...
$("#ID").on ("eventNameN.nameSpace", additionalCss, handlerFunctionN);
// and to remove handlerFunction from 1 to N, just use this
$("#ID").off(".nameSpace");
I found this works as second argument (function) to .hover()
$('#yourId').hover(
function(){
// Your code goes here
},
function(){
$(this).unbind()
}
});
The first function (argument to .hover()) is mouseover and will execute your code. The second argument is mouseout which will unbind the hover event from #yourId.
Your code will be executed only once.