是否可以在JavaScript中检测到“ 空闲 ”时间?
我的主要用例可能是预取或预加载内容。
空闲时间:用户不活动或没有任何CPU使用的时间
答案 0 :(得分:406)
这是一个使用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>
答案 1 :(得分:272)
不使用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
}
};
/*call the function*/
<script>
inactivityTime();
</script>
致谢: http://forums.devshed.com/javascript-development-115/alert-time-inactivity-click-logout-501444.html
如果需要,您可以添加更多DOM事件。最常用的是:
document.onload = resetTimer;
document.onmousemove = resetTimer;
document.onmousedown = resetTimer; // touchscreen presses
document.ontouchstart = resetTimer;
document.onclick = resetTimer; // touchpad clicks
document.onscroll = resetTimer; // scrolling with arrow keys
document.onkeypress = resetTimer;
或使用数组
注册所需的事件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
。在这里,您可以看到它们之间的差异:What is the difference between window, screen, and document in Javascript?
答案 2 :(得分:66)
改善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使用率。
答案 3 :(得分:31)
我在一年前创建了一个小型lib:
https://github.com/shawnmclean/Idle.js
说明
用于在浏览器中报告用户活动的小型JavaScript库 (离开,闲置,不看网页,在不同的标签中等)。这是独立的 其他javascript库,如jquery。
Visual Studio用户可以通过以下方式从NuGet获取它:PM> Install-Package Idle.js
答案 4 :(得分:30)
这是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.
}
})
答案 5 :(得分:23)
与上面的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)))
答案 6 :(得分:18)
您可以使用underscore和jquery -
更优雅地完成这项工作$('body').on("click mousemove keyup", _.debounce(function(){
// do preload here
}, 1200000)) // 20 minutes debounce
答案 7 :(得分:15)
我的回答受到vijay's answer的启发,但这是一个更短,更通用的解决方案,我认为我可以为任何可能帮助的人分享。
(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分钟后重新加载当前页面。
这利用普通的vanilla JavaScript和immediately-invoked function expression以干净,自包含的方式处理空闲超时。
答案 8 :(得分:13)
我知道这是一个相对古老的问题,但我遇到了同样的问题,我找到了一个非常好的解决方案。
我用过:jquery.idle 我只需要这样做:
$(document).idle({
onIdle: function(){
alert('You did nothing for 5 seconds');
},
idle: 5000
})
请参阅JsFiddle demo。
(仅供参考:see this for back-end event tracking Leads browserload)
答案 9 :(得分:11)
通过检测表单主体上的鼠标移动并使用上次移动时间更新全局变量,您可能会将某些内容混合在一起。然后你需要有一个间隔定时器运行,定期检查最后一个移动时间,如果检测到最后一次鼠标移动已经足够长,就会做一些事情。
答案 10 :(得分:11)
以前的所有答案都有一个始终有效的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);
}
}
答案 11 :(得分:6)
试试这个完美的工作..
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";
}
}
答案 12 :(得分:5)
如果您定位supported browser(自2018年12月起使用Chrome或Firefox),您可以试用requestIdleCallback,并为不受支持的浏览器添加requestIdleCallback shim。
答案 13 :(得分:5)
<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库!
答案 14 :(得分:4)
通过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);
});
}());
答案 15 :(得分:3)
我写了一个简单的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]
});
该脚本将监听鼠标,键盘,触摸和其他自定义事件的不活动(空闲)并触发全局&#34;活动&#34;和&#34;不活动&#34;事件
希望这会有所帮助:)
答案 16 :(得分:2)
我使用这种方法,因为你不需要经常重置事件触发的时间,而只记录时间,这会产生空闲的起点。
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);
},
答案 17 :(得分:2)
基于@equiman提供的输入
class _Scheduler {
timeoutIDs;
constructor() {
this.timeoutIDs = new Map();
}
addCallback = (callback, timeLapseMS, autoRemove) => {
if (!this.timeoutIDs.has(timeLapseMS + callback)) {
let timeoutID = setTimeout(callback, timeLapseMS);
this.timeoutIDs.set(timeLapseMS + callback, timeoutID);
}
if (autoRemove !== false) {
setTimeout(
this.removeIdleTimeCallback, // Remove
10000 + timeLapseMS, // 10 secs after
callback, // the callback
timeLapseMS, // is invoked.
);
}
};
removeCallback = (callback, timeLapseMS) => {
let timeoutID = this.timeoutIDs.get(timeLapseMS + callback);
if (timeoutID) {
clearTimeout(timeoutID);
this.timeoutIDs.delete(timeLapseMS + callback);
}
};
}
class _IdleTimeScheduler extends _Scheduler {
events = [
'load',
'mousedown',
'mousemove',
'keydown',
'keyup',
'input',
'scroll',
'touchstart',
'touchend',
'touchcancel',
'touchmove',
];
callbacks;
constructor() {
super();
this.events.forEach(name => {
document.addEventListener(name, this.resetTimer, true);
});
this.callbacks = new Map();
}
addIdleTimeCallback = (callback, timeLapseMS) => {
this.addCallback(callback, timeLapseMS, false);
let callbacksArr = this.callbacks.get(timeLapseMS);
if (!callbacksArr) {
this.callbacks.set(timeLapseMS, [callback]);
} else {
if (!callbacksArr.includes(callback)) {
callbacksArr.push(callback);
}
}
};
removeIdleTimeCallback = (callback, timeLapseMS) => {
this.removeCallback(callback, timeLapseMS);
let callbacksArr = this.callbacks.get(timeLapseMS);
if (callbacksArr) {
let index = callbacksArr.indexOf(callback);
if (index !== -1) {
callbacksArr.splice(index, 1);
}
}
};
resetTimer = () => {
for (let [timeLapseMS, callbacksArr] of this.callbacks) {
callbacksArr.forEach(callback => {
// Clear the previous IDs
let timeoutID = this.timeoutIDs.get(timeLapseMS + callback);
clearTimeout(timeoutID);
// Create new timeout IDs.
timeoutID = setTimeout(callback, timeLapseMS);
this.timeoutIDs.set(timeLapseMS + callback, timeoutID);
});
}
};
}
export const Scheduler = new _Scheduler();
export const IdleTimeScheduler = new _IdleTimeScheduler();
答案 18 :(得分:2)
我写了一个小的ES6类来检测活动,否则在空闲超时时引发事件。它涵盖了键盘,鼠标和触摸,可以激活和停用,并且具有非常精简的API:
const timer = new IdleTimer(() => alert('idle for 1 minute'), 1000 * 60 * 1);
timer.activate();
它确实不依赖于jQuery,尽管您可能需要通过Babel运行它以支持较旧的浏览器。
https://gist.github.com/4547ef5718fd2d31e5cdcafef0208096
一旦获得一些反馈,我可能会将其作为npm软件包发布。
答案 19 :(得分:2)
这是我找到的最佳解决方案: 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)
答案 20 :(得分:2)
您可以使用下面提到的解决方案
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);
}
答案 21 :(得分:2)
所有这些解决方案的问题虽然正确,但考虑到会话超时有价值的设置,使用PHP,.NET或Coldfusion开发人员的Application.cfc文件时,它们是不切实际的。上述解决方案设置的时间需要与服务器端会话超时同步。如果两者不同步,您可能遇到的问题会让您的用户感到沮丧和困惑。例如,服务器端会话超时可能设置为60分钟,但用户可能认为他/她是安全的,因为JavaScript空闲时间捕获增加了用户可以在单个页面上花费的总时间。用户可能花时间填写长表格,然后去提交。会话超时可能会在表单提交处理之前启动。我倾向于给我的用户180分钟,然后使用JavaScript自动登出用户。基本上,使用上面的一些代码,创建一个简单的计时器,但没有捕获鼠标事件部分。通过这种方式,我的客户端&amp;服务器端时间完美同步。如果您在UI中向用户显示时间,则不会产生混淆,因为它会减少。每次在CMS中访问新页面时,服务器端会话&amp; JavaScript计时器被重置。简单&amp;优雅。如果用户在单个页面上停留的时间超过180分钟,我认为该页面出现了问题。
答案 22 :(得分:2)
我已经测试了这段代码的工作文件:
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);
});
答案 23 :(得分:1)
这是一个AngularJS服务,用于在Angular中完成。
/* 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();
}]);
答案 24 :(得分:1)
您肯定想知道window.requestIdleCallback(),它在浏览器空闲期间将要调用的函数排队。
您可以在Quicklink repo中看到此API的优美用法。
const requestIdleCallback = window.requestIdleCallback ||
function (cb) {
const start = Date.now();
return setTimeout(function () {
cb({
didTimeout: false,
timeRemaining: function () {
return Math.max(0, 50 - (Date.now() - start));
},
});
}, 1);
};
上面的代码的含义是:如果浏览器支持requestIdleCallback
(检查兼容性),请使用它。如果不支持,则使用setTimeout(()=> {}, 1)
作为后备,这将在事件循环结束时将要调用的函数排队。
然后您可以像这样使用它:
requestIdleCallback(() => {...}, {
timeout: 2000
});
第二个参数是可选的,如果要确保函数已执行,可能需要设置timeout
。
答案 25 :(得分:1)
尽可能简单地检测鼠标何时移动:
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');
}
答案 26 :(得分:1)
(部分受此线程前面的Equiman良好的核心逻辑启发。)
sessionExpiration.js轻巧但有效且可自定义。实施后,仅使用一行:
sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
这是一个示例,说明如果不更改CSS的话。
答案 27 :(得分:1)
只是一些想法,一两个探索大道。
是否可以每隔10秒运行一次功能,并检查“计数器”变量?如果可能,您可以在页面上进行鼠标悬停,不是吗?如果是这样,请使用mouseover事件重置“counter”变量。如果调用了您的函数,并且计数器高于您预先确定的范围,请执行您的操作。
再次,只是一些想法...... 希望它有所帮助。
答案 28 :(得分:1)
您可能会使用列出的mousemove技巧检测网页上的不活动状态,但这不会告诉您用户不在另一个窗口或标签中的其他页面上,或者用户在Word或Photoshop中,或者WOW,而且目前还没有看你的页面。一般来说,我只是做预取并依赖客户端的多任务处理。如果真的需要这个功能,你可以在windows中使用activex控件做一些事情,但它最多也是丑陋的。
答案 29 :(得分:1)
对于遇到同样问题的其他用户。这是我刚刚编写的一个函数。
它不会在用户每次移动鼠标时运行,也不会在每次鼠标移动时清除计时器。
<script>
// Timeout in seconds
var timeout = 10; // 10 seconds
// You don't have to change anything below this line, except maybe
// the alert('Welcome back!') :-)
// ----------------------------------------------------------------
var pos = '', prevpos = '', timer = 0, interval = timeout / 5 * 1000;
timeout = timeout * 1000 - interval;
function mouseHasMoved(e){
document.onmousemove = null;
prevpos = pos;
pos = e.pageX + '+' + e.pageY;
if(timer > timeout){
timer = 0;
alert('Welcome back!');
}
}
setInterval(function(){
if(pos == prevpos){
timer += interval;
}else{
timer = 0;
prevpos = pos;
}
document.onmousemove = function(e){
mouseHasMoved(e);
}
}, interval);
</script>
答案 30 :(得分:0)
您可以将click或mousemove事件附加到重置计时器的文档正文。拥有一个定时调用的函数,用于检查计时器是否超过指定时间(如1000毫秒)并开始预加载。
答案 31 :(得分:0)
尝试@freddoo解决方案,但它没有1分钟的超时工作,所以我稍微改了一下,记录用户上次点击页面和timerIncrement
时的日期+时间function我计算当前时间和最后点击时间之间的差异,如果值恰好大于或等于超时值,那么我重定向:
var clickedDate = new Date();
var idleTime = 1;//
function timerIncrement() {
var nowDate = new Date();
var diffMs = (nowDate - clickedDate); //Milliseconds between now & the last time a user clicked somewhere on the page
var diffMins = Math.round(((diffMs % 86400000) % 3600000) / 60000); //Convert ms to minutes
if (diffMins >= idleTime) {
//Redirect user to home page etc...
}
}
$(document).ready(function () {
var idleInterval = setInterval(timerIncrement, 60000); // 1 minute
$(this).click(function (e) {
clickedDate = new Date();
});
});
答案 32 :(得分:0)
反跳实际上是个好主意! 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 )
}
答案 33 :(得分:0)
我终于在我的网站上使用了它。我发现对等人的回答最有帮助。这个答案的问题是javascript中的alert()
函数会暂停脚本执行。如果您希望像我一样发送警报,然后又没有收到要站点自动注销的响应,则暂停执行是一个问题。
解决方案是用here所述的自定义分隔符替换alert()
。
以下是代码:(注意:您需要更改第58行才能重定向到适合您网站的网址)
var inactivityTracker = function () {
// Create an alert division
var alertDiv = document.createElement("div");
alertDiv.setAttribute("style","position: absolute;top: 30%;left: 42.5%;width: 200px;height: 37px;background-color: red;text-align: center; color:white");
alertDiv.innerHTML = "You will be logged out in 5 seconds!!";
// Initialise a variable to store an alert and logout timer
var alertTimer;
var logoutTimer;
// Set the timer thresholds in seconds
var alertThreshold = 3;
var logoutThreshold = 5;
// Start the timer
window.onload = resetAlertTimer;
// Ensure timer resets when activity logged
registerActivityLoggers(resetAlertTimer);
// ***** FUNCTIONS ***** //
// Function to register activities for alerts
function registerActivityLoggers(functionToCall) {
document.onmousemove = functionToCall;
document.onkeypress = functionToCall;
}
// Function to reset the alert timer
function resetAlertTimer() {
clearTimeout(alertTimer);
alertTimer = setTimeout(sendAlert, alertThreshold * 1000);
}
// Function to start logout timer
function startLogoutTimer() {
clearTimeout(logoutTimer);
logoutTimer = setTimeout(logout, logoutThreshold * 1000);
}
// Function to logout
function sendAlert() {
// Send a logout alert
document.body.appendChild(alertDiv);
// Start the logout timer
startLogoutTimer();
// Reset everything if an activity is logged
registerActivityLoggers(reset);
}
// Function to logout
function logout(){
//location.href = 'index.php';
}
// Function to remove alert and reset logout timer
function reset(){
// Remove alert division
alertDiv.parentNode.removeChild(alertDiv);
// Clear the logout timer
clearTimeout(logoutTimer);
// Restart the alert timer
document.onmousemove = resetAlertTimer;
document.onkeypress = resetAlertTimer;
}
};
<html>
<script type="text/javascript" src="js/inactivityAlert.js"></script>
<head>
<title>Testing an inactivity timer</title>
</head>
<body onload="inactivityTracker();" >
Testing an inactivity timer
</body>
</html>
答案 34 :(得分:0)
我在这里提出的实现与其他答案在以下方面有所不同:
文件Idle.js
:
import $ from 'jquery';
export const IDLE_EVENT_NAME = 'idleTimeSeconds';
/**
* How often an 'idleTimeSeconds' event is fired on the document instance.
*
* @type {number}
*/
const IDLE_EVENT_RATE_SECONDS = 10;
/**
* How often the idle time is checked against the IDLE_EVENT_RATE_SECONDS.
*
* Should be much smaller than the value of IDLE_EVENT_RATE_SECONDS
* (the smaller the value is, the more precisely the event is fired) -
* because the actual delay may be longer, see "Reasons for delays
* longer than specified in WindowOrWorkerGlobalScope.setTimeout() for examples":
* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Reasons_for_delays_longer_than_specified
*
* @type {number}
*/
const IDLE_TIMER_RATE_SECONDS = 1;
/**
* Because the actual timer delay may be longer, we track the timestamp
* when the idle time started, instead of incrementally adding to the total idle time.
* Having a starting point, we can always calculate the idle time precisely
* without accumulating delay errors.
*
* @type {number}
*/
let idleStartTimeMilliseconds;
/**
* Holds the interval reference.
*/
let idleInterval;
/**
* Holds the value of the latest idle time value
* for which the event was fired (integer value in seconds).
*
* The value is therefore factor of IDLE_EVENT_RATE_SECONDS.
*
* @type {number}
*/
let lastFiredSeconds;
const $document = $(document);
/**
* Resets the idle timer.
* Called on user interaction events, like keydown or touchstart.
*/
function resetIdleStartTime() {
// Reset the timestamp when the idle time started
idleStartTimeMilliseconds = (new Date).getTime();
// Reset the latest idle time value for which the even was fired
// (integer value in seconds).
lastFiredSeconds = 0;
}
/**
* Ticks every IDLE_TIMER_RATE_SECONDS, which is more often than the expected
* idle event firing rate.
*
* Fires the 'idleTimeSeconds' event on the document instance.
*/
function timerCallback() {
const nowMilliseconds = (new Date).getTime();
const idleTimeSeconds = Math.floor((nowMilliseconds - idleStartTimeMilliseconds) / 1000);
// When do we expect the idle event to be fired again?
// For example, if the event firing rate is 10 seconds,
// and last time it was fired at 40 seconds of idle time,
// the next one will be at 40 + 10 = 50 seconds.
const nextIdleSecondsToFire = lastFiredSeconds + IDLE_EVENT_RATE_SECONDS;
if (idleTimeSeconds >= nextIdleSecondsToFire) {
// Record last fired idle time that is factor of the rate,
// so that we keep firing the event as close to the desired rate as possible
lastFiredSeconds = nextIdleSecondsToFire;
$document.triggerHandler(IDLE_EVENT_NAME, [idleTimeSeconds]);
}
}
// Initialize the idle timer once only per the document instance
$(function() {
// Start the idle timer
idleInterval = setInterval(timerCallback, IDLE_TIMER_RATE_SECONDS * 1000);
// Reset the idle time start timestamp
$document.on('mousemove keydown mousedown touchstart', resetIdleStartTime);
});
用法示例(例如文件index.js
)
import {IDLE_EVENT_NAME} from './Idle';
import $ from 'jquery';
$(function() {
$(document).on(IDLE_EVENT_NAME, function(e, idleSeconds) {
console.log('IDLE SECONDS:', idleSeconds);
});
});
示例输出(摘录):
IDLE SECONDS: 580
IDLE SECONDS: 590
IDLE SECONDS: 600
IDLE SECONDS: 610
IDLE SECONDS: 620
IDLE SECONDS: 630
IDLE SECONDS: 640
IDLE SECONDS: 650
IDLE SECONDS: 660
IDLE SECONDS: 670
IDLE SECONDS: 680
IDLE SECONDS: 691
IDLE SECONDS: 700
IDLE SECONDS: 710
IDLE SECONDS: 720
IDLE SECONDS: 730
IDLE SECONDS: 740
IDLE SECONDS: 750
IDLE SECONDS: 761
IDLE SECONDS: 770
IDLE SECONDS: 780
IDLE SECONDS: 790
IDLE SECONDS: 800
IDLE SECONDS: 810
IDLE SECONDS: 820
IDLE SECONDS: 830
IDLE SECONDS: 840
IDLE SECONDS: 850
IDLE SECONDS: 860
IDLE SECONDS: 871
IDLE SECONDS: 880
IDLE SECONDS: 890
IDLE SECONDS: 900
IDLE SECONDS: 910
IDLE SECONDS: 921
当我切换到另一个选项卡并在那里进行一些活动时,会产生上面的输出。可以看出,计时器有时会延迟(我想是因为在后台选项卡中以精确的速率触发计时器不是优先事项)。但是空闲计时器仍会以+/- 1秒的正确间隔触发。在这种情况下,空闲计时器的精度为1秒(通过IDLE_TIMER_RATE_SECONDS
中的Idle.js
常量配置)。
答案 35 :(得分:0)
您要求优雅,除了命令式(带有回调)之外,我创建了一个简单的类来支持懒惰检查(具有空闲状态)。另外,在违反空闲时间时,此类支持“ backToActive”。
class Idle {
constructor(timeout = 10, idleCallback = null, backToActiveCallback = null, autoStart = true, backToActiveOnXHR = false) {
this.timeout = timeout
this.idleCallback = idleCallback
this.backToActiveCallback = backToActiveCallback
this.autoStart = autoStart // only F5
this.backToActiveOnXHR = backToActiveOnXHR
this.idle = false
this.timer = null
this.events = ['scroll', 'mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart']
this.init()
}
init() {
if(this.backToActiveOnXHR) {
this.events.push('load')
}
this.events.forEach(name => {
window.addEventListener(name, this.backToActive, true)
})
if(this.autoStart) {
this.backToActive()
}
}
goIdle = () => {
this.idle = true
if(!!this.idleCallback) {
this.idleCallback(this.timeout)
}
}
backToActive = () => {
if(this.idle) {
this.backToActiveCallback()
}
this.idle = false
clearTimeout(this.timer)
this.timer = setTimeout(this.goIdle, this.timeout * 1000)
}
}
用法:
let idleCallback = timeout => { console.log(`Went idle after ${timeout} seconds`) }
let backToActiveCallback = () => { console.log('Back to active') }
let idle = new Idle(30, idleCallback, backToActiveCallback)
devtools中的结果:
// Went idle after 30 seconds <--- goes idle when no activity is detected
// Back to active <--- when the user is detected again
支持懒惰的优势:
setInterval(() => {
common.fetchApi('/api/v1/list', { status: idle.idle ? 'away' : 'online' }).then(/* show a list of elements */)
}, 1000 * 5)
您为什么要懒惰检查?有时我们使用定期的XHR(带有setInterval),即当用户观看航班,游乐设施,电影,订单等列表时。然后,通过每个XHR,我们可以添加有关其活动状态(在线/离开)的信息,因此系统中活跃用户的感觉。
我的课程基于Equiman和Frank Conijn的答案。
答案 36 :(得分:0)
使用此: 在此,我测试了两秒钟空闲后背景变黑。
< script type = "text/javascript"
src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js" >
< /script> < script type = "text/javascript" >
$(document).ready(function() {
var idle = false;
var time = null;
$('*').bind('mousemove click mouseup mousedown keydown keypress keyup submit change mouseenter scroll resize dblclick', function() {
clearTimeout(time);
if (idle == true) {
$("body").css('background-color', '#fff');
}
idle = false;
time = setTimeout(function() {
$("body").css('background-color', '#000');
idle = true;
}, 2000);
});
$("body").trigger("mousemove");
}); < /script>
答案 37 :(得分:-3)
Javascript无法告诉CPU使用情况。这会打破沙箱javascript在里面运行。
除此之外,挂钩页面的onmouseover和onkeydown事件可能会有效。
您还可以在onload事件中设置use setTimeout来安排在延迟后调用的函数。
// Call aFunction after 1 second
window.setTimeout(aFunction, 1000);