Тайм-аут Javascript, когда никаких действий от пользователя в течение указанного времени - PullRequest
15 голосов
/ 16 августа 2011

Я хочу вызвать функцию js, если в течение определенного времени нет активности пользователя на веб-странице. Если есть активность от пользователя, то сбросьте тайм-аут. Я пытался найти, но ничего не смог найти. Я знаком с setTimeout () и clearTimeout () и как они работают. Что я ищу, так это где / как отслеживать активность пользователей. Есть ли событие, в котором я могу установить и очистить таймер?

Спасибо.

Редактировать # 1:

Эта веб-страница имеет одно поле ввода и одну кнопку. Это своего рода обычная страница чата. Когда я говорю «нет активности пользователя», я имею в виду, что пользователь ничего не печатал в текстовом поле или не нажимал никаких кнопок в течение указанного времени. И еще одна вещь, которая предназначена для сенсорных смартфонов.

Редактировать # 2:

Спасибо всем за предложения. Я реализовал решение на основе более чем одного ответа. Поэтому я буду отвечать на все ответы, которые мне показались полезными, вместо того, чтобы принимать один из них в качестве ответа.

Ответы [ 7 ]

27 голосов
/ 16 августа 2011
// Using jQuery (but could use pure JS with cross-browser event handlers):
var idleSeconds = 30;

$(function(){
  var idleTimer;
  function resetTimer(){
    clearTimeout(idleTimer);
    idleTimer = setTimeout(whenUserIdle,idleSeconds*1000);
  }
  $(document.body).bind('mousemove keydown click',resetTimer); //space separated events list that we want to monitor
  resetTimer(); // Start the timer when the page loads
});

function whenUserIdle(){
  //...
}

Редактировать : По какой-то причине не используете jQuery?Вот некоторый (непроверенный) код, который должен быть кросс-браузерным (до некоторой степени; например, не работает на IE5 Mac;):

attachEvent(window,'load',function(){
  var idleSeconds = 30;
  var idleTimer;
  function resetTimer(){
    clearTimeout(idleTimer);
    idleTimer = setTimeout(whenUserIdle,idleSeconds*1000);
  }
  attachEvent(document.body,'mousemove',resetTimer);
  attachEvent(document.body,'keydown',resetTimer);
  attachEvent(document.body,'click',resetTimer);

  resetTimer(); // Start the timer when the page loads
});

function whenUserIdle(){
  //...
}

function attachEvent(obj,evt,fnc,useCapture){
  if (obj.addEventListener){
    obj.addEventListener(evt,fnc,!!useCapture);
    return true;
  } else if (obj.attachEvent){
    return obj.attachEvent("on"+evt,fnc);
  }
} 
9 голосов
/ 16 августа 2011

Для этого нужен дебоузер:

function debounce(callback, timeout, _this) {
    var timer;
    return function(e) {
        var _that = this;
        if (timer)
            clearTimeout(timer);
        timer = setTimeout(function() { 
            callback.call(_this || _that, e);
        }, timeout);
    }
}

Используется так:

// we'll attach the function created by "debounce" to each of the target
// user input events; this function only fires once 2 seconds have passed
// with no additional input; it can be attached to any number of desired
// events
var userAction = debounce(function(e) {
    console.log("silence");
}, 2000);

document.addEventListener("mousemove", userAction, false);
document.addEventListener("click", userAction, false);
document.addEventListener("scroll", userAction, false);

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

Обратите внимание, что не нужны глобальные флаги или переменные тайм-аута. Глобальная область получает только ваш отклоненный обратный вызов. Остерегайтесь решений, которые требуют поддержания глобального состояния ; о них будет сложно рассуждать в контексте более крупного приложения.

Обратите внимание, что это решение является полностью общим . Остерегайтесь решений, применимых только к вашему крайне узкому варианту использования.

5 голосов
/ 16 августа 2011

Большинство событий JavaScript bubble , так что вы можете сделать что-то вроде следующего:

  • Составьте список всех событий, которые вы считаете «активностью пользователя» (например, click, mousemove, keydown и т. Д.)
  • Присоедините одну функцию в качестве прослушивателя событий для всех этих событий к document (или, возможно, document.body для некоторых из них; я не могу вспомнить, является ли это проблемой или нет).
  • Когда слушатель запускается, сбросьте таймер с помощью clearTimeout / setTimeout

Итак, вы получите что-то вроде этого:

var events = ['click', 'mousemove', 'keydown'],
    i = events.length,
    timer,
    delay = 10000,
    logout = function () {
        // do whatever it is you want to do
        // after a period of inactivity
    },
    reset = function () {
        clearTimeout(timer);
        timer = setTimeout(logout, 10000);
    };

while (i) {
    i -= 1;
    document.addEventListener(events[i], reset, false);
}
reset();

Обратите внимание, что есть некоторые проблемы, которые вы должны решить с помощью приведенного выше кода:

  • Он не совместим с разными браузерами. Используется только addEventListener, поэтому он не будет работать в IE6-8
  • Загрязняет глобальное пространство имен. Создает много лишних переменных, которые могут конфликтовать с другими скриптами.

Это больше, чтобы дать вам представление о том, что вы могли бы сделать.

А теперь есть еще четыре ответа, но я уже все набрал, так что там: P

3 голосов
/ 16 августа 2011

Вы хотите отслеживать такие события, как mousemove, keypress, keydown и / или click на уровне документа.

Редактировать: Это смартфонПриложение меняет, какие события вы хотите слушать.Учитывая ваши требования к текстовым полям и кнопкам, я прослушаю oninput, а затем добавлю вызов resetTimeout() в обработчик кликов для вашей кнопки.

var inactivityTimeout = 0;
function resetTimeout() {
    clearTimeout(inactivityTimeout);
    inactivityTimeout = setTimeout(inactive, 300000);
}
function inactive() {
   ...
}
document.getElementById("chatInput").oninput = resetTimeout;
2 голосов
/ 16 августа 2011

Примерно так:

function onInactive(ms, cb){   

    var wait = setTimeout(cb, ms); 

    // Bind all events you consider as activity
    // Note that binding this way overrides any previous events bound the same wa
    // So if you already have events bound to document, use AddEventListener and AttachEvent instead
    document.onmousemove = document.mousedown = document.mouseup = document.onkeydown = document.onkeyup = document.focus = function(){
        clearTimeout(wait);
        wait = setTimeout(cb, ms);

    };

}

IE: http://jsfiddle.net/acNfy/ Активность в нижнем правом фрейме задержит обратный вызов.

1 голос
/ 04 мая 2014

Я использую изящный метод «задержки» для этого, который я нашел в этой теме

var delay = (function(){
  var timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  };
})();

используйте как

delay(function(){ doSomethingWhenNoInputFor400ms(); },400);
0 голосов
/ 16 августа 2011

Кроме того, посмотрите на плагин jQuery idleTimer от Пола Айриша ( jquery.idle-timer.js ).Это было основано на Николаса С. Закаса 'Обнаружение, если пользователь бездействует с JavaScript и YUI 3 статья ( idle-timer.js ).

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

events  = 'mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove';
// activity is one of these events
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...