Since you have no submit button (type="submit"), the form doesn't submit at all, unless you press enter with the text field selected. But then there is no validation taking place at all, since you don't do validation onsubmit.
I also noticed you do an asynchronous call, but expect the response to be there immediately. When you call doWork(), a request to the server is made, but the code continues to execute BEFORE that request is responded to, meaning that you check the value of the hidden field before it has been assigned one (or you possibly get an old value from a previous response).
I put up a testcase on the server using your code to verify what I thought happens. I had to change it around a bit to get it to not generate errors tho. Since we switched to POST, the data shouldn't go via the querystring. Instead it should be passed as an argument to the send() method.
There were some more syntax errors in the JS code, mostly case sensitive stuff, like validateinput instead of ValidateInput.
We also need to set a few headers to use the correct content type, but it seemed to work for me without them so I'm skipping that here.
The serverside needs a few changes too, to use $_POST instead of $_GET.
I also changed the validation to this, for testing:
Code:
<?php
if(isset($_POST['inputText']) && $_POST['inputText']=="aaa")
echo "T"; //true
else
echo "F"; //false
?>
and I made the thankyou page print out the values it gets:
HTML Code:
<html>
<head>
<title>Thankz</title>
</head>
<body>
<?php
echo $_POST['inputText'];
echo $_POST['hGo'];
?>
</body>
</html>
So stepping through the process you get this:
- User inputs text
- User hits enter, the form is submitted to the thankyou page, unconditionally, without validation. The JavaScript execution is disrupted and the browser jumps to thankyou.php.
- User clicks "Submit Now", keep going down
- validateinput() is called
- doWork is called and sets up a call to the server, but the code goes directly to the next step without waiting for the response
- You check the value of the hidden box
- The check returns true, NOTHING happens, no form submission, nothing...
- The check returns false, an alert box pops up, NOTHING ELSE happens here either.
I wonder why you use AJAX here at all. At the moment it looks to me like you wish to validate the data before the user submits the form, but you've got it a bit backwards.
What if the user doesn't have JavaScript enabled? The only way to submit the form then is to hit enter while the textbox has focus, and then the user goes straight to thankyou.php without ever passing or failing the validation. The "Submit Now" button will not work as it is only connected to the script.
Validation should always happen [again] after the form has been submitted, on the server, as the user can NEVER be trusted. As it is now, you try to do validation before the form is submitted, tell the client if it was successful or not, and then let the client make it's own decision about what to do. On top of that, there's a bug/misunderstanding which prevents the result of the validation reach the client in time for its decision, and another one preventing the form from being submitted at all, no matter what decision was made.
What I think you might have wanted was a way for the user to notice that the data they filled in was not correct, before they actually submit the form. Maybe give them a chance to fix it before having to reload the page when the form is actually submitted?
Either that, or maybe you just want to keep the state of the page, if possible, by not reloading it when the form is submitted.
In either case, you should make sure the form actually works like a normal form if JavaScript happens to be disabled. (At which point the form WILL trigger a page reload.) And to stop it from submitting, we should return false in the onsubmit handler. And we need an actual submit button to trigger the onsubmit event other then by pressing enter in a textfield.
validateinput should be called from onSubmit, like this.
HTML Code:
<form name="testForm" method="post" action="thankyou.php" onsubmit="return validateinput()">
...
<input type="submit" value="Submit Now">
</form>
There are a few things preventing you from using it successfully that way tho.
validateinput() should return true/false for all codepaths. Returning nothing equals returning false, meaning the form won't be submitted at all as it is now.
Another thing is the fact that the validation takes place serverside, using an asynchronous call, and before form submission. This is a bit unusual as most people usually use clientside validation in onsubmit, or possibly send it to the server with a synchronous call so that the form submission is delayed until the response has been received.
But doing serverside validation onsubmit kinda defeats the purpose of being "transparent" to the users, since in all cases you need to re-validate the data when the form is received on the server. When doing it synchronously you'll just be delaying the form submit (and probably irritating the user as nothing else can happen while that synchronous call is being taken care of) until it is once again submitted and re-evaluated, doubling the workload on the server for nothing in return.
The user doesn't expect the page to freeze a few seconds before the form is submitted, they expect to either be shown a notification saying that some data was incorrect (and the page not being reloaded) as in the case of clientside [pre]-validation, or to be taken to a new page where the notification about incorrect data being displayed somewhere near the form they just submitted, as in serverside validation. You should of course have both so that someone without JavaScript enabled still gets the notification when the page has reloaded, and they get a new chance to submit the form.
If you do asynchronous serverside validation onsubmit, you'll get the dilemma you have now. The clientside script is told (by you stating that the call should be in async mode) to keep going until either true or false is returned in the onsubmit handler. That there happened to be an async request somewhere on the way will only ever make any difference if false is returned to onsubmit so the form isn't submitted. That's only when there will be time to receive the response. But does it really make any difference? No, since the form submission has already been cancelled, the contents of the response are irrelevant as they were supposed to tell us whether to cancel or not.
The paradox is then, how to delay the form submission to be able to wait for the response and then decide whether to go on or stop without actually cancelling the form submission each time and then re-submit the form depending on the answer? We can't... creating a "sleep"-loop won't work, as all scripts need to stop executing before the asynchronous callback function can be called. And if we always stop the form from submitting before actually submitting it, then why do we use an asynchronous request and simulate what a synchronous request does much better? (The only addition being that we could add max time to wait for the server to respond to the validation request before just ignoring it and submitting anyway. But is that actually helpful?)
Hmm, I think I got "a bit" carried away in my rant here. What I wanted to really say was: Don't use serverside validation onsubmit. There's not much point to it. Use a JavaScript to do a quick validation instead, and then repeat that on the server in case it broke down on the client.
What could make sense would be to use the onchange handler of the textfield to do asynchronous serverside validation. This is often used to check if say a nickname is taken when registering on a site. The user fills in a nick, moves down to fill in some more info, when they suddenly notice the nickname box turning red and a text next to it sayin "That nick is taken, please chose another on." That's the power of async calls used well. If JavaScript happens to be turned off, the user will fill out the form as usual and then get the same message on the next page after submitting the form. They might have to submit the form say 10+ times to find an available nick, but it'll work as expected. If they happen to have JavaScript enabled, they'll just change the nickname field 10 times instead before finally submitting the form once.
Here's some example code to show how I'd do it, based on my rant above.
Disclaimer: I'm not sure this is exactly what you want, you're very welcome to correct me.
submitTest.htm:
HTML Code:
<body>
<script language="javascript" type="text/javascript">
function getHTTPObject()
{
if (window.ActiveXObject)
return new ActiveXObject("Microsoft.XMLHTTP");
else if (window.XMLHttpRequest)
return new XMLHttpRequest();
else
{
alert("Your browser does not support AJAX.");
return null;
}
}
function setOutput()
{
if(httpObject.readyState == 4 && httpObject.status == 200)
{
var outElement = document.getElementById('validateResult');
if(httpObject.responseText && httpObject.responseText=="T")
{
outElement.style.color="lime";
outElement.innerHTML="Correct!";
}
else
{
outElement.style.color="red";
outElement.innerHTML="Nope, that's wrong...";
}
}
}
var httpObject = null;
function validateinput()
{
if(document.getElementById('inputText').value!="aaa")
{
alert('Please key in the value again');
return false;
}
return true;
}
function ajaxCheck(inputBox)
{
httpObject = getHTTPObject();
var params = "inputText="+inputBox.value+"&isAjax=1";
var outElement = document.getElementById('validateResult');
if (httpObject != null)
{
outElement.style.color="silver";
outElement.innerHTML="Checking...";
httpObject.open("POST", "validate.php", true);
httpObject.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
httpObject.setRequestHeader("Content-length", params.length);
httpObject.setRequestHeader("Connection", "close");
httpObject.onreadystatechange = setOutput;
httpObject.send(params);
}
else
{
outElement.style.color="yellow";
outElement.innerHTML="Could not contact server.";
}
}
</script>
<form name="testForm" method="post" action="validate.php" onsubmit="return validateinput();">
Input text: <input type="text" name="inputText" id="inputText" onchange="ajaxCheck(this)" /> <span id="validateResult"></span>
<br /><br />
<input type="submit" value="Submit Now">
</form>
</body>
</html>
validate.php, for the sake of not overcomplicating things, I used this page both for validating the AJAX POST and the normal form POST, as well as showing the response.
Code:
<?php
$isValid = false;
if(isset($_POST['inputText']) && $_POST['inputText']=="aaa")
{
$isValid = true;
}
if(isset($_POST['isAjax']))
{
if($isValid)
{
echo "T";
}
else
{
echo "F";
}
exit; // To make sure nothing else is printed after this
}
else if($isValid)
{
?>
<html>
<head>
<title>Thankz</title>
</head>
<body>
Thank you for entering:
<?php
echo $_POST['inputText'];
?>
</body>
</html>
<?php
}
else
{
?>
<html>
<head>
<title>Whoopz</title>
<meta http-equiv="refresh" content="5;url=submitTest.htm"/>
</head>
<body>
Something went wrong, you typed:
<?php
echo $_POST['inputText'];
?>
. Try going back and submitting again if you are not redirected in a few seconds.
</body>
</html>
<?php
}
?>
This example will gracefully degrade but still work if you disable JavaScript.
Sorry for the wall of text. Please don't take it personal, it's just me typing too much.
