Solved

Ajax Problem

Posted on 2016-09-12
9
38 Views
Last Modified: 2016-09-13
Javascript Code
	function chk_vals() {
		if (document.st.firm.value == "" || document.st.faddr.value == "" || document.st.fcity.value == "" || document.st.fzip.value == "" || document.st.fphone.value == "" || document.st.tname.value == "" || document.st.ctno.value == "" || document.st.tgmm.value == "" || document.st.tgsn.value == "" || document.st.tgcdate.value == "" || document.st.pwd.value == "" || document.st.email.value == "" || document.st.pname.value == "") {
			alert("All form values required.");
			return false;
		}
		//check for dupe of email & pwd with Ajax 
		chk_dupe();
		alert("resp = " + document.getElementById("resp").value);
		if (document.getElementById("resp").value == "N") {
			alert("This password cannot be used, please choose another.");
			return false;
		}	
		dok = true;
		for (i = 0; i < nu; i++) {
			if (document.st.tname.value.trim() == tstr[i].trim()) {
				dok = false;
				break;
			}
			if (document.st.ctno.value.trim() == lic[i].trim()) {
				dok = false;
				break;
			}
		}
		if (! dok) {
			alert("Tester name & License number must be unique.");
			return false;
		}	
		if (tp == "u") {
			if (document.st.pwdr.value == "") {
				return true;
			}
		}		
		if (document.st.pwd.value != document.st.pwdr.value) {
			alert("Passwords do not match.");
			return false;
		}

		return true;
	}
	function chk_dupe() {
		var xhttp = new XMLHttpRequest();
		xhttp.onreadystatechange = function() {
		if (this.readyState == 4 && this.status == 200) {
			document.getElementById("resp").innerHTML = this.responseText;
		}
		};
		xhttp.open("GET", "chk_dupe_id.php?em=" + document.getElementById("email").value + "&pwd=" + document.getElementById("pwd").value, true);
		xhttp.send();
	}

Open in new window


Related html:
<form method="POST" name="st" action="proc_register.php?tp=<?print $tp; ?>" onSubmit="return chk_vals();">
<input type="hidden" id="resp"><div class="row">
		<div class="col-xs-4 text-right" style="padding-top:10px;">email Address:</div>
		<div class="col-xs-4 col-xs-offset-2" style="padding-top:10px;">&nbsp;<input type="text" id="email" name="email" <? if ($tp == "u") { ?>value="<? print $_SESSION['email']; ?>"<? } ?>></div>
	</div>
	<div class="row">
		<div class="col-xs-8 col-xs-offset-2">Password must be 8 or more, contain at least one number.</div>
	</div>	
	<div class="row">
		<div class="col-xs-4 text-right " style="padding-top:10px;">Password:</div>
		<div class="col-xs-4 col-xs-offset-2" style="padding-top:10px;">&nbsp;<input type="password" id="pwd" name="pwd" <? if ($tp == "u") { ?>value="<? print $_SESSION['pwd']; ?>"<? } ?>></div>
	</div>

Open in new window


php:
<?php
// chk_dupe_id.php
include "db_connect.php";
$qry = "SELECT * from users where email = '" . $_GET['em'] . "' and password = '" . $_GET['pwd'] . "'";
$res = mysqli_query($link, $qry);
$nr = mysqli_num_rows($res);
if ($nr == 0) {
	echo "Y";
} else {
	echo "N";
}
exit;	
?>

Open in new window


Alert after chk_dupe() shows resp as blank.

Do I have to put a Javascript timer in here to wait for result from php?

I ran the php manually entering the url & query string; it returned echoed "N" when it was supposed to.

What's wrong?
0
Comment
Question by:Richard Korts
  • 4
  • 4
9 Comments
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
AJAX is asynchronous - but you are using it synchronously.

You need to call chkdup - and then everything that comes after that is dependent on the return from the server has to happen in the success callback for the server.

Otherwise what happens is this
chkdup() is called
It starts the AJAX request
Control is returned to the line after chkdup() and processing continues while the AJAX call is processing.
When AJAX is complete it calls the complete function - which may happen well after processing in the calling function has finished.

Therefore all processing that must use the return from AJAX must run instead in the success callback.

See comments in your code below
<!doctype html>
<html>
<body>
<form method="POST" name="st" action="proc_register.php?tp=<?php print $tp; ?>" onSubmit="return chk_vals();">
  <input type="hidden" id="resp"><div class="row">
		<div class="col-xs-4 text-right" style="padding-top:10px;">email Address:</div>
		<div class="col-xs-4 col-xs-offset-2" style="padding-top:10px;">&nbsp;<input type="text" id="email" name="email" <?php if ($tp == "u") { ?>value="<?php  print $_SESSION['email']; ?>"<?php  } ?>></div>
	</div>
	<div class="row">
		<div class="col-xs-8 col-xs-offset-2">Password must be 8 or more, contain at least one number.</div>
	</div>	
	<div class="row">
		<div class="col-xs-4 text-right " style="padding-top:10px;">Password:</div>
		<div class="col-xs-4 col-xs-offset-2" style="padding-top:10px;">&nbsp;<input type="password" id="pwd" name="pwd" <?php  if ($tp == "u") { ?>value="<?php  print $_SESSION['pwd']; ?>"<?php  } ?>></div>
	</div>
</form>
<script>
	function chk_vals() {
		if (document.st.firm.value == "" || document.st.faddr.value == "" || document.st.fcity.value == "" || document.st.fzip.value == "" || document.st.fphone.value == "" || document.st.tname.value == "" || document.st.ctno.value == "" || document.st.tgmm.value == "" || document.st.tgsn.value == "" || document.st.tgcdate.value == "" || document.st.pwd.value == "" || document.st.email.value == "" || document.st.pname.value == "") {
			alert("All form values required.");
			return false;
		}
		//check for dupe of email & pwd with Ajax 
		chk_dupe();
		// RESP IS NOT AVAILE HERE AJAX CALL IS STILL EXECUTING
		// EVERYTHING FROM HERE ON THAT IS DEPENDENT ON THE RESPONSE 
		// MUST BE IN THE onreadystatechanged FUNCTION BELOW
		
		alert("resp = " + document.getElementById("resp").value);
		if (document.getElementById("resp").value == "N") {
			alert("This password cannot be used, please choose another.");
			return false;
		}	
		dok = true;
		for (i = 0; i < nu; i++) {
			if (document.st.tname.value.trim() == tstr[i].trim()) {
				dok = false;
				break;
			}
			if (document.st.ctno.value.trim() == lic[i].trim()) {
				dok = false;
				break;
			}
		}
		if (! dok) {
			alert("Tester name & License number must be unique.");
			return false;
		}	
		if (tp == "u") {
			if (document.st.pwdr.value == "") {
				return true;
			}
		}		
		if (document.st.pwd.value != document.st.pwdr.value) {
			alert("Passwords do not match.");
			return false;
		}

		return true;
	}
	function chk_dupe() {
		var xhttp = new XMLHttpRequest();
		xhttp.onreadystatechange = function() {
		if (this.readyState == 4 && this.status == 200) {
			document.getElementById("resp").innerHTML = this.responseText;
			// PUT ALL PROCESSING DEPENDENT ON AJAX RETURN HERE
		}
		};
		xhttp.open("GET", "chk_dupe_id.php?em=" + document.getElementById("email").value + "&pwd=" + document.getElementById("pwd").value, true);
		xhttp.send();
	}
</script>
</body>
</html>

Open in new window

0
 

Author Comment

by:Richard Korts
Comment Utility
Julian,

Thanks for that response.

I tried this - Javascript:
	function chk_vals() {
		if (document.st.firm.value == "" || document.st.faddr.value == "" || document.st.fcity.value == "" || document.st.fzip.value == "" || document.st.fphone.value == "" || document.st.tname.value == "" || document.st.ctno.value == "" || document.st.tgmm.value == "" || document.st.tgsn.value == "" || document.st.tgcdate.value == "" || document.st.pwd.value == "" || document.st.email.value == "" || document.st.pname.value == "") {
			alert("All form values required.");
			return false;
		}
		//check for dupe of email & pwd with Ajax 
		kk = chk_dupe();
		if (! kk) {
			return false;
		}	
		dok = true;
		for (i = 0; i < nu; i++) {
			if (document.st.tname.value.trim() == tstr[i].trim()) {
				dok = false;
				break;
			}
			if (document.st.ctno.value.trim() == lic[i].trim()) {
				dok = false;
				break;
			}
		}
		if (! dok) {
			alert("Tester name & License number must be unique.");
			return false;
		}	
		if (tp == "u") {
			if (document.st.pwdr.value == "") {
				return true;
			}
		}		
		if (document.st.pwd.value != document.st.pwdr.value) {
			alert("Passwords do not match.");
			return false;
		}

		return true;
	}
	function chk_dupe() {
		var xhttp = new XMLHttpRequest();
		xhttp.onreadystatechange = function() {
		if (this.readyState == 4 && this.status == 200) {
			document.getElementById("resp").innerHTML = this.responseText;
			if (document.getElementById("resp").value == "N") {
				alert("This password cannot be used, please choose another.");
				return false;
			}	
			return true	
		}
		};
		xhttp.open("GET", "chk_dupe_id.php?em=" + document.getElementById("email").value + "&pwd=" + document.getElementById("pwd").value, true);
		xhttp.send();
	}

Open in new window


Clicking submit does nothing, just stuck on the page. I turned on Firebug, expecting a Javascript error. None reported.

Any ideas?

Thanks
0
 
LVL 42

Expert Comment

by:zephyr_hex
Comment Utility
Julian's explanation is correct. Another way to achieve your result is to use JavaScript Promises.
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
You are still falling into the AJAX async trap.

The onreadystate function returning a value is meaningless.

Think of it like this.

You initiate an AJAX request to go and do something (Line 7)
chk_dupe() sets up the AJAX call and returns when it has made the call NOT when the AJAX call completes.
Line 8 you are checking for a return value from chk_dupe() - this will be the return of the actual chk_dupe() function (i.e. what happens after line 52) NOT the onreadystatechange (Line 45 /47) which only happens once the AJAX call is complete.

Imagine the AJAX call takes a minute to complete.
chk_dupe() returns immediately after the AJAX call is started.
Your code will then continue on executing lines 8, 9, 10 etc - the AJAX call is still running it has not come back yet. Your chk_vals() function runs to completion - AJAX still has not completed.
59 seconds later the AJAX call completes and onreadystatechange fires (Line 41).
You do you checks and return true and false - but this return goes to the void because firstly, the process that invoked the onreadystatechange function was the browser - not your code and secondly it is happening long after your chk_vals() function has completed.

This is going to get complicated because you are wanting to do a validation of the username by AJAX but you also want to validate the form on submit.

Ideally you want to wait for your AJAX call to complete before you allow the form to be submitted. One way is to force the AJAX call to be synchronous - not a good practice.
The option is do the AJAX verification on blur and disable the  form until it completes (effectively the same result as a synchronous AJAX call). When the AJAX call completes you unblock the form and proceed. When your form is submitted you do the rest of the validation there.

I am a bit confused though as to what you are trying to achieve. You are still going to have to validate the username when the form is submitted and if there is a clash you are going to have to come back to the form with an error.

The use of AJAX on a form in this manner is usually when the form is going to be submitted via AJAX - and in such cases the method described above is used to verify the username.

In your previous question the code I posted demonstrated the concept. I am not sure how to advise you going forward though as I am not 100% sure what effect you are trying to achieve.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:Richard Korts
Comment Utility
Julian,

I think you are saying I have to take the chk_dupe() function out & just put that code "in line" so it can "wait" for the response from php?

Is that correct?
0
 
LVL 51

Accepted Solution

by:
Julian Hansen earned 500 total points
Comment Utility
No it is more than that. When you do the request to the server to validate the username - you should wait for it to resolve - or at least prevent form submit until it is done - otherwise your submit could happen with an invalid email which sort of defeats the purpose of the pre-check.

What you can do is link to the blur event on the username input.

The article below has good explanation of what you want to do and how to do it.
https://www.formget.com/form-validation-using-ajax/
0
 

Author Comment

by:Richard Korts
Comment Utility
Julian,

What a nightmare. That onBlur stuff won't work, I have to validate a COMBINATION of things, not just simple field by field.

I know I have done this before & it was EASY, I just cannot fathom why it has to be so complex.

Probably the jQuery was better, but I don;t want to do something I don;t understand & then be unable to fix it when it breaks.

I give up, I will do all the checking in php, redisplay the HTML form if errors with message(s). I have to save ALL the form values as $_SESSION or or $_POST so if I go back they are still there, that is EXACTLY what I was trying to avoid.

But it's simple compared to this nightmare.

Thanks for your efforts, I'll give you the points, but I have to (to be honest) say problem NOT solved.

Richard
0
 

Author Closing Comment

by:Richard Korts
Comment Utility
Pints awarded for effort, problem not solved.
0
 
LVL 51

Expert Comment

by:Julian Hansen
Comment Utility
The onblur is only to validate the username - not the rest of the fields which are validated on form submit. The username still has to be validated on the server - the AJAX solution should only be a convenience to prevent an unnecessary round trip to the user.

In most situations like this one the email is checked on blur not Submit.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Suggested Solutions

Introduction Got endorsements from your clients?  Great!  There is almost nothing better than word-of-mouth advertising.  But how can you do that on the internet?  Sure you can make a page for endorsement quotations and list them all, but who is …
The Confluence of Individual Knowledge and the Collective Intelligence At this writing (summer 2013) the term API (http://dictionary.reference.com/browse/API?s=t) has made its way into the popular lexicon of the English language.  A few years ago, …
This video discusses moving either the default database or any database to a new volume.
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now