how to call javascript methods sequentially on onclick event - javascript

I need to call two functions sequentially (means one by one) in javascript on onclick event.
The requirement is to get the data from the backend and then make the cell highlight.
Below code snippet is used for this:
cell1.onclick=function() {
getData("FileName");
setTimeout("setHighlight('FileName')", 500);
};
Currently i am using the setTimeout for calling the second method after a delay of 500ms.
The problem with above code is if getData method takes more than 500ms to get the data from backend then in that case cell would not get highlighted.
Is there any way to do this?
Thanks
Jyoti

To get data from the backend, you probably are using AJAX.
And in the callback function you are populating the data. After this step, call the highlight function.
You probably have something like this:
xmlHttp.onreadystatechange = function()
{
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
{
// do something with the response here
highlightData(); //<---- the function to highlight data
}
}

You should add another parameter to getData, which is a function to execute when you have the data. So,
function getData(filename, callback) {
// get the data
// when you have the data, do callback(filename);
}
then you can do
getData("FileName", setHighlight);

Related

What is a better alternative to $("#myDiv").html(myResult); in this scenario?

I am currently using Ajax to update a feed of information. The Ajax should add to the current list of results rather than replace the existing results.
So far I have created the Ajax required to fetch the data from a database, but in the callback function I am using the following callback function
fetchPosts.onreadystatechange = function() {
if(fetchPosts.readyState === 4) {
$("#resultfeed").html(fetchPosts.responseText);
}
}
Obviously using $("#resultfeed").html(fetchPosts.responseText); in the callback function means that any prior results are overwritten on the page. How can I change this so that the results add to the current list of results?
Use append or prepend
$("#resultfeed").append(fetchPosts.responseText); // Adds at the end
$("#resultfeed").prepend(fetchPosts.responseText); // Adds at the top

How to change a dynamically created element after it loads javascript

I have a site that makes an HTTP request for JSON data, then a callback function processes the data and displays it by creating a series of divs dynamically. What I want to do is to wait for that function to finish adding the divs to the page, then apply labels only to specific divs created by the previous code.
HTTP Request and Callback
function data(callback){
var url = //request url;
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState === 4) {
if (request.status === 200) {
document.body.className = 'ok';
//Parse returned string into an object, then pass the object to the callback function.
var data = JSON.parse(request.responseText);
callback(data);
} else {
document.body.className = 'error';
}
}
};
request.open("GET", url , true);
request.send(null);
}
function dataDisplay(data){
//outputs <div id="1064" class="displayed-data">
<p id="message1" class="hidden"></p>
}
data(dataDisplay);
The code above displays my data exactly how I want it to, but when I try to access the numbered ID of the divs I want to change, the function runs before the data is displayed on the page, causing a 'null' error because the data I am trying to change hasn't been added to the DOM yet.
Second Function to change original
function label(){
var message1 = document.createTextNode('//some label');
var displayedData = document.getElementById('1064').getElementById('message1');
displayedData.appendChild(message1);
document.getElementById('message1').classList.remove('hidden');
}
How do I get the second function to wait until the callback has completed before trying to access and change it? I tried a callback inside of a callback, something like: label(data(dataDisplay)); but it still threw the same errors, so I clearly did it wrong. Sorry, I am brand new to JavaScript and don't really know where to go from here.
Thanks for your help!
A pretty quick way of doing it correctly is with this inline function.
data(function(result) {
dataDisplay(result);
label();
});
Be aware that your data function itself completes very quickly - if you need something from its result, you will need to include it in its callback.

javascript calling DataSnap REST makes browser unresponsive

I use Delphi XE7. When my Javascript calls my server function that need around 800ms to read sensor and return data, The browser is unresponsive from the moment I click the button to invoke the Javascript until it finally response returns. I'm using the default Javascript generated by the proxy var serverMethods().getChannel(i); to call into my server function.
Javascript call look like this:
var s = serverMethods().getChannel(i);
serial[i].$sensorlValue.text(s.result.fields.sensorString);
serial[i].$sensorlRealValue.text(s.result.fields.sensor);
serial[i].$sensorStatus.text(s.result.fields.sensorStatus+' '+s.result.fields.name);
serial[i].$sensorError.text(s.result.fields.sensorError);
serial[i].$AVString.text(s.result.fields.AVString);
serial[i].$AVError.text(s.result.fields.AVError);
So by default example there are no Javascript callbacks or promise, so embaracaderom manage somehow to block Javascript from executing until response is back and variable a receive values?
I think about try using jQuery Ajax call on URL, but is there any other solution?
Because serverMethods are generated from proxy but for $ajax I need to manually set each of them. Or maybe I do something wrong here and serverMethods can be used without blocking ?
Thanks.
I found the solution to this problem after researching execution path in ServerFunctionExecutor.js that is called on serverMethods().SOMEAPIFUNCTION()
1. Help and documentation are 0, and google + XE7 questions are 0. So if someone from embaracadero read this PLS MAKE DECENT DOCUMENTATION.
ServerFunctionExecutor.js had on line 263
//async is only true if there is a callback that can be notified on completion
var useCallback = (callback != null);
request.open(requestType, url, useCallback);
if (useCallback)
{
request.onreadystatechange = function() {
if (request.readyState == 4)
{
//the callback will be notified the execution finished even if there is no expected result
JSONResult = hasResult ? parseHTTPResponse(request) : null;
callback(JSONResult, request.status, owner);
}
};
}
So it is posible and NOT DOCUMENTED to use callback for unblocking GUI.
Use it as:
serverMethods().SOMEAPIFUNCTION(par1,par2,.... callback)
If you have Server method defined in delphi code with for example 3 parameters in js 4th parameter is callback:
For this example code now look like this:
serverMethods().getChannel(i,function(a,b,c){
serial.$sensorlValue.text(a.result[0].fields.sensorString);
serial.$sensorlRealValue.text(a.result[0].fields.sensor);
serial.$sensorStatus.text(a.result[0].fields.sensorStatus+' '+s.result.fields.name);
serial[i].$sensorError.text(a.result[0].fields.sensorError);
serial[i].$AVString.text(a.result[0].fields.AVString);
serial[i].$AVError.text(a.result[0].fields.AVError);
});
a is JSON reponse
b is Request status as number 200 or somethin else
c is owner usuali undefined

Trying to get the newest innerHTML text of a label

I have a function that queries a database for info, when a button is clicked. This info gets written to innerHTML of a label. When this function returns, I read the innerHTML of this label. Problem is, it always returns the old value, not the new value that was pulled from the database. The label on the scree is displaying the correct value, though. When I click the button again, the value that I was expecting on the previous click, is now given. Seems like a timing issue but can't seem to figure it out.
example:
SQL Data - cost = 10
I expect to see 10 alerted to me when I click the button. I get a blank alerted to me, even though 10 is now in the label. When I click the button again, 10 is alerted, but 20 is now in the label.
function getInfo() {
var ctlMonthly = document.getElementById("cellMonthlyCost")
getSQLData(ctlMonthly);
alert(ctlMonthly.innerHTML);
}
function getSQLData(ctlCell){
...
var my_ctlCell = document.getElementById(ctlCell);
$.each(objData.items, function() {
my_ctlCell.innerHTML = this.Param1
});
...
}
Thanks.
you need to add the alert after the data is received from the database. I am assuming that you're sending an ajax request to fetch data. You will be able to get the new value in the callback of you're ajax request function.
Currently what is happening in your code is that
1. getSQLData(ctlMonthly);
// This sends a request to the data base to fetch data
2. alert(ctlMonthly.innerHTML);
// This shows the current value in an alert
3. data is received and shown in the label
This process happens so fast that you don't notice the difference between step 2 and 3.
Is this what you want?
I used a callback function
function getInfo() {
var ctlMonthly = document.getElementById("cellMonthlyCost")
getSQLData(ctlMonthly,alertInfo);
}
function alertInfo(info){
alert(info);
}
function getSQLDate(ctlCell,callbackFn){
...
var my_ctlCell = document.getElementById(ctlCell);
$.each(objData.items, function() {
my_ctlCell.innerHTML = this.Param1;
callbackFn(this.Param1);
});
...
}
to piggyback on Himanshu's answer, your request to your server is async. Meaning javascript will execute the GET request and continue on with the script, when the requests comes back from the server it will run whatever callback you give it. ( i.e. update label tag )
assuming getSQLData is a ajax call or something promised based, something like:
function getSQLData(ctlCell){
return $.get('/sql/data').done(function () {
var my_ctlCell = document.getElementById(ctlCell);
$.each(objData.items, function() {
my_ctlCell.innerHTML = this.Param1
});
});
}
you can change your code to:
function getInfo() {
var ctlMonthly = document.getElementById("cellMonthlyCost")
getSQLData(ctlMonthly)
.done(function () {
alert(ctlMonthly.innerHTML);
});
}
Basically the difference is your telling javascript to alert the innerHTML after the requests comes back from the server.
The more correct answer would be to alert the data straight from the response instead of reading from the DOM.

How do I execute a Javascript function requires a value after an onload function is completed that gives the value?

I know its a long question, so allow me to explain as best as I can.
I have two javascript functions that I want to run after the page loads, we will call them function1() and function2().
function1() uses AJAX to retrieve information from the database that will arrange the contents in a div from the information obtained in the database. It also returns the contents from the database once the function has finished.
function2() requires the value from the database in order to run properly, so it needs to wait until function1() returns its value before function2() runs. Unfortunately my code is not working, and without going into too much detail, below is a schematic of the code:
function function1() {
if (some_cookie_exists) {
//run some code
} else {
//send parameters through "POST"
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var a = some_value_from_database;
// change div content
return a;
}
}
//sending parameters
}
function function2(a) {
//run code that depends on value of "a"
}
window.onload = function() {
var data = function1();
function2(data);
The error I get is that var data is undefined. function1() retrieves the data successfully, and runs as I intended it to, but function2() does not execute at all, because the value is missing. Can anyone figure out why I am getting this and how I should go about solving this?
NOTE: I am really only familiar with Javascript (still novice at that), I know essentially nothing about JQuery, so if you do use this to fix the code, please explain to me why this works (it will save me trouble later)
AJAX is asynchronous (that's what the first A stands for). The results of the AJAX operation are not available in function1(), they're retrieved in the onreadystatechange handler that you attach to the XMLHttpRequest object. So it's not clear how you could be doing
var a = some_value_from_database;
in function1().
What you need to do is call function2() from the onreadystatechange handler.
If you post the actual implementation of function1 we may be able to provide more specific details.
UPDATE:
Here's how to call function2() when the value becomes available from the AJAX call:
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var a = some_value_from_database;
function2(a);
}
}
Do it with a callback.
function function1(callback) {
/* ... */
callback(data); // instead of return
}
var function2 = function(data) { // important: make "function2" a variable so that it can be passed as an argument later on
/* ... */
}
window.onload = function() {
function1(function2); // important: no parentheses after function2, otherwise it would be executed right away
}
Because ajax by definition is asynchronous, function2 will start executing before the ajax completes in function1. JQuery would be useful here, as you can place function2 in the success callback of the ajax call in function1.
So include JQuery in your HTML and the following JS should work:
$(function() { //same as onload
function1() ;
}
function function1() {
$.ajax({
url: "url here",
type: "GET",
success: function(data) { // data is what is returned in ajax response
// rearrange divs
function2(data);
}
});
);
function function2(data) {
}
More on the JQuery ajax function here:
http://api.jquery.com/jQuery.ajax/

Categories

Resources