Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

Reiniciando o botão a qualquer hora

No meu código eu preferi que o usuário pudesse reiniciar o jogo a qualquer momento, invés de somente poder reiniciar o jogo quando ele termina. Para isso eu transformei a variável (cronometroID), responsável por finalizar o cronômetro utilizando clearInterval() em uma variável global. Gostaria de saber se existe algum problema em reutilizar essa variável, segue o código abaixo.

var cronometroID = 0;

function inicializaCronometro() {

    var tempoRestante = $("#tempo-restante").text();
    areaTexto.one("focus", function(){
        cronometroID = setInterval(function(){
            tempoRestante--;
            console.log(cronometroID);
            $("#tempo-restante").text(tempoRestante);
            console.log(tempoRestante);    
            if (tempoRestante < 1){
                areaTexto.attr("disabled", true);
                clearInterval(cronometroID);
            }
        }, 1000);
    });

}    


$("#botao-iniciar").click(reiniciarJogo);

function reiniciarJogo() {

    console.log("deu bom");

    areaTexto.val("");
    areaTexto.attr("disabled", false);
    $("#contador-caracteres").text("0");
    $("#contador-palavras").text("0");
    $("#tempo-restante").text(tempoInicial);
    clearInterval(cronometroID);
    tempoRestante = tempoInicial;
    inicializaCronometro();


}
6 respostas
solução!

Oi Daniel, fica tranquilo, seu código ficou legal e olhando daqui ele deve funcionar certinho (:

Só não consigo achar da onde vem a variavel tempo inicial.

O colega deve ter deixado a variável tempoInicial no início do código, isolada das funções. Fiz a aula poucas horas atrás e fiz isso, pelo menos.

Foi isso mesmo Roger, essa variável foi declarada em no inicio do código. Valeu pela resposta eu só estava com receio de utilizar a variável cronometroID.

Olá senhores, também gostaria de implementar a lógica de reiniciar o jogo a qualquer instante e pensei no mesmo mecanismo do Daniel. Mas esta implementação (a dele e a minha) têm um bug que não consegui entender o motivo. Poderiam analisar o código e verificar o que está acontencendo? O bug acontece quando se digita algumas palavras e antes do tempo terminar reiniciamos o jogo. Ao fazer isto algumas vezes o contador não mais respeita o limite de zero e começa a apresentar números negativos.

HTML

<!DOCTYPE html>
<html lang="pt-br">

<head>
    <meta charset="UTF-8">
    <title>Alura Typer</title>
</head>

<body>
    <h1>Alura Typer</h1>
    <p class="frase">Frase aleatória</p>

    <ul class="informacoes">
        <li><span id="tamanho-frase"></span> palavras</li>
        <li><span id="tempo-digitacao">10</span> segundos</li>
    </ul>

    <textarea class="campo-digitacao" rows="8" cols="40"></textarea>
    <button id="botao-reiniciar">Reiniciar jogo</button>

    <ul>
        <li><span id="contador-caracteres">0</span> caracteres</li>
        <li><span id="contador-palavras">0</span> palavras</li>
    </ul>

    <script src="js/jquery.js"></script>
    <script src="js/main.js" /></script>
</body>

</html>

JQUERY

var campo = $(".campo-digitacao");
var tempoInicial = $("#tempo-digitacao").text();
var cronometroID = 0;

function atualizaTamanhoFrase() {
    var frase = $(".frase").text();
    var numPalavras = frase.split(" ").length;
    var tamanhoFrase = $("#tamanho-frase");
    tamanhoFrase.text(numPalavras);
}

function incicializaContadores() {
    campo.on("input", function () {
        var conteudo = campo.val();
        var qtdPalavras = conteudo.split(/\S+/).length - 1;
        $("#contador-palavras").text(qtdPalavras);
        //conta apenas os caracteres sem considerar os espaços inseridos
        $("#contador-caracteres").text(conteudo.replace(/\s+/g, '').length);
    });
}

function inicializarCronometro() {
    var tempoRestante = $("#tempo-digitacao").text();

    console.log("inicio inicializarCronometro() var [tempo inicial]: " + tempoInicial);
    console.log("inicio inicializarCronometro() var [tempo restante]: " + tempoRestante);
    console.log("\n");

    campo.one("focus", function () {
        cronometroID = setInterval(function () {
            tempoRestante--;
            $("#tempo-digitacao").text(tempoRestante);
            if (tempoRestante < 1) {
                campo.attr("disabled", true);
                console.log("parando cronometro ID: " + cronometroID + " em inicializarCronometro");
                console.log("\n");
                clearInterval(cronometroID);
                cronometroID = 0;
            }
        }, 1000);
        console.log("novo cronometro ID em focus: " + cronometroID);
    });

    console.log("fim inicializarCronometro() var [tempo inicial]: " + tempoInicial);
    console.log("fim inicializarCronometro() var [tempo restante]: " + tempoRestante);
    console.log("\n");
}

function reiniciarJogo() {
    $("#botao-reiniciar").click(function () {
        console.log("parando cronometro ID: " + cronometroID + " em reiniciarJogo");
        console.log("\n");
        campo.attr("disabled", false);
        campo.val("");
        $("#contador-palavras").text("0");
        $("#contador-caracteres").text("0");
        $("#tempo-digitacao").text(tempoInicial);
        clearInterval(cronometroID);
        inicializarCronometro();
    });
}

$(document).ready(function () {
    atualizaTamanhoFrase();
    incicializaContadores();
    inicializarCronometro();
    $("#botao-reiniciar").on("click", reiniciarJogo);
})

Pessoal, como fiquei "encucado" com esse código que a princípio não era pra ter nenhum bug, pesquisei na Internet e acabei descobrindo que isso é um problema relacionado ao próprio evento "focus". Podem notar no código que a partir da terceira vez que clicamos em reiniciar e damos o foco no campo de digitação o evento é disparado duas vezes criando dois contadores. Um deles é finalizado, mas como o outro continua contando, começam a aparecer os números negativos. Isso é um problema do próprio browser, na maneira como ele comunica o evento de forma assíncrona e pelo que testei aconteceu em todos os navegadores (IE 10, Chrome e Firefox). Pra resolver isso segui a orientação de um post inserido na discussão do link abaixo. No caso, antes de associar o evento "onfocus", fiz a dissociação do mesmo, ficando assim:

campo.off("focus").one("focus", function () {
        cronometroID = setInterval(function () {
            tempoRestante--;
            $("#tempo-digitacao").text(tempoRestante);
            if (tempoRestante < 1) {
                campo.attr("disabled", true);

                if (cronometroID != 0) {
                    console.log("parando cronometro ID: " + cronometroID + " em tempo esgotado");
                    console.log("\n");
                    clearInterval(cronometroID);
                    cronometroID = 0;                    
                }
            }
        }, 1000);

https://stackoverflow.com/questions/14410075/jquery-receiving-two-focusin-events-on-focus

Oi Bruno !

Abre uma dúvida nova? Vc tem um material legal pra uma dúvida nova e essa dúvida já foi resolvida (:

Abraços!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software