This is my first question and I hope I don't do anything wrong. First of all, thank you for reading.
And my problem is...
The design is to read some data in a text file with JavaScript, process them through a number of functions before creating the content to display in an HTML div.
After some searching, I figured that it could be done with XMLHttpRequest. Because the read data will be processed by some functions, I decided to store them to a global variable for easy access. The code seemed to be working fine at first and I could print the obtained data to a div. But then I noticed a strange bug. If I assign those data to a global variable and attempt to retrieve them later, I will get the initially assigned value or undefined. I try to alert that global variable's value and I see what I get above. However, if I alert again, the value changes to what I needed. I have just been learning JavaScipt for a short while, facing this error completely leaves me at lost.
The html file:
<html>
<head>
<meta charset="UTF-8">
<title>Read file</title>
<script>
var output = ["next"];
function edit()
{
var rawFile = new XMLHttpRequest();
rawFile.open("GET", "test.txt", true);
rawFile.responseType = "text";
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
output[0] = rawFile.responseText;
//alert("Reading okay!");
}
}
};
rawFile.send(null);
console.log(output[0]); // initial value
alert(output[0]); // initial value
console.log(output[0]); // desired value
alert(output[0]); // desired value
}
</script>
</head>
<body>
<button onclick="edit()">Read test.txt</button>
</body>
</html>
The text file:
This is the content of the text file.
Temporarily, I have to alert every single time the text file is read which isn't a good idea to solve the problem.
My question is, with the above design, is there any better way to implement it without having to deal with this bug?
And here is the demo: html and text.
Thank you very much.
That's because the value changes asynchronously.
The alert is no guaranty, it's just a delay after which the AJAX callback could have been executed or not.
If you want to use the desired value, you must run your code in onreadystatechange.
Example:
function edit(callback)
{
/* ... */
rawFile.onreadystatechange = function () {
if(rawFile.readyState === 4 && (rawFile.status === 200 || rawFile.status == 0)) {
output[0] = rawFile.responseText;
//alert("Reading okay!");
callback();
}
};
/* ... */
}
fuunction afterEdit(){
alert(output[0]); // desired value
}
<button onclick="edit(afterEdit)">Read test.txt</button>
Since the AJAX call is asynchronous, it is being executed after your edit function returns... Since it sounds like you are passing your data through a series of functions, I suggest using a promise library (Q.js for instance). Here is a simple jsfiddle that demonstrates using Q.js.
Your AJAX call would simply resolve the promise, kicking off the chain of functions to execute. My example shows modifying the data at each step, but this is not necessary. The return value of the prior function will be used as the input for the next function. I've commented out the AJAX stuff and used setTimeout to mimic async call:
//Global variable for test.txt
var test;
function edit()
{
/*
var deferred = Q.defer();
var rawFile = new XMLHttpRequest();
rawFile.open("GET", "test.txt", true);
rawFile.responseType = "text";
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
//resolve promise with responseText;
deferred.resolve(rawFile.responseText);
}
}
};
deferred.promise
.then(processStep1)
.then(processStep2)
.then(processStep3);
*/
//Imitating async call that will finish after 2 seconds
var deferred;
var promise;
//if we haven't read the file yet, then make async call
if (test === undefined) {
deferred = Q.defer();
setTimeout(function () {
test = "This is the content of the text file."
deferred.resolve(test);
}, 2000);
promise = deferred.promise;
}
//Else we've already read the file.
else {
promise = Q(test);
}
//Start adding your functions to process text here:
promise.then(processStep1)
.then(processStep2)
.then(processStep3);
}
function processStep1(data) {
alert("Step 1: " + data);
//adding some stuff onto data for example
data = data + "... And more data.";
return data;
}
function processStep2(data) {
alert("Step 2: " + data);
data = "Adding data to front. " + data;
return data;
}
function processStep3(data) {
alert("Step 3: " + data);
return data;
}
Above, I also use a global variable (test) for the data retrieved from async call. I check this value when deciding if I need to make an async call to get the value, or use the value that was already populated from the original async call. Use whatever pattern most fits your needs.
I would also recommend a library for doing the async calls as your project might get messy fast by doing raw AJAX calls.
Related
I've got an AJAX page that returns some data from a GET. All good. I'm trying to call it from Javascript in response to a user changing the value of a select element called ProductCode. I've come from the C# world if some of my terminology is a little off.
Javascript:
function ProductCodeChange()
{
try
{
elProductCode = document.getElementById("ProductCode");
ProductCode = elProductCode.value;
var AJAX_MAGICTOKEN = "773d8626-6b78-4055-bf8b-4fbbaa725550";
url = "AJAX_GetData.php?";
url += "MagicToken=" + AJAX_MAGICTOKEN + "&";
url += "Query=GetProduct&";
url += "ProductCode=" + ProductCode;
httpxml = new XMLHttpRequest();
httpxml.onreadystatechange = PopulateProductCode(httpxml);
alert(">httpxml.open");
httpxml.open("GET", url, true);
httpxml.send(null);
}
catch (e)
{
alert(e.message);
}
}
function PopulateProductCode(httpxml)
{
try
{
alert(">ProductCodePopulate");
if (httpxml.readyState == 4 && httpxml.status == 200)
{
data = httpxml.responseText;
alert(data);
}
else
{
alert("readyState: " + httpxml.readyState.toString());
alert("status: " + httpxml.status.toString());
}
}
catch (e)
{
alert(e.message);
}
}
HTML:
<select id="ProductCode" name="ProductCode" onchange="ProductCodeChange();">
<option value="AP1A" >Annual Licence</option>
<option value="AP1M" >Monthly Licence</option>
</select>
I've configured the XMLHttpRequest object to call PopulateProductCode when the onreadystatechange event is fired. I've got quite a lot of work to do with the data returned, and would prefer to have a separate function called when the XMLHttpRequest returns data.
If my C# world, the line httpxml.onreadystatechange = PopulateProductCode(httpxml); sets up the httpxml object with a delegate to call once its ready state has changed. However, when executing the code above, the order of events is:
alert(">ProductCodePopulate");
alert(">httpxml.open");
so my delegate is being called before the GET request is sent.
Am I completely misunderstanding how this object works? How can I achieve what I'd like to do (i.e. keep the functionality in a separate function)?
If you could stick to vanilla Javascript in your answer, that'd be great. I'm not familiar with JQuery yet. Thanks.
Edit:
An alternative is:
httpxml.onreadystatechange =
function()
{
if (this.readyState == 4 && this.status == 200)
{
data = httpxml.responseText;
alert(data);
}
}
This does work correctly and doesn't get executed until data is returned. From #James answer below, the first version gets executed immediately, but the version immediately above doesn't. I don't understand what is the difference between the two, except that the second doesn't have a function name. Surely they are the same thing, but one version is nameless? Why the difference in processing?
In Javascript, this line httpxml.onreadystatechange = PopulateProductCode(httpxml) first calls PopulateProductCode with the httpxml parameter, and assigns the return value of that as the event handler to use when ready state changes.
Simplest is to wrap your call to PopulateProductCode in an anonymous function.
httpxml.onreadystatechange = () => PopulateProductCode(httpxml);
I would recommend changing the approach to a newer implementation. The fetch API. It returns a promise. Improves code readability and is a better approach now days.
Suggested reading:
Fetch API vs XMLHttpRequest
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
Hi I've been trying to clarify this but there's something I'm still confused about. I know that you can't return values from asynchronous functions so I've referenced this answer's top answer Returning value from asynchronous JavaScript method?
What I'm trying to do is use the flickrAPI to get the biggest size image. The flickrAPI allows one to search images, so I use this to get the photo_id, then I use this photo_id to procses another request to the API's getSize method to get the URL for the biggest size photo.
The code looks a little messy as it is, because I have a method called flickrRequest which sends an XMLHttp request and gets back a JSON string. I know that I can achieve what I want by writing the functions as follows:
function flickRQforimage() {
...got ID
function flickrRQforSize() {
...got maxsizeURL
create image based on maxsizeURL here
}
}
but I was wondering if it was possible to do something like this
function flickRQforimage() {
...got ID
function flickrRQforSize() {
...got maxsizeURL
}
create image based on maxsizeURL here
}
or even create image based on maxsizeURL here
In general my question is whether it is possible to have a callback function that references another statically defined function (I think?). The specifics of the my function is that it takes a callback and the ID and URL processing happens in those callbacks:
flickrRQ(options, cb)
I am wondering whether/what would happen if that unnamed function is instead something else, say flickrRQ(options, processPhoto(data)), and then I define the function in a separate method. This just makes sense for me because I want to keep functionality for the URL processing separate in an attempt to make my code cleaner and more readable.
I tried the following below and it didn't work. Nothing prints. I even have a console.log in the processPhoto method. In fact anything inside of the flickrRQforSize method seems to not evaluate
flickrRQforSize(options, function(data) {
processPhoto(data)
}
even though in the flickrRQforSize definition, a callback function is taken as an argument. I'm suspecting there must be something about functions/async calls that I don't understand.
I hope this is clear -- if not, I can post my actual code.
Here's my code:
var flickrRequest = function(options, xhrRQ, cb) {
var url, xhr, item, first;
url = "https://api.flickr.com/services/rest/";
first = true;
for (item in options) {
if (options.hasOwnProperty(item)) {
url += (first ? "?" : "&") + item + "=" + options[item];
//parses to search equest;
first = false;
}
}
//XMLHttpRQ to flickr
if(xhrRQ == 1 ) {
xhr = new XMLHttpRequest();
xhr.onload = function() { cb(this.response); };
xhr.open('get', url, true);
xhr.send();
};
}
var processPhotoSize = function(photoJSON) {
var parsedJSON = JSON.parse(data);
var last = parsedJSON.sizes.size.length;
console.log(parsedJSON.sizes.size[last-1].source);
return parsedJSON.sizes.size[last-1].source;
}
...
flickrRequest(options, 1, function(data) {
...
flickrRequest(sizesOptions, 0, function(data) {
parsedJSON = JSON.parse(data);
console.log(parsedJSON);
processPhotoSize(data);
});
}
Javascript : return XMLHttpRequest out of scope
I need to return the data from my AJAX call
series: [{
data: ( )
in order to update one of the keys data in dictionary series but my function retrieve does not seem to return the data that I am getting.
var myPopulation = {
series: [{
data: (
function() {
function retrieve() {
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
var obj = JSON.parse(httpRequest.responseText)
console.log(obj.V1, obj.V2, obj.V3, obj.V4);
var data = [],
time = (new Date()).getTime(),
i;
for (i = -60; i <= 0; i++) {
console.log(obj.V2)
data.push({
x: time + i * 60 * 1000,
y: obj.V2
});
}
myPopulation.series[1].data = data
// ???
console.log(data)
}
}
};
httpRequest.open('GET', "/myCall");
httpRequest.send();
}
retrieve();
}()
)
}],
What should I do to return the value out of the function and update data?
Well, since you are using jQuery tag, I think my answer could be valid and I prefer doing this way for what you need and I understood (it is well explained so please read code comments and check browser console, this can be found at the end of the answer).
Remember that you won't be able to return a XMLHttpRequest because ajax calls are async but you can force an ajax call to be sync in order to get your data on a return statement from any function or do other things as you expected. However, forcing is not a good approach to do because UI will freeze for the user until getting the response back from server and you really don't know how much time that will take (specially if you are expecting a big amount of data to be returned - I know that's not entirely a metric but other factors may apply).
Hope this helps and please take your time and read the following post and user comments: Reasons not to use native XMLHttpRequest - why is $.ajax mandatory?
Live Demo: http://jsfiddle.net/4mbjjfx8/
HTML:
<div id="wrapper">
<div id="loader"></div>
<div id="content"></div>
</div>
jQuery
$(function() {
var series = [], // Your series array
loader = $('#loader'), // UI loader sample
request = {}; // Request params
/**
* Set request method, url and data if needed
* In this case I am sending an object with a text property
* that will be returned from jsfiddle "echo" service
*/
request.method = 'GET';
request.url = '/echo/jsonp/';
request.data = {
text: 'Second message returned from "echo" service'
};
// Send ajax call
retrieveData(request, series, handleData);
// Set loading message to UI
loader.html('Loading...');
// Just do some logging to know how process goes
console.log('Populating series for the first time');
/**
* Populate series for the first time, at this point process
* will go on and after the response from server was finally
* done, process will go to the callback (since ajax calls
* are async).
*/
populate(series);
// Just do some logging to know how process goes
console.log('End populating series for the first time');
});
function populate(series) {
var dummy = {
text: 'First message populated over process'
};
// Set dummy object to series array
series.push(dummy);
};
/**
* Used to make ajax call and return data from server
*/
function retrieveData(cfg, series, callback) {
$.ajax({
type: cfg.method,
url: cfg.url,
data: cfg.data
}).done(function(data, status, xhr) {
// Pass args to callback function if defined
if (callback) callback(series, data);
}).fail(function(xhr, status) {
/**
* Pass args to callback function if defined
* At this point, request wasn't success so
* force data arg at callback to be 'null'
*/
if (callback) callback(series, null);
});
};
/**
* Used to handle data returned from server
* Note: Your series array can be modified here since you
* passed it into the callback
*/
function handleData(series, data) {
var loader = $('#loader');
// Just do some logging to know how process goes
console.log('Populating series from server');
// Check if data is defined and not an empty object
if(data && !($.isEmptyObject(data))) {
// Add it to series array
series.push(data);
}
// Set UI loader empty
loader.html('');
// Retrieve series
showData(series);
};
function showData(series) {
var contentDiv = $('#content');
// Loop process and append to UI
for(var i = 0; i < series.length; ++i) {
contentDiv.append(series[i].text + '<br>');
}
};
You should put retrieve function outside. You can invoke retrieve function. And, It will call ajax. When ajax is success, it will update data of population. Like this.
var myPopulation = {
series: [{
data: undefined
}]
};
function retrieve() {
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
var obj = JSON.parse(httpRequest.responseText)
console.log(obj.V1, obj.V2, obj.V3, obj.V4);
var data = [],
time = (new Date()).getTime(),
i;
for (i = -60; i <= 0; i++) {
console.log(obj.V2)
data.push({
x: time + i * 60 * 1000,
y: obj.V2
});
}
myPopulation.series[0].data = data
// ???
console.log(data)
}
}
};
httpRequest.open('GET', "/myCall");
httpRequest.send();
}
retrieve();
Assuming you're simply trying to set the value of myPopulation.series[0].data when the array is first defined...
myPopulation.series[1].data = data
...should be...
myPopulation.series[0].data = data;
Also, some parts of you code are missing closing semicolons, closing brackets and/or curly brackets. Please make sure you end all statements with a semicolon and you have an equal number of opening and closing (curly) brackets.
I've tested your code with the above changes. The HTTP request I made returned a simple "Test successful" string, so I've replaced the code which handles the structure of the response text to simply var data = httpRequest.responeText;. This worked fine. Of course, this assumes the code which handles the structure of the returned httpRequest.responeText in your case is correct, as I have no way of knowing what the responseText in your case looks like. If you receive any errors regarding this part of your code, we'll need to see what the responseText looks like before we can help you.
I'm not judging whether you are doing the right thing. Im merely presenting you a working version of your code.
Errors in your code:
You mean to set result of the "function" to data but your function is not returning anything in the first place.
XMLHttpRequest is async so even if you return you will not have the data set, simply because the outer function exited after making the http request setting a callback to trigger when it is completed.
Note: The fix is by making XMLHttpRequest synchronous.
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests
Here is the corrected version of your code
var myPopulation = {
series: [{
data: (
function() {
function retrieve() {
var httpRequest = new XMLHttpRequest();
var result = []; //[1] just renamed data to result to avoid confusion
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
var obj = JSON.parse(httpRequest.responseText)
console.log(obj.V1, obj.V2, obj.V3, obj.V4);
var time = (new Date()).getTime(),
i;
for (i = -60; i <= 0; i++) {
console.log(obj.V2)
result.push({
x: time + i * 60 * 1000,
y: obj.V2
});
}
//myPopulation.series[1].data = data //[2] commented this as it is not necessary
// ???
console.log(result)
}
}
};
httpRequest.open('GET', "/myCall", false); //[3] Added 3rd argument 'false' to make the call synchronous
httpRequest.send();
return result //[4] to convey the result outside
}
return retrieve(); //[5] added return to set it to the data
}()
)
}],
The above code is not tested however. Here is a tested solution http://jsfiddle.net/98f9amo8/1/
The jsfiddle content is different for obvious reasons.
Working with async code means you have to change the way you code because the code is not executed top-down any more.
So, in your case, you would do something like:
var myPopulation = {series: []};
$.get(..., my_function_that_will_format_the_data_after_they_have_been_received);
...
my_function_that_will_format_the_data_after_they_have_been_received() {
// Do stuff here
var formattedData = ...
myPopulation.series.push(formattedData);
// ONLY NOW, myPopulation is ... populated with data.
// So, whatever you use this for, need to be called here
doMagicWith(myPopulation);
}
...
/// Here, myPopulation is empty. doMagicWith(myPopulation) will fail here.
I do not know the context of how you are doing this, seeing no jQuery tells me you wish to avoid it.
So no matter what happens the call is going to take time, and you need to wait for it for whatever you may need to do with it. Loaders can help tell a user that its processing but there are other ways to do that as well. The common factor is no matter what the data is not going to be there when you need it unless you do some sort of callback.
So here is an idea, create your on onload event more or less. There are many things to keep an eye on so jQuery's is probably the most complete, but going to keep it simple here.
window.isLoaded = false;
window.ajaxLoaded = false;
window.onload = function(){
if(window.ajaxLoaded){
onReadyFunction();
}else{
window.isLoaded = true;
}
}
//skipping most of your code, the key part is the retrieve function.
//So its the only part I am going to include in this part.
function retrieve() {
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
var obj = JSON.parse(httpRequest.responseText)
console.log(obj.V1, obj.V2, obj.V3, obj.V4);
var data = [],
time = (new Date()).getTime(),
i;
for (i = -60; i <= 0; i++) {
console.log(obj.V2)
data.push({
x: time + i * 60 * 1000,
y: obj.V2
});
}
myPopulation.series[1].data = data
// ???
console.log(data)
}
}
//here is my only addition
if(window.isLoaded){
onReadyFunction();
}else{
window.ajaxLoaded = true;
}
};
httpRequest.open('GET', "/myCall");
httpRequest.send();
}
So all I am doing is adding another part to the typical DOM load. Waiting for the data you need to be available before it initialized the rest of the JS. Doing this you can keep the least downtime for your app (although it depends on where you are trying to get this data though). All you need is to define the onReadyFunction like so.
function onReadyFunction(){
//all the rest of your JS here
}
This can be expanded and organized very easy, just a simple example to get started.
I have a JavaScript function that is being called. I need to have it call a PHP function and return a true/false.
The script with the function is in the file /db/cancel_hike.php
My current JS looks like this:
function uncancelHike( hike_id )
{
//var url = "/db/cancel_hike.php;
var success = null;
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.open("GET", url , true);
request.onreadystatechange = function()
{
if (request.readyState == 4)
{
var xmlDoc = request.responseXML;
// obtain the array of markers and loop through it
markers = xmlDoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++)
{
// obtain the attribues of each marker
success = markers[i].getAttribute("success");
if ( success == "true" )
{
document.getElementById("success").style.display = 'block';
document.getElementById("warning").style.display = 'none';
document.getElementById("error").style.display = 'error';
}
if ( success == "false" )
{
document.getElementById("success").style.display = 'none';
document.getElementById("warning").style.display = 'none';
document.getElementById("error").style.display = 'block';
}
}
}
}
request.send(null);
return false;
}
What I am having trouble with is:
How to call an actual function in the PHP script?
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
I am using YUI JS library. Do I need to make some calls to it, or is it not necessary in this case?
How to call an actual function in the PHP script?
You can't. You request URIs.
Write a PHP script that calls the function you want and place it at the URI you call.
(You can use query strings and the like as the input to an if statement that you use to conditionally call different functions)
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
You can return any kind of data you like.
I am using YUI JS library. Do I need to make some calls to it, or is it not necessary in this case?
It's a library. You never need to make calls to it. It often simplifies the code you have to write.
How to call an actual function in the PHP script?
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
Well, you don't call the actual function. What you want to do is pass variables using GET, that is, by appending them to the URL like file_name.php?var1=this&var2=that to pass var1 of "this" and var2 equaling "that." You retrieve them in the PHP file with $_GET['this'] and $_GET['that']. Whatever PHP outputs to the page via echo, print_r, etc. is then sent back in a request object as part of its responseText property.
You just set url in request.open to a URL on your site. For example, in your .js file:
request.open("GET", "answer_me.php?hike_id=" + hike_id, true);
And in your .php file:
<?php
$hike_id = $_GET['hike_id'];
if ($hike_id < 5) {
echo "true"; // echo true would return "1", BTW
} else {
echo "false"; // echo false would return nothing
}
Note that that will just return a string value to request.responseText of false, thus you could do this:
var result = request.responseText;
if (result === "true") {
...
document.getElementById("success").style.display = "block";
...
} else {
...
document.getElementById("success").style.display = "none";
...
}
You do not need it to be XML, especially as it looks like you're not really using the loop (the same three DOM elements are being assigned values each time).
And honestly, for AJAX I'd recommend using a framework like jQuery (or YUI, although I don't find its AJAX stuff as intuitive). Your entire code would look like this:
var $success = $("#success");
var $error = $("#error");
function cancelHikeCallback(data) {
var is_success = (data === "true");
$success.toggle(is_success);
$error.toggle(!is_success);
}
function cancelHike(hikeIdToSend) {
$.get("/db/cancel_hike.php", {hike_id: hikeIdToSend}, cancelHikeCallback);
}
IMO things like jQuery's $.ajax ($.get is a specialized form of $.ajax) make this stuff much easier to read and debug.
jsFiddle Example
function addphoto()
{
var ajaxRequest = initAjax();
if (ajaxRequest == false)
{
return false;
}
// Return Ajax result when the state changes later
ajaxRequest.onreadystatechange = function()
{
if(ajaxRequest.readyState == 4)
{
alert(ajaxRequest.responseText);
return ajaxRequest.responseText;
}
}
// Capture form elements
var values = {
"category" : encodeURIComponent(document.addphoto.category.options[document.addphoto.category.selectedIndex].value),
"photo_title" : encodeURIComponent(document.addphoto.photo_title.value),
"photo_descrip" : encodeURIComponent(document.addphoto.photo_descrip.value)
}
var queryString = '?', i = 0;
for (var key in values)
{
if (i != 0)
{
queryString += '&'
}
queryString += key + '=' + values[key];
i++;
}
// Execute Ajax
ajaxRequest.open("POST", "ajaxcheckform.php" + queryString, true);
ajaxRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajaxRequest.setRequestHeader("Content-length", queryString.length);
ajaxRequest.setRequestHeader("Connection", "close");
ajaxRequest.send(null);
}
function ajaxCheckform(formname)
{
var response = addphoto(); // <--This is undefined and not sure why
var responseObj = JSON.parse(response);
if (responseObj.success == 1)
{
// Successful form!
alert(responseObj.success_text);
}
else
{
// Error!
alert(responseObj.error);
}
}
I'm sure I must be making some basic error somewhere, but I'm having trouble locating it. In this script, ajaxCheckform() is a function that executes one of several similar functions. Above, I included addphoto(), which is one of several functions I'll need that look like this.
On a side note, I'd love to know I can call upon a function dynamically. The addphoto() function will be only one such function being called up at that moment and I'm trying to find a way to pass formname as the function I need. I've searched Stackoverflow and Google. I've found nothing that works.
Note, I'm aware of jQuery, but I'm not there yet. I need this function to work first.
It is not addphoto() thats undefined but response is undefined. ajaxRequest is asynchronous and the addphoto() function will return before the request completes.
try this
function addphoto() {...
// Return Ajax result when the state changes later
ajaxRequest.onreadystatechange = function()
{
if(ajaxRequest.readyState == 4)
{
alert(ajaxRequest.responseText);
var responseObj = JSON.parse(ajaxRequest.responseText);
if (responseObj.success == 1) {
// Successful form!
alert(responseObj.success_text);
}
else {
// Error!
alert(responseObj.error);
}
}
}
....
}
function ajaxCheckform(formname) {
addphoto();
}
That's because response is set to the return of addphoto(), which is nothing. What you want to do is have ajaxCheckForm get called when the AJAX call is completed:
// Return Ajax result when the state changes later
ajaxRequest.onreadystatechange = function()
{
if(ajaxRequest.readyState == 4)
{
ajaxCheckform(ajaxRequest.responseText);
}
}
Then your ajaxCheckform will work with that data:
function ajaxCheckform(responseText)
{
var responseObj = JSON.parse(responseText);
if (responseObj.success == 1)
{
// Successful form!
alert(responseObj.success_text);
}
else
{
// Error!
alert(responseObj.error);
}
}
You can't return from an event handler (which onreadystatechange is).
You have to do the work inside that event handler.
addphoto() does not return anything (or rather, returns inconsistently) ... the onreadystatechange event's handler is returning the value, but there is no caller that will receive that json string.
I'd highly suggest that you abstract these details away with something like jquery ... just follow the docs for suggested usage and this code will be much simpler
You're sending a GET style parameter list to a POST method.
You need to send that string in the body of your HTTP request.
var response = addphoto(); // <--This is undefined and not sure why
The addphoto() function never has a return statement in it, so it returns undefined. And the ajaxRequest is asynchrous and wont return immediately.