jQuery.bind'ing things loaded with jQuery.load - javascript

When using jQuery.load to dynamically load HTML content into a webpage, what is the best way to "rebind" any handlers?
Normally you bind handlers in jQuery.ready, but they obviously don't work on newly loaded content. This is for handlers used both outside and inside the loaded content, so just binding them in the load success function is not really nice.

When subscribing to those handlers you could use the .on function which allows you to subscribe to even non existing yet DOM elements and when they are added the subscription will be done. The .on function was introduced in jQuery 1.7. If you are using an older version you could use the .delegate function to achieve the same effect which was introduced in jQuery 1.4.2. And if you are using an even older version you could use the .live method.
Here's an example of how you could subscribe to the click event of some element (existing or not yet existing that will be added in the future):
$('#someParentElement').on('click', '#someElement', function() {
});

You need to delegate events for the new content to a static parent element, for example:
$("#myDiv").load(myUrl);
$("#myDiv").on('click', '#myElement', function() {
// do stuff when #myElement (which was part of the HTML
// returned in the load() call) is clicked.
})
This assumes you're using jQuery 1.7+, if not, use delegate():
$("#myDiv").delegate('#myElement', 'click', function() {
// do stuff when #myElement (which was part of the HTML
// returned in the load() call) is clicked.
})

Related

jQuery code not applying to a form when the form is rendered via AJAX

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] )

Use JS that is already loaded, on HTML loaded via jQuery's load() function?

Not sure if this is posible or not, but I'm trying to use JavaScript that I loaded via a script tag when the page was initially requested on dynamic HTML that was loaded via jQuery's load() function.
Example: http://jsfiddle.net/3MR43/
As you can see in the example, after clicking a link in the pop up box, the link goes. The problem is that the link was suppose to be stopped, and you were suppose to see an alert.
However, if I paste the HTML that I am loading via jQuery, it works, so the code is fine.
Description
You need jQuery .live() or .on() method to bind events to dynamically created html.
Choose .live() or .on() depending on the version of jQuery you are using.
.live() Available since jQuery 1.3. Attach an event handler for all elements which match the current selector, now and in the future.
.on() Available since jQuery 1.7. Attach an event handler function for one or more events to the selected elements.
Check out my sample and this jsFiddle Demonstration
Sample
... for jQuery.live()
$('.lang').live("click", function(e) {
e.preventDefault();
alert('Testing..');
});
... for jQuery.on()
$('.lang').on("click", function(e) {
e.preventDefault();
alert('Testing..');
});
More Information
jsFiddle Demonstration
jQuery.live()
jQuery.on()
The problem is your .click will do it for only elements that exist at that time. If you want to do it for all potential future elements that that selector will match, you want to use on() (delgate() or live() with older versions of jQuery).
The $('.lang').click() event must be registered after the element is created!
You need a callback on the load function to register this.
You need to use live to attach handlers to elements that are loaded dynamically.
Try this, it will solve your problem.
$('.lang').live('click',function(e) {
e.preventDefault();
alert('Testing..');
});
You have to use on function for dynamicly loaded elements:
$('.open_lang').click(function(e) {
e.preventDefault();
$('#popup').load('http://skins.thehabbos.org/pop_up/language.php').css('display', 'block');
});
$('body').on('click', '.lang', function(e) {
e.preventDefault();
alert('Testing..');
});
(live and delegate are deprecated in JQuery 1.7+ which is the version of your JSFiddle)
Fixed JSFiddle

JQuery processing interactive content

I noticed that in jquery appended text won't be processed by jquery functions. For example, you append a code containing dropdown-list and you have a function that invokes on changing its value. This function works on existing code only, not on appended one.
And the correct answer is:
Instead of using:
$('#purchase-table select').change(function() {
});
Use:
$('#purchase-table select').live('change', function() {
});
You need it to be able to process ajax-appended content by your jquery functions. Have a nice day.
Thanks to everyone helped.
You can use JQuery .live()
Append new content:
$('body').append('<div class="clickme">Another target</div>');
Add handler to it:
$('.clickme').live('click', function() {
// Live handler called.
});
Then clicks on the new element will also trigger the handler.
The easiest way to handle events on interactive content is the jQuery.live method.
http://api.jquery.com/live/
Description: Attach a handler to the event for all elements which match the current selector, now and in the future.

jquery load / get and dom elements not triggering...?

I'm loading a simple page using:
$.get('../admin/login.php', function(data) { $('#box-contents').html(data); });
Now, on this login.php page I have an input field, and in my global JavaScript file, I have an event that triggers on .change() - but this isn't firing!?
Is this because I have loaded this file on the page so jquery doesn't know that it's now there? Do I need to also include my global JS file within the 'login.php' page too?
Any help on this would be much appreciated
instead of using .get(), use .load() as it was intended for this purpose. Also for your .change() event, you need to either attach it after the element exists (which could be done in your callback below), or you can use .live() to attach the event to any current or future DOM elements.
Callback method
$('#box-contents').load('../admin/login.php', function() {
$('input').change(function() {
//do stuff on change
});
});
Live method
$('input').live('change', function() {
//do stuff on change
});

jQuery scripts no longer run on partially refreshed elements

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.
});

Categories

Resources