I want to return the responsetext of an ajax call. I'm not succeeding and I get the whole time undefined:
function ajaxFunction(callback,tekstvar){
xmlhttp= new GetXmlHttpObject();
if (xmlhttp==null)
{
alert ("Browser does not support HTTP Request");
return;
}
var url="php/functions_translate.php";
url=url+"?tekst="+tekstvar;
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200){
return callback(xmlhttp.responseText)
};
};
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
function translate(tekstvar) {
var text = ajaxFunction(function(tekst){return tekst;},tekstvar);
return text;
}
I'm calling the translate function to give me a certain translation of word. Does anyone know, what i'm doing wrong?
I've voted to close this due to duplicate. This answer is merely to make the answer found in the duplicate question more relevant to this specific question.
Please read this for more info: Undefined return value from the function call Javascritpt
You need to add a callback to the translate() function:
function translate(tekstvar,callback) {
ajaxFunction(callback,tekstvar);
}
If you expect to call translate like this:
var newtext = translate(text);
displayText(newtext);
doSomethingElseWith(newtext);
then I'm sorry but that's not possible with asynchronous code. You need to put all the code that you would have written after calling the translate function to be inside the callback you pass into the translate function.
In other words, modify it like this:
var newtext = translate(text);
//
//--------------------------------------- move everything below this line
// into the callback
displayText(newtext);
doSomethingElseWith(newtext);
so that it looks like this:
translate(text,function(newtext){
displayText(newtext);
doSomethingElseWith(newtext);
});
Related
I need help figuring out how i can setInterval while keeping a "str" to the function.
The client chooses an option, and the function "GET"'s the selected option.. But when it refreshes in setInterval, it looses the string.. How can i do this?
I have tried this:
<script type="text/javascript">
function countrystats(str)
{
if (str=="")
{
document.getElementById("countrystats").innerHTML="";
return;
}
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("countrystats").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","countrystats.php?q="+str,true);
xmlhttp.send();
setInterval(countrystats, 5000);
}
</script>
Hopefully you can help me sort out this mess :-)
I am aware that this can be done with some jQuery, but i cat seem to get that to work. Maybe those two things are related, i dont know :-)
Here is how the function countrystats gets its input:
script type="text/javascript">
$("#countrystats_menu > li > a").click(function (ev) {
var str = $(this).html();
countrystats(str);
$('#country_span').html(str);
});
</script>
EDIT/Solution:
It seems that the problem was, when doing setInterval, it looses the str attached, this code is however preserving it.
setTimeout((function(strPriorToTimeout)
{//IIFE's scope preserves state of str variable
return function()
{
countrystats(strPriorToTimeout);
};
})(str),5000);
The argument str goes out of scope at the end, the interval simply calls the function without passing any value to str. As some comments suggest, countrystats(str) would appear to do the trick, but it doesn't, here's why:
setInterval(countrystats(str), 500);
This line contains multiple expressions that will be evaluated/resolved to some value, like countrystats(str), which is a direct call to a function. The function, then, will be called prior to the interval being set. The quickest solution is creating an anonymous function, and call the function from within:
setInterval(function()
{
countrystats(str);
},5000);
You can even play it extra safe, by creating a closure, actually passing the intended value of str to the interval function. This is optional, and might look a bit confusing (and messy):
setInterval((function(strPriorToTimeout)
{//IIFE's scope preserves state of str variable
return function()
{
countrystats(strPriorToTimeout);
};
})(str),5000);
There is just one thing that's bothering me about your code: you're using setInterval, which repeats the same function call every X ms. If you only need to call a function once, it might be better using setTimeout.
Another thing is: setInterval returns the interval's id, so you can stop the constant function calls if needed. You don't seem to be assigning that ID anywhere, so your code will keep on running, unless you're brute-forcing the clearInterval calls. Perhaps consider assigning the return value of setInterval to some variable you can access.
If you don't the only way of clearing intervals AFAIK would be:
for (var i=0;i<Number.MAX_VALUE;i++)
{
clearInterval(i);
}
Now that's just terrible, isn't it?
In light of the comments, I thought I'd do well adding some info on webworkers here. From what I gather the OP wants to acchieve, I recommended using webworkers as much as possible. A basic setup here could be:
//client.js
var worker = new Worker('dashWorker.js');//worker script
//to kick off the worker:
function countrystats(str)
{
str = str || document.getElementById('countrystats').innerHTML;//get str value
worker.postMessage(str);//that's it, the worker takes care of everything else
}
worker.onmessage = function(response)
{
document.getElementById('countrystats').innerHTML = response.response;//cf worker code
return countrystats(response.str);//choose when to call the countrystats function again, as soon as the worker responded... easy!
};
//the worker:
self.onmessage = function(e)
{//you could add a way of stopping the constant updates, by posting a 'stopDash' or something...
//do ajax call using e.data --> this is the string anyhow
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(response)
{
if (this.readyState === 4 && this.status === 200)
{
self.postMessage({str: e.data,
response: response.responseText});
}
};
xhr.open('GET', 'countrystats.php?q=' + e.data,true);
xhr.send();
};
Of course, this code is far from "clean": it could do with some performance tweaks (like not querying the DOM all the time), but the basic principal stands...
A couple of important links for you here:
MDN
John Resig's blog post on workers
A step-by-step introduction to webworkers
you are calling setInterval(countrystats, 5000); in the same function. you can do with jquery also
url='countrystats.php?q='+str;
ajax calll
$.get(url, function(data) {
$('#countrystats').html(data);
});
once the get finishes. you can call setInterval(countrystats, 5000); for refreshing the content.
I've simplified your code with jQuery. I've used jQuery.load to load the remote html to the start element.
And whenever a new item is clicked you need to create the previous interval, otherwise multiple request threads will be running
function countrystats(str) {
if (str == "") {
$('#countrystats').empty();
return;
}
$('#countrystats').load('countrystats.php?q=' + str)
}
var interval;
$("#countrystats_menu > li > a").click(function(ev) {
if (interval) {
clearInterval(interval);
}
var str = $(this).html();
countrystats(str);
interval = setInterval(function() {
countrystats(str);
}, 5000);
$('#country_span').html(str);
});
I have an input field for a concept and when the user fills it out, he has to then check if the concept exists. So I made a check button, which checks a database using ajax and JavaScript to see if the concept exists. My problem is when using ajax and JavaScript I get this exception:
unexpected end of input
JS :
var concept = document.getElementById('acConceptName').value;
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4 && xmlhttp.status==200){
var isexisted = JSON.parse(xmlhttp.responseText);
if(isexisted[0]==true){
var errorMessage = document.getElementById('acSuggesConcepts');
var p = document.createElement('p');
p.innerHTML="this concept is already existed";
errorMessage.appendChild(p);
errorMessage.style.display="block";
}
}
}
xmlhttp.open("GET","http://localhost/Mar7ba/Ontology/isExistedConcept/"+concept+"/TRUE",true);
xmlhttp.send();
What is the exception and how can I solve it ?
PHP : function to check database and I always return true in it
public function isExistedConcept($concpetName,$Ajax){
if($Ajax==true){
$results=true
$d=array($results);
return json_encode($d);
}
}
Demo: http://jsfiddle.net/Wiliam_Kinaan/s7Srx/2/
After looking at the code for a while, one thing that might be a suspect is your PHP.
Your function in php ends with a return command. What the AJAX call is actually waiting for is some data to be sent back. The return command simply passes that value back to the entity that originally called the function.
Try alter your function to echo the result as opposed to returning it. Save your return value for when you need the result to go into another PHP function, not when you are returning data to the client.
I only put this return command here for readability.
public function isExistedConcept($concpetName,$Ajax){
if($Ajax==true){
$results=true
$d=array($results);
echo json_encode($d);
}
return;
}
Try this:
public function isExistedConcept($concpetName,$Ajax) {
if( $Ajax) return "1";
}
// This is a simplified version of what you're doing, but it returns "1" instead of "[true]"
// Now for the JS:
if( xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var isexisted = xmlhttp.responseText == "1";
if( isexisted) {...}
If that doesn't work, try adding alert(xmlhttp.responseText) and see if you're getting anything other than what should be there.
try this :
var concept = document.getElementById('acConceptName').value;
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","http://localhost/Mar7ba/Ontology/isExistedConcept/"+concept+"/TRUE",true);
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4){
if(xmlhttp.status==200){
var isexisted = JSON.parse(xmlhttp.responseText);
if(isexisted[0]==true){
var errorMessage = document.getElementById('acSuggesConcepts');
var p = document.createElement('p');
p.innerHTML="this concept is already existed";
errorMessage.appendChild(p);
errorMessage.style.display="block";
}
else{
console.log('error');
}
}
}
}
xmlhttp.send(null);
For some reason I always receive undefined if I return the value but if I'm trying to display it in alert I receive the php values.
function getXMLHttp() {
var xmlHttp
try {
//Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
} catch(e) {
//Internet Explorer
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
//Browser does not support AJAX
return false;
}
}
}
return xmlHttp;
}
function isUsernameExists() {
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
handleResponse(xmlHttp.responseText);
}
}
var str = document.getElementById('username').value.toString();
xmlHttp.open("GET", "ajax.php?username="+str, true);
xmlHttp.send(null);
}
Edit:
function handleResponse(response) {
return response.toString();
}
Thanks,
Guy Dor
It looks like you are trying to read the return value from this function:
function isUsernameExists() {
It doesn't have a return statement, so it will always be undefined.
I'm guessing you expect this return statement to pass the value you want:
return xmlHttp.responseText.toString();
But that is part of this function:
xmlHttp.onreadystatechange = function() {
Which is called automatically when the readystatechange event fires, and not by any function call you make.
Asynchronous JavaScript and XML rarely uses XML but is asynchronous. Anything you want to do with the data fetched needs to be done by the callback function you assign to onreadystatechange. It can call other functions, but it cannot return anything (at least not that will be received anywhere useful).
We can't see enough of your code to fully understand the situation, but you are dealing with an asynchronous operation and the only way to communicate the result of that asynch operation is to call a function with the value you got from that operation. You cannot just return from the function.
This is a common misunderstanding (the sixth time I've answered this issue today). The function on have for the ready state change is not called by any of your code. It's called by the browser internally when the ajax call completes. That means that returning your value from that function will do nothing and certainly won't communicate that result to any of your code. If you want to communicate that result to some of your code, then you need to call some of your code from inside that function and pass it the desired result so that code can act on it. This breaks the normal flow of programming, but is required when dealing with asynchronous operations.
you have a return statement in the function your create here,
xmlHttp.onreadystatechange = function() {
but there is no return statement in the function,
function isUsernameExists() {
just because you created the function within another function does not mean the code in that function gets run.
the code within the function you created will not run until a response is received from the server, by which point the original function that created the second function will have already finished execution.
the code does not halt to wait for a response from the server, it instead continues to run and finishes execution. the function that you created to handle the response from the server then gets run at a later time when a response is received.
I have a little script which uses AJAX and PHP to display an image. You can see below that if I call the function mom() it looks in the PHP file index.php?i=mom and displays the image I'm looking for.
But I need the javascript to be lighter as I have 30 images and for each one I have to modify and copy the script below. Is there not a simpler way to have the functions be different and still call a different page?
<script type="text/javascript">
function mom()
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
HandleResponse(xmlHttp.responseText);
}
}
xmlHttp.open("GET", "index.php?i=mom", true);
xmlHttp.send(null);
}
function HandleResponse(response)
{
document.getElementById('mom').innerHTML = response;
}
</script>
My Trigger is this
<a href="#" onclick='mom();' />Mom</a>
<div id='mom'></div>
You could modify your function so it takes a parameter :
// The function receives the value it should pass to the server
function my_func(param)
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
// Pass the received value to the handler
HandleResponse(param, xmlHttp.responseText);
}
}
// Send to the server the value that was passed as a parameter
xmlHttp.open("GET", "index.php?i=" + param, true);
xmlHttp.send(null);
}
And, of course, use that parameter in the second function :
function HandleResponse(param, response)
{
// The handler gets the param too -- and, so, knows where to inject the response
document.getElementById(param).innerHTML = response;
}
And modify your HTML so the function is called with the right parameter :
<!-- for this first call, you'll want the function to work on 'mom' -->
<a href="#" onclick="my_func('mom');" />Mom</a>
<div id='mom'></div>
<!-- for this secondcall, you'll want the function to work on 'blah' -->
<a href="#" onclick="my_func('blah');" />Blah</a>
<div id='blah'></div>
This should work (if I understand correctly)
<script type="text/javascript">
function func(imgName)
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
document.getElementById(imgName).innerHTML =
}
}
xmlHttp.open("GET", "index.php?i=mom", true);
xmlHttp.send(null);
}
</script>
MARTIN's solution will work perfectly.
By the way you should use some javascript framework for Ajax handling like jQuery.
It will make your life easy.
If you are having light weight images you preload the images on your page.
I solved this by making an array of in your case xmlHttp and a global variable, so it increments for each request. Then if you repeatedly make calls to the same thing (eg it returns online users, or, whatever) then you can actually resubmit using the same element of the array too.
Added example code:
To convert it to a reoccuring event, make a copy of these 2, and in the got data call, just resubmit using reget
var req_fifo=Array();
var eleID=Array();
var i=0;
function GetAsyncData(myid,url) {
eleID[i]=myid;
if (window.XMLHttpRequest)
{
req_fifo[i] = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
req_fifo[i] = new ActiveXObject("Microsoft.XMLHTTP");
}
req_fifo[i].abort();
req_fifo[i].onreadystatechange = function(index){ return function() { GotAsyncData(index); }; }(i);
req_fifo[i].open("GET", url, true);
req_fifo[i].send(null);
i++;
}
function GotAsyncData(id) {
if (req_fifo[id].readyState != 4 || req_fifo[id].status != 200) {
return;
}
document.getElementById(eleID[id]).innerHTML=
req_fifo[id].responseText;
req_fifo[id]=null;
eleID[id]=null;
return;
}
function reget(id) {
myid=eleID[id];
url=urlID[id];
req_fifo[id].abort();
req_fifo[id].onreadystatechange = function(index){ return function() { GotAsyncData(index); }; }(id);
req_fifo[id].open("GET", url, true);
req_fifo[id].send(null);
}
The suggestions to parameterize your function are correct and would allow you to avoid repeating code.
the jQuery library is also worth considering. http://jquery.com
If you use jQuery, each ajax call would literally be this easy.
$('#mom').load('/index.php?i=mom');
And you could wrap it up as follows if you'd like, since you say you'll be using it many times (and that you want it done when a link is clicked)
function doAjax(imgForAjax) { $('#'+imgForAjax).load('/index.php&i='+imgForAjax);}
doAjax('mom');
It makes the oft-repeated ajax patterns much simpler, and handles the issues between different browsers just as I presume your getXMLhttp function does.
At the website I linked above you can download the library's single 29kb file so you can use it on your pages with a simple <script src='jquery.min.js'></script> There is also a lot of great documentaiton. jQuery is pretty popular and you'll see it has a lot of questions and stuff on SO. ajax is just one of many things that jQuery library/framework (idk the preferred term) can help with.
I have the following code, which is the core part of my small AJAX application. I am not getting any errors, it is just that nothing happens. I am guessing there is a more efficient way to do what I am trying to do.
Here is the code:
var xmlHttp
var layername
function update(layer, part, pk, query)
{
if (part=="1")
{
$url "get_auction.php?cmd=GetAuctionData&pk="+pk+"&sid="+Math.random()
}
else if (part=="2")
{
var url "get_records.php?cmd=GetRecordSet&query="+query+"&sid="+Math.random()
}
xmlHttp=GetXmlHttpObject()
if(xmlHttp==null)
{
alert("Your browser is not supported?")
}
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState==4 || xmlHttp.readyState=="complete") {
document.getElementById(layer).innerHTML=xmlHttp.responseText
} else if (xmlHttp.readyState==1 || xmlHttp.readyState=="loading") {
document.getElementById(layer).innerHTML="loading"
}
};
xmlHttp.open("GET",url,true)
xmlHttp.send(null)
}
function GetXmlHttpObject()
{
var xmlHttp=null;
try
{
xmlHttp=new XMLHttpRequest();
}catch (e)
{
try
{
xmlHttp =new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
return xmlHttp;
}
function makewindows(){
child1 = window.open ("about:blank");
child1.document.write(json_encode(<?php echo $row2["ARTICLE_DESC"]; ?>));
child1.document.close();
}
and an example of how I am calling the function from php
onclick="update(\'Layer3\',\'2\','.$pk.'\',\'0\',)">'
pk or query will never be passed at the same time, only one of them will ever be passed.
edit: I am also wondering if it would make more sense for the makewindows function to take a parameter, or stay as it is. Are there advantages and disadvantages for each approach?
Looks like you may have some javascript errors:
if (part=="1")
{
$url "get_auction.php?cmd=GetAuctionData&pk="+pk+"&sid="+Math.random()
}
else if (part=="2")
{
var url "get_records.php?cmd=GetRecordSet&query="+query+"&sid="+Math.random()
}
Use Firefox and Open the javascript console to get the javascript errors, then try to fix the lines it complains about.
Javascript will stop running as soon as it encounters an error.
Also, checkout firebug if you haven't already. Great tool!
I'd check the HTML the PHP is generating. Assuming $pk is a string it looks like you're missing an opening quote. Try this:
onclick="update(\'Layer3\',\'2\',\''.$pk.'\',\'0\',)">
json_encode is a PHP function, and thus you need to modify that particular line like so:
child1.document.write(<?php echo json_encode($row2["ARTICLE_DESC"]); ?>);