如何优雅地检测JavaScript中的空闲时间?

时间:2009-03-20 19:15:50

标签: javascript

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

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

38 个答案:

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

请记住根据您的需要使用windowdocument。在这里,您可以看到它们之间的差异: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();


除了有关活动检测的改进以及从documentwindow的更改之外,此脚本实际上调用了该函数,而不是让它闲置。

它没有直接捕获零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)

您可以使用underscorejquery -

更优雅地完成这项工作
$('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);
    }
}

http://jsfiddle.net/jndxq51o/

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

正确设置重置时间和绑定的纯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);
  });

}());

答案 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.js轻巧但有效且可自定义。实施后,仅使用一行:

sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
  • 会影响浏览器的所有标签,而不仅仅是一个。
  • 纯JavaScript 编写,没有依赖关系。完全是客户端。
  • (如果需要的话。)具有警告横幅倒计时时钟,这些时钟会被用户互动取消。
  • 仅包含 sessionExpiration.js ,并使用参数 [1] (在所有选项卡上)的空闲分钟数(在所有选项卡上)调用该函数,直到用户注销,< strong> [2] 空闲分钟数,直到显示警告和倒计时,以及 [3] 注销网址。
  • 将CSS放入样式表中。如果愿意,可以自定义它。 (或者,如果不需要,也可以跳过并删除横幅。)
  • 但是,如果您要做想要警告标语,则必须在页面上放置一个ID为 sessExpirDiv 的空div(建议将其放在页脚)
  • 现在,如果在指定的时间内所有选项卡都处于非活动状态,则用户将自动注销。

这是一个示例,说明如果不更改CSS的话。

demo_image

答案 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)

我在这里提出的实现与其他答案在以下方面有所不同:

  • 空闲事件(默认名称为'idleTimeSeconds')每10秒触发一次,因此您可以有多个订阅者订阅同一事件
  • 每个文档实例仅设置一个计时器
  • 与空闲事件相比,计时器触发频率更高(默认情况下,每1秒vs每10秒触发一次)-这将使默认间隔精度达到目标
  • 记录空闲时间开始的时间戳,并用于计算总空闲时间;其他解决方案建议为空闲时间计数器增加秒数,这会降低价格,因为计时器的实际延迟可能比配置的时间长,请参见"Reasons for delays longer than specified in WindowOrWorkerGlobalScope.setTimeout()"
  • 如其他解决方案所建议的,计时器永远不会取消/重置;取消和重置计时器更加昂贵

文件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);