cannot click links contained within ajax response - ajax

I have some content returned via ajax, and that content contains some links, but if I click them nothing happens (they don't respond to the JS written for them). Then, If i refresh the page, the first time I click, it works, and then it doesn't again.
How can I make it work normally?
This is basically my ajax call:
$('a.add').click(function() {
var data = {
action: 'ADD_PROD'
};
// make the request
$.get(ajax_object.ajax_url, data, function(response) {
// $('#vru_div').html(data);
$('div.left').html(response);
});
// $('div.left').html('<img src=712.gif>');
// alert('code');
return false;
});

The new links won't have any event handlers attached to them.
try using
$('.left').on('click','a',function(){
//your logic
});

Related

passing data to jquery modal aside from adding parameters to url?

On click of a #dtDelete button I am opening an ajax modal in bootstrap 3. I am also passing a parameter, selected, along with it and using $_GET on the php page to retrieve it.
As the value of selected may or may not be extremely large I think I should avoid passing the value this way / using $_GET.
How the heck can I pass values other than this method? Due to the nature of opening the modal (loading it then showing it) I am stuck on any other ways.
$('#dtDelete').on('click', function () {
//open the modal with selected parameter attached
$('#modal-ajax').load('/modals/m_keystroke_delete.php?selected='+selected);
$('#modal-ajax').modal('show');
});
Pass a data object as a second param to load for it to make a POST request.
$('#dtDelete').on('click', function () {
var data = { 'propertyA': 'extremely large data' };
//open the modal with selected parameter attached
$('#modal-ajax').load(
'/modals/m_keystroke_delete.php?selected=' + selected, // url
data, // data
function(responseText, textStatus, XMLHttpRequest) { } // complete callback
);
$('#modal-ajax').modal('show');
});
You can even pass your "selected" param through the POST request and use $_POST or even $_REQUEST to retrieve the data. Also notice that the modal now shows once the request has completed.
$('#dtDelete').on('click', function () {
var data = {
'selected': selected
'largeData': '...'
};
$('#modal-ajax').load(
'/modals/m_keystroke_delete.php',
data,
function() {
// Invoke the delete-function
deleteComp();
// Show the modal
$(this).modal('show');
}
);
});

How to use AJAX as an alternative to iframe

I'm trying to put together a snappy webapp, utilizing JS, Prototype and AJAX for all my requests once the GUI has loaded. The app is simple: A set of links and a container element to display whatever the links point to, just like an iframe. Here's an approximate HTML snippet:
<a class="ajax" href="/somearticle.html">An article</a>
<a class="ajax" href="/anotherarticle.html">Another article</a>
<a class="ajax" href="/someform.html">Some form</a>
<div id="ajax-container"></div>
The JS that accompanies the above (sorry it's a bit lengthy) looks like this:
document.observe('dom:loaded', function(event) {
ajaxifyLinks(document.documentElement);
ajaxifyForms(document.documentElement);
});
function ajaxifyLinks(container) {
container.select('a.ajax').each(function(link) {
link.observe('click', function(event) {
event.stop();
new Ajax.Updater($('ajax-container'), link.href, {
method: 'get',
onSuccess: function(transport) {
// Make sure new ajax-able elements are ajaxified
ajaxifyLinks(container);
ajaxifyForms(container);
}
});
});
});
}
function ajaxifyForms(container) {
console.debug('Notice me');
container.select('form.ajax').each(function(form) {
form.observe('submit', function(event) {
event.stop();
form.request({
onSuccess: function(transport) {
$('ajax-container').update(transport.responseText);
// Make sure new ajax-able elements are ajaxified
ajaxifyLinks(container);
ajaxifyForms(container);
}
});
});
});
}
When clicking a link, the response is displayed in the container. I'm not using an iframe for the container here, because I want whatever elements are on the page to be able to communicate with each other through JS at some point. Now, there is one big problem and one curious phenomenon:
Problem: If a form is returned and displayed in the container, the JS above tries to apply the same behavior to the form, so that whatever response is received after submitting is displayed in the container. This fails, as the submit event is never caught. Why? Note that all returned form elements have the class="ajax" attribute.
Phenomenon: Notice the console.debug() statement in ajaxifyForms(). I expect it to output to the console once after page load and then every time the container is updated with a form. The truth is that the number of outputs to the console seems to double for each time you click a link pointing to a form. Why?
I found another way to achieve what I wanted. In fact, the code for doing so is smaller and is less error prone. Instead of trying to make sure each link and form element on the page is observed at any given time, I utilize event bubbling and listen only to the document itself. Examining each event that bubbles up to it, I can determine whether it is subject for an AJAX request or not. Here's the new JS:
document.observe('submit', function(event) {
if (event.target.hasClassName('ajax')) {
event.stop();
event.target.request({
onSuccess: function(transport) {
$('ajax-container').update(transport.responseText);
}
});
}
});
document.observe('click', function(event) {
if (event.target.hasClassName('ajax')) {
event.stop();
new Ajax.Updater($('ajax-container'), event.target.href, {
method: 'get'
});
}
});
Works like a charm :)

jquery mobile ajax sends both GET and POST requests

Here is the problem:
By default jQuery Mobile is using GET requests for all links in the application, so I got this small script to remove it from each link.
$('a').each(function () {
$(this).attr("data-ajax", "false");
});
But I have a pager in which I actually want to use AJAX. The pager link uses HttpPost request for a controller action. So I commented the above jQuery code so that I can actually use AJAX.
The problem is that when I click on the link there are two requests sent out, one is HttpGet - which is the jQuery Mobile AJAX default (which I don't want), and the second one is the HttpPost that I actually want to work. When I have the above jQuery code working, AJAX is turned off completely and it just goes to the URL and reloads the window.
I am using asp.net MVC 3. Thank you
Instead of disabling AJAX-linking, you can hijack clicks on the links and decide whether or not to use $.post():
$(document).delegate('a', 'click', function (event) {
//prevent the default click behavior from occuring
event.preventDefault();
//cache this link and it's href attribute
var $this = $(this),
href = $this.attr('href');
//check to see if this link has the `ajax-post` class
if ($this.hasClass('ajax-post')) {
//split the href attribute by the question mark to get just the query string, then iterate over all the key => value pairs and add them to an object to be added to the `$.post` request
var data = {};
if (href.indexOf('?') > -1) {
var tmp = href.split('?')[1].split('&'),
itmp = [];
for (var i = 0, len = tmp.length; i < len; i++) {
itmp = tmp[i].split('=');
data.[itmp[0]] = itmp[1];
}
}
//send POST request and show loading message
$.mobile.showPageLoadingMsg();
$.post(href, data, function (serverResponse) {
//append the server response to the `body` element (assuming your server-side script is outputting the proper HTML to append to the `body` element)
$('body').append(serverResponse);
//now change to the newly added page and remove the loading message
$.mobile.changePage($('#page-id'));
$.mobile.hidePageLoadingMsg();
});
} else {
$.mobile.changePage(href);
}
});
The above code expects you to add the ajax-post class to any link you want to use the $.post() method.
On a general note, event.preventDefault() is useful to stop any other handling of an event so you can do what you want with the event. If you use event.preventDefault() you must declare event as an argument for the function it's in.
Also .each() isn't necessary in your code:
$('a').attr("data-ajax", "false");
will work just fine.
You can also turn off AJAX-linking globally by binding to the mobileinit event like this:
$(document).bind("mobileinit", function(){
$.mobile.ajaxEnabled = false;
});
Source: http://jquerymobile.com/demos/1.0/docs/api/globalconfig.html

Ajax loader and events runs more than once

I have a website that pages' contents loaded by ajax. All of my pages are seperate files actually and when I need to call a page, I just passed the link to my "pageLoader" function.
pageLoader handle with content loading and re-ignite/re-define the necessary functions like close button.
Since the actual function have ~250 lines, I did re-write a short version;
var pageLoader = function(link){
var page = $(link).attr("href").replace('#','');
if(page != lastCalledURL){
// Load the page.
$.ajax({
beforeSend: function(){ /* remove previously loaded content; */ },
success: function(data){
// remove the loaded content if user clicked to close button.
$("a.close-button").live("click", function(){
$(this).parent().fadeOut().remove();
return false;
});
// load another page if user click another page's link.
$("a.content-loader-link").live("click",function(){
pageLoader(this);
});
// handle with tabs
$("a.tabs").live("click", function(){
var index = $("a.tabs").index(this);
console.log(index);
return false;
});
}
});
lastCalledURL = page;
}
return false;
OK. If I click a link in the page, It calls pageLoader. If I click one of the links just once, pageLoader called once. If I click another link, pageLoader called twice. If I click another link again, pageLoader called third times and so on.
Same things happen for the links that bind with "live" function in the code. If I click a.tabs, it write to console twite. If I clicked another .tabs link, it write to console four times and increasing double for every click.
I don't why it happens. Please let me know if you have any idea.
You can solve it by using the bind and unbind. Like this:
$("a.tabs").unbind('click').bind("click", function(){
var index = $("a.tabs").index(this);
console.log(index);
return false;
});
But i would prefer that you attach this events in your $(document).ready function instead of everytime you make an AJAX call.
$(document).ready(function() {
// Attach your events here.
});
Those live event handlers "Attach a handler to the event for all elements which match the current selector, now and in the future." so you shouldn't need them in your ajax call.

Can I make an Ajax request inside an ongoing Ajax request (e.g. on the success callback function)?

I have a jQuery application, a shopping cart, that posts back info to the server, if the text inputfield is changed. This is done in an Ajax request. Now, if the Ajaxrequest is a success, I want to reload the shoppingcart asynchronously. The code is as follows:
$(document).ready(function() {
var jInput = $(":input");
jInput.change(function() {
var vareAntal = $(this).val();
var vareID = $(this).siblings("input#vareID").val();
$.ajax({
type: 'POST',
url: 'checkout.aspx',
data: { 'ID': vareID, 'Antal': vareAntal },
success: function() {
$("#newbasket").load(location.href + " #newbasket>*", "");
}
});
});
});
This works, but only once! If I change the text inputfield, after the page is loaded for the first time, the div with the ID of newbasket reloads asynchronously. But if I try to change it again, nothing happens.
I've tried to do some debugging with Firebug, and the first time I change the text inputfield, it fires a POST-event, and afterwards a GET-event, when the POST-event is succesful. But after that, nothing happens when I change the text inputfield again.
So, how do I achieve triggering the .load() method after each text input change?
I've also tried experimenting with the .ajaxComplete() function, but that, of course, resulted in an infinite loop, since the .load() is an ajax-object.
Instead of .change(func), use .live('change', func) here, like this:
jInput.live('change', function() {
This will make the selector work on any new inputs added as well. When you're replacing the elements like you are currently, their event handlers are lost (or rather, not re-created, because you have new elements). .live() is just for this purpose, it listens for events from old and new elements, regardless of when they were added.

Resources