Call the rest of the javascript after an Ajax event - javascript

Hi
I am trying to do an auto complete functionality for an input field.
psuedo code
<input type="text"/>
<script>
var ref,resp;//Global Variables
$('input').live('keyup',function(){
/* Get the input offset, so that list container can be palced at the bottom of the input once get the values through Ajax call */
ajaxCall();
/***
Here I want to write a code to create a div and place the values with in the div and show at the respective input field.
***/
});
function ajaxCall(){
var ref = new XMLHttpRequest();
ref.open();
ref.readStateChange = function(){
if(ref.readyState == 4 && ref.status ==200)
resp = ref.responseText();
}
ref.send();
}
</script>
The problem that I am getting here is, the part of the code that is after ajax call should be executed once ajax readyState is 4 and values are retrived.
But that code is being executed when readyState is 1(Its not being called after the other states) where the values are not retrieved from the database.The lets me unable to show the list.
Note: I know that the below part can be put in ajaxCall but it contains some variables which can be set at the place....
Does my problem make sense? If so,can some body let me know the solution...

You have to call the functions that depend on the result of the AJAX call during the AJAX callback. That's just how it is:
function ajaxCall(callback) {
var ref = new XMLHttpRequest();
ref.open();
ref.readStateChange = function() {
if (ref.readyState === 4 && ref.status === 200) {
resp = ref.responseText();
callback.call(null, ref.responseText); // invoke the callback here
}
}
ref.send();
}
and then:
ajaxCall(function(resp) {
// handle "resp" here
});
That said, please don't re-invent the wheel. You'll end up with code that's hard to maintain and not portable across browsers. There's plenty of libraries that make AJAX code like this a complete doddle. I use jQuery.

The code that you expect to run after the completion of ajax call should be put in the onSuccess() or onComplete() method of your code.
ajaxCall(function(resp) {
/***
Here I want to write a code to create a div and place the values with in the div and show at the respective input field.
***/
});
i.e.. This part of your code must come in the onComplete() method, whic will have the data returned by the ajax call as parameter.

Related

How to wait for a button to complete its task then execute the next line of code

I have a button as follows that I programmatically click.
document.getElementById("generateButton").click();
This button creates a table and loads the data from the database.
I then have options to sort the table that if specified in the url, the table will be sorted once loaded.
if(COL_ONE == "true")
sortTable("COL_ONE");
My problem is that the table takes around 3 seconds to load. Therefore, the if statement where the sorting happens, ends up running before the table is created. Therefore, the sorting does not occur. If I place a break point at the if statement and stop execution at the if statement, and wait until I see the table load, then run the if statement (through the debugger) then my sorting does work. Therefore, the code is all working, its just a matter of figuring out a way to stall until the table is loaded. Is there anyway I can do this, where until the table is loaded, then run the next if statement, I am doing this on page load.
You can make use of callback in this case
function tableLoaded(callback) {
//Code to load the table
callback();
}
In your main function
tableLoaded(function(){
//have your if statement
if(COL_ONE == "true")
sortTable("COL_ONE");
});
Please post the relevant DB code.
I can only guess, though, that it looks similar to this:
document.getElementById("generateButton").addEventListener('click', function() {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if ( xmlHttp.readyState == 4 && xmlHttp.status == 200 ) {
updateTable(xmlHttp.responseText);
}
};
xmlHttp.open("GET", '/get-info-from-db', true);
xmlHttp.send();
});
In which case, it is a simple change:
document.getElementById("generateButton").addEventListener('click', function() {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if ( xmlHttp.readyState == 4 && xmlHttp.status == 200 ) {
updateTable(xmlHttp.responseText);
if(COL_ONE == "true")
sortTable("COL_ONE");
}
};
xmlHttp.open("GET", '/get-info-from-db', true);
xmlHttp.send();
});
You absolutely must put the sorting functionality in a callback and set it up to be called after the data loads. I noticed you might be loading the data into the tables asynchronously, i.e. loading data in a callback function, which is probably why the sorting function is kicking in before the load.. don't do that, have the sorting to excute right after call the function to load data.. Prehaps it would be better if you told me how you are loading the data so i can tell you extactly when and where to place to the callback function with the sorting functionality. For example, if you are using third-party support to load the data, you should probably try to find in the api a function call to load data that also accepts a callback, or completion handler. For the callback, you must pass your sorting functionality in the form of an anonymous function. Hope this helps!!

Need to Populate Javascript Array BEFORE (document).ready()

How can I get some javascript to run before a document ready function?
I have the following snippet finished first...
var applicantlist = [];
$.getJSON("apps.json", function(appsdata) {
for (var i = 0; i<appsdata.applications.length; i++){
var tempapp = [appsdata.applications[i].name, appsdata.applications[i].server];
applicantlist.push(tempapp);
}
});
I've tested this, and the data gets pushed into the array just fine. The problem is that I need this array to make some ajax calls that are found in my page ready function as follows...
$(document).ready(function(){
window.jsonpCallbacks = {};
alert(applicantlist.length);
for (var i = 0; i < applicantlist.length; i++){
(function(index){
window.jsonpCallbacks["myCallback" + index] = function(data){
myCallback(data,index);
};
})(i);
//Jquery/Ajax call to the WoW API for the data.
$.ajax({
"url":"http://us.battle.net/api/wow/character/" + applicantlist[i][1] + "/" + applicantlist[i][0] + "?jsonp=jsonpCallbacks.myCallback" + i,
"type":"GET",
"data": { fields: "items, talents, progression, professions, audit, guild, stats"},
"dataType":"jsonp",
"contentType":"application/json",
"jsonpCallback":"jsonpCallbacks.myCallback"+i,
"success":function(data1){
}
})
}
All of this fires off before the first snipet, no matter where I seem to put it. So, the array is empty (the alert message just shows "0").
As you can see by the URL of my ajax call, I need that array populated beforehand. I've tried putting the first snippet in a seperate .js file and calling it before all other javascript files on the actual HTML page...
What am I missing?
Move the code that sends the first request to the document.ready. You don't usually want anything happening before the document is ready. Then move the code that sends the next request(s) to the callback of the first request after you populate the array and do whatever else you need to happen first
$(document).ready(function () {
$.getJSON("apps.json", function(appsdata) {
...
// add items to your array
sendNextRequest();
}
});
function sendNextRequest() {
//Jquery/Ajax call to the WoW API for the data.
...
}
This gurantees that the calls to the WoW api don't get fired until the first $.getJSON call completes and you populate your array.
FYI this is a common challenge in javascript. You need one operation to run only after another finishes. When you use ajax, you have callbacks like in my example above that help you achieve this. Outside of ajax requests, you can use jQuery Promises to defer tasks until after something else finishes.

execute callback after all iframes finish loading

Trying out a small jquery plugin to make the user experience of html input file upload control consistent across browsers. Its basically a form which has an html input control which is nested in a hidden iframe.
The plugin exposes events like beforeUpload, afterUpload etc, and I am able to wire these correctly.
Here is a sample of how I'd invoke the afterUpload event.
$.fn.createUpload = function(config){
//stuff
$(myUploadIframe).load(function(){
var doc = this.contentWindow.document;
var txt = $(doc).text();
//parse txt to get json results
var result = frameWorkParser(txt);
if(result.uploadSuccess){
if(config.afterUpload){
config.afterUpload(sender, result);
}
}
});
//other stuff
};
Here is how I'd consume the plugin:
var config = {
afterUpload: function(el, data){
//set some hidden field
},
//other options
};
$('#btnSelectFile').createUpload(config);
If I've somehow invoked nested form (i.e inside the iframe) submit method, the iframe loads and I am able to successfully call the afterUpload event.
But here is where things get trickier. I am trying to execute some logic after all uploads are completed.
$.doUploads = function (callback) {
$('iframe').each(function () {
if (this.id.indexOf('_uploadContainer') > -1) {
var doc = this.contentWindow.document;
doc.forms[0].submit();
}
});
callback();
};
Here I am iterating all the plugin-created iframes (created for uploading) and invoking the nested form submit method. But this call doesn't wait for the consequent iframe onload event to complete, and the callback executes.
I want the callback to execute post the afterUpload event of my plugin. How to accomplish this?
Set some int variable(say totaliframeloaded=0;) which gets incremented on every iframe load. also give a call to callback function on every iframe load.
In callback check, whether that int variable has length equal to $('iframe').length. This condition will be getting matched when all the iframes gets loaded.
if(`totaliframeloaded==$('iframe').length){//all iframes are loaded
//callback coad
}else{
//do nothing/return
}

function not working correctly unless there is an alert

The problem
I am having is the following code will not update the tow select boxes "select1" and "select2", unless I have an alert immediately preceding the code.
Background info -
I am posting two variables to this page, "sel1val" and "sel2val", and I am assigning them to hidden input boxes with id's "sel1valtry" and "sel2valtry" respectively. I am assigning the values of these input boxes to the variables in the function and have named them "sel1val" and "sel2val". I can post more code if need be, but it is what I call "franken code"...haha! because I am a novice, it is assembled from many different styles of code.
Objective - what I am trying to achieve is to set two select boxes based upon the value of "sel1val" and "sel2val". The correct functionality is only obtained when I have an alert prior to the code.
Methods I have tried - I have left in some commented out code, to illustrate my attempts. I have been through many forums and that is where I got these ideas from. I suspect that the alert "reloads" the javascript part of the page, but I have no real basis for this. I have tried "document ready", variations of "window load", and even tried slowing things down with a delay, in case it was a timing issue. Each of the methods I have tried have resulted in the same outcome, whereby it only works with an alert.
I have achieved much success with my web based projects, and this would not have been possible without the invaluable resource in forums such as this one. I would like to thank anyone that has ever provided input/solutions, as without this I would never have been able to progress.
$(document).ready(function(){
// $(document).ajaxSuccess(function(){
// alert("AJAX request successfully completed");
// });
//$(window).load(function()
//window.onload = function()
//$(function ()
//Code goes here
//alert("got here");
//{
var sel1val = $("#sel1valtry").val()
var sel2val = $("#sel2valtry").val()
if (sel2val)
{
//alert("will not work without this alert"+sel1val);
//$("#select1").delay(2000).val(sel1val);
//$("#select1").val(sel1val);
$("#select1").prop('value',sel1val);
// var element = document.getElementById('select1');
// element.value = sel1val;
dochange('selection2', sel1val)
//var element = document.getElementById('select2');
// element.value = sel2val;
alert("will not work without this alert"+sel2val);
$("#select2").val(sel2val);
}
//}
});
//}
It seems like the dochange function is using some asynchronous API (like an AJAX call for example) which is setting value to the sel2val variable in its success callback. But since AJAX is asynchronous, this function returns immediately, not waiting for the server to return a response. By putting an alert you are blocking the execution of the next line of code and leaving enough time for the AJAX call to complete and assign a value to the sel2val variable.
The proper way to fix your code is to provide a callback to this function where you will perform the necessary actions:
dochange('selection2', sel1val, function(result) {
$("#select2").val(result);
});
And in your dochange function you will invoke this callback in the success event of your AJAX call.

JavaScript - Why function wasn't called?

It's a weird doubt, but it goes....
I have a button in a page, that makes a Ajax request, and when i have the answer, I write it to the page and then it's called a function to adjust Page Elements. When i click the button the first time, this function isn't called, but in the next request it is.
But...if I place a alert in the scope of the function, when i make the same first ajax request and wait for the answer to call the function, it displays the content of the alert and adjust my page elements.
Well...i don't see any logic in that, but if this ring's a bell to anyone, I apreciate the help.
EDIT:
function HandleResponseCellVehicleReport()
{
if (XmlHttp.readyState == 4) {
if (XmlHttp.status == 200) {
WriteCellVehicleReport(XmlHttp.responseText);
}
else {
alert("Problema: " + XmlHttp.statusText);
}
}
}
function WriteReport(myJSONtext) {
(....)
EndLoad(document);
EnableButtons(document);
adjustPageElements(pageId,document);
}
function adjustPageElements(client, __document) {
var viewportwidth;
var viewportheight;
if (!__document) {__document = document;}
(....)
}
I place the alert in the beginning of adjustPageElements function.
Thanks
I think this is because you ajax call goes Asynchronous, the content isn't yet fetched from the backend script before you try to put it in a page element. Take a look at this. If you make a synchronous ajax call the browser waits until the content is parsed back. also see this article

Categories