# mixed AJAX/Javascript form validation check

I've got a form, for which the "Send" button should only be available, upon each form field being validated. For most of my check, I call a function checkFormValue() which is a function gathering all the simple checks, give warning where check failed, and if at least one of the check fail, disable the button. The call are made on the blur event for each field of the form.

function checkFormValue(){
var form = document.myform;

//initializing a few variable with check, amongst them the following
//Those are example of check which are pure javascript function
var checkIDField = checkField(form.myids) && checkIDs();
//...

//This is an example of AJAX function
if(checkIDField){
checkIDValidity();
}

//Checks variables are gathered under one variable
var validform = checkIDField && CheckContactField && CheckPathsField;

var warnings = document.getElementsByClassName('warning');
var i;
var count = 0;

//Loop to check the number of warnings
for (i = 0; i < warnings.length; i++){
// Check that current character is number.
if(warnings[i].style.display===""){
count++
}
}
validform = validform && (count === 0);
document.form.send.disabled = !(validform);
}


A few check needs to be done on the server (SELECT query, check if some file exists,etc.). For those check,, I do AJAX calls, and I added in the checkFormValue() a loop which count the number of warning displayed. If none are displayed, then the button is not disable anymore.

One of my field should contain a series of ID, in the form of a space separated list. After checking that the list is correctly formatted (list of integer separated by space, no duplicate), I want to see if those ID exist in the database. The following function set the AJAX call:

function checkIDValidity(){
var xmlhttp;
if (window.XMLHttpRequest){
//code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{
// code for IE6, IE5
xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');
}
var existingIDs = xmlhttp.responseText;
var idcomponent = document.myform.myids;
var idwarningdiv = document.getElementById('nonexistingid');
if(existingIDs==="Existing"){
idcomponent.setAttribute('class', 'valid');
if(idwarningdiv.style.display !== 'none'){
idwarningdiv.style.display='none';
idwarningdiv.innerHTML='';
}
}else{
idcomponent.setAttribute('class', 'invalid');
if(idwarningdiv.style.display !== ''){
idwarningdiv.style.display='';
}
if(idwarningdiv.innerHTML.substr(51,existingIDs.length)!==existingIDs){
idwarningdiv.innerHTML='<br /><img src="img/warning2.png" alt="Warning!" />'+existingIDs+' is not an existing id.';
}
}
}
};
var idnumbers = document.myform.myids.value;
var d=new Date();
//d.toUTCString() is used so the result never get cached
xmlhttp.open('GET', 'checkidvalidity.php?id='+idnumbers+'&rand='+d.toUTCString(), true);
xmlhttp.send();
}


When I enter an ID, which doesn't exist in the database, I got a warning, and if the ID is valid, the warning disappear. But the enabled/disabled status of the "Send button" is not immediately updated, on the contrary, I need to click twice on other field in the form before I can see any change on the button.

Adding a listener on the warning div for non existent IDs, triggering on propertyChanged event and calling checkFormValue did at first the trick, but the event is only supported on IE, and as such it didn't work on other browser. Using the mutation event "DOMAttrModified" when it was supported, helped for Firefox and Opera.

function formLink(objectid){
var xmlhttp;
if (window.XMLHttpRequest){
//code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{
// code for IE6, IE5
xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');
}
document.getElementById('terminal').innerHTML=xmlhttp.responseText;
if(isDOMAttrModifiedSupported()){
checkFormValue,
false);
}
checkFormValue();
}
};
xmlhttp.open('GET', 'myform.php?id='+objectid, true);
xmlhttp.send();
}


Details on the isDomAttrModifiedSupported function can be found on this post about detecting if the DomAttrModified event listener is supported.

But using that approach leaves my with no solution for the WebKit browsers (Chrome, Safari). Is there a way to refactor my code so I can do my AJAX call, and it would result on an update of the disabled status of the "Send" button, without discounting the result of my other simple checks? In other word, is my validation approach correct?

PS: I get some restraints on this project, and I am not allowed to use jQuery.

I would approach it slightly differntly.

Have functions to change when the field has been validated or not:

function checkFormValues(){

var invalidFields = 0;

function updateValidFields(isValidField)
{

invalidFields += isValidField ? -1 : 1;
if(!invalidFields)
{
// Enable Submit Button
// ???
// Profit
}
else
{
// Disable submit Button
// Fail!
}
}

// etc
}


then your validation functions look something like:

function validateMe()
{
//Always assume invalid to startwith
updateValidFields(false);

// do awesome field checking.

if(thisFieldIsValid)
{
updateValidFields(true);
}
}


then your checkValidID function would look like:

function checkIDValidity(){
updateValidFields(false);


xmlhttp.onreadystatechange=function(){
var existingIDs = xmlhttp.responseText;
var idcomponent = document.myform.myids;
var idwarningdiv = document.getElementById('nonexistingid');
if(existingIDs==="Existing"){
// Do valid stuff
updateValidFields(true);
}else{
//do invalid stuff.
}
}
};

• Didn't you mean for invalidField to be a global variable, as well as for updateValidField() to be a publich function? – Eldros Sep 13 '11 at 6:55
• @Eldros Nope. This way it creates the variable and function in the same scope and a new one each time. You coould make it Global if you wanted but i think its better this way as each new time it starts fresh. [yoda] Think it is a matter of preference I do.[/yoda] – James Khoury Sep 13 '11 at 23:36
• Then I don't understand why the variable is in checkIDValidity, I mean it is only one check for one field (where there could be already many check on a field). It might be that I still think as a PHP developer, but wouldn't it be better to put it in the validateMe()(Which I take is your form validation function)? – Eldros Sep 14 '11 at 6:15
• @eldros Sorry That first one was supposed to be CheckFormValue. oops! Fixed now. Then validateme would either check its validity for required and if that pass it would then check its ID (if needed). – James Khoury Sep 14 '11 at 6:34
• Now, with a few adaptation from my side, it works perfectly. I may edit my post with the refactored code at a later time. – Eldros Oct 10 '11 at 11:06