views:

112

answers:

5

Hi,

the following function does not work as I thought it should have. For some reason, the loop breaks whenever one the the validate function returns false. Why is that?

Here is my code :

function validateGroup(input) {
    if (!input.value.match(/^[0-9]{0,2}$/)) {
        $(input).addClass("invalidField");
        return false;
    }
    $(input).removeClass("invalidField");
    return true;
}

function validateClass(input) {
    if (!input.value.match(/^[a-zA-Z0-9-]{0,9}$/)) {
        $(input).addClass("invalidField");
        return false;
    }
    $(input).removeClass("invalidField");
    return true;    
}

function validateData() {
    var rows = document.getElementsByTagName("tbody")[0].getElementsByTagName("tr");

    var valid = true;

    for (var i = 0, arrayLength = rows.length; i < arrayLength; ++i) {
        valid = valid && validateClass(rows[i].getElementsByTagName("input")[0]);
        valid = valid && validateGroup(rows[i].getElementsByTagName("input")[1]);
        valid = valid && validateGroup(rows[i].getElementsByTagName("input")[2]);     
    }
    return valid;
}

Thanks a lot!

A: 

It sounds like that is the intent of the function. The three lines of

valid = valid && validate...

mean that if any of the validate functions ever hits false valid will remain false for the rest of the loop.

Pablo
Of course, I want valid to remain false, but the rest of the validate functions never get called even though I still want them to!
Gab Royer
+12  A: 

the statement valid && validateClass(...) will not call the validateClass method if valid is false. I think what you want to do is change the order of those to

valid = validateClass(rows[i].getElementsByTagName("input")[0]) && valid;
valid = validateGroup(rows[i].getElementsByTagName("input")[1]) && valid;
valid = validateGroup(rows[i].getElementsByTagName("input")[2]) && valid;

Javascript doesn't bother evaluating the rest of an && expression if it already knows that the result is false.

Shaun
Gab Royer
Aaarg, using side effects in shortcircuited operations. Everyone knows you shouldn't do that and still it happens :) Great observation!
extraneon
Nice... I didn't even think of that! +1
md5sum
using side effects in short-circuited operations is often desirable, especially in the case of checking if something is null and if it isn't, doing something to it. It's just that it backfired in this particular case...
rmeador
+2  A: 

It looks like you want to run the validate functions on each iteration even if ‘valid’ was already set to false. However the && operation you are using will short-circuit, so although the loop will continue the validate functions will not be called on subsequent iterations.

A really simple alternative which would work the way you want would be:

for (var i = 0, arrayLength = rows.length; i < arrayLength; ++i) {
   if(!validateClass(rows[i].getElementsByTagName("input")[0]))  valid = false;
   if(!validateGroup(rows[i].getElementsByTagName("input")[1]))  valid = false;
   if(!vvalidateGroup(rows[i].getElementsByTagName("input")[2])) valid = false;
}
Ciarán Walsh
A: 

I think it's because of the lazy evaluation scheme Javascript uses with &&. Try a single & instead.

Short-circuit evaluation: Support in common programming languages

RamboNo5
A: 

It's called short-circuiting. Quick fix: replace each line with

valid = validateClass(rows[i].getElementsByTagName("input")[0]) && valid;
erikkallen