如何知道浏览器空闲时间?

IT技术 javascript browser
2021-03-17 19:29:52

如何跟踪浏览器空闲时间?我正在使用 IE8。

我没有使用任何会话管理,也不想在服务器端处理它。

5个回答

这是跟踪空闲时间的纯 JavaScript 方法,当它达到一定限制时执行一些操作:

var IDLE_TIMEOUT = 60; //seconds
var _idleSecondsTimer = null;
var _idleSecondsCounter = 0;

document.onclick = function() {
    _idleSecondsCounter = 0;
};

document.onmousemove = function() {
    _idleSecondsCounter = 0;
};

document.onkeypress = function() {
    _idleSecondsCounter = 0;
};

_idleSecondsTimer = window.setInterval(CheckIdleTime, 1000);

function CheckIdleTime() {
     _idleSecondsCounter++;
     var oPanel = document.getElementById("SecondsUntilExpire");
     if (oPanel)
         oPanel.innerHTML = (IDLE_TIMEOUT - _idleSecondsCounter) + "";
    if (_idleSecondsCounter >= IDLE_TIMEOUT) {
        window.clearInterval(_idleSecondsTimer);
        alert("Time expired!");
        document.location.href = "logout.html";
    }
}
#SecondsUntilExpire { background-color: yellow; }
You will be auto logged out in <span id="SecondsUntilExpire"></span> seconds.

此代码将在显示警报和重定向之前等待 60 秒,任何操作都将“重置”计数 - 鼠标单击、鼠标移动或按键。

它应该尽可能跨浏览器,并且是直接的。它还支持显示剩余时间,如果您向页面添加 ID 为 的元素SecondsUntilExpire

上面的代码应该可以正常工作,但是有几个缺点,例如它不允许运行任何其他事件并且不支持多个选项卡。包含这两者的重构代码如下:(无需更改 HTML)

var IDLE_TIMEOUT = 60; //seconds
var _localStorageKey = 'global_countdown_last_reset_timestamp';
var _idleSecondsTimer = null;
var _lastResetTimeStamp = (new Date()).getTime();
var _localStorage = null;

AttachEvent(document, 'click', ResetTime);
AttachEvent(document, 'mousemove', ResetTime);
AttachEvent(document, 'keypress', ResetTime);
AttachEvent(window, 'load', ResetTime);

try {
    _localStorage = window.localStorage;
}
catch (ex) {
}

_idleSecondsTimer = window.setInterval(CheckIdleTime, 1000);

function GetLastResetTimeStamp() {
    var lastResetTimeStamp = 0;
    if (_localStorage) {
        lastResetTimeStamp = parseInt(_localStorage[_localStorageKey], 10);
        if (isNaN(lastResetTimeStamp) || lastResetTimeStamp < 0)
            lastResetTimeStamp = (new Date()).getTime();
    } else {
        lastResetTimeStamp = _lastResetTimeStamp;
    }

    return lastResetTimeStamp;
}

function SetLastResetTimeStamp(timeStamp) {
    if (_localStorage) {
        _localStorage[_localStorageKey] = timeStamp;
    } else {
        _lastResetTimeStamp = timeStamp;
    }
}

function ResetTime() {
    SetLastResetTimeStamp((new Date()).getTime());
}

function AttachEvent(element, eventName, eventHandler) {
    if (element.addEventListener) {
        element.addEventListener(eventName, eventHandler, false);
        return true;
    } else if (element.attachEvent) {
        element.attachEvent('on' + eventName, eventHandler);
        return true;
    } else {
        //nothing to do, browser too old or non standard anyway
        return false;
    }
}

function WriteProgress(msg) {
    var oPanel = document.getElementById("SecondsUntilExpire");
    if (oPanel)
         oPanel.innerHTML = msg;
    else if (console)
        console.log(msg);
}

function CheckIdleTime() {
    var currentTimeStamp = (new Date()).getTime();
    var lastResetTimeStamp = GetLastResetTimeStamp();
    var secondsDiff = Math.floor((currentTimeStamp - lastResetTimeStamp) / 1000);
    if (secondsDiff <= 0) {
        ResetTime();
        secondsDiff = 0;
    }
    WriteProgress((IDLE_TIMEOUT - secondsDiff) + "");
    if (secondsDiff >= IDLE_TIMEOUT) {
        window.clearInterval(_idleSecondsTimer);
        ResetTime();
        alert("Time expired!");
        document.location.href = "logout.html";
    }
}

上面重构的代码使用本地存储来跟踪上次重置计数器的时间,并在每个打开的包含代码的新选项卡上重置它,然后所有选项卡的计数器都将相同,并在一个中重置将导致所有选项卡重置。由于 Stack Snippets 不允许本地存储,将它托管在那里毫无意义,所以我做了一个小提琴:http : //jsfiddle.net/yahavbr/gpvqa0fj/3/

@ShadowWizard 有人复制了您的代码并且比您获得的声誉更高。只是让你知道。
2021-04-22 19:29:52
@ChetanPatel 仅当 iframe 包含同一域中的页面时。
2021-04-23 19:29:52
@Yegya 但是我将无法显示剩余的时间,就像我在示例代码中所做的那样。虽然不是很重要,但有一个没有就不可能的功能是很好的setInterval()
2021-04-30 19:29:52
我的意思是CheckIdleTime(),您可以将超时设置为 60 秒,而不是每秒调用一次。我猜你不能显示剩余时间,但它要简单得多。您的解决方案也与 OP 所要求的略有不同。
2021-05-09 19:29:52
@CJRamki 刚刚拥有if (confirm("Sure you want to leave?") { document.location.href = "logout.html"; }.
2021-05-17 19:29:52

希望这是您正在寻找的 jquery-idletimer-plugin

@Yegya 总的来说,这是真的,但是这个插件是由业内知名的 Paul Irish 编写的,所以我会对他的代码更有信心。
2021-05-06 19:29:52
实际上忽略插件很好,当您可以使用非常简单的脚本实现相同的功能时。
2021-05-14 19:29:52

回复太晚了,但这可能有助于某人编写干净实用的解决方案。这是一个理想的解决方案,当您不需要显示会话到期的剩余时间时。可以忽略setInterval(),它会在整个应用程序运行时间内继续运行脚本。

    var inactivityTimeOut = 10 * 1000, //10 seconds
        inactivitySessionExpireTimeOut = '';

    setSessionExpireTimeOut();

    function setSessionExpireTimeOut () {
        'use strict';
        
        clearSessionExpireTimeout();
        inactivitySessionExpireTimeOut = setTimeout(function() {
            expireSessionIdleTime();
        }, inactivityTimeOut);
    }

    function expireSessionIdleTime () {
        'use strict';

        console.log('user inactive for ' + inactivityTimeOut + " seconds");
        console.log('session expired');
        alert('time expired');
        clearSessionExpireTimeout();
        document.location.href = "logout.html";
    }

    function clearSessionExpireTimeout () {
            'use strict';

            clearTimeout(inactivitySessionExpireTimeOut);
    }
Running example: Timeout alert will be popped up in 10 seconds

这是一种使用 jquery 的方法,因为我需要在文档上保留现有的键盘事件。

我还需要在不同的空闲时间做不同的事情,所以我把它包装在一个函数中

var onIdle = function (timeOutSeconds,func){
    //Idle detection
    var idleTimeout;
    var activity=function() {
        clearTimeout(idleTimeout);
        console.log('to cleared');
        idleTimeout = setTimeout(func, timeOutSeconds * 1000);
    }
    $(document).on('mousedown mousemove keypress',activity);
    activity();
}
onIdle(60*60,function(){
    location.reload();
});
onIdle(30,function(){
    if(currentView!=='welcome'){
        loadView('welcome');
    }
});

我需要一个类似的东西并创建了这个:https : //github.com/harunurhan/idlejs

它在某种程度上简单、可配置且功能强大,没有任何依赖性。这是一个例子。

import { Idle } from 'idlejs/dist';

// with predefined events on `document`
const idle = new Idle()
  .whenNotInteractive()
  .within(60)
  .do(() => console.log('IDLE'))
  .start();

您还可以使用自定义事件目标和事件

const idle = new Idle()
  .whenNot([{
    events: ['click', 'hover'],
    target: buttonEl,
  },
  {
    events: ['click', 'input'],
    target: inputEl,
  },
  ])
  .within(10)
  .do(() => called = true)
  .start();

(用typescript编写并编译为es5)