是否可以在JavaScript中检测“ 空闲 ”时间?
我的主要用例可能是预取或预加载内容。
空闲时间:用户不活动或没有使用CPU的时间
是否可以在JavaScript中检测“ 空闲 ”时间?
我的主要用例可能是预取或预加载内容。
空闲时间:用户不活动或没有使用CPU的时间
Answers:
这是一个使用JQuery的简单脚本,用于处理mousemove和keypress事件。如果时间到了,页面将重新加载。
<script type="text/javascript">
var idleTime = 0;
$(document).ready(function () {
//Increment the idle time counter every minute.
var idleInterval = setInterval(timerIncrement, 60000); // 1 minute
//Zero the idle timer on mouse movement.
$(this).mousemove(function (e) {
idleTime = 0;
});
$(this).keypress(function (e) {
idleTime = 0;
});
});
function timerIncrement() {
idleTime = idleTime + 1;
if (idleTime > 19) { // 20 minutes
window.location.reload();
}
}
</script>
setInterval
,然后将其评估为JavaScript。
idleTime++;
,而不是idleTime = idleTime + 1;
'mousemove keydown click'
使用字符串的函数,例如使用位标志(Event.MOUSEMOVE | Event.KEYDOWN | Event.CLICK
),因为它们比字符串操作快得多。但是您真的要这样做吗?
如果不使用jQuery,则仅使用普通JavaScript:
var inactivityTime = function () {
var time;
window.onload = resetTimer;
// DOM Events
document.onmousemove = resetTimer;
document.onkeypress = resetTimer;
function logout() {
alert("You are now logged out.")
//location.href = 'logout.html'
}
function resetTimer() {
clearTimeout(time);
time = setTimeout(logout, 3000)
// 1000 milliseconds = 1 second
}
};
然后在需要的地方初始化函数(例如:onPageLoad)。
window.onload = function() {
inactivityTime();
}
如果需要,可以添加更多的DOM事件。最常用的是:
document.onload = resetTimer;
document.onmousemove = resetTimer;
document.onmousedown = resetTimer; // touchscreen presses
document.ontouchstart = resetTimer;
document.onclick = resetTimer; // touchpad clicks
document.onkeypress = resetTimer;
document.addEventListener('scroll', resetTimer, true); // improved; see comments
或使用数组注册所需的事件
window.addEventListener('load', resetTimer, true);
var events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'];
events.forEach(function(name) {
document.addEventListener(name, resetTimer, true);
});
DOM事件列表:http : //www.w3schools.com/jsref/dom_obj_event.asp
记住使用window
,或document
根据您的需要。在这里,您可以看到它们之间的区别:Java窗口,屏幕和文档之间的区别是什么?
使用@ frank-conijn和@daxchen进行更新的代码得到改进:window.onscroll
如果滚动位于可滚动元素内部,则不会触发,因为滚动事件不会冒泡。window.addEventListener('scroll', resetTimer, true)
,第三个参数告诉侦听器在捕获阶段而不是冒泡阶段捕获事件。
document.onload = function () { inactivityTime(); }; document.onmousedown = function () { inactivityTime(); }; document.onkeypress = function () { inactivityTime(); }; document.ontouchstart = function () { inactivityTime(); };
改善Equiman的答案:
function idleLogout() {
var t;
window.onload = resetTimer;
window.onmousemove = resetTimer;
window.onmousedown = resetTimer; // catches touchscreen presses as well
window.ontouchstart = resetTimer; // catches touchscreen swipes as well
window.onclick = resetTimer; // catches touchpad clicks as well
window.onkeypress = resetTimer;
window.addEventListener('scroll', resetTimer, true); // improved; see comments
function yourFunction() {
// your function for too long inactivity goes here
// e.g. window.location.href = 'logout.php';
}
function resetTimer() {
clearTimeout(t);
t = setTimeout(yourFunction, 10000); // time is in milliseconds
}
}
idleLogout();
。
除了在活动检测方面的改进以及从document
到的更改之外window
,该脚本实际上调用了该函数,而不是让其闲置。
它不会直接捕获零CPU使用率,但这是不可能的,因为执行函数会导致CPU使用率。用户的不活动最终导致CPU使用率为零,因此间接地确实导致CPU使用率为零。
document.onscroll
有相同的问题,如果滚动位于可滚动子项中,则不会触发?
addEventListener
而不是onscroll
。
我一年前创建了一个小库:
https://github.com/shawnmclean/Idle.js
描述:
小型的javascript库,用于报告用户在浏览器中的活动(离开,空闲,不查看网页,在其他标签中等)。与其他任何JavaScript库(例如jquery)无关。
Visual Studio用户可以通过以下方式从NuGet中获取它: PM> Install-Package Idle.js
这是tvanfosson想法的jQuery粗略实现:
$(document).ready(function(){
idleTime = 0;
//Increment the idle time counter every second.
var idleInterval = setInterval(timerIncrement, 1000);
function timerIncrement()
{
idleTime++;
if (idleTime > 2)
{
doPreload();
}
}
//Zero the idle timer on mouse movement.
$(this).mousemove(function(e){
idleTime = 0;
});
function doPreload()
{
//Preload images, etc.
}
})
setInterval
字符串!只要给一个函数作为变量!
setInterval()
评估全局范围内的表达式,因此无法找到timerIncrement()
.ready处理函数内部的函数。这是永远不要将字符串传递给的另一个原因setInterval()
。只要传递一个实际的函数引用,您就不会遇到这个问题,因为它们是在当前范围内进行评估的。
类似于上面的Iconic解决方案(带有jQuery自定义事件)...
// use jquery-idle-detect.js script below
$(window).on('idle:start', function(){
//start your prefetch etc here...
});
$(window).on('idle:stop', function(){
//stop your prefetch etc here...
});
//jquery-idle-detect.js
(function($,$w){
// expose configuration option
// idle is triggered when no events for 2 seconds
$.idleTimeout = 2000;
// currently in idle state
var idle = false;
// handle to idle timer for detection
var idleTimer = null;
//start idle timer and bind events on load (not dom-ready)
$w.on('load', function(){
startIdleTimer();
$w.on('focus resize mousemove keyup', startIdleTimer)
.on('blur',idleStart) //force idle when in a different tab/window
;
]);
function startIdleTimer() {
clearTimeout(idleTimer); //clear prior timer
if (idle) $w.trigger('idle:stop'); //if idle, send stop event
idle = false; //not idle
var timeout = ~~$.idleTimeout; // option to integer
if (timeout <= 100) timeout = 100; // min 100ms
if (timeout > 300000) timeout = 300000; // max 5 minutes
idleTimer = setTimeout(idleStart, timeout); //new timer
}
function idleStart() {
if (!idle) $w.trigger('idle:start');
idle = true;
}
}(window.jQuery, window.jQuery(window)))
我的回答受到了vijay的回答的启发,但是是一个简短,更笼统的解决方案,我认为我会与可能会帮助的任何人分享。
(function () {
var minutes = true; // change to false if you'd rather use seconds
var interval = minutes ? 60000 : 1000;
var IDLE_TIMEOUT = 3; // 3 minutes in this example
var idleCounter = 0;
document.onmousemove = document.onkeypress = function () {
idleCounter = 0;
};
window.setInterval(function () {
if (++idleCounter >= IDLE_TIMEOUT) {
window.location.reload(); // or whatever you want to do
}
}, interval);
}());
按照目前的状态,此代码将立即执行,并在3分钟内没有鼠标移动或按键按下的情况下重新加载当前页面。
这利用普通的JavaScript和立即调用的函数表达式以干净且自成体系的方式处理空闲超时。
onclick
作业,因为除此作业外可能没有其他必要onmousemove
,但显然,以编程方式触发的所有这些事件都将继续重置idleCounter
。我不确定您为什么要模拟用户交互而不仅仅是调用一个函数,但是如果出于某种原因您需要这样做,那么此答案显然对您不起作用,其他大多数答案我也不会我看了这个问题。
我知道这是一个相对较旧的问题,但是我遇到了同样的问题,并且找到了一个很好的解决方案。
我使用过:jquery.idle ,我只需要这样做:
$(document).idle({
onIdle: function(){
alert('You did nothing for 5 seconds');
},
idle: 5000
})
参见JsFiddle演示。
(仅供参考:后端事件跟踪Leads browserload参见此内容)
先前的所有答案都有一个始终处于活动状态的mousemove处理程序。如果处理程序是jQuery,则jQuery所执行的其他处理可以加起来。特别是如果用户使用游戏鼠标,则每秒最多可能发生500个事件。
此解决方案避免处理每个mousemove事件。这样会导致较小的时序误差,但是您可以根据需要进行调整。
function setIdleTimeout(millis, onIdle, onUnidle) {
var timeout = 0;
startTimer();
function startTimer() {
timeout = setTimeout(onExpires, millis);
document.addEventListener("mousemove", onActivity);
document.addEventListener("keydown", onActivity);
}
function onExpires() {
timeout = 0;
onIdle();
}
function onActivity() {
if (timeout) clearTimeout(timeout);
else onUnidle();
//since the mouse is moving, we turn off our event hooks for 1 second
document.removeEventListener("mousemove", onActivity);
document.removeEventListener("keydown", onActivity);
setTimeout(startTimer, 1000);
}
}
$(startTimer)
相当于$(document).ready(startTimer)
,确保DOM你钩鼠标移动和按键事件之前准备就绪。
您可能会通过检测鼠标在表单主体上的移动并使用最后一次移动时间更新全局变量来一起破解某些东西。然后,您需要运行一个间隔计时器,该计时器会定期检查上一次移动时间,并且如果自检测到上一次鼠标移动以来时间足够长,则应执行一些操作。
我写了一个小的ES6类来检测活动,否则将在空闲超时时触发事件。它涵盖了键盘,鼠标和触摸,可以被激活和停用,并且具有非常精简的API:
const timer = new IdleTimer(() => alert('idle for 1 minute'), 1000 * 60 * 1);
timer.activate();
它不依赖于jQuery的,虽然你可能需要通过通天运行它支持旧版浏览器。
https://gist.github.com/4547ef5718fd2d31e5cdcafef0208096
一旦收到一些反馈,我可能会将其作为npm软件包发布。
如果您要定位受支持的浏览器(截至2018年12月为Chrome或Firefox),则可以尝试使用requestIdleCallback并为不受支持的浏览器添加requestIdleCallback填充程序。
试试此代码,它可以完美地工作。
var IDLE_TIMEOUT = 10; //seconds
var _idleSecondsCounter = 0;
document.onclick = function () {
_idleSecondsCounter = 0;
};
document.onmousemove = function () {
_idleSecondsCounter = 0;
};
document.onkeypress = function () {
_idleSecondsCounter = 0;
};
window.setInterval(CheckIdleTime, 1000);
function CheckIdleTime() {
_idleSecondsCounter++;
var oPanel = document.getElementById("SecondsUntilExpire");
if (oPanel)
oPanel.innerHTML = (IDLE_TIMEOUT - _idleSecondsCounter) + "";
if (_idleSecondsCounter >= IDLE_TIMEOUT) {
alert("Time expired!");
document.location.href = "SessionExpired.aspx";
}
}
<script type="text/javascript">
var idleTime = 0;
$(document).ready(function () {
//Increment the idle time counter every minute.
idleInterval = setInterval(timerIncrement, 60000); // 1 minute
//Zero the idle timer on mouse movement.
$('body').mousemove(function (e) {
//alert("mouse moved" + idleTime);
idleTime = 0;
});
$('body').keypress(function (e) {
//alert("keypressed" + idleTime);
idleTime = 0;
});
$('body').click(function() {
//alert("mouse moved" + idleTime);
idleTime = 0;
});
});
function timerIncrement() {
idleTime = idleTime + 1;
if (idleTime > 10) { // 10 minutes
window.location.assign("http://www.google.com");
}
}
</script>
我认为这个jquery代码是完美的,尽管是从上面的答案中复制和修改的!不要忘记在文件中包含jquery库!
所有这些解决方案的问题,尽管是正确的,但考虑到会话超时有价值的设置(使用PHP,.NET或Coldfusion开发人员的Application.cfc文件)时,它们都不切实际。上述解决方案设置的时间需要与服务器端会话超时同步。如果两者不同步,则可能会遇到麻烦,只会使用户感到沮丧和困惑。例如,服务器端会话超时可能设置为60分钟,但用户可能认为他/她是安全的,因为JavaScript空闲时间捕获增加了用户可以花在单个页面上的总时间。用户可能已经花了很长时间填写较长的表格,然后去提交。会话超时可能在处理表单提交之前开始。我倾向于给用户180分钟,然后使用JavaScript自动将用户注销。本质上,使用上面的一些代码创建一个简单的计时器,但没有捕获鼠标事件部分。这样,我的客户端和服务器端时间可以完美同步。如果您在用户界面中向用户显示时间,则不会造成混乱,因为这会减少时间。每次在CMS中访问新页面时,服务器端会话和JavaScript计时器都会重置。简单而优雅。如果用户在一个页面上停留超过180分钟,那么我认为该页面首先存在问题。随着它减少。每次在CMS中访问新页面时,服务器端会话和JavaScript计时器都会重置。简单而优雅。如果用户在一个页面上停留超过180分钟,那么我认为该页面首先存在问题。随着它减少。每次在CMS中访问新页面时,服务器端会话和JavaScript计时器都会重置。简单而优雅。如果用户在一个页面上停留超过180分钟,那么我认为该页面首先存在问题。
具有正确设置重置时间和绑定的纯JavaScript addEventListener
(function() {
var t,
timeout = 5000;
function resetTimer() {
console.log("reset: " + new Date().toLocaleString());
if (t) {
window.clearTimeout(t);
}
t = window.setTimeout(logout, timeout);
}
function logout() {
console.log("done: " + new Date().toLocaleString());
}
resetTimer();
//And bind the events to call `resetTimer()`
["click", "mousemove", "keypress"].forEach(function(name) {
console.log(name);
document.addEventListener(name, resetTimer);
});
}());
(部分受本主题前面的Equiman良好的核心逻辑启发。)
sessionExpiration.js轻巧但有效且可自定义。实施后,只需一行即可使用:
sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
如果您不更改CSS,这就是实际操作的一个示例。
我写了一个简单的jQuery插件,可以完成您想要的工作。
https://github.com/afklondon/jquery.inactivity
$(document).inactivity( {
interval: 1000, // the timeout until the inactivity event fire [default: 3000]
mouse: true, // listen for mouse inactivity [default: true]
keyboard: false, // listen for keyboard inactivity [default: true]
touch: false, // listen for touch inactivity [default: true]
customEvents: "customEventName", // listen for custom events [default: ""]
triggerAll: true, // if set to false only the first "activity" event will be fired [default: false]
});
该脚本将侦听鼠标,键盘,触摸和其他自定义事件的不活动(空闲),并触发全局“活动”和“不活动”事件。
希望这可以帮助 :)
我已经测试了此代码工作文件:
var timeout = null;
var timee = '4000'; // default time for session time out.
$(document).bind('click keyup mousemove', function(event) {
if (timeout !== null) {
clearTimeout(timeout);
}
timeout = setTimeout(function() {
timeout = null;
console.log('Document Idle since '+timee+' ms');
alert("idle window");
}, timee);
});
这是我找到的最佳解决方案:http : //css-tricks.com/snippets/jquery/fire-event-when-user-is-idle/
这是JS:
idleTimer = null;
idleState = false;
idleWait = 2000;
(function ($) {
$(document).ready(function () {
$('*').bind('mousemove keydown scroll', function () {
clearTimeout(idleTimer);
if (idleState == true) {
// Reactivated event
$("body").append("<p>Welcome Back.</p>");
}
idleState = false;
idleTimer = setTimeout(function () {
// Idle Event
$("body").append("<p>You've been idle for " + idleWait/1000 + " seconds.</p>");
idleState = true; }, idleWait);
});
$("body").trigger("mousemove");
});
}) (jQuery)
您可以使用以下提到的解决方案
var idleTime;
$(document).ready(function () {
reloadPage();
$('html').bind('mousemove click mouseup mousedown keydown keypress keyup submit change mouseenter scroll resize dblclick', function () {
clearTimeout(idleTime);
reloadPage();
});
});
function reloadPage() {
clearTimeout(idleTime);
idleTime = setTimeout(function () {
location.reload();
}, 3000);
}
我使用这种方法,因为您不需要在事件触发时不断重置时间,而是只记录时间,这会生成空闲开始点。
function idle(WAIT_FOR_MINS, cb_isIdle) {
var self = this,
idle,
ms = (WAIT_FOR_MINS || 1) * 60000,
lastDigest = new Date(),
watch;
//document.onmousemove = digest;
document.onkeypress = digest;
document.onclick = digest;
function digest() {
lastDigest = new Date();
}
// 1000 milisec = 1 sec
watch = setInterval(function(){
if (new Date() - lastDigest > ms && cb_isIdel) {
clearInterval(watch);
cb_isIdle();
}
}, 1000*60);
},
这是用于在Angular中完成的AngularJS服务。
/* Tracks now long a user has been idle. secondsIdle can be polled
at any time to know how long user has been idle. */
fuelServices.factory('idleChecker',['$interval', function($interval){
var self = {
secondsIdle: 0,
init: function(){
$(document).mousemove(function (e) {
self.secondsIdle = 0;
});
$(document).keypress(function (e) {
self.secondsIdle = 0;
});
$interval(function(){
self.secondsIdle += 1;
}, 1000)
}
}
return self;
}]);
请记住,此空闲检查程序将在所有路径上运行,因此应在.run()
有角度应用程序加载时对其进行初始化。然后,您可以idleChecker.secondsIdle
在每条路线内使用。
myApp.run(['idleChecker',function(idleChecker){
idleChecker.init();
}]);
反跳实际上是个好主意!此处为jQuery免费项目版本:
const derivedLogout = createDerivedLogout(30);
derivedLogout(); // it could happen that user too idle)
window.addEventListener('click', derivedLogout, false);
window.addEventListener('mousemove', derivedLogout, false);
window.addEventListener('keyup', derivedLogout, false);
function createDerivedLogout (sessionTimeoutInMinutes) {
return _.debounce( () => {
window.location = this.logoutUrl;
}, sessionTimeoutInMinutes * 60 * 1000 )
}
尽可能简单地检测鼠标何时移动:
var idle = false;
document.querySelector('body').addEventListener('mousemove', function(e) {
if(idle!=false)idle = false;
});
var idleI = setInterval(function()
{
if(idle == 'inactive')
{
return;
}
if(idle == true)
{
idleFunction();
idle = 'inactive';
return;
}
idle = true;
}, 30000);// half the expected time, idle will trigger after 60s in this case.
function idleFuntion()
{
console.log('user is idle');
}
Javascript无法告诉CPU使用情况。这将破坏沙箱中运行的javascript。
除此之外,挂接页面的onmouseover和onkeydown事件可能会起作用。
您还可以在onload事件中设置使用setTimeout来安排延迟后调用的函数。
// Call aFunction after 1 second
window.setTimeout(aFunction, 1000);