How to bind event after ajax success in jQuery - ajax

So here is my code:
$(document).ready( function() {
$('#form').bind('change', function(){
$.ajax({
type: 'get',
url: 'api.php',
data: 'task=getdirs&formname='+$('#form').attr('value'),
dataType: "text",
success: function (html){
$('#chdir').html(html);
$('#chdir select').bind('change', getDirs());
}
});
});
function getDirs(){
}})
#form here has a <select> element. The ajax call returns a piece of html with a new <select> element.It works nice: in the #chdir div I get a new dropdown element. But the event inside the success part fires only once. Then this event does not work anymore at all.What can I do to make the newly created <select> element work in the same way as the first?

You are invoking the getDirs function directly on the bind method call, you should only do it if this function returns another function, but I think that's not the case.
Change:
$('#chdir select').bind('change', getDirs());
To:
$('#chdir select').bind('change', getDirs);
Or if you are using jQuery 1.4+, you can bind the change event with the live method only once, and you will not need to re-bind the event after that:
$(document).ready(function () {
$('#chdir select').live('change', getDirs);
});

Because this SO post came up in my google search, I thought I should mention that .live has been deprecated as of 1.9, and the recommended method is now .on
http://api.jquery.com/on/

If I understand you correctly, the problem is with the event not working with your dynamically created select element.
If so, the solution is simple...try this:
$('#form').live('change', function()...
Update: With newer versions of jQuery you have to use on() instead of live().

If you're using jQuery 1.9+, .on method should be used to attach event handlers. However, after appending HTML to document you still have to attach new event handlers.
To write small piece of simple, working code and handle new elements you can use .on on document:
$(document).on('click', '.close-icon', function() { // selector as a parameter
$(this).parent().fadeOut(500); // - example logic code
});

Instead of using bind, try using .live. You'll need the latest version of jQuery to do that.

From the jQuery API:
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().
So you should use .delegate() if you are working with a jQuery version previous to 1.7.
http://api.jquery.com/live/

Related

how to access the id of div which is loaded through ajax

I have button with id = new which loads the new page
$("#new").click(function(){
$('#message_area').load('new.php');
});
There is a button in new.php which sends message to database. But i have a problem with it , it only works for first time when page loads if i navigate to some other links via ajax and again load new.php using above code then send button in new.php does not work i have to refresh the page then it works. I think its because the send button in new.php is added after DOM is created for first time .
Please help Thanks in advance ..
You will need to post more details of your markup for a more accurate answer, but the general idea is to use event delegation. Bind the event handler to an ancestor of the button that does not get removed from the DOM. For example:
$("#message_area").on("click", "#yourButton", function() {
//Do stuff
});
This works because DOM events bubble up the tree, through all of an elements ancestors. Here you are simply capturing the event higher up the tree and checking if it originated from something you are interested in (#yourButton).
See jQuery .on for more. Note that if you're using a version of jQuery below 1.7, you will need to use delegate instead.
//jquery >= v1.7
$("body").on('click', '#new', function(){
$('#message_area').load('new.php');
});
//jquery < v1.7
$("#new").live('click',function(){
$('#message_area').load('new.php');
});
$("#new").live("click", function(){
$('#message_area').load('new.php');
});
just realized this was deprecated-- should be using on instead.. my bad.
To manage dynamically created elements like this, you need to use .on() (jQuery 1.7 and above) or .delegate() (jQuery 1.4.3 and above) to assign the events. Seems everyone has beaten me to the code, but I'll post this for the links to the functions.

How to trigger unobtrusive javascript when the content is dynamic with ajax (Lightbox)

I've got some links coming in from ajax that need lightbox functionality:
<img src='...'>
Normally this is given behavior via an on page load handler, but since the content is coming from ajax, the UJS isn't getting triggered.
Any way to do this?
If the content is coming from AJAX, then din't setup the event handling during page load. Instead, let the event bubble to the topmost container that is not being changed or replaced by AJAX. Worst case, use document as the topmost node.
$('<root element selector>').on('click', 'a.lightbox', function() {
// activate lightbox on the clicked element.
});
I'm not sure how you're triggering the ajax requests, but if it's with jQuery which seems likely, you can bind the lightbox in the success callback:
$.ajax({
url: '/route',
success: function (response, status) {
$('.lightbox').lightbox();
}
});
You can pass in a context to the jQuery selector so you don't re-attached the lightbox to links that are already in the page, for example if your ajax call is adding the links to a div with id 'lightbox_links', use this selector instead:
$('.lightbox', '#lightbox_links').lightbox();

Using jQuery Plugins with live()

I have a page that dynamically loads content with the jQuery load() function, so I need to use live() for each of my jQuery functions on this page. However, I am unable to get live() to work with jQuery plugins. For example, I want to use jQuery accordion:
$("#accordion").accordion();
But I cannot find the right syntax to get accordion to work with live(). I have tried:
$("#accordion").live("load", accordion());
$("#accordion").live("load", $("#accordion").accordion());
$("#accordion").live("load", $(this).accordion());
I either receive the "b is undefined" error, or "accordion is not defined."
You must use anonymous function
$("#accordion").live('load',function(){
$(this).accordion();
});
Edit:
If the accordion is already in the page when you first render it, then you shouldn't call it using live(), but by page load
$(function(){
$("#accordion").accordion();
});
This could partly answer your question:
I would suggest using livequery instead to do this:
$("#accordion").livequery(
function() { $(this).accordion(); },
function() { $(this).accordion("destroy"); }
);
The first function will initialize jQuery UI's accordion functionality on any $("#accordion") element that's added to the DOM, and the second one will destroy the accordion object when that same element is removed from the DOM.

jQuery: Can I automatically apply a plug-in to a dynamically added element?

I'm in the process of converting my web app to a fully AJAX architecture.
I have my master page that is initially loaded and a div container that is loaded with dynamic content.
I created a few jQuery plugins that I apply to certain elements in order to extend their functionality. I'd normally call the functions as follows during each page load:
$(document).ready(function () {
// Enable fancy AJAX search
$(".entity-search-table").EntitySearch();
});
This would find the appropriate div(s) and call the plugin to enable the necessary functionality.
In an AJAX environment I can't just apply the plugin during the page load since elements will be added and removed dynamically.
I'd like to do something like this:
$(document).ready(function () {
// Enable fancy AJAX search
$(".entity-search-table").live("load", function () {
$(this).EntitySearch();
});
});
Question: Is there any way that I can trigger an event when a <div> or other element that matches a selector is added to the DOM?
It seems incredibly wasteful to activate the plug-in every time an AJAX request completes. The plug-in only needs to be applied to the element once when it is first added to the DOM.
Thanks for any help!
Yes - take a look at liveQuery. Example:
$('.entity-search-table').livequery(function(){
$(this).EntitySearch();
});
It seems incredibly wasteful to activate the plug-in every time an AJAX request completes. The plug-in only needs to be applied to the element once when it is first added to the DOM.
You can get the best of both worlds here, for example:
$("#something").load("url", function() {
$(".entity-search-table", this).EntitySearch();
});
This way it's only applying the plugin to the .entity-search-table elements you just loaded, since we specified a context to $(selector, context) to limit it.
The DOM 2 MutationEvent is what you really want, but unfortunately it isn't supported by IE. You'll need to either use live()/ delegate() binding in the plug-in, or (as I did when I had to work around this) use callbacks from your AJAX loaders indicating the scope of what has changed.
Use the live binding in your plugin code directly
jQuery.fn.EntitySearch = function() {
this.live(..., function(){ your plugin code });
return this;
}

Bind custom event handler after ajax load

Specifically I'm looking to bind lightbox to a specific element. Normally I would just do this: $('a.lightbox').lightBox(); but that isn't working since I'm doing some loading with AJAX. Looking at the jQuery API I found .bind() and .live() but I'm not getting anything when I do $('a.lightbox').bind('lightBox') after the AJAX .load() call.
What am I missing?
You need to add a callback function that handles that.
$("#div").load(url, {}, function(){ $('a.lightbox').lightBox(); });
Bind isn't going to help you, as the event isn't getting an event fired on it.
Another way would be to bind to an element higher up in the dom and check the target type. Such as:
$('#div').bind('click', function (event) {
target = $(event.target);
if (target.hasClass('lightbox')) {
// do stuff here
}
});
Just don't go too far up or you'll be catching way too many clicks.

Resources