Ajax response and anonymous function scope - ajax

In the following code
var entryTemplate = document.getElementById('entryTemplate');
entryTemplate = entryTemplate.firstChild;
for (var ipost in posts)
{
var post = posts[ipost];
var clone = entryTemplate.cloneNode(true);
clone = $(clone);
if (post.imageURL)
{
var imgElement = document.createElement('img');
var largeImageURL = post.largeImageURL ? post.largeImageURL : post.imageURL;
imgElement.src = post.thumbPresent ? POST_THUMB_URL + '/' + post.postID : largeImageURL;
imgElement.alt = '';
clone.find('div.BlogImageURL a').attr('href', largeImageURL).text(largeImageURL);
clone.find('div.BlogImage a').attr('href', imgElement.src).append(imgElement);
// get bytesize
var postdata = 'inline_image_url=' + encodeURIComponent(post.imageURL);
postdata += '&linked_image_url=' + encodeURIComponent(post.largeImageURL);
$.ajax({
type: 'POST',
url: ASYNC_GET_BYTESIZE_URL,
data: postdata,
success: function(bytesize) {
clone.find('.BlogImageBytesize').html(bytesize);
}
});
}
else
{
clone.find('div.BlogImageURL').text('(This post contains no images)');
clone.find('div.BlogImage').remove();
}
$('#outputDiv').append(clone);
}
clone.find('.BlogImageBytesize').html(bytesize);
All ajax responses (bold line) modify the last clone, probably because the loop is finished when the first response arrives and clone points to the last clone.
How can I fix this?
Thanks.

Perhaps you could set clone as the context of your ajax call. (See docs here.) Then, I think it would work something like this:
$.ajax({
type: 'POST',
url: ASYNC_GET_BYTESIZE_URL,
data: postdata,
context: clone,
success: function(bytesize) {
$(this).find('.BlogImageBytesize').html(bytesize);
}
});
I don't know for sure if the context has to be a plain DOM element or if it can be a jQuery object, but hopefully this gets you on the right track.

Related

Ajax inside ajax not working

I have a function that calls an ajax, inside that ajax another ajax needs to be executed. In the below code I gave my full function. Just to ensure that everything but the 2nd ajax works perfectly, I should point you out that before the 2nd ajax call there is an alert() function which works. That means everything works if I comment the 2nd ajax call. If I uncomment it then after the first alert a second alert should appear saying 'inside 2nd call', but nothing happens. Got any suggestions?
function get_employee_list(Parameter){
$.ajax({
url: 'resource/php/search_profile.php',
type: 'POST',
data: { var1 : Parameter},
async: false,
success: function (response) {
//alert(response);
reset_search_table();
$(response).find('employee').each(function() {
var ebasp_id = $(this).find('ebasp_id').text();
var ebasp_name = $(this).find('ebasp_name').text();
var ebasp_gender = $(this).find('ebasp_gender').text();
var ebasp_category = $(this).find('ebasp_category').text();
//var ebasp_region_type = $(this).find('ebasp_region_type').text();
//var ebasp_region_name = $(this).find('ebasp_region_name').text();
var code_sub_region = $(this).find('ebasp_sub_region').text();
var code_location = $(this).find('ebasp_location').text();
var code_office = '';
if (code_location === '0')
code_office = code_sub_region;
else
code_office = code_location;
var office = '';
//alert('before 2nd call -- '+code_office);
$.ajax({
url: 'resource/php/show_cost_center_name.php',
type: POST,
data: { var1 : code_office},
success: function(response){
office = response;
alert('inside 2nd call');
}
});
var ebasp_designation = $(this).find('ebasp_designation').text();
var ebasp_date_of_joining = $(this).find('ebasp_date_of_joining').text();
var ebasp_grade = $(this).find('ebasp_grade').text();
var ebasp_slab = $(this).find('ebasp_slab').text();
var ebasp_basic = $(this).find('ebasp_basic').text();
var ebasp_photo_upload = $(this).find('ebasp_photo_upload').text();
var ebasp_created_on = $(this).find('ebasp_created_on').text();
var ebasp_created_by = $(this).find('ebasp_created_by').text();
$("#search_table").show();
$('<tr></tr>').html('<td>'+ebasp_id+'</td>'+
'<td>'+ebasp_name+'</td>'+
'<td>'+ebasp_gender+'</td>'+
'<td>'+ebasp_category+'</td>'+
'<td>'+office+'</td>'+
'<td>'+ebasp_designation+'</td>'+
'<td>'+ebasp_date_of_joining+'</td>'+
'<td>'+ebasp_grade+'</td>'+
'<td>'+ebasp_slab+'</td>'+
'<td>'+ebasp_basic+'</td>'+
'<td>'+ebasp_created_on+'</td>'+
'<td>'+ebasp_created_by+'</td>').appendTo("#search_table");
});
},
cache: false,
});return false;
}

responseText always returns 'undefined' even though Im using asynchrous 'success' trigger

function WyslijRequestAjaxem(){
var pole1 = document.getElementById("data_albo_czas");
var url1 = "date_time_now.php";
alert(pole1.value);
alert("xd");
$.ajax({
url: url1,
type: "get",
dataType: "html",
data: { zmienna: pole1.value},
success: OdbierzResponse
})
}
function OdbierzResponse(response) {
var p = document.getElementById("pt1");
p.innerHTML = response.responseText;
}
In the case of a html dataType for jQuery's AJAX function, the first argument passed to the success callback is the responseText, so change your function to:
function OdbierzResponse(response) {
var p = document.getElementById("pt1");
p.innerHTML = response;
}
As explained in the docs this function is passed three arguments:
The function gets passed three arguments: The data returned from the server, formatted according to the dataType parameter; a string describing the status; and the jqXHR (in jQuery 1.4.x, XMLHttpRequest) object.
If you need the actual jqXhr object to work with you'd need to do:
function OdbierzResponse(response, status, xhr) {
var p = document.getElementById("pt1");
p.innerHTML = response;
...
}
and use xhr to access the properties or methods that you require.
function WyslijRequestAjaxem() {
var pole1 = document.getElementById("data_albo_czas");
var url1 = "date_time_now.php";
alert(pole1.value);
alert("xd");
$.ajax({
url: url1,
type: "get",
dataType: "html",
data: {
zmienna: pole1.value
},
success: function (response) {
OdbierzResponse(response); // call OdbierzResponse function with parameter here
}
})
}
Try change
p.innerHTML = response.responseText;
to
p.innerHTML = response;

Reduce Repetitiion with AJAX JSON Calls to an API

I have about 15 copies of the following code on my site. The only things changing are the url, longitude, latitude, and the marker variable title. How can I chop this up and reduce the repetition?
$.ajax({
url: "http://api.wunderground.com/api/<api_key>/conditions/q/pws:KCASANFR128.json",
dataType: "jsonp",
success: function(parsed_json) {
var location = parsed_json['current_observation']['observation_location']['city'];
var temp_f = parsed_json['current_observation']['temp_f'];
var weather = parsed_json['current_observation']['weather'].toLowerCase();
var iconUrl = parsed_json['current_observation']['icon_url'];
var iconPic = new MyIcon(iconUrl);
var markerRichmond = new L.Marker(new L.LatLng(37.779806, -122.471895), {icon: iconPic});
markerRichmond.bindPopup("Current temperature in " +location+ " is: " +temp_f+ " and it is " + weather);
map.addLayer(markerRichmond);
}});
You could make a function which takes in those variables and feeds them to the ajax call. Then you would only need one copy of this ajax block, which you could call by calling the getWeather function
function getWeather(url, lat, long, title){
$.ajax({
url: url,
dataType: "jsonp",
success: function(parsed_json) {
var location = parsed_json['current_observation']['observation_location']['city'];
var temp_f = parsed_json['current_observation']['temp_f'];
var weather = parsed_json['current_observation']['weather'].toLowerCase();
var iconUrl = parsed_json['current_observation']['icon_url'];
var iconPic = new MyIcon(iconUrl);
var markerRichmond = new L.Marker(new L.LatLng(lat, long), {icon: iconPic});
markerRichmond.bindPopup(title);
map.addLayer(markerRichmond);
}
});
}
I am not sure if I handled the title correctly here, but you get the idea. If you give an idea of how the title may change, I can fix the code accordingly.
Hope this helps.
var current_observation = parsed_json['current_observation'];
This also shortens amount of times parsed. Then you can refer to your variable as
current_observation['observation_location']['city'];

Synchronised Ajax requests with JQuery in a loop

I have the following situation: I need to make synchronized Ajax requests within a loop and display the returned result after each iteration in a div-element (appended on top with the previous results at the bottom). The response time of each request can be different but the order in which it should be displayed should be the same as issued. Here is an example with 3 requests. Lets say request "A" needs 3 seconds, "B" needs 1 second and "C" needs 5 seconds. The order I want to display the result is A, B, C as the requests were issued but the code I use shows the results in B, A, C.
Here is the code (JQuery Ajax request):
$(document).ready(function(){
var json = document.getElementById("hCategories").value;
var categories = eval( '(' + json + ')' );
for(curCat in categories) {
curCatKey = categories[curCat]['grKey'];
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) +
"&search=" + escape($("#hQuery").val()),
timeout: 8000,
async: false,
success: function(data) {
$("#content").append(data);
}
});
});
I thought it would work with "async:false" but then it waits until every Ajax call is finished and presents the results after the loop. I hope some of you can point out some different solutions, I am pretty much stuck.
Thanks in advance,
Cheers Chris
EDIT: Thanks for all the possible solutions, I will try these now one by one and come back with that one that fits my problem.
I have two solution proposals for this problem:
Populate generated divs
You could generate divs with ids in the loop and populate them when the request finishes:
$(document).ready(function() {
var json = document.getElementById("hCategories").value;
var categories = eval('(' + json + ')');
for (curCat in categories) {
(function(curCat) {
var curCatKey = categories[curCat]['grKey'];
$('#content').append('<div id="category-"' + escape(curCat) + '/>');
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) + "&search=" + escape($("#hQuery").val()),
success: function(data) {
$("#category-" + escape(curCat)).html(data);
}
});
})(curCat);
}
});
Or use a deferred
You can store jqXHR objects in an array and use a deferred to call the success functions in order, when all calls have finished.
$(document).ready(function() {
var json = document.getElementById("hCategories").value;
var categories = eval('(' + json + ')');
var requests;
for (curCat in categories) {
var curCatKey = categories[curCat]['grKey'];
requests.push($.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) + "&search=" + escape($("#hQuery").val())
}));
}
$.when.apply(requests).done(function() {
for (i in requests) {
requests[i].success(function(data) {
$("#content").append(data);
});
}
});
});
The first method has the advantage that it populates the containers continuously. I have not tested either of these function, but the logic should work the way I described it.
This would do the trick
var results = [];
var idx = 0;
for(curCat in categories) {
curCatKey = categories[curCat]['grKey'];
(function( i ) {
$.ajax({
type: "POST",
url: "get_results.php",
data: "category=" + escape(curCatKey) +
"&search=" + escape($("#hQuery").val()),
timeout: 8000,
async: false,
success: function(data) {
results[i] = data;
if (i == idx - 1) { // last one
for (var j=0; j < results.length; j++) {
$("#content").append(results[j]);
}
}
}
});
})(idx++);
I think something like this is what you're looking for. Might need some tweaking, I'm a little rusty on Deferred. Read up on it though, mighty powerful
deferred = $.Deferred()
for(curCat in categories) {
deferred.pipe(
function(resp){
postData = {} // set up your data...
return $.post("get_results.php", {data: postData, timeout: 8000})
.done(function(content){ $("#content").append(content) })
})
)
}
// Trigger the whole chain of requests
deferred.resolve()

synonym api Ajax call return

Have struggled with this call for a while now but i can't get it to work. dataToReturn still returns Error and not the called data. What am i doing wrong?
function get_translation(search) {
search = search.replace(/(<([^>]+)>)/ig, "").toLowerCase();
original = search;
google.language.translate( original , 'en', 'sv',
function(result) {
translated = result.translation;
$("#results").html('<li class="ui-li-has-icon ui-li ui-li-static ui-btn-up-c" role="option" tabindex="0">'+ translated + '</li>')
});
};
function get_synonyms(items) {
var dataToReturn = "Error";
$.ajax({
url: 'http://words.bighugelabs.com/api/1/xxx/' + items+ '/json',
type: 'GET',
dataType: 'jsonp',
async: false,
cache: false,
success: function(data) {
dataToReturn = data;
}
});
return dataToReturn;
}
$('#results').delegate("li", "tap", function(){
myDate = new Date();
displayDate = myDate.getDate() + "/" + myDate.getMonth()+1 + "/" + myDate.getFullYear();
id = myDate.getTime();
var wordObject = {'id' : id, 'date': displayDate, 'translated': translated, 'original': original, 'nmbr': "0", 'syn': get_synonyms('hello')};
save_terms(wordObject);
loopItems() ;
$("#results").html("");
$("#addField").val("");
// location.reload(true);
});
It's because the return dataToReturn line is being executed before the AJAX call is complete. When you call $.ajax, the browser says, "Okay, I'll just move on to the next thing while I'm waiting for that to get back to me."
The simplest way to fix this would be to change the success function to actually do whatever it is you're trying to do with dataToReturn. But if that's not really feasible, then more context would help come up with a better answer.

Resources