Предотвратить js alert () от приостановки таймеров - PullRequest
5 голосов
/ 13 октября 2008

Итак, я сделал несколько таймеров для викторины. Дело в том, что я просто понял, когда ставлю

javascript: alert("blah");

в адресе, всплывающее окно с предупреждением пауза мой таймер. Что очень нежелательно в викторине.

Я не думаю, что есть способ остановить это поведение ... но я все равно спрошу.

Если нет, подумайте, что мне делать?

Ответы [ 8 ]

10 голосов
/ 13 октября 2008

Никогда, никогда не полагайтесь на javascript (или любое другое время на стороне клиента) для расчета прошедшего времени для операций, выполняемых между постбэками или различными страницами.

Если вы всегда сравниваете даты сервера, людям будет непросто обмануть:

  1. запрос первой страницы, сохранение времени сервера
  2. пинг с вызовами javascript каждые N секунд, сравнение двух серверных времен и возврат истекшего времени (только для галочки)
  3. когда пользователь отправляет форму, сравнивает 2 серверных времени, вычисляет истекшее время и отбрасывает те, которые заняли слишком много времени (то есть: возможные читеры)
6 голосов
/ 13 октября 2008

Видимо, предварительный рендеринг отличается от опубликованного рендеринга. Этот абзац здесь, чтобы убедиться, что следующие две строки отображаются как код.

// 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).
};
5 голосов
/ 13 октября 2008

Нет, нет способа предотвратить остановку оповещения одним потоком в JavaScript. Возможно, вы можете использовать другой способ уведомления пользователя, например плавающий слой.

3 голосов
/ 13 октября 2008

Я думаю, что задающий вопрос пытается предотвратить мошенничество. Так как пользователь может ввести javascript: alert («paused»); в адресную строку или сделайте букмарклет, чтобы сделать это, можно легко приостановить тест и обмануть.

Единственное, о чем я могу думать, - это использовать Date (), чтобы получить текущее время, и проверить его снова, когда сработает таймер. Затем, если разница во времени не достаточно близка к предполагаемой продолжительности таймера, покажите предупреждение и дисквалифицируйте ответ на этот вопрос или позвольте им провалить тест. Нет способа предотвратить приостановку вашего теста пользователем, но должна быть возможность его поймать.

Конечно, с любой проверкой на обман, вы мотивируете людей становиться лучшими читерами. Человек может изменить системное время на своем ПК и обмануть конструктор JavaScript (), который получает время от операционной системы.

Вы можете использовать интервал для повторного сравнения тактовых импульсов с интервалом в одну секунду. Обработчик интервалов также может обновлять оставшееся время поле на дисплее пользователя. Тогда пользователи могут почувствовать, что давление возрастает на их викторине. Веселые времена!

3 голосов
/ 13 октября 2008

Это модально и останавливает выполнение. Рассмотрим альтернативу, которая не приостанавливает выполнение, как техника Lightbox.

2 голосов
/ 14 октября 2008

В конечном счете, вы не можете доверять пользовательскому вводу. Без учета времени, прошедшего на сервере, нет никакой гарантии, что данные не были обработаны.

Однако, если вы уверены, что ваши тестеры не разбираются в JavaScript и просто полагаются на «хитрость», которую они где-то нашли, вы можете проверить на мошенничество (паузу) с помощью следующего кода, который не Не требуется изменять 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();
            }
        }
    }
};

Этот объект таймера имеет единственный метод count (), который принимает объект в качестве входных данных. Ожидается как минимум свойство секунд во входном объекте.

По какой-то причине window.setTimeout не всегда работает должным образом. Иногда на моем компьютере window.setTimeout (x, 1000), который должен выполнить код через 1 секунду, занимал более 2 секунд. Таким образом, в таком случае вы должны допустить отклонение, чтобы люди, которые не обманывают, не отмечались как мошенники. Дисперсия по умолчанию равна 1, но она может быть переопределена во входном объекте. Вот пример того, как использовать этот код, который дает 2,5 секунды «комнаты для маневра» для медленных ударов:

timer.count({
    seconds: 10,
    onPause: function () { alert("You cheated!"); window.location.replace("cheatersAreBad.html"); },
    onFinish: function () { alert("Time's up!"); },
    variance: 2.5
});

С таким решением вы могли бы использовать Ajax, чтобы сообщить серверному скрипту, что пользователь приостановил таймер, или перенаправить пользователя на страницу, объясняющую, например, что его поймали на мошенничестве. Если по какой-то причине вы хотите, чтобы пользователь продолжил принимать участие в опросе после того, как его поймали на мошенничестве, вы можете установить для exitOnPause значение false:

timer.count({
    seconds: 10,
    exitOnPause: false,
    onPause: function () { recordCheaterViaAjax(); },
    onFinish: function () { alert("Time's up!"); },
    variance: 2.5
});
2 голосов
/ 14 октября 2008

Цикл обратной связи по вопросу SyaZ прояснил поставленные вопросы.

Вот попытка обобщить хорошие ответы на данный момент:

  • Клиентские скрипты по своей природе легко манипулировать, чтобы обмануть онлайн-викторину. СМ. @ Подход на стороне сервера Filini

  • window.alert = function (msg) {} переопределит alert () и, возможно, победит низко висящий плод ввода в адресную строку: javascript: alert ('пауза страницы так что я могу найти ответ в Google '), или я сейчас воспользуюсь моим другом по телефону. Предоставлено @ eyelidlessness

  • Если вы должны использовать подход на стороне клиента, вместо использования setTimeOut (), вы можете использовать пользовательскую функцию паузы, основанную на сравнении дат, например, такую ​​( concept by @ Mnebuerquo , код мой пример ( @ micahwittman )):

Пример: * * тысяча тридцать-один

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);
0 голосов
/ 26 июня 2012

Для сеанса сервера может быть установлен срок действия, скажем, 1 час. Javascript может быть использован в качестве только инструмента отображения для пользователя, чтобы знать, сколько времени осталось. Если он решит обмануть, приостановив таймер, то при публикации теста он может удивиться, что его сеанс истек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...