在JavaScript中优雅地检测空闲时间

是否有可能在JavaScript中检测到“ 闲置 ”时间?
我的主要用例可能是预取或预加载内容。

空闲时间: 用户不活动期间或没有任何CPU使用情况

这是一个简单的脚本,使用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> 

不使用jQuery,只有JavaScript:

 var inactivityTime = function () { var t; window.onload = resetTimer; // DOM Events document.onmousemove = resetTimer; document.onkeypress = resetTimer; function logout() { alert("You are now logged out.") //location.href = 'logout.php' } function resetTimer() { clearTimeout(t); t = setTimeout(logout, 3000) // 1000 milisec = 1 sec } }; 

学分: 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; 

DOM活动列表: http : //www.w3schools.com/jsref/dom_obj_event.asp

请记住使用window ,或根据您的需要logging。 在这里你可以看到它们之间的区别: Javascript中的窗口,屏幕和文档有什么区别?

我在一年前创build了一个小的库:

https://github.com/shawnmclean/Idle.js

描述:

微小的JavaScript库,以在浏览器中报告用户的活动(离开,闲置,不看网页,在不同的标签等)。 这是独立于任何其他的JavaScript库,如jQuery。

Visual Studio用户可以通过以下方式从NuGet获得它: PM> Install-Package Idle.js

提高Equiman的答案:

 function idleLogout() { var t; window.onload = resetTimer; window.onmousemove = resetTimer; window.onmousedown = resetTimer; // catches touchscreen presses window.onclick = resetTimer; // catches touchpad clicks window.onscroll = resetTimer; // catches scrolling with arrow keys window.onkeypress = resetTimer; function logout() { window.location.href = 'logout.php'; } function resetTimer() { clearTimeout(t); t = setTimeout(logout, 10000); // time is in milliseconds } } idleLogout(); 


除了关于活动检测的改进,以及从documentwindow的改变之外,这个脚本实际上是被调用的,而不是被闲置的。

这是一个粗略的jQuery实现tvanfosson的想法:

 $(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. } }) 

与上面的Iconic解决scheme类似(使用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))) 

你可以更优雅地用下划线和jQuery来做 –

 $('body').on("click mousemove keyup", _.debounce(function(){ // do preload here }, 1200000)) // 20 minutes debounce 

通过检测表单主体上的鼠标移动,并用最后一次移动时间更新一个全局variables,你可能可以一起窃取一些东西。 然后,您需要有一个间隔定时器运行,定期检查最后一次移动时间,如果自从检测到最后一次鼠标移动起已经足够长时间,就会执行一些操作。

我知道这是一个比较老的问题,但是我遇到了同样的问题,我find了一个很好的解决scheme。

我用: jquery.idle ,我只需要做:

 $(document).idle({ onIdle: function(){ alert('You did nothing for 5 seconds'); }, idle: 5000 }) 

看到JsFiddle演示 。

(仅供参考: 关于后端事件跟踪的信息请参阅浏览器加载 )

尝试这个工作完美..

 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库!

所有以前的答案都有一个永远在用的mousemove处理程序。 如果处理程序是jQuery,那么jQuery执行的额外处理可以加起来。 特别是如果用户使用游戏鼠标,每秒可能发生多达500个事件。

此解决scheme避免处理每个鼠标移动事件。 这导致一个小的时间错误,但你可以根据你的需要进行调整。

 function setIdleTimeout(millis, onIdle, onUnidle) { var timeout = 0; $(startTimer); function startTimer() { timeout = setTimeout(onExpires, millis); $(document).on("mousemove keypress", 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).off("mousemove keypress", onActivity); setTimeout(startTimer, 1000); } } 

http://jsfiddle.net/q8wLuLbw/

我的答案受到维杰的回答的启发,但这是一个更短,更一般的解决scheme,我想我会分享给任何人可能的帮助。

 (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和一个立即调用的函数expression式来处理空闲超时,以一种干净的,独立的方式。

我写了一个简单的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] }); 

该脚本将听取鼠标,键盘,触摸和其他自定义事件不活动(空闲),并触发全局“活动”和“不活动”事件。

希望这可以帮助 :)

如果您的目标是Chrome,则可以尝试使用requestIdleCallback

通过addEventListener正确设置重置时间和绑定的纯JavaScript

 (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); }); }()); 

我已经testing了这个代码工作文件:

 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); }); 

所有这些解决scheme的问题虽然是正确的,但是考虑到会话超时有价值的设置,使用PHP,.NET或ColdFusion开发人员的Application.cfc文件,这些问题是不切实际的。 上述解决scheme设置的时间需要与服务器端会话超时同步。 如果两者不同步,可能会遇到一些问题,只会让用户感到沮丧和困惑。 例如,服务器端会话超时可能设置为60分钟,但用户可能认为他/她是安全的,因为JavaScript空闲时间捕获已经增加了用户在单个页面上花费的总时间。 用户可能花了很长时间填写表格,然后提交。 在处理表单提交之前,会话超时可能会启动。 我倾向于给我的用户180分钟,然后使用JavaScript自动login用户。 本质上,使用上面的一些代码来创build一个简单的计时器,但没有捕获鼠标事件的一部分。 这样我的客户端和服务器端时间就完全同步了。 如果您在UI中向用户显示时间,则不会有任何混淆。 每次在CMS中访问新页面时,服务器端会话和JavaScript定时器都将被重置。 简单而优雅。 如果用户在单个页面上停留超过180分钟,我认为页面出现了问题。

这是我find的最好的解决scheme: 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) 

您可以使用下面提到的解决scheme

 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); } 

我使用这种方法,因为您不需要不断地重置事件触发的时间,而只是logging时间,这就产生了空闲起点。

  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); }, 

您可以使用列出的鼠标移动技巧检测网页上的不活动状态,但不会告诉您用户不在另一个窗口或选项卡中的另一个页面上,或者用户在Word或Photoshop中,或者WOW和只是不看你的网页在这个时候。 一般来说,我只是做预取,并依靠客户端的多任务处理。 如果你真的需要这个function,你可以在Windows中使用activex控件,但是最好是这样。

这是一个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; }]); 

请记住,这个空闲检查器将运行所有的路由,所以它应该在angular度的应用程序加载.run()初始化。 那么你可以在每个路由中使用idleChecker.secondsIdle

 myApp.run(['idleChecker',function(idleChecker){ idleChecker.init(); }]); 

只有几个想法,一个或两个探索。

是否有可能每10秒运行一个函数,并检查一个“计数器”variables? 如果可能的话,你可以有一个页面的鼠标hover,你不能? 如果是这样,请使用mouseover事件来重置“counter”variables。 如果您的function被调用,并且计数器高于您预先确定的范围,则请执行您的操作。

再次,只是一些想法…希望它有帮助。

那么你可以附加一个点击或鼠标移动事件的文档正文重置计时器。 有一个定时调用的函数,用于检查定时器是否超过指定的时间(如1000毫秒)并开始预加载。

对于具有相同问题的其他用户。 这是我刚刚编好的一个function。

它不会在用户进行每一次鼠标移动时运行,或者每当鼠标移动时清除计时器。

 <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> 

试过@freddoo解决scheme,但它没有工作1分钟的超时,所以我已经稍微改变了它,以loggingdate+时间,当用户最后一次点击页面,并在我的timerIncrement函数我计算当前时间和最后点击的时间,如果该值发生大于或等于超时值,那么我redirect:

 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(); }); }); 

JavaScript没有办法告诉CPU使用率。 这将打破在内部运行的沙箱。

除此之外,挂钩页面的onmouseover和onkeydown事件可能会起作用。

您也可以在onload事件中使用setTimeout来安排延迟后调用的函数。

 // Call aFunction after 1 second window.setTimeout(aFunction, 1000);