Pergunta

Estou tendo problemas com meu javascript. Parece estar agindo estranhamente. Isto é o que está acontecendo. Eu tenho um formulário, após os submete usuário, ele chama uma função (evento onsubmit) para verificar os dados apresentados, se algo de ruim ou se o nome de usuário / e-mail já está em banco de dados (usando ajax para esta parte) ele vai retornar falso e erros de exibição usando DOM. Aqui está o código abaixo. O que é estranho sobre isso, é que ele só funciona quando eu uso um alerta vazia ( '') mensagem, sem ela, ele simplesmente não funciona. Obrigado pela ajuda.

//////////////////////////////////////

function httpRequest() {
    var xmlhttp;

    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        // code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    } else {
        alert("Your browser does not support XMLHTTP!");
    }

    return xmlhttp;
}

function validateRegForm(reg) {

    var isValidForm = true;
    var warningIcon = "";//for later in case we want to use an icon next to warning msg

    with(reg) {


        var regFormDiv = document.getElementById("registration_form");

        //Check if dynamic div exist, if so, remove it
        if(document.getElementById('disp_errors') != null) {
            var dispErrorsDiv = document.getElementById('disp_errors');
            document.getElementById('reg_form').removeChild(dispErrorsDiv);
        }           

        //Dynamically create new 'div'
        var errorDiv = document.createElement('div');
        errorDiv.setAttribute('id','disp_errors');
        errorDiv.setAttribute('style','background-color:pink;border:1px solid red;color:red;padding:10px;');
        document.getElementById('reg_form').insertBefore(errorDiv,regFormDiv);




        var xmlhttp = httpRequest();
        var available = new Array();
        xmlhttp.onreadystatechange = function() {
            if(xmlhttp.readyState == 4)
            {   
                var response = xmlhttp.responseText;
                if(response != "") {

                    //Return values
                    var newValue = response.split("|");
                    available[0] = newValue[0]; 
                    available[1] = newValue[1]; 
                }
            }
        }

        xmlhttp.open("GET","profile_fetch_reg_info.php?do=available&un="+u_username.value+"&email="+u_email.value+"",true);
        xmlhttp.send(null);


        alert(' '); ////////////WITHOUT THIS, IT DOESN'T WORK. Why?

        if(available[1] == "taken") {
            errorDiv.innerHTML += warningIcon+'Username is already taken!<br />';
            isValidForm = false;
        } else if(u_username.value.length < 4){
            errorDiv.innerHTML += warningIcon+'Username must be more than 4 characters long!<br />';
            isValidForm = false;
        } else if(u_username.value.length > 35) {
            errorDiv.innerHTML += warningIcon+'Username must be less than 34 characters long!<br />';
            isValidForm = false;
        }


        if(available[0] == "taken") {
            errorDiv.innerHTML += warningIcon+'Email address entered is already in use!<br />';
            isValidForm = false;
        } else if(u_email.value == ""){
            errorDiv.innerHTML += warningIcon+'Email address is required!<br />';
            isValidForm = false;
        } else {
            //Determine if email entered is valid
            var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
            if (!filter.test(u_email.value)) {
                errorDiv.innerHTML += warningIcon+'Email entered is invalid!<br />';
                u_email.value = "";
                isValidForm = false;
            }
        }


        if(u_fname.value == ""){
            errorDiv.innerHTML = warningIcon+'Your first name is required!<br />';
            isValidForm = false;
        }

        if(u_lname.value == ""){
            errorDiv.innerHTML += warningIcon+'Your last name is required!<br />';
            isValidForm = false;
        }



        if(u_password.value.length < 4){
            errorDiv.innerHTML += warningIcon+'Password must be more than 4 characters long!<br />';
            isValidForm = false;
        } else if(u_password.value.length > 35) {
            errorDiv.innerHTML += warningIcon+'Password must be less than 34 characters long!<br />';
            isValidForm = false;
        } else if (u_password.value != u_password2.value) {
            errorDiv.innerHTML += warningIcon+'Password and re-typed password don\'t match!<br />';
            isValidForm = false;
        }


        if(u_squestion.value == ""){
            errorDiv.innerHTML += warningIcon+'A security question is required!<br />';
            isValidForm = false;
        }

        if(u_sanswer.value == ""){
            errorDiv.innerHTML += warningIcon+'A security answer is required!<br />';
            isValidForm = false;
        }

        if(u_address.value == ""){
            errorDiv.innerHTML += warningIcon+'Address is required!<br />';
            isValidForm = false;
        }

        if(u_city.value == ""){
            errorDiv.innerHTML += warningIcon+'City is required!<br />';
            isValidForm = false;
        }

        if(u_state.value == ""){
            errorDiv.innerHTML += warningIcon+'State is required!<br />';
            isValidForm = false;
        }

        if(u_zip.value == ""){
            errorDiv.innerHTML += warningIcon+'Zip code is required!<br />';
            isValidForm = false;
        }

        if(u_phone.value == ""){
            errorDiv.innerHTML += warningIcon+'Phone number is required!<br />';
            isValidForm = false;
        }

        if(isValidForm == false)
            window.scroll(0,0);

        return isValidForm;
    }

}
Foi útil?

Solução

O alert() ajuda porque que os atrasos de processamento do javascript permanecendo nessa função (tudo, desde o alert() até o fundo), deixando tempo suficiente para o pedido de AJAX para ser concluído. A primeira letra em AJAX significa "assíncrona" o que significa que (por padrão) a resposta virá em "algum momento no futuro", mas não imediatamente.

Uma correção (que você deve não implementar) é fazer com que o síncrono processamento (alterando o terceiro argumento de open() ser false) que vai parar o processamento do seu script (e toda a página web ), até a solicitação retorna. Isso é ruim porque vai efetivamente congelar o navegador até que os concluída solicitação.

A correção adequada é para reestruturar seu código para que qualquer tratamento que depende do resultado da solicitação AJAX vai para a função onreadystatechange, e não pode ser na função principal que inicia o pedido de AJAX.

A forma como este é geralmente tratado é modificar o DOM (antes do pedido de AJAX é enviada) para tornar o formulário somente leitura e exibir algum tipo de mensagem "processamento", em seguida, no manipulador de resposta AJAX, se está tudo ok (o servidor respondeu adequadamente e validação foi bem sucedida) submit() chamada no formulário, caso contrário, tornar o formulário wriable novamente e exibir quaisquer erros de validação.

Outras dicas

O problema é que XMLHTTPRequest é assíncrona -. Ele envia a solicitação em segundo plano e não esperar que ela termine

A declaração alert faz com que o código de esperar até que o usuário clica em OK, durante a qual o pedido acabamentos.

Você precisa usar o evento onreadystatechange, como este:

xmlhttp.onreadystatechange = function() {
    if(xmlhttp.readyState==4) {
        // Do things
    }
};

O método de atribuir a esta propriedade será chamado após a resposta é recebida. (E em outros momentos, que é por isso que você precisa verificar se readyState é 4)

Você está enviando o pedido de forma assíncrona , por causa disso:

xmlhttp.open(..., true);

Passando true como o terceiro argumento a meios open() que o código continuará a ser executado antes do resultado vem de volta.

O alert() está dando esse tempo solicitação assíncrona para concluir antes de os subseqüentes código é executado.

Eu normalmente recomendo que se deslocam todo o código que depende do resultado da chamada AJAX para o retorno de chamada, dentro de:

if(xmlhttp.readyState == 4)

bloco, mas no seu caso é necessário o resultado da chamada para saber o que retornar de sua função de validação. Nesse caso, você vai ter que usar uma chamada síncrona, passando false para open(). Em seguida, seu código subseqüente não será executado até que a resposta veio de volta.

Esses caras estão certos, mas eu também não se esqueça de devolver o bool do método de validação para que o envio do formulário é cancelado se o formulário não é válido.

Algo ao longo das linhas de:

<form onsubmit="return IsValid();">

...

</form>

Você também pode sempre retornar falso de validateRegForm e ter o xmlhttp.onreadystatechange = function () enviar o formulário se ele é válido, ou de outra forma exibir sua mensagem de erro.

Isso é porque a sua chamada AJAX é assíncrona. A seguir xmlhttp.send() código é executado imediatamente. Não esperar por sua chamada ajax ao fim (a menos que você colocar o alerta).

Mover todo o código a ser executado após a chamada ajax para o método de retorno para garantir que ele é executado depois de terminar a chamada.

[Edit]:. Para além do problema, eu acho que usando AJAX apenas para validar o formulário e, em seguida, permitindo que o usuário envie a maneira usual parece um pouco estranho para mim

Você pode dividir a validação em 2 partes? Um que pode ser feito puramente no lado do cliente e outra que envolve a validação do lado do servidor. Você pode fazer a segunda parte completamente no lado do servidor após enviar e retornar os erros de volta ao cliente.

Outra opção é evitar o tradicional submeter completamente. Desde que você está fazendo a chamada ajax de qualquer maneira, por que não fazer o save / editar / whatever no próprio chamada ajax eliminando a necessidade de um envio? Tenha em mente, porém, você ainda vai precisar para apoiar o regulares enviar se o usuário tem o javascript desabilitado.

Você tem que passar o terceiro parâmetro para xmlhttp.open () como falso, então ele vai funcionar bem

Eu estava tendo o mesmo problema quando eu estava usando o type = "submit", por exemplo:

<button type="submit" class="btn btn-default" name="btn-login" id="btn-login" onclick="submitForm()">
  <span class="glyphicon glyphicon-log-in"></span> &nbsp; Sign In

mas eu mudá-lo a type = "button" e ele funciona.

Eu tive o mesmo problema. Uma vez que eu remover o alert("") ele não funciona. Eu percebi isso e que é o negócio.

Em HTML, quando você usa <button></button> para colocar o botão, o navegador age de forma diferente; quando você clicar nele, depois de chamar o manipulador de eventos, ele recarrega a página e é por isso que você deve colocar um alert("") apenas após o seu código para impedir que a página recarregar.

Você pode simplesmente usar <input type="button" value="something"> vez de <button></button> para evitar que o navegador recarregar a página.

Eu tive o mesmo problema e simplesmente acrescentou:

    <?php
    usleep(200000)// 2 seconds

?>

após o javascript (que btw, implicou o adiamento jQuery 1.9.1 para a cabeça

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top