I have an Ajax call to comments-set.php. In the php file I set a session variable to a random value. In the Ajax.done callback I'd like to retrieve the session variable.
I have verified that the session variable is being correctly set to a new random value but the old value is still displayed by the code in .done.
$(document).on("click", "#submit", function () {
var comment = document.getElementById('comment').value
var no_spam = document.getElementById('no_spam').value
var jqxhr = $.ajax({
type:"POST",
url: "comments-set.php",
dataType: "html",
data:{no_spam:no_spam, comment:comment}
})
.done(function(data) {
$("#display").html(data);
$('input[type="text"],textarea').val('');
var nsq = '<label for="no_spam" style="color:#717171;" id="no_spam_Q"><?php echo $_SESSION['q']; ?></label>';
$("#no_spam_Q").replaceWith(nsq);
});
});
I assume (with my very limited knowledge!) this has something to do with Ajax being async or JS not waiting for the php to resolve. How can I get round this?
I've tried using events like Ajax.complete instead of doing it in the .done without success, I've even used onMouseUp on the button that triggers this code, figuring it gets fired in mouse down, so I'll get the session variable in mouse up, still no joy.
Related
Creating a 'refresh' button via jQuery, AJAX and PHP.
This particular one I'm having control two DOM instances (divs) - #sold-container, and also #totalorderswidget.
$(document).ready(function() {
$(function() {
$('#orderfeed').on('click', function() {
var orders;
$.ajax({
type: 'POST',
url: 'liveorderwidget.php',
beforeSend: function() {
$('#sold-container').html('<div class="page-loader"></div>');
$.ajax({
url: "totalorderswidget.php",
beforeSend: function() {
$('#totalorderswidget').html('<div class="page-loader"></div>');
},
success: function(orderdata) {
// $('#totalorderswidget').html(orderdata);
orders = orderdata;
}
});
},
success: function(solddata) {
$('#sold-container').html(solddata);
$('#totalorderswidget').html(orders);
}
})
});
});
});
I didn't like how each DIV was updating and showing my page-loader CSS at different times, so I thought I'd try and grab the data to pass and display them both at the same time (get data from the first ajax call, display both on the second).
This is working as two normal AJAX calls, and each appends the success html to each id on it's own. (uncommenting // $('#totalorderswidget').html(orderdata); works),
but initializing a variable like var orders; outside the functions and trying to put the data in the success call (orders = orderdata;) does not work.
Doing a console.log on the first AJAX success call (orderdata) brings back the expected response, but trying to use it in the second AJAX call ($('#totalorderswidget').html(orders);) does not work and a console.log brings back undefined for the order variable.
What must I change in order to grab data from the first success call function and bring this data into the second/final ajax success call?
I have a large number of inputs on a page, each input is disabled (and hidden) by default unless a checkbox is checked. Checking a related checkbox enables the input for a user to type an amount - that works fine.
After I've typed an amount into a given box and I shift my blur focus to something else (indicating I'm done with this input), I'm looping through every visible input to check if it has an amount in it and then sending an ajax request to update the back-end (this also works but maybe approach is wrong?).
What doesn't work is when I loop through more than 5-10 checkboxes, it seems to be extremely slow or simply doesn't send the ajax requests.
Code the listens for an enabled/visible amount box to change:
$(document).on("blur", ".dollar-amount", function(){
MainPage.amountInputListener('add');
});
Here is the foreach loop, which updates each associated user's backend data with the amount in the visible field:
var MainPage = {
amountInputListener: function (type) {
$(".dollar-amount:visible").each(function () {
//Get the employee being updated
var empID = $(this).data('empid');
//get the amount
var amount = $(this).val();
//Send update request to backend
$.ajax({
type: "POST",
url: "update/amount?empid=" + empID + "&amt=" + amount + '&type=' + type,
dataType: "html"
});
});
},
}
The HTML for the input:
<input type="text" name="dollar_hour_amountX" value="0" class="form-control dollar-amount disabled" data-empid="1" tabindex="-1" disabled>
Note: dollar_hour_amountX, X is a dynamic number related to the row's employee ID. data-empid is the same dynamic number, also used in the for loop.
Things I've tried to ensure the loop works properly:
Adding async: false. This allows it to work 100% of the time, but it's extremely slow the more inputs that are added.
Adding a timeout of 100-1000ms around the entire function, this simply delays the round-trip time of the Ajax call.
I'm open to Vanilla JS suggestions if it aids in making the calls to my back-end much faster and consistent.
// capture the passed in event
$(document).on("blur", ".dollar-amount", function(e){
// give the element to the method
MainPage.amountInputListener(e.target, 'add');
});
var MainPage = {
// accept the element on the arguments
amountInputListener: function (element, type) {
// use the element in place of `this`
//Get the employee being updated
var empID = $(element).data('empid');
//get the amount
var amount = $(element).val();
//Send update request to backend
$.ajax({
type: "POST",
url: "update/amount?empid=" + empID + "&amt=" + amount + '&type=' + type,
dataType: "html"
});
},
}
Does not make sense to update everything, just update what changes.
$('.dollar-amount').on("change", function () {
console.log(this.value, $(this).data('empid'))
// make the one Ajax request
})
Or change your backend to be able to handle multiple things being sent up at once so you are not hammering the backend with a bunch of calls.
"I'm looping through every visible input to check if it has an amount in it and then sending an ajax request to update the back-end (this also works but maybe approach is wrong?)."
I would strongly recommend you change this approach. I suspect it will fix your issues. Don't loop through all of these each time. There is no need. Simply, on blur, just check if this specific input has changed, and then send an ajax call ONLY if that specific one was edited.
Just pass "this" into the amountInputListener as an argument, and then get rid of the above "each" function. The rest would be the same. Instead of $(this), just pass the argument value that represents "this" from the event.
The first and foremost thing is using a get http verb request for update should be avoided.
This is not per standard, usually get requests are used to retrieve data.
And the next thing is instead of making an ajax call for each element with callname .dollar-amount and visible, it is better to declare a global variable above the foreach block of type array of objects and then add each item in the block to that global variable and then finally make an ajax request after the for block execution is done
amountInputListener: function (type) {
var objList = [];
$(".dollar-amount:visible").each(function () {
//Get the employee being updated
var empID = $(this).data('empid');
//get the amount
var amount = $(this).val();
//Send update request to backend
objList.push({
'empId':empId,
'amt':amount,
'type': type
});
});
$.ajax({
type: "post",
url: "update/amount"
dataType: "application/json",
data:{'data':objList}
});
},
}
This way you can send all data in one shot to server and it really helps in the performance.
Note: code is just to give you an idea.
I have links in a JQuery DataTable that use JQuery UI's tooltip feature. Each link has a tooltip that is populated by an Ajax call. I would like to limit the number of Ajax calls to as few as possible. The DataTable uses server-side processing, and the results are paginated, so there will never be more than ten links on the page at any one time.
The data that is returned by the Ajax call will never change and thus can be safely cached. In my testing, I have seen that the browser does cache the result of each Ajax call, so that it only makes one call per link, and then uses the cache thereafter. My concern is that some user might have their browser configured in such a way that it doesn't use the cache for some reason, and they will be firing off one Ajax call after another, every time they mouse over a link.
Here is the JavaScript for the tooltip:
$('.jobId').tooltip({
content: function(callback) {
var jobId = $(this).text();
$.ajax({
url: 'myUrl',
data: {jobId: jobId},
dataType: 'json',
success: function(data) {
var html = formatResults(data);
callback(html);
},
error: function() {
callback('An error has occurred.');
}
});
}
});
I considered storing the result of each Ajax call in a JavaScript object declared at global scope, and then checking that before making the Ajax call, but I have the vague sense that this might cause a memory leak somehow.
var gJobs = new Object();
$('.jobId').tooltip({
content: function(callback) {
var jobId = $(this).text();
if (gJobs[jobId]) {
callback(gJobs[jobId]);
} else {
$.ajax({
url: 'myUrl',
data: {jobId: jobId},
dataType: 'json',
success: function(data) {
var html = formatResults(data);
gJobs[jobId] = html;
callback(html);
},
error: function() {
callback('An error has occurred.');
}
});
}
}
});
I am also concerned that if the table has a large number of rows, the gJobs object could end up using a lot of memory. To prevent the gJobs object from growing indefinitely, every time the user goes to the next or previous page of results in the DataTable, I use the fnDrawCallback function to reinitialize gJobs:
$('#jobsTable').dataTable({
...
"fnDrawCallback": function() {
gJobs = new Object();
}
});
I should mention that since the data returned by each Ajax call doesn't change, I could also just store the data in the JSP as static text, and populate the tooltips that way instead of using Ajax. However, I have to make a separate web service call to get the data for each link, and rather than make ten web service calls every time the user pages forward or back, I would rather load the data on demand via Ajax.
Is there anything wrong with this approach? Is there any way this can cause a memory leak? Should I explicitly delete all the properties of gJobs before reinitializing it? Thanks for your help.
I try to manipulate a variable inside a function. But it seems to forget the values once I exit the function, eventhough the variable is declared outside the function.
The essential code:
var posts = {};
// Perform a data request
// skjutsgruppens-page
$.oajax({
url: "https://graph.facebook.com/197214710347172/feed?limit=500",
*SNIP*
success: function(data) {
$.extend(posts, data);
}
});
// Gruppen
$.oajax({
url: "https://graph.facebook.com/2388163605/feed?limit=500",
*snip*
success: function(data) {
$.extend(posts, data);
}
});
The oajax retrievies data from facebook. I want to make a variable that contains the data from both oajax methods.
The actual code: http://eco.nolgren.se/demo/resihop/#
The issue is likely that the success function executes at an arbitrary time in the future--unless you specifically access posts after you know the success function has executed, you will receive undefined results, completely dependent on function and access timing.
The best approach is to handle this correctly by doing necessary work inside in the success function, or use something like jQuery's .when function.
I am pretty new to this, so go easy on me:
I am building an image gallery with a main index page which allows users to select different categories of projects, a sub-index page which allows users to select specific projects within their selected category, and then the gallery page for that project.
The code below is for the main index page. I am trying to pass the value of the src attribute of the first image of the first gallery page to the main index page to use as a thumbnail.
I have effectively been able to load the correct URL into the imageLoc variable, but I need to pass it outside of the Ajax request to pass it into my HTML document.
Simply put, I am trying to pass the value of the imageURL variable to the imageLoc variable.
Thanks for your help.
$('.galleryIndex a img').hide().each(function(){
var destination = $(this).parent('a').attr('href');
var imageLoc = $.ajax({
url: destination,
success: function(data){
var pageLoc = $(data).find('.galleryList a:first').attr('href');
$.ajax({
url: pageLoc,
success: function(data){
var imageURL = $(data).find('.galleryBox img:first').attr('src');
return imageURL
}
});
}
});
alert(imageLoc);
});
This will cause troubles do to the way the callback function is handled. It's a closure block that is called after the request has returned, so it runs apart from your main code in the function. If you want to alert the imageURL variable, alert it inside the callback function, or call another function to handle it. Since it is a callback function for an asynchronous server request, the part that alerts "imageLoc" will have run long before you ever get your async request back.
Edit: The only way to achieve what you're trying to do is to not make the ajax request asynchronously. If you set async:false, then you can call on the "responseText" property like this:
var html = $.ajax({
url: "some.php",
async: false
}).responseText;
But be warned...this will halt browser operation while the request is pending. It's usually best to block user interaction by other means if you don't want them to screw with the page while something is loading.
I was able to get what I wanted as follows:
$('.galleryIndex a img[id!="fp"]').hide().each(function(){
var destination = $(this).parent('a').attr('href');
$.ajax({
url: destination,
context: $(this),
success: function(data){
var pageLoc = $(data).find('.galleryList a:first').attr('href');
$.ajax({
url: pageLoc,
context: $(this),
success: function(data){
var imageURL = $(data).find('.galleryBox img:first').attr('src'); //returns the src for the thumbnails
$(this).attr('src', imageURL);
$(this).load(function(){
$(this).show();
});
}
});
}
});
});