views:

39

answers:

3

I have a sign-up form which prompts for the first name, last name, username, password and e-mail address. I'm using two separate $.get() methods to check if the username and e-mail address are not existing.

This is my function:

 function validateSignUp() {
        var firstName = $("#first-name").val();
        var lastName = $("#last-name").val();
        var username = $("#username").val();
        var password = $("#pass").val();
        var email = $("#email").val();
        var passwordVerifier = $("#retype-pass").val();
        var emailVerifier = $("#retype-email").val();

        errorMessage = "";
        var isUsernameValid = validateUsername(username);

        var isError = false;

        // validate first name field
        if (firstName == "" || lastName == "") {
            isError = true;
            $("#error-message").html("All fields are required");
        }

        // validate password
        if (validatePassword(password) == false) {
            isError = true;
            $("#check-password").html("Password is invalid");
        }
        else {
            $("#check-password").html("");
        }

        // validate password verifier
        if (passwordVerifier == password) {
            if (validatePassword(passwordVerifier) == false) {
                isError = true;
                $("#recheck-password").html("Minimum of 6 characters and maximum of 30 characters");
            }
            else {
                if (password != passwordVerifier) {
                    isError = true;
                    $("#recheck-password").html("Minimum of 6 characters and maximum of 30 characters ");
                }
                else {
                    $("#recheck-password").html("");
                }
            }
        }
        else {
            isError = true;
            $("#recheck-password").html("Passwords didn't match");
        }

        // validate username field
        if (isUsernameValid == false) {
            isError = true;
            $("#check-username").html("Alphanumeric characters only");
        } // if
        else if (isUsernameValid == true) {
            $.get("/account/checkavailabilitybyusername", { username: username },
                    function(data) {
                        if (data == "Not Existing") {
                            $("#check-username").html("");
                        }
                        else if (data == username) {
                            isError = true;
                            $("#check-username").html("Sorry, this username is already registered");
                        }
                    }
                    );
        } // else
        // validate e-mail address field

        if (validateEmail(email) == false) {
            isError = true;
            $("#check-email").html("Sorry, the e-mail you typed is invalid");
        } // if
        else if (validateEmail(email) == true) {
        $.get("/account/checkavailabilitybyemail", { email: email },
                    function(data) {
        if (data == "Not Existing") {
                            $("#check-email").html("");
                        }
                        else if (data == email) {
                        isError = true;
                            $("#check-email").html("Sorry, this e-mail is already registered");
                        }
                    });
                }
                if (isError == true) {
                    return false;
                }
        return true;
   }

When other fields are blank and the username and/or e-mail address is existing, the form is not submitted. And the callback functions of the get methods are called as well. But when I'm going to submit my form with no empty fields, it is automatically submitted without checking the username and/or e-mail by $.get(). Is there anything wrong with my function or I'm not yet discovering something. Thanks.

A: 

Inside your main function, you cannot directly wait for the $.get() to return. But you can move the form submission to the success callback of the AJAX call (assuming form to contain a reference to the actual form element):

$.get("/account/checkavailabilitybyusername", { username: username },
                    function(data) {
                        if (data == "Not Existing") {
                            $("#check-username").html("");
                            form.submit();
//--------------------------^
                        }
                        else if (data == username) {
                            isError = true;
                            $("#check-username").html("Sorry, this username is already registered");
                        }
                    }
                    );

Note however, that then the form submission depends on the AJAX to return. Most useful would be a timeout (with window.setTimeout()) and a server-side validation, if the JS doesn't respond or the user has JS disabled.

Boldewyn
+3  A: 

You need to use a full ajax() call and set the async property to false. This makes your request synchronous, i.e. it forces the browser to wait until doing anything else. Try this:

 $.ajax({
     url: "/account/checkavailabilitybyemail",
     data: { email: email },
     async: false,
     success: function(data) {
         if (data == "Not Existing") {
             $("#check-email").html("");
         } else if (data == email) {
             isError = true;
             $("#check-email").html("Sorry, this e-mail is already registered");
         }
     })
 });

 if (isError == true) {
      return false;
 }
Tatu Ulmanen
And freeze the whole user interface during the check. Thank you. *Don't ever, ever do synchronous calls.* That's my motto, and I'm obviously not alone with that opinion.
Boldewyn
@boldewyn I've successfully used synchronous calls to do a last-ditch effort save of dynamic data in response to an onBeforeUnload event. Other than to prevent a data-loss causing page unload however, I'd tend to agree with you.
Tobias Cohen
@Boldewyn, you're welcome. Freezing the _page_ (not the browser) for less than half a second doesn't seem problematic to me - this request should hardly take any longer than that.
Tatu Ulmanen
You freeze the UI at least in FF < 3.0. And the request might take longer in unforeseen cases, such as DNS hickups that are beyond your grasp. Even if it blocks only the current tab: The user can't do anything on your page, if the request freezes. It doesn't respond to any click and the look'n feel seems to the user like an error *on your page*. And that on the *Register for this cool site* page? I don't think, that is a good idea.
Boldewyn
I agree that you have a point, but as a last resort, you can set a low timeout for the call so that it won't freeze indefinitely. That would be good for an asynchronous calls aswell, as if the request takes longer than expected, the user will still think there's an error on the page - regardless of synchronicity.
Tatu Ulmanen
Thanks for helping me.
jean27
+1  A: 

I suggest you leverage Jquery validate with two remote rules. It's quite easy to implement and a very mature plugin. This way you can focus on other aspects of your UX and not have to re implement this validation logic should you need to validate another form in your project.

JoseMarmolejos