I'm building a user signup for a web site. It uses AJAX to send data. I have created an object to store user data and send the object to the server via function.
sendUserData(passenger, "user_registration.php");
Note :
signupUser(); is called with a button click in HTML document.
sendUserData() is the function for sending the user details.
passenger is the object which stores the user data.
sendUserData(); is in a separate Script linked to the HTML page.(Global Scope)
This is the code I used to do this
//Sign Up A User
var signupUser = function () {
// User Object
var passenger = {
userName : document.getElementById("userFirstName").value,
userEmail : document.getElementById("userEmail").value,
country : document.getElementById("country").value,
password : document.getElementById("userPassword").value,
passwordVerify : document.getElementById("userPasswordVerify").value,
passwordStatus : Boolean
};
// Verifies the password ("password" and "re-enter password")
verifyPassword(passenger.password,passenger.passwordVerify,passenger.passwordStatus);
if (passenger.passwordStatus == true) {
sendUserData(passenger, "user_registration.php");
console.log(passenger);
}
};
The problem is with invoking the function signupUser() on the button,
the function stops after verifyPassword(); .
sendUserData(passenger, "user_registration.php"); invoked in the chrome debugging tool, it gives an error "passenger is not defined at : 1:13"
Please help me to find an answer.
Thank you.
Edit:
sendUserData(); function
This is in a separate javascript file linked to the HTML page.
function sendUserData (userDetails, destinationPage, functionToExecute) {
var userDetailsJson = JSON.stringify(userDetails);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState == 4 && xhr.status == 200 ) {
console.log(userDetailsJson);
window.alert("Successfully Posted");
console.log(xhr.responseText);
if(functionToExecute) {
functionToExecute();
}
}
};
xhr.open("POST", destinationPage, false);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send("m=" +userDetailsJson);
}
So this hinges on passenger.passwordStatus == true not working out.
You initialised it as passwordStatus: Boolean which already doesn't do what you think it does.
Then you pass the parameter to the verifyPassword function, which presumably looks something like:
function verifyPassword( password, retype, status) {
// verify...
status = true;
}
This reassigns status and does not affect passenger.passwordStatus in the outer scope at all.
Therefore, when it comes time to check the status, you're still comparing Boolean == true, which is never going to work.
You probably want something more like:
if( verifyPassword( passenger.password, passenger.passwordVerify)) {
sendUserData(...);
}
Have verifyPassword do either return true; or return false; as required.
And get rid of this passenger.passwordStatus thing entirely.
Related
I am using facebook login api to get user information, code can exceed correctly and FirstName can get from facebook api, but the first alert has correct value, the second value is still "". First I think it is because remote call time cause the second alert is before the first alert, after I using a delay function before second alert, also I can not get value in the second alert.
Part of code like below.
if (response.status === 'connected') {
FirstName="";
LastName="";
FB.api('/me', function(response) {
FirstName = response.first_name;
LastName = response.last_name;
Email = response.email;
alert(FirstName);
});
alert(FirstName);
}
FB.Api is asynchronies method, which will post/get to a remote server.
The execution don’t wait for it to finish before your second “alert”
The only way you can be sure your FirstName is initialized, is using callbacks or MVVM pattern.
Here MVVM with knockout.js code:
var fbModel = function () {
var self = this;
self.FirstName = ko.observable("");
self.FirstName.subscribe(function () {
//DO what you want, first name just been changed from FB
});
self.load = function () {
FB.api('/me', function (response) {
self.FirstName(response.first_name); // WILL TRIGGER self.FirstName.subscribe
});
};
};
And don’t forget, applying this model is easy, I can give you some links if you want. (But just go and look on examples on their site)
Edit : callback version
var FirstName = ""; // Global
function callback(name) {
//your name has been loaded
FirstName = name; // Global is initialized
};
function load (callback) {
FB.api('/me', function (response) {
callback(response.first_name);
});
};
//Now just call the load :
load(callback);
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.
I have been working on a peske problem the last few days. I have created an object to handle a login script. The login script is processed by a PHP script witch echo's out a json object:
{'status' : true} // could also be false
The ajax request completes everytime and I can console.log() it. The problem is in the callback function. I have tried the following allowable parameters/functions from the docs:
complete
success
.done()
In the call back I am attempting to set an object property/variable depending on the return. It does not see this assignment until the second time the script is run. I am assuming it is because something runs before the other or a scope issue?
So to clarify:
Lets say the script runs and I get back true. I then want to set the status of the object property to that instead of false. I put a console.log() inside the callback and that works everytime however the main object wont see it unless i submit it twice.
Here is the code. Any and all help is appreciated:
var loginAuth = {
form : $('form'),
status : false,
init : function() {
loginAuth.ajaxCall();
},
ajaxCall : function(loginData) {
// Get Post variables
var loginData = {
username : $('input[name=username]').val(),
password : $('input[name=password]').val()
};
// Proccess the form
$.ajax(
{
url : "http://localhost/url-where-results-are",
dataType : "json",
type : "post",
data : loginData,
}).done(function(data) {
if(typeof data != 'object')
{
$.parseJSON(data);
} else {
loginAuth.status = data;
console.log(loginAuth.status);
}
});
}
} //// END loginAuth Object ////
You have some things wrong. You only want to $.parseJson if it is an object. Furthermore, you do not need to call that as jQuery handles the parsing for you.
if(typeof data != 'object')
{
$.parseJSON(data);
} else {
loginAuth.status = data;
console.log(loginAuth.status);
}
This would be correct:
if(typeof data == 'object') {
alert(data.status);
if(data.status == true) {
loginAuth.status = true;
} else {
loginAuth.status = false;
}
} else {
console.log(data);
}
In a chrome extension I am writing I need to validate some objects I have stored in localStorage against my server . For this I created a for loop that simply sends the data for each localstorage element and that needs to do something with the response . The code is something like this:
for (var key in localStorage) {
if (! some condition )
continue;
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === 4 && httpRequest.response == 200) {
do something with 'key' from the for loop
}
}
};
var url = BASE_PATH ;
httpRequest.open("POST", url);
httpRequest.send(some data);
}
However while debugging it seems that in the ajax response , the 'key' from the for loop isn't the key I need : I was expecting to get the same key from the for loop that matches each ajax call , what I got was the same key for all ajax calls .
Am I doing something wrong or expecting something that isn't possible ? I thought that since the ajax is inside a closure function , the values are kept in memory or something of the sort .
Extract the actual Ajax call to a separate function:
function AjaxCall( key ) {
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
if ((httpRequest.readyState === 4) && (httpRequest.response == 200)) {
do something with 'key' from the for loop
}
};
var url = BASE_PATH ;
httpRequest.open("POST", url);
httpRequest.send(some data);
}
for (var key in localStorage) {
if ( some condition ) {
AjaxCall( key );
}
}
Reason is, that you are creating a closure with the function passed to onreadystatechange. All those functions point to the same key variable, which holds just one (the last) value for all Ajax calls, after the loop is finished.
When you create a separate function (like the AjaxCall() in my example), you create a different context for each call and hence all callbacks point to different keys.
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.