javascript - ejemplo - Evite que js alert() pause temporizadores
sleep javascript (8)
Así que hice algunos temporizadores para una prueba. El caso es que me acabo de dar cuenta cuando puse
javascript: alert("blah");
en la dirección, el cuadro de alerta emergente pausa mi temporizador. Lo cual es muy no deseado en un cuestionario.
No creo que haya ninguna forma de detener este comportamiento ... pero lo preguntaré de todos modos.
Si no lo hay, sugiérame qué debo hacer?
Aparentemente, la representación de vista previa difiere de la representación publicada. Este párrafo está aquí para asegurarse de que las dos líneas siguientes aparezcan como código.
// Preserve native alert() if you need it for something special
window.nativeAlert = window.alert;
window.alert = function(msg) {
// Do something with msg here. I always write mine to console.log,
// but then I have rarely found a use for a real modal dialog,
// and most can be handled by the browser (like window.onbeforeunload).
};
Creo que la pregunta que asker está tratando de evitar hacer trampa. Dado que un usuario puede escribir javascript: alert ("paused"); en la barra de direcciones, o crea un bookmarklet para hacer eso, es fácil detener la prueba y hacer trampa.
Lo único que se me ocurre es usar Date () para obtener la hora actual y volver a verificarla cuando el temporizador se dispare. Luego, si la diferencia de tiempo no es razonablemente cercana a la duración prevista del temporizador, muestre una amonestación y descalifique la respuesta a esa pregunta o deje que suspenda el cuestionario. No hay forma de evitar que el usuario detenga su prueba, pero debería ser posible atraparlos.
Por supuesto, con cualquier prueba de trucos, motivar a las personas a convertirse en mejores tramposos. Una persona puede cambiar la hora del sistema en su PC y engañar al constructor de fecha () de javascript que obtiene el tiempo del sistema operativo.
Puede usar un intervalo para hacer una comparación de reloj repetida contra una longitud de intervalo de un segundo. El manejador de intervalos también puede actualizar un campo de tiempo restante en la pantalla del usuario. Luego, los usuarios pueden sentir que la presión aumenta a medida que se agota el tiempo en su cuestionario. ¡Tiempos divertidos!
En última instancia, no puede confiar en la entrada del usuario. Sin hacer un seguimiento del tiempo transcurrido en el servidor, simplemente no hay garantía de que los datos no hayan sido manipulados.
Sin embargo, si está seguro de que sus examinadores no conocen JavaScript, y simplemente se basan en un "truco" que encontraron en alguna parte, podría probar para hacer trampa (pausar) con el siguiente código, que no requiere modificación. window.alert:
var timer = {
startDatetime: null,
startSec: 0,
variance: 1,
exitOnPause: true,
count: function (config) {
var that = this;
if (typeof config == "object" && typeof parseInt(config.seconds) == "number" && !isNaN(parseInt(config.seconds)))
{
if (typeof parseFloat(config.variance) == "number" && !isNaN(parseFloat(config.variance))) this.variance = config.variance;
if (typeof config.exitOnPause == "boolean") this.exitOnPause = config.exitOnPause;
if (config.seconds > 0)
{
if (!this.startSec) this.startSec = config.seconds;
if (!this.startDatetime) this.startDatetime = new Date();
var currentDatetime = new Date();
if (currentDatetime.getTime() - this.startDatetime.getTime() > (this.startSec - config.seconds) * this.variance * 1000)
{
if (typeof config.onPause == "function") config.onPause();
if (!this.exitOnPause)
{
this.startDatetime = new Date();
this.startSec = config.seconds--;
window.setTimeout(function () { that.count(config); }, 1000);
}
}
else
{
config.seconds--;
window.setTimeout(function () { that.count(config); }, 1000);
}
}
else
{
if (typeof config.onFinish == "function") config.onFinish();
}
}
}
};
Este objeto de temporizador tiene un único método, count (), que acepta un objeto como entrada. Espera una propiedad de segundos en el objeto de entrada como mínimo.
Por alguna razón, window.setTimeout no siempre funciona como se esperaba. A veces, en mi máquina, window.setTimeout (x, 1000), que debería ejecutar el código después de 1 segundo, tomó más de 2 segundos. Entonces, en un caso como este, debe permitir una variación, para que las personas que no están haciendo trampa no sean señaladas como tramposas. La varianza predeterminada es 1, pero puede anularse en el objeto de entrada. Aquí hay un ejemplo de cómo usar este código, que permite 2,5 segundos de "margen de maniobra" para los golpes lentos:
timer.count({
seconds: 10,
onPause: function () { alert("You cheated!"); window.location.replace("cheatersAreBad.html"); },
onFinish: function () { alert("Time''s up!"); },
variance: 2.5
});
Con una solución como esta, podría usar Ajax para indicarle a un script del lado del servidor que el usuario ha detenido el temporizador o redirigido al usuario a una página explicando que se los capturó haciendo trampa, por ejemplo. Si, por alguna razón, quisiera permitir que el usuario continúe tomando el cuestionario después de haber sido descubierto haciendo trampa, podría establecer exitOnPause en false:
timer.count({
seconds: 10,
exitOnPause: false,
onPause: function () { recordCheaterViaAjax(); },
onFinish: function () { alert("Time''s up!"); },
variance: 2.5
});
Es modal y detiene la ejecución. Considere una alternativa que no pause la ejecución como una técnica de Lightbox.
No, no hay forma de evitar que la alerta detenga el único hilo en JavaScript. Probablemente pueda utilizar alguna otra forma de notificación al usuario, por ejemplo, una capa flotante.
Nunca, nunca confíe en javascript (o en cualquier otro momento del lado del cliente) para calcular los tiempos transcurridos para las operaciones realizadas entre las devoluciones de mensajes o diferentes páginas.
Si siempre compara las fechas del servidor, será difícil para las personas hacer trampa:
- solicitud de la primera página, almacenar la hora del servidor
- ping con llamadas javascript cada N segundos, compare los 2 tiempos del servidor y devuelva el tiempo transcurrido (solo para mostrar)
- cuando el usuario envía el formulario, compare los 2 tiempos del servidor, calcule el tiempo transcurrido y descarte los que tardaron demasiado (es decir, posibles tramposos)
La sesión del servidor se puede configurar para que expire a, por ejemplo, 1 hora. El javascript podría usarse como una herramienta de visualización para que el usuario sepa cuánto tiempo le queda. Si decide hacer trampa haciendo una pausa en el cronómetro, puede que le sorprenda al publicar su prueba que su sesión ha expirado.
El ciclo de retroalimentación sobre la pregunta de SyaZ ha aclarado los problemas en juego.
Aquí hay un intento de resumir las buenas respuestas hasta ahora:
Los scripts de los clientes son fáciles de manipular por naturaleza para engañar a un cuestionario en línea. VER el enfoque de @Filini en el lado del servidor
window.alert = function (msg) {} anulará alert () y tal vez derrotará al fruto de poner en la barra de direcciones: javascript: alert (''Pausa de la página para que pueda googlear la respuesta'') o usaré mi teléfono -A-amigo ahora. Cortesía de @eyelidlessness
Si debe usar un enfoque del lado del cliente, en lugar de usar setTimeOut (), podría usar una función de pausa personalizada basada en la comparación de fechas como esta ( concepto por @Mnebuerquo , ejemplo de código por mí ( @micahwittman )):
Ejemplo:
var beginDate = new Date();
function myTimeout(milsecs){
do { curDate = new Date(); }
while((curDate-beginDate) < milsecs);
}
function putDownYourPencils(milsecs){
myTimeout(milsecs);
var seconds = milsecs / 1000;
alert(''Your '' + seconds + '' seconds are up. Quiz is over.'');
}
putDownYourPencils(3000);