Cuestionario JavaScript V2

Fecha de publicación: 04/08/20

Antes de empezar

Esta es una segunda versión del cuestionario en JavaScript. Si quieres ver la estructura principal te recomiendo que visites Cuestionario JavaScript.

Propósito del proyecto

Mejorar la experiencia de usuario y una mejora en el código. Encontrarás todo el código en mi github.

Por parte de la experiencia de usuario queremos añadir una cuenta atrás, una barra de progreso y un panel emergente que se muestre cuando se ha respondido la pregunta o se ha terminado el tiempo.

Por parte del código queremos mejorar su escalabilidad modularizando la estructura. También aprovechamos para mejorar la documentación completa de todos los métodos y variables, un control de versiones del documento, así como todo aquello que pueda no quedar claro sin un comentario.

¿Que necesitamos?

  • Conocimientos de programación orientada a objetos
  • Un navegador
  • Un procesador de texto, en mi caso VSCode
  • Ciertos conocimientos de css y bootstrap

Explicación

Estructura

Para tener claro de qué estamos hablando en cada momento vamos a ver antes de nada la estructura del cuestionario. Se divide en tres grandes bloques: progreso, cuestionario y pasar pregunta/answer-block

Estructura visual del cuestionario

Cuenta atrás

Para poner una cuenta atrás usaremos JavaScript haciendo que el tiempo se actualice cada segundo, que se ponga el contador en rojo al llegar a 15 segundos y que si llega a terminar el contador nos salte como no contestada. La cuenta atrás se divide en varios métodos los cuales vamos a explicar ahora.

iniciarCuentaAtras()

Cambiamos el color del temporizador a verde. Para ello quitamos las clases CSS de error (color rojo) y gray-light (color gris) para añadirle la clase success (color verde). En la primera pregunta no tendrá ni el color rojo y el gris para quitar pero es necesario quitarlos en las siguientes para que no haya problemas con los colores.

                        
document.getElementById("temporizador").classList.remove("error");
document.getElementById("temporizador").classList.remove("gray-light");
document.getElementById("temporizador").classList.add("success");
                        
                    

Ahora necesitamos que el tiempo se vaya actualizando cada segundo. LLamaremos al método actualizarCuentaAtras para ello y le tendremos que pasarle el valor de TOTAL_TIME. La llamada será actualizarCuentaAtras(TOTAL_TIME);

actualizarCuentaAtras(timer)

Tiene varias cosas que hacer este método, actualizar el temporizador cada segundo, cambiar el color del temporizador si llega a 15 segundos y desencadenar los eventos que produce el contador al llegar a cero.

Lo primero es simple. Solo tiene que mostrar en pantalla el valor que tiene timer cada vez que se ejecuta: document.getElementById('cuentraAtras').innerHTML = timer;.

Ahora lo que hacemos es preguntarle cada vez si ha llegado el contador a cero. Este supuesto nos lo vamos a dejar para el final. En caso de no ser el final lo que va ha hacer si o si es descontar 1 a timer y volver a ejecutar el método. En el caso de que hayamos llegado a 15 segundos cambiará el color de la cuenta atrás a rojo.

                        
else {

    if (timer == 15) {//pasar a rojo la cuenta atrás

        document.getElementById("temporizador").classList.remove("success");
        document.getElementById("temporizador").classList.add("error");
    }

    timer--;

    //ejecutará mismo método una vez haya pasado un segundo
    temporizador = setTimeout(function () { actualizarCuentaAtras(timer) }, 1000);
}
                        
                    

En el caso de que el contador llegue a cero tenemos que marcar cual era la respuesta correcta, dehabilitar los botones de las posiblres respuestas, quitarle los colores al AnswerBlock, mostrarlo con el modo "timeOut" que es con todo en gris(veremos este bloque más adelante) y sumar uno a la variable sinContestar.

                        
//coge la respuesta correcta de la pregunta que estamos viendo
var idRespuestaCorrecta = respuestasCorrectasObjeto[contador - 1].idRespuesta;

//marca cual era la opción correcta
document.getElementById(idRespuestaCorrecta).classList.remove("btn-outline-secondary");
document.getElementById(idRespuestaCorrecta).classList.add("btn-success");

deshabilitarBotones("respuesta");
quitarColoresAnswerBlock();
mostrarAnswerBlock("timeOut");

sinContestar++;
                        
                    

pararCuentaAtras()

En el caso de que hayamos respondido la pregunta se ejecutará el método pararCuentaAtras(). Este evento a parte de parar la cuenta atrás eliminará el color que tuviese (rojo o verde) y pondrá el gris para indivar que se ha detenido.

                        
/**
 * Detiene la cuenta atras y cambia el color del temporizador a gris
 */
function pararCuentaAtras() {

    //Ponemos el color gris al temporizador
    document.getElementById("temporizador").classList.remove("success");
    document.getElementById("temporizador").classList.remove("error");
    document.getElementById("temporizador").classList.add("gray-light");

    //detiene el temporizador
    clearTimeout(temporizador);
}
                        
                    

Barra de progreso

Lo único que tiene que hacer la barra es rellenar cada vez que aparezca una pregunta nueva para que el usuario sepa cuanto le puede llegar a quedar hasta terminar el cuestionario. Esto lo conseguimos dividiendo 100 entre la variable preguntasObjeto.length obteniendo cuanto tiene que avanzar la barra por cada pregunta.

AnswerBlock

Aquí ya estaba casi todo hecho desde la primera versión. El primer cambio ha sido que al añadir el temporizador surge una tercera posbilidad a parte de correto y incorrecto, que es sinContestar la cual pondrá todo el bloque en escala de grises mediante el método mostrarAnswerBlock("timeOut");

Mensaje

En los mensajes lo único que cambia es que ahora muestran un icono. Dependiendo de la respuesta que tenga que mostrar el mensaje saltará un icono diferente: <i class='fas fa-check-circle'></i> cuando la respuesta sea la correcta, <i class='fas fa-times-circle'></i> cuando hayamos fallado al responder y <i class='fas fa-clock'></i> si ha expirado el tiempo para responder la pregunta.

Resto

El cambio más grande que habia que hacer entre la v 1.0 y v 2.0 era añadir una tercera respuesta del cuestionario debido a la aparición del contador el resto de cambios hecho y no explicados son la modularización, limpieza y documentación del código. Algo tan importante como la función que vaya a desempeñar el propio proyecto.

Conclusión

Muy satisfecho con el resultado de esta segunda versión a la cual no le aplicaría ninguna mejora más ya que tampoco es bueno sobrecargar un proyecto con cosas que puedan no llegar a ser necesarias. Así que de esta forma podemos dar este proyecto por terminado con la única excepción de seguir añadiendo más cuestionarios.