This question already has answers here:
What's the difference between jQuery .live() and .on()
(8 answers)
Closed 9 years ago.
This may sound "silly" but I have a simple calendar that is loaded onto the page like this:
jQuery('#calendar .show_hide').load('plugins/calendar.html', function(){ // do something // });
That is not a problem
The calendar has 2 links that should scroll through the months - typical next prev links. So inside my load function I have this
jQuery('#calendar .show_hide').load('plugins/calendar.html', function(){
jQuery('a.month_change').on('click',function(){
jQuery.ajax({
type: "post",
data: jQuery(this).attr('href').replace('#',''),
url: 'plugins/calendar.html',
success:function(msg){
jQuery('#calendar .show_hide').html(msg);
}
});
});
});
where a.month_change is a class attached to the prev/next links. The Ajax post sends the data and returns the html. So far so good.
The first time you click a.month_change it works, but every time afterwards the page is not loaded. if I try .live('click;,function ... nothing happens the first time, nor any other.
I always get confused on these things, which is the correct way to dynamically load the page and then have the ajax calls/links etc. always work. Note the dynamic load and the ajax receiving page are the same page - plugins/calendar.html and JQ version is jquery-1.9.0
Live is deprecated since 1.7 and removed in 1.9 you must use it like this
$(document).on('click','selector',function(){
});
You should use the closest static element instead of document if you have one closer.
live() is depreciated, you should use the on() function instead.
$(document).on('click','selector',function(){
});
None of the answers here effectively show you how to use it, OR the documentation, so here you go.
jQuery(document).on('click', 'a.month_change', function(){
jQuery.ajax({
type: "post",
data: jQuery(this).attr('href').replace('#',''),
url: 'plugins/calendar.html',
success:function(msg){
jQuery('#calendar .show_hide').html(msg);
}
});
});
Where the first element we target is a static element that exists during page load, then the event we wish to capture, followed by the element that should have the event bound to it. This is event delegation in newer versions of jQuery. You don't need to use .live(), or .bind().
Here's the documentation for jQuery's .on()
use .on() because it also works on dynamically added DOM.
.live() is deprecated from new version.
Run Test
try
<script type="text/javascript">
$(function()
{
jQuery('a.month_change').on('click',function()
{
jQuery.ajax(
{
type: "post",
data: jQuery(this).attr('href').replace('#',''),
url: 'plugins/calendar.html',
success:function(msg)
{
jQuery('#calendar .show_hide').html(msg);
}
});
});
jQuery('#calendar .show_hide').load('plugins/calendar.html', function()
{
});
});
</script>
best is use Jquery on method. .live() is deprecated from new version.
for eg;
$('#yourElement').on('click',function(){});
Try
$(parentcontainer).on('click',elementtoclick,function(...){....});
Usually bind in this way solved my problems with new HTML contents
.click and .bind are binding with dom element currently present in the DOM during page load.
.live is one used to attach event for element which might be filled in DOM later either by Ajax or Javascript. But .live have major issue related to performance.
To over come this $.delegate where introduce with better performance in DOM Hierarchy.
With Latest Jquery 1.7 or above coming in place .on is used which used to bind event to element ( Run Time ) whenever element will be filled in DOM. It have improved performance
then .live you can have more information on this site
http://api.jquery.com/live/
Which will provide to insite of jQuery event binding
Since none of the other answers address the point you make that:
The first time you click a.month_change it works, but every time
afterwards the page is not loaded
then let me attempt to explain…
Your code is actually making two AJAX calls, one from .load() and one from .ajax()
The problem of the click events only firing once is caused because you are replacing the HTML of the calendar in the success handler for the .ajax() call with jQuery('#calendar .show_hide').html(msg); thereby replacing the a.month_change elements that you previously bound the click handler on.
The fix is to move the click event binding to be captured on an element in the page that is not being replaced by any AJAX call.
For example on the #calender element:
jQuery('#calendar').on('click', 'a.month_change', function(){ ... });
So you can therefore replace all content inside the #calendar and the click events will still be captured and then filtered by the click handler on the static ancestor element.
As the other answers have mentioned that .live() is removed in v1.9 you are using the correct .on() method but just in the wrong place.
i prefer and recommend you to use on() .. you can have a look to this post to learn more about on direct and delegated methods ....
$(document).on('click','yourselector',function{....});
this delegates the click event to document which is always static.. and finds the selector to put th events on.... however, using closest static element is always preferred since document is not good performances wise.
Related
I have a fairly standard star voting functionality in my app that uses jQuery's hover event. The partial that the star voting logic is in used to be rendered with the rest of the page once the DOM was initially loaded (HTML request). However, I would like to move the partial so that it's not loaded with the page but can be loaded when the user wants. I made a typical AJAX request to load the partial but when it gets rendered the stars don't react properly to events like a mouseover. Is this issue being brought on because I'm rendering the forms via AJAX or is there just a bug in my code? Thanks for the help
Update: Got it working using the on handler, thanks for the help all!
You are likely trying to bind events to nodes that don't exist in the DOM yet. The best way to solve this is to bind to a listener that exists prior to the Ajax request, that is an ancestor (sometimes incorrectly called "parent", which is only one level of ancestor) of the content being fetched. For example, given this markup in the page itself:
<div id="ajaxContainer">
<!-- content will be periodically replaced with Ajax -->
</div>
"ajaxContainer" is an ancestor of whatever you're going to fetch. Then you need to bind a listener using an appropriate method. In the old days you could use live() but it's deprecated and was not so efficient anyhow. Then the recommendation was for delegate(), which solved efficiency problems. Now it's for a delegated listener syntax of on(), which is roughly the same performance as delegate() but with different syntax.
All that to say, use .on() if you are using jQuery 1.7+.
Imagine your Ajax function retrieves a portion of a page containing your star system mouseover, which is inside a series of divs classed as "stars". The syntax might look like:
$(document).ready(function() {
$('#ajaxContainer').on('mouseenter', '.stars', function() {
$this = $(this); // cache this specific instance of a stars div as a jQuery object
// do stuff with $this
});
});
This says "Start listening inside ajaxContainer for events that match 'mouse enters stars divs' and when that happens, do stuff."
The elements that are created with Ajax will not respond to your event handlers, as the event handlers only work on elements that are present in the DOM at the time of initializiation.
You need to delegate, and listen for events on elements that are present in the DOM, and catch the bubbling of the dynamic elements.
You should use on() for this:
$('#nonDynamicElement').on('mouseenter', '#dynamicElement', function() {
//do stuff
});
As from jQuery 1.7+ you should use on()
for older versions of jquery you can use live()
jQuery has a function called live which lets you apply event handlers to not yet created objects.
As said in the comment, use on() instead.
If your using jQuery within an AJAX script, be sure to use jQuery instead of $.
jQuery( selector [, context] )
Instead of
$( selector [, context] )
I am trying to bind click handlers to incoming ajaxed content. I used to use 'live'
$('#div').live('click', function(event) {
alert('I got clicked, Live style');
});
But now as my site is getting more complicated, I am realizing how crazy things can get using live and having everything bubble to the top of the DOM. Which is not ideal.
So I started using on(),
$('#div').on('click', function(event) {
alert('I got clicked, On style');
});
But I miss the fact that using live() I could just initialize the click handlers once and be done with it instead of reinitialize them every time new content is loaded. Is there a best of both worlds?
Is there a better way to "reload" click handlers to recognize new ajax content aside from creating the handlers in the ajax callback function? To me that seems highly suspect. Whats the appropriate way to do this?
As of jQuery 1.7 the following .on() event binding is equivalent to the deprecated live:
$(document).on('click', '#div', function(event) {
alert('I got clicked, On style');
});
You can also bind the event to some fixed element further down the DOM which doesn't get re-generated, this functionality would be the same as .delegate():
$('#parentofdiv').on('click', '#div', function(event) {
alert('I got clicked, On style');
});
It is advisable to use the second form to narrow down the scope of the event binding as much as possible to make it easier to maintain.
Edit: For the record, what you originally did in your post would be the preferred replacement for your .bind() calls in your code.
Have you looked at using .delegate? http://api.jquery.com/delegate/
jQuery's on() method can be used to attach various events to already existing items as well as items added by ajax calls to the DOM in the future:
$(document).on("click", ".ajax-added-content", function(event) {
alert('I got clicked, On style');
});
It is possible to do what you want with
.on()
and it is actually the recommended method.
.live()
is deprecated as of jquery 1.7.
You can attach your event to the body and use this overload of "on" to get the functionality you desire. Check the next to last example in jquery's doco of .on
$("body").on("click", "#div", function(){
alert('I got clicked, On style');
});
I have an group of checkboxes with id's starting with somename and I want catch the click event of these checkboxes. Previously I have done this through jQuery. i.e.:
$("input[id^='somename']").click(function(){
// my code follows here
})
but this is not working this time around. Why?
P.S. The element is created via JavaScript after the page is fully loaded after making some ajax request. I don't know if this may be the problem?
just use live if elements are created after the page is loaded.
$("input[id^='somename']").live('click', function(){ // my code follows here })
P.S : Your search selector is "somename" but you search it on the attribute ID, are you sure that you don't want :
$("input[name^='somename']").live('click', function(){ // my code follows here })
instead?
This indeed could be the problem. Replace .click with .live()
$("input[id^='somename']").live('click', function(){ // my code follows here })
and you should be fine.
Since a call to .click is just a shortcut for .bind('click', fnc), this will not work if the element is not in the DOM when calling this. Even better than using .live() would be to use .delegate(). Have a read:
.live(), .delegate()
Using the standard binding functions only works on elements that exist at the time of the bind. You need to use something called event delegation, where elements further up the DOM tree are notified of events on descendant elements. The best way to do this is with .delegate():
$('#containingElement').delegate("input[id^='somename']", 'click', function(){
// your code here
});
This assumes that you have an element #containingElement that contains all the elements that you want to capture the events on.
NB that other answers recomment live. live and delegate use the same backend code, but for various reasons delegate is more efficient.
I believe that because you want this applied to dynamically created elements in the DOM you are going to have to use the the jQuery .live() method:
$("input[id^='somename']").live('click', function(e) {
// Your code
});
Instead of .click() try .change() event.
I have a number of jQuery scripts that select elements within the area that I run a partial page refresh on.
I am using this css tricks code snippet to refresh that part of the page:
$('#refreshbutton').click(function() {
var url = "http://myUrl.com/indexTest.php?ID=" + Math.random();
setTimeout(function() {
$("#maindisplay").load(url+" #maindisplay>*","");
}, 100);
});
The problem is that the elements within #maindisplay are changed, thus are considered new elements in the dom. Since the scripts that select those elements and attach functions to them run at domready and not during the partial refresh, this poses a problem.
So far I have been unable to find a way to reattach the scripts to the elements within #maindisplay after I partially refresh it.
My question is: What is the optimal way to reattach the scripts to the refreshed area of the page.
Thank you for any advice.
You need to use the live() function to attach your click handler.
You have the following options that I can think of:
Put the attach in a function and call that function on page refresh
Use the .live() functionality
Use .delegate() functionality
Put the Javascript reference to the functionality in a reference in the refresh so that it executes as a part of that refresh
Put the function in the callback
make it part of your setTimeout
some other creative method I did not think of...
Just a note: I would look at the .delegate() with contextual selection added in recent versions (available in 1.4.2 for instance).
Does load() not take a callback function as it's second argument? Why not reattach event handlers to the elements with that function?
$('#result').load('ajax/test.html', function() {
//reattach event handlers here.
});
I am using Jquery to dynamically add some HTML into a page.
Now this new HTML code should trigger additional Jquery functions to enable more processing to be done but this new HTML code isnt recognized and thus the additional Jquery functions arent triggered.
How can I get the new HTMl code to be recognized and the additional functions triggered?
Thanx
It depends on what you want to do. The first thing to look into would be jQuery's .live() methods. You can associate events to matching elements that either exist or will exist in the future. For example, this click method will only bind to existing elements with the class of 'clickme'
$('.clickme').bind('click', function() {
// Bound handler called.
});
However, if you bind it using the.live() methods then it will work for existing elements and any new elements that are created:
$('.clickme').live('click', function() {
// Live handler called.
});
These examples are taken right off the API page for the live method. Check it out here: http://api.jquery.com/live/
There are 2 concerns normally, event handlers and plugins, which are two different things.
Part 1: Event Handlers
Event handlers are easy, because they act upon events, events behave identically no matter when the element as added. For this there's .live() and .delegate(), .live() listens for events on document and runs if an event comes from an element that matches the selector, let's take a table row for example:
$("tr").click(function() { ... });
This would find all current table rows, when it ran and bind a click event handler to them, the same as .bind('click', function). Then there's .live(), like this:
$("tr").live('click', function() { ... });
This listens for the click event to bubble up to document (this happens automatically, by default) and executes the handler...current and future elements behave the same way here. This means it works for both. Then there's .delegate() which is a local version of .live() like this:
$("#myTable").delegate('tr', 'click', function() { ... });
If you're just adding rows to #myTable but not removing/adding the table itself, the same type of listener for bubbling events can sit there, instead of all the way up on document, this means the event has to bubble fewer times before reaching the handler you want to execute.
Part 2: Plugins
Plugins are a bit trickier, because they take elements and do things with them (this is true for most plugins). You have two decent options here, either running the plugin when new elements yourself, for example loading via $.ajax() or a shorthand version would look like this:
$.ajax({
//options...
success: function(data) {
//add elements
$("tr", data).myPlugin();
}
});
This finds new <tr> elements, but only in a local context (in the returned HTML) and executes only on those elements. Alternatively, there's a plugin for this, less efficient, but usually not a noticeable difference on most pages. The .livequery() plugin actively looks for and acts up new elements, the same code would look like this:
$("tr").livequery(function() {
$(this).myPlugin();
});
Either of these are valid solutions, just see which fits your needs better.
More details might be helpful but it sounds like Jquery.live() might be what you need. Jquery.live() binds handlers to elements dynamically.