What does bind and unbind mean in jquery in idiot slow learner terms?
Binding: coupling an handler to an element(s), that will run when an event occurs on said element(s). Depending on what kind of event you want to handle you'd use different functions like click(function) (alt: bind('click', function) or focus(function) (alt: bind('focus', function).
Unbinding: de-coupling of an handler from an element(s), so that when an event occurs the handler function will no longer run. Unbinding is always the same; unbind('click', function) to unbind a certain handler, unbind('click') to unbind ALL click handlers, and unbind() to unbind ALL handlers. You can substitute click for other types of events of course.
In simple terms: for binding and unbinding event handlers to elements.
$("#divElement").bind('click', functionName);
binds a click event handler to the element with id divElement
$("#divElement").unbind('click', functionName);
unbinds a click event handler to the element with id divElement
Edit:
Bind also allows you to bind a handler to one or more events.
$("#divElement").bind("click dblclick mouseout", function(){ // your code });
Update:
As of jQuery 1.7, the .on() and .off() methods are preferred to attach and remove event handlers on elements.
In three sentences:
An event is a signal that is visible in your program - a key press, for example.
A handler is a function that is geared towards reacting to a certain event.
Binding associates a handler with an event, unbinding does the opposite.
Bind attaches a piece of code to be run to a given HTML element (which is run on the supplied event). unbind removes it.
Related
I see how you might do this with an onclick event: How do you override inline onclick event?
However there is an event which seems to be bound to a specific HTML element that I would like to remove/nullify.
Here is how it is bound with jQuery:
$('.play-control').bind('click', function(evt){
player.play();
});
Using the SE link I provided above does not "disassociate" the original binding. Seems to only work with onclick events.
How then would I "unbind" an event binding in Javascript (or jQuery)?
You can unbind all click handlers hooked up with jQuery using unbind or, with more up-to-date versions of jQuery, off:
$('.play-control').unbind('click');
// or
$('.play-control').off('click');
But unless you can change that code hooking up that handler, you can't unhook just that specific one without delving into jQuery internal data structures which can change without notice between dot releases.
If you can change that code, here are two ways you could target just that handler:
1. Use a named function:
Hooking it up:
function playClick(evt){
player.play();
}
$('.play-control').on('click', playClick); // Or use `bind`
Unhooking it:
$('.play-control').off('click', playClick); // Or use `unbind`
2. Use an "event namespace":
Hooking it up:
$('.play-control').on('click.play', function(evt){ // Or use `bind`
player.play();
});
Unhooking it:
$('.play-control').off('click.play'); // Or use `unbind`
Note the .play added to click.
More in the documentation: on, off
Event handlers attached with .bind() can be removed with .unbind().
(As of jQuery 1.7, the .on() and .off() methods are preferred to
attach and remove event handlers on elements.) In the simplest case,
with no arguments, .unbind() removes all handlers attached to the
elements: http://api.jquery.com/unbind/
According to Jquery, use of off and on is preferred
$(document).bind('click', '.play-control', function(evt){
player.play();
})
$('.play-control').off('click');
Need to get info from any element, which was clicked.
Example:
<div>text1<section>text2</section></div>
and JS
$(function(){
$('body *').click(function(){
alert($(this).get(0).tagName.toLowerCase());
});
});
If I click text2, parent element throw alert too. I need only first alert from section. How I can block next alerts from all parent elements of section.
Use event.stopPropagation() to prevent the event from firing on the containing elements.
$(function(){
$('body *').click(function(e){
e.stopPropagation();
alert($(this).get(0).tagName.toLowerCase());
});
});
Just wanted to expand on Kooilnc answer - Using on with event delegation is another option.
Event delegation would be nice if you have an event listener bound before or after on a node that needs to listen to a click handler that has bubbled up. If you stopPropagation, this obviously would be an issue.
Here's a fiddle with a demo:
http://jsfiddle.net/ahgtLjbn/
Let's say a buddy of yours has bound an event listener to a node higher up in the DOM tree. He expects any events that bubble up to it, to be handled by his script.
Using event delegation, the event still bubbles up (so your buddies code will still fire), but it will only alert once (since we called e.stopPropagation).
Calling on without event delegation, or binding the event directly using click (which, under the hood, is just calling on) will prevent the event from bubbling, so your buddies code will never run.
It's an audio player: the idea is that the play button turns into a pause button (and viceversa) when clicked.
Thing is that the .pause event doesn't trigger the following function:
$('.pause').click(function(){
player.pause();
$(this).addClass('play');
$(this).removeClass('pause');
});
The css shows that the pause class is set, but the function doesn't work. Is there a way to make it work? (would be great to know why it didn't work)
jsFiddle
Use a delegated event binding to bind a handler that will be selector-aware without requiring rebinding on events.
For the purposes of your demo, the selector would be along the lines of:
$('.player_controls').on('click', '.pause', function () {...});
Delegate event bindings attach the listener to a parent element that checks to see if the event fired was fired on an element that matches the provided selector.
jQuery docs
When a selector is provided, the event handler is referred to as delegated. The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector. jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page. If new HTML is being injected into the page, select the elements and attach event handlers after the new HTML is placed into the page. Or, use delegated events to attach an event handler, as described next.
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, you can use delegated events to avoid the need to frequently attach and remove event handlers. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready.
You can use event delegation for this. The issue is that binding directly (without delegation) binds to whichever elements exist at the time click is called.
$(".player_controls").on("click", ".pause", function(){
/* ... */
});
Instead of using $('.pause').click(function(){...}) you would need to start using the $.on method to start listening for objects which are still not in the DOM.
e.g
$(".pause").parent().on("click",".pause", function(event){
player.pause();
$(this).addClass('play');
$(this).removeClass('pause');
});
I've a bad-programmed library which is doing this
$(document).on('click','#keep_first_only_button', function(){
I wrote, after this, a piece of code to 'override' this bad behaviour
$("keep_first_only_button").unbind("click");
$("keep_first_only_button").on("click", selectKeepFirstOfAll);
BUT this is not working, then document.click function handler is triggered again
I cannot unbind all click events from document, because disasters will happen in the page.
Which is the right way to proceed in this situation?
EDIT: Sorry for time loosing question, I didn't see the missing '#' in my selector. I'm really sorry !
The original event handler was bound as a delegated event, so you can't remove it from $('#keep_first_only_button') itself. You need to remove it on the document level.
From the documentation:
To remove specific delegated event handlers, provide a selector
argument. The selector string must exactly match the one passed to
.on() when the event handler was attached. To remove all delegated
events from an element without removing non-delegated events, use the
special value "**".
In other words, to unbind a delegated event, you should just use the same set of arguments you used to bind them but pass them to off instead. Since the bound function is anonymous you can't reference it, so you'll have to settle with unbinding all delegated event handlers bound to #keep_first_only_button on the document level:
$(document).off('click', '#keep_first_only_button');
EDIT: Looks like the problem was just the missing hash. Odd, I thought you couldn't unbind delegated event handlers using a regular .off() call...
$("#keep_first_only_button")...
Missing the hash?
For anyone wondering ...Mattias Buelens is correct.
If you have the element bound like
$(document).on("click","#element",function(){ });
And want to shut it off later, you have to do it as:
$("#element").click(function(e) {
$(document).off('click', '#element');
});
If you want remove event with out consider selector use
$(document).off("click","**");
HTML
<div>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
jQuery
$('div span').on('click', function(){
//direct - 1st method
});
$('div').on('click','span', function(){
//delegation - 2nd method
});
I have used both above method in my code. I know second method is better due to it has only got single handler. My problems are:
Is first method (direct) refers to the concept called event capturing? Is it an example for event capturing?
Is second method (delegation) refers to the concept called event bubbling? Is it an example for event bubbling?
It appears as though All jQuery event methods use Event Bubbling, not Event Capturing.
Therefore, both of your examples will use Event Bubbling.
There is an edge case with focus and blur events not bubbling in some browsers. In the affected browsers, Event Capturing is used for focus and blur events.
For reference, you can simply view the source. http://code.jquery.com/jquery.js
$('div span').on('click', function(){
//direct - 1st method
});
This event only attached the event handler to the spans inside Div that are currently present in the DOM.. i.e; if a new span element is added to the div , that span will not have a click event associated with it..
The first and second one are example's of Event Bubbling
There comes the concept of Event delegation where in the ancestor is given the event handler and it is delegated to the children..
The second example is an example of event delegation .
Wherein event is attached to the parent element..So all the span element's inside the div class are attached to the event handler ..
So if a new span element is added to the div , becoz the event is associated with the span's ancestor the event will fire in this case
This helps in cases
$('div').on('click','span', function(){
//delegation - 2nd method
});
I have no idea where event capturing is used in the jQuery library
Answers to your questions:
This isn't bubbling, capturing, or delegating. It's just adding an event listener directly to an element.
Yep, this is delegation that under the hood relies on clicks bubbling up.
Event bubbling and capturing are different implementations of the same concept, brought to you by Microsoft and Netscape, respectively. Both listening for events on parent elements. Note that they occur in a different order: capturing happens from the parent down to descendent, whereas bubbling happens the other way around.
More details and its history on PPK's website: http://www.quirksmode.org/js/events_order.html
Modern browsers support both capture and bubbling (bubbling is the default now), and you can specify which one you want to use when you use the native addEventListener:
element.addEventListener('click', function(){}, false); // bubble
element.addEventListener('click', function(){}, true); // capture
However, some events, such as focus, blur, scroll, mouseover, etc only are supported through capture phase events, so you MUST specify "true" when you use addEventListener.
Unfortunately, it looks like jQuery doesn't support delegation for all capture phase events, only focus and blur (see https://github.com/jquery/jquery/blob/ad032d3c7df04827989a4187117614c29bf3a4ad/src/event.js#L728).
The short answer: for delegation of capture-phase events other than focus and blur, you need to use the native addEventListener, not jQuery.