Why use jQuery on() instead of click() - javascript

Currently with jQuery when I need to do something when a Click occurs I will do it like this...
$(".close-box").click( function() {
MoneyBox.closeBox();
return false;
});
I was looking at some code someone else has on a project and they do it like this...
$(".close-box").live("click", function () {
MoneyBox.closeBox();
return false;
});
Notice it seems to do the same thing as far as I can tell except they are using the live() function which is now Deprecated and jQuery docs say to use on() instead but either way why use live/on() instead of my first example?

Because you might have a dynamically generated elements (for example coming from an AJAX call), you might want to have the same click handler that was previously bound to the same element selector, you then "delegate" the click event using on() with selector argument
To demonstrate:
http://jsfiddle.net/AJRw3/
on() can also be synonymous with click() if you don't have a selector specified:
$('.elementClass').click(function() { // code
});
is synonymous with
$('.elementClass').on('click', function() { // code
});
In the sense that it only add the handler one time to all elements with class elementClass. If you have a new elementClass coming from, for example $('<div class="elementClass" />'), the handler won't be bound on that new element, you need to do:
$('#container').on('click', '.elementClass', function() { // code
});
Assuming #container is .elementClass's ancestor

There are a lot of answers, each touching on a few points - hopefully this can give you your answer, with a good explanation of what's what and how to use it.
Using click() is an alias to bind('click' ...). Using bind() takes the DOM as it is when the event listener is being set up and binds the function to each of the matching elements in the DOM. That is to say if you use $('a').click(...) you will bind the function supplied to the click event of every anchor tag in the DOM found when that code runs.
Using live() was the old way in jQuery; it was used to bind events just like bind() does, but it doesn't just bind them to elements in the DOM when the code runs - it also listens to changes in the DOM and will bind events to any future-matched elements as well. This is useful if you're doing DOM manipulation and you need an event to exist on some elements that may get removed/updated/added to the DOM later but don't exist when the DOM is first loaded.
The reason that live() is now depreciated is because it was poorly implemented. In order to use live(), you had to be able to select at least one element in the DOM initially (I believe). It also caused a copy of the function to run to be bound to each element - and if you have 1000 elements, that's a lot of copied functions.
The creation of the on() function was to overcome those problems. It lets you bind a single event listener to an object that will not change in the DOM (so you can't use on() on an element that will be removed/added to the DOM later - bind it to a parent object), and simply apply an element "filter" so that the function is only run when it is bubbled up to an element that matches the selector. This means you have just one function that exists (not a bunch of copies) bound to a single element - a much better approach to adding "live" events in the DOM.
... and that is what the differences are, and why each function exists and why live() is depreciated.

$("a").live() --> It will apply to all <a>, even if it is created after this is called.
$("a").click() --> It will only apply to all <a> before this is called. (This is a shortcut of bind(), and on() in 1.7)
$("a").on() --> Provides all functionality required for attaching event handlers. (Newest in jQuery 1.7)
Quotes:
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().This method provides a means to attach delegated event handlers to the document element of a page, which simplifies the use of event handlers when content is dynamically added to a page. See the discussion of direct versus delegated events in the .on() method for more information.
The .on() method attaches event handlers to the currently selected set of elements in the jQuery object. As of jQuery 1.7, the .on() method provides all functionality required for attaching event handlers.
For earlier versions, the .bind() method is used for attaching an event handler directly to elements.

click() is a shortcut to the non delegation method of on(). So:
$(".close-box").click() === $(".close-box").on('click')
To delegate events with on(), ie. in dynamic created objects you can do:
$(document).on('click', '.close-box') // Same as $('.close-box').live()
But, on() introduces delegation in any static element, not just document as live() does, so:
$("#closestStaticElement").on('click', '.close-box')

You should read up on the difference between live and bind.
In a nutshell, live uses event delegation, allowing you to bind to elements that exist now and in the future.
In contrast, handlers attached via bind (and its shortcuts, like click) attach handlers directly to the DOM elements matching the selector, and therefore are only bound to elements that exist now.
A consequence of live's flexibility is decreased performance, so only use it when you need the functionality it provides.

$el.click(fn) is a shortcut for $el.on('click', fn)
See http://api.jquery.com/click/ and http://api.jquery.com/on/ for more info.

When you need to bind some event handlers to dynamically added elements you have to use live (deprecated) or on make the it working. Simply $('element').click(...); won't work on any dynamically added element in to the DOM.
More on The Difference Between jQuery’s .bind(), .live(), and .delegate().

$.click() is merely a shortcut for either bind or on. From jQuery docs:
In the first two variations, this method is a shortcut for .bind("click", handler), as well as for .on("click", handler) as of jQuery 1.7. In the third variation, when .click() is called without arguments, it is a shortcut for .trigger("click").

The .on() method attaches event handlers to the currently selected set of elements in the jQuery object. The click() method binds an event handler to the "click" JavaScript event, or triggers that event on an element.
In the plain .click(... if the target of the selector changes on the fly (e.g via some ajax response) then you'd need to assign the behavior again.
The .on(... is very new (jQuery 1.7) and it can cover the live scenario using delegated events which is a faster way to attach behavior anyway.

In on method, event handler is attached to the parent element instead of target.
example: $(document).on("click", ".className", function(){});
In above example, click event handler is attached to document.
And it uses event bubbling to know whether someone clicked on the target element.

Related

.bind not working for dynamically creating id?

I am trying to bind to dynamically changing id , the code works fine for static id but once i used to bind dynamically its not binding .
$("#placeholder"+id).bind("\""+"plothover"+id+"\"", function (event, pos, item) {--some code here --}
If use in this way it works fine
$("#placeholder"+id).bind("plothover", function (event, pos, item) {--some code here --}
This is due to bind not working for dynamic elements, taken from the jQuery site:
As of jQuery 1.7, the .on() method is the preferred method for
attaching event handlers to a document. For earlier versions, the
.bind() method is used for attaching an event handler directly to
elements. Handlers are attached to the currently selected elements in
the jQuery object, so those elements must exist at the point the call
to .bind() occurs. For more flexible event binding, see the discussion
of event delegation in .on() or .delegate().
The solution here is to use the .on method.
We also need to know which event you want to catch, bind is binding an event to an element, such as "click". At the minute, you seem to not be binding to any specific event.
Try by including "live" method instead of "bind".
If your element is not yet created .bind() will not work! You have to use .live()
http://api.jquery.com/live/
It binds the event one time on the parent element and you handle all child events from there. It's the right approach and that way you have just one event on the parent which prevents memory leaks if you don't remove properly the dynamic elements.
Ooops:
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().
But it still doing the same stuff : )
Use the 'on' function:
use as bind - $(el).on('event name',callback);
use as live - $(el parent).on('event name','element selector',[may be some data],callback)
namespace - $(el).on('namespace.event',callback)
data - $(el).on('event',{col: varCol},callback)

Use jquery inside or outside document ready

Below two scenario give me the same behavior. But What is the difference technically? (I put the below code in the last section of script tags in the body.)
$(document).ready(function() {
$('.collapse').collapse({toggle: false});
$(document).on('click', '#expandAllLessons', function() {
$('div.accordion-body').collapse('show');
});
$(document).on('click', '#collapseAllLessons', function() {
$('div.accordion-body.collapse').collapse('hide');
});
});
or
$(document).ready(function() {
$('.collapse').collapse({toggle: false});
});
$(document).on('click', '#expandAllLessons', function() {
$('div.accordion-body').collapse('show');
});
$(document).on('click', '#collapseAllLessons', function() {
$('div.accordion-body.collapse').collapse('hide');
});
Thanks.
More or less, it's doing the same thing.
With the use of .on() with a child selector, you're using event delegation to bind any future events to any elements that match that selector. document is the very tippy top of the DOM tree (and available upon script execution), so your event delegation works.
.ready() waits until the DOM has assembled, so you can, more reliably, directly bind events using methods like .click(), .hover(), etc.
So your first example is just waiting for the DOM to assemble, then delegating the event. The second example is just delegating the event immediately upon script execution.
From jQuery's documentation regarding .on():
Direct and delegated events
The majority of browser events bubble, or
propagate, from the deepest, innermost element (the event target) in
the document where they occur all the way up to the body and the
document element. In Internet Explorer 8 and lower, a few events such
as change and submit do not natively bubble but jQuery patches these
to bubble and create consistent cross-browser behavior.
If selector is omitted or is null, the event handler is referred to as
direct or directly-bound. The handler is called every time an event
occurs on the selected elements, whether it occurs directly on the
element or bubbles from a descendant (inner) element.
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.
Whenever you do a function, regardless of whether it's $(document).ready(function(){}); or something else, all the contents inside that function can only read stuff that's at its level or above it (unless you're using return functions).
The top paragraph means that all your code won't be executed until it's loaded, but it also means that it's nested code. Nested code means certain variables and functions won't be readable from outside. Example:
function bob(){
function sandy(){
function joe(){
alert("I can access anything written by sandy, bob or ray!");
}
}
}
function ray(){
alert("I can't see anything from anybody but bob!");
}
Look at the comments first. After jQuery 1.7 on can delegate events as well:
"The .on() method attaches event handlers to the currently selected
set of elements in the jQuery object. As of jQuery 1.7, the .on()
method provides all functionality required for attaching event
handlers. For help in converting from older jQuery event methods, see
.bind(), .delegate(), and .live()."
So before jQuery 1.7 this is the correct answer:
First is better because, document ready event is triggered when HTML document is fully loaded to DOM. And then you're sure you have all elements in place, and you can bind events to them.
But if you bind event before loading '#expandAllLessons' element to DOM, then it will simply not work, as jQuery selector will not find any elements, and will not bind this event anywhere.
After 1.7 both will work almost in the same way. Almost, because in first case, when you trigger event before document will be ready, it will not be executed. In second example it will be executed, because it was attached when script was loaded.

Remove specific event

Suppose i have a component, inputType="text" with id ="cmp";
In a js file ,
$("input[type='text']").bind('keypress', function(e) {
//Case 1
});
In my jsp file,
$("#cmp").keypress(function() {
//Case 2
});
Now I need to remove only one keypress event.
Is it possible to remove the keypress event for id ="cmp" that is registered from js file.
But we should not not remove event that is registered from jsp file.
Note:
According to my requirement, I cannot change .js file.
you can use off of jquery method to remove events Jquery OFf
The off() method removes event handlers that were attached with .on().
See the discussion of delegated and directly bound events on that page
for more information. Specific event handlers can be removed on
elements by providing combinations of event names, namespaces,
selectors, or handler function names. When multiple filtering
arguments are given, all of the arguments provided must match for the
event handler to be removed.
$('#cmp').off('keypress');
use off()
off: Remove an event handler.
$('#cmp').off('keypress');
You will want to use either .unbind() or .off() (jQuery 1.7+) depending on how the event was originally attached and what version of jQuery you are using.
// Prior to jQuery 1.7
$("#cmp").unbind("keypress");
// jQuery 1.7+
$("#cmp").off("keypress");
If you can modify the original location where you are binding the event handler, you might also be able to use event namespaces to remove only a specifically named event.
// Original binding
$("#cmp").on("keypress.someName", function() {
...
});
// Unbinding
$("#cmp").off("keypress.someName");
EXAMPLE

jQuery .live() vs .on() method for adding a click event after loading dynamic html

I am using jQuery v.1.7.1 where the .live() method is apparently deprecated.
The problem I am having is that when dynamically loading html into an element using:
$('#parent').load("http://...");
If I try and add a click event afterwards it does not register the event using either of these methods:
$('#parent').click(function() ...);
or
// according to documentation this should be used instead of .live()
$('#child').on('click', function() ...);
What is the correct way to achieve this functionality? It only seems to work with .live() for me, but I shouldn't be using that method. Note that #child is a dynamically loaded element.
Thanks.
If you want the click handler to work for an element that gets loaded dynamically, then you set the event handler on a parent object (that does not get loaded dynamically) and give it a selector that matches your dynamic object like this:
$('#parent').on("click", "#child", function() {});
The event handler will be attached to the #parent object and anytime a click event bubbles up to it that originated on #child, it will fire your click handler. This is called delegated event handling (the event handling is delegated to a parent object).
It's done this way because you can attach the event to the #parent object even when the #child object does not exist yet, but when it later exists and gets clicked on, the click event will bubble up to the #parent object, it will see that it originated on #child and there is an event handler for a click on #child and fire your event.
Try this:
$('#parent').on('click', '#child', function() {
// Code
});
From the $.on() documentation:
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().
Your #child element doesn't exist when you call $.on() on it, so the event isn't bound (unlike $.live()). #parent, however, does exist, so binding the event to that is fine.
The second argument in my code above acts as a 'filter' to only trigger if the event bubbled up to #parent from #child.
$(document).on('click', '.selector', function() { /* do stuff */ });
EDIT: I'm providing a bit more information on how this works, because... words.
With this example, you are placing a listener on the entire document.
When you click on any element(s) matching .selector, the event bubbles up to the main document -- so long as there's no other listeners that call event.stopPropagation() method -- which would top the bubbling of an event to parent elements.
Instead of binding to a specific element or set of elements, you are listening for any events coming from elements that match the specified selector. This means you can create one listener, one time, that will automatically match currently existing elements as well as any dynamically added elements.
This is smart for a few reasons, including performance and memory utilization (in large scale applications)
EDIT:
Obviously, the closest parent element you can listen on is better, and you can use any element in place of document as long as the children you want to monitor events for are within that parent element... but that really does not have anything to do with the question.
The equivalent of .live() in 1.7 looks like this:
$(document).on('click', '#child', function() ...);
Basically, watch the document for click events and filter them for #child.
I know it's a little late for an answer, but I've created a polyfill for the .live() method. I've tested it in jQuery 1.11, and it seems to work pretty well. I know that we're supposed to implement the .on() method wherever possible, but in big projects, where it's not possible to convert all .live() calls to the equivalent .on() calls for whatever reason, the following might work:
if(jQuery && !jQuery.fn.live) {
jQuery.fn.live = function(evt, func) {
$('body').on(evt, this.selector, func);
}
}
Just include it after you load jQuery and before you call live().
.on() is for jQuery version 1.7 and above. If you have an older version, use this:
$("#SomeId").live("click",function(){
//do stuff;
});
I used 'live' in my project but one of my friend suggested that i should use 'on' instead of live.
And when i tried to use that i experienced a problem like you had.
On my pages i create buttons table rows and many dom stuff dynamically. but when i use on the magic disappeared.
The other solutions like use it like a child just calls your functions every time on every click.
But i find a way to make it happen again and here is the solution.
Write your code as:
function caller(){
$('.ObjectYouWntToCall').on("click", function() {...magic...});
}
Call caller(); after you create your object in the page like this.
$('<dom class="ObjectYouWntToCall">bla... bla...<dom>').appendTo("#whereeveryouwant");
caller();
By this way your function is called when it is supposed to not every click on the page.

Does the jQuery .unbind() method only work on jQuery created events?

I am trying to unbind all event handlers for all elements that are inside a particular container. Like a DIV. But those events have been bound/registered not using jQuery. Some are bound the manual way with onclick="...." or using regular native JavaScript.
But when I do something like this
$('#TheDivContainer').find('div,td,tr,tbody,table').unbind();
It does not appear to work. Which leads me to believe that the .unbind() only works if the events have been originally bound by jQuery.
Is that true? Is there another way of unbinding all events from a group of elements?
Thanks!
You are right. As in the API:
Any handler that has been attached
with .bind() can be removed with
.unbind().
Unbind will only work on jQuery created events as all methods that does this (addEventListener, and attachEvent) requires the both the node, the eventname, and the handler as an argument. bind takes care of storing these for you..
By the way, DOM0 style event listerens (.foo = function(...) can only by removed by setting the same property to something else like null.
You could always do this:
$('#TheDivContainer').find('div,td,tr,tbody,table')
.unbind('click')
.attr('onclick', ''); // edited to change null to ''
etc. for all appropriate event types.

Categories