วิธีการตรวจสอบเวลาว่างใน JavaScript อย่างหรูหรา?


478

เป็นไปได้หรือไม่ที่จะตรวจสอบเวลา " ไม่ได้ใช้งาน " ใน JavaScript?
กรณีการใช้งานหลักของฉันอาจเป็นไปเพื่อดึงเนื้อหาล่วงหน้าหรือโหลดล่วงหน้า

เวลาว่าง: ระยะเวลาที่ผู้ใช้ไม่มีกิจกรรมหรือไม่มีการใช้งาน CPU


7
คุณกำหนด IDLE TIME อย่างไร
Itay Moav -Malimovka

4
ตรวจสอบgithub.com/kidh0/jquery.idle
apneadiving

74
เกือบ 50% ของคำตอบที่นี่ใช้ jQuery สำหรับงานง่ายๆสำหรับจาวาสคริปต์ล้วนๆ มันเกินความคาดหมายโดยเฉพาะอย่างยิ่งเมื่อ OP ต้องการ Javascript ขอไอศกรีมสตรอเบอร์รี่ แต่ไปซื้อยุ้งฉางแบบบ้านแฝดแทน
TheCarver

4
StackOver thats สำหรับคุณ
robertmain

5
@TheCarver - การติดตั้งไลบรารี jQuery เพื่อสิ่งที่เรียบง่ายนั้นเป็นเรื่องไร้สาระแน่นอนและจะยืดเวลาในการเรนเดอร์และเพิ่มการใช้พลังงาน ผู้คนควรเลื่อนลงอีกเล็กน้อย มีวิธีแก้ปัญหาการคัดลอกวางใน Javascript วานิลลาเช่นกัน
Frank Conijn

คำตอบ:


437

นี่คือสคริปต์ง่ายๆที่ใช้ JQuery ที่จัดการกับ mousemove และ keypress events หากเวลาหมดอายุหน้าโหลดซ้ำ

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

16
คุณไม่มีเครื่องหมายอัฒภาคหลังจากเนื้อหา $ (document) .ready (function () นอกจากนี้ในการเรียกใช้ setInterval มันจะไม่ทำงานกับเครื่องหมายคำพูดรอบชื่อฟังก์ชันและคุณไม่จำเป็นต้องใส่เครื่องหมายวงเล็บหลังจากนั้น Just: setInterval (timerIncrement, 60000)
Jesse Roper

9
@Jesse: คำแนะนำของคุณดีมากนี่คือวิธีการที่รหัสควรจะเป็น แต่ฉันแค่อยากจะชี้ให้เห็นว่าแม้จะไม่มีการเปลี่ยนแปลงเหล่านี้รหัสก็ยังทำงานได้อย่างสมบูรณ์ อัฒภาคในตอนท้ายของคำสั่งการแสดงออกเป็นตัวเลือกและในความเป็นจริงคุณสามารถส่งสตริงไปยังsetIntervalซึ่งจะได้รับการประเมินเป็น JavaScript
เฟลิกซ์ลิ่ง

6
คุณสามารถใช้idleTime++;แทนidleTime = idleTime + 1;
Mike Causer

7
สิ่งนี้ไม่หนักในระบบของผู้ใช้หรือไม่? สมมติว่าผู้ใช้ที่มีเบราว์เซอร์ที่ค่อนข้างเก่าบนพีซีที่ไม่ทำงานหนักกำลังทำงานในแอปพลิเคชันจาวาสคริปต์สำหรับครึ่งวันและกำลังประมวลผลฟังก์ชั่นเหล่านี้ทุกครั้งที่ผู้ใช้เลื่อนเมาส์ ... ฉันสงสัยว่าจะชนะหรือไม่ ไม่ส่งผลกระทบต่อประสบการณ์ของผู้ใช้ ...
Sander

5
@PietBinnenbocht นอกจากนี้หากคุณเริ่มปรับสิ่งต่าง ๆ เช่นนี้คุณอาจเปลี่ยนฟังก์ชั่นทุกอย่างที่ใช้สตริงที่ต้องการ'mousemove keydown click'ใช้ค่าสถานะบิต ( Event.MOUSEMOVE | Event.KEYDOWN | Event.CLICK) เนื่องจากมันเป็น waaaaay เร็วกว่าการดำเนินการกับสตริง แต่คุณจริงๆต้องการที่จะทำเช่นนี้?
Killah

361

โดยไม่ใช้ 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ตามความต้องการของคุณ ที่นี่คุณสามารถเห็นความแตกต่างระหว่างพวกเขา: อะไรคือความแตกต่างระหว่างหน้าต่างหน้าจอและเอกสารใน Javascript?

โค้ดที่ได้รับการอัปเดตด้วย @ frank-conijn และการปรับปรุง @daxchen: window.onscrollจะไม่ทำงานหากการเลื่อนอยู่ในองค์ประกอบที่เลื่อนได้เนื่องจากเหตุการณ์การเลื่อนไม่เกิดฟอง window.addEventListener('scroll', resetTimer, true)อาร์กิวเมนต์ที่สามบอกให้ผู้ฟังจับเหตุการณ์ระหว่างเฟสการจับภาพแทนเฟสบับเบิล


58
ฉันชอบจาวาสคริปต์ธรรมดาที่ดีกว่ามาก
Manatax

4
การรีเซ็ตตัวจับเวลาอย่างแน่นอนเป็นวิธีที่ตรงกว่าและใช้งานง่ายและแม่นยำมากกว่าการหมดเวลาทำสิ่งนั้นเพียงเพื่อเก็บจำนวนเต็มของสิ่งอื่นเมื่อตัวจับเวลาสามารถเป็นตัวนับ (ความแม่นยำสูง)
Josh Sutterfield

2
@mpsbhat เพียงเพิ่ม console.log หรือแจ้งเตือนดูว่าทำงาน หรือลงทะเบียนกิจกรรมนี้:document.onload = function () { inactivityTime(); }; document.onmousedown = function () { inactivityTime(); }; document.onkeypress = function () { inactivityTime(); }; document.ontouchstart = function () { inactivityTime(); };
equiman

2
ใช่ ... ทำงานอยู่ jsfiddle.net/mpsbhat/6b6mja5t/1 ขอบคุณ @equiman
mpsbhat

6
มันจะดีกว่ามากที่จะมีธง notidle; ตั้งค่าสถานะนั้น = จริงในเหตุการณ์เท่านั้น จากนั้นในการทดสอบฟังก์ชั่น resetTimer หากธง notidle เป็นจริงหากมีการรีเซ็ตตัวจับเวลาหรือโทรออกจากระบบ สิ่งนี้จะลบความซับซ้อนของค่าใช้จ่ายในการรีเซ็ตตัวจับเวลาอย่างต่อเนื่อง
MartinWebb

75

การปรับปรุงคำตอบของ 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
แค่ต้องการชี้ให้เห็นว่าwindow.onscrollจะไม่เริ่มทำงานหากการเลื่อนอยู่ในองค์ประกอบที่เลื่อนได้เนื่องจากเหตุการณ์การเลื่อนไม่เกิดฟอง การใช้window.addEventListener('scroll', resetTimer, true)อาร์กิวเมนต์ตัวที่สามบอกให้ผู้ฟังจับเหตุการณ์ระหว่างcaptureเฟสแทนที่จะเป็นbubbleเฟส (IE> 8) ดูคำตอบนี้
DaxChen

@DaxChen - ไม่ได้document.onscrollมีปัญหาเดียวกันไม่ยิงถ้าเลื่อนอยู่ภายในเด็กเลื่อนได้หรือไม่
Frank Conijn

2
ใช่จุดที่ผมบอกว่าคือการใช้แทนaddEventListener onscroll
DaxChen

@ DaxChen - โอเคฉันสงสัยว่าคุณหมายถึงอย่างนั้นหรือไม่ แต่มันชัดเจนแล้ว ฉันแก้ไขคำตอบตามนั้น ขอบคุณสำหรับความคิดเห็น
Frank Conijn

ฉันจะอัปเดตคำตอบของฉันด้วยข้อมูลที่สำคัญนี้เพื่อหลีกเลี่ยงการคัดลอกและวางข้อผิดพลาดของฉัน ขอบคุณ @DaxChen และ Frank
equiman

33

ฉันได้สร้าง lib ขนาดเล็กที่ทำสิ่งนี้เมื่อปีที่แล้ว:

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

รายละเอียด:

ไลบรารี javascript ขนาดเล็กเพื่อรายงานกิจกรรมของผู้ใช้ในเบราว์เซอร์ (ไม่ได้ใช้งาน, ไม่ได้ดูหน้าเว็บ, ในแท็บอื่น ฯลฯ ) ที่เป็นอิสระจากห้องสมุด javascript อื่น ๆ เช่น jquery

ผู้ใช้ Visual Studio สามารถรับได้จาก NuGet โดย: PM> Install-Package Idle.js


32

นี่คือการดำเนินการ 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.
   }

})

9
วิธีการแก้ปัญหานี้ไม่ได้พิจารณาเหตุการณ์แป้นพิมพ์
Daniel Silveira

7
ไม่เคยผ่านsetIntervalสาย! เพียงแค่ให้ฟังก์ชั่นเป็นตัวแปร!
Eric

1
สิ่งนี้จะไม่ทำงานจริง ๆ เพราะส่งผ่านสตริงเพื่อsetInterval()ประเมินค่านิพจน์ในขอบเขตส่วนกลางและดังนั้นจึงไม่พบtimerIncrement()ฟังก์ชันที่อยู่ในฟังก์ชัน. ready setInterval()นี่คือเหตุผลที่ยังไม่เคยผ่านสายไปยังอีก เพียงแค่ผ่านการอ้างอิงฟังก์ชั่นจริงและคุณจะไม่มีปัญหานี้เพราะพวกเขาได้รับการประเมินในขอบเขตปัจจุบัน
jfriend00

ขอบคุณฉันไม่ได้ตระหนักถึงความจำเป็นในการไม่เคยผ่านสตริงเพื่อ setInterval อัปเดตคำตอบของฉัน
Peter J

24

คล้ายกับโซลูชันของ 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)))


16

คำตอบของฉันได้รับแรงบันดาลใจจากคำตอบของวีเจย์ แต่เป็นวิธีแก้ปัญหาที่สั้นกว่าและทั่วไปกว่าที่ฉันคิดว่าฉันจะแบ่งปันให้ใครก็ได้ที่อาจช่วยได้

(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 วานิลลาธรรมดาและฟังก์ชั่นการแสดงออกทันทีเพื่อจัดการกับการหมดเวลาว่างในลักษณะที่สะอาดและมีอยู่ในตัวเอง


document.onclick พิจารณาฟังก์ชั่นจาวาสคริปต์โดยใช้. trigger ('คลิก') ซึ่งฉันเขียนโดยอัตโนมัติ ดังนั้นมันไม่ใช่การโต้ตอบกับผู้ใช้จริง ๆ แต่มันจะรีเซ็ต idleCounter ในกรณีนี้
Carmela

@Carmela: ฉันไม่แน่ใจว่าทำไมฉันเพิ่งเห็นสิ่งนี้; ฉันจะต้องพลาดมันไป ขอบคุณฉันออกonclickที่ได้รับมอบหมายเพราะมันอาจจะไม่จำเป็นนอกเหนือไปonmousemoveแต่เห็นได้ชัดว่าการใด ๆ idleCounterของเหตุการณ์เหล่านี้ซึ่งจะมีการหารือโปรแกรมจะยังคงตั้งค่า ฉันไม่แน่ใจว่าทำไมคุณจึงจำลองการโต้ตอบของผู้ใช้แทนที่จะเรียกฟังก์ชั่น แต่ถ้านั่นคือสิ่งที่คุณต้องทำด้วยเหตุผลบางอย่างคำตอบนี้จะไม่เหมาะกับคุณ ฉันได้ดูคำถามนี้แล้ว
johnnyRose

15

ฉันรู้ว่ามันเป็นคำถามที่ค่อนข้างเก่า แต่ฉันมีปัญหาเดียวกันและฉันพบวิธีแก้ปัญหาที่ค่อนข้างดี

ฉันใช้: jquery.idle และฉันต้องทำเท่านั้น:

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

ดูการสาธิต JsFiddle

(เพียงเพื่อข้อมูล: ดูสิ่งนี้สำหรับการติดตามกิจกรรมแบ็กเอนด์นำไปสู่การโหลดเบราว์เซอร์ )


ฉันจะหยุดฟังก์ชั่นนี้ได้อย่างไรพวกเขาระบุเหตุการณ์ที่ไม่ได้ใช้งาน: หยุด แต่ฉันไม่รู้วิธีใช้สิ่งนี้โดยสุจริต ฉันต้องการที่ถ้าฉันย้ายไปหน้าถัดไป (ajax ตามดังนั้นส่วนของหน้า HTML ปรับปรุง) แล้วฟังก์ชั่นไม่ได้ใช้งานหยุด คุณรู้วิธีการทำสิ่งนี้หรือไม่?
Mubasher

ที่นี่มันบอกว่า: "ไม่ได้ใช้งาน: หยุด": จะหยุดและลบการติดตามผู้ใช้
DDan

ฉันอ่านแล้ว แต่ไม่สามารถหาวิธีใช้สิ่งนี้คุณช่วยฉันได้ไหม
Mubasher

หากคุณต้องการที่จะยิงเพียงครั้งเดียวคุณสามารถตั้งค่าตัวเลือกในการkeepTracking falseหากคุณต้องการรีเซ็ตคุณสามารถลองเริ่มใหม่ได้ นี่คือตัวอย่างที่แก้ไขแล้วซึ่งจะเริ่มทำงานเพียงครั้งเดียว: jsfiddle.net/f238hchm/12
DDan

ไม่ฉันไม่ได้ยิงอีกครั้งการติดตามต่อไปควรเป็นความจริง แต่ในการนำทางไปยังหน้าอื่นฉันต้องการหยุดการทำงานนี้ไว้
Mubasher

15

คำตอบก่อนหน้าทั้งหมดมีตัวจัดการ 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/


1
สิ่งนี้จะทำงานโดยอัตโนมัติหากวางไว้บนหน้าเว็บหรือจำเป็นต้องอยู่ในเสื้อคลุม $ (เอกสาร). ready () ขอบคุณ! นอกจากนี้ส่วนที่ดำเนินการเมื่อตัวจับเวลาหมดอายุอยู่ที่ไหน
ส้ม

1
คุณสามารถเรียกสิ่งนี้ได้ตลอดเวลาก่อนที่เอกสารจะพร้อม คุณผ่านฟังก์ชั่น 'โทรกลับ' ที่จะถูกเรียกเมื่อหมดเวลา
Sarsaparilla

1
$(startTimer)เทียบเท่ากับการ$(document).ready(startTimer), เพื่อให้แน่ใจว่า DOM ที่มีความพร้อมก่อนที่คุณจะขอ mousemove และปุ่มกดเหตุการณ์ที่เกิดขึ้น
Sarsaparilla

1
+1 นี่คือสิ่งที่ฉันทำ - ตัวจัดการ mousemove มีส่วนทำให้เกิดความเฉื่อยชาและอายุการใช้งานแบตเตอรี่ที่ลดลงดังนั้นการเปิดใช้งานเป็นระยะจึงเป็นความคิดที่ดีถ้าคุณสามารถจ่ายข้อผิดพลาดเล็กน้อยของเวลาได้ ฉันมักจะใช้การตรวจจับเวลาที่ไม่ได้ใช้งานสำหรับคำเตือนการหมดอายุเซสชันอัตโนมัติ (เช่น "คุณยังอยู่ที่นั่นหรือไม่") ดังนั้นฉันจึงมักจะมีเวลาหลายนาทีก่อนที่ผู้ใช้จะ "ไม่ได้ใช้งาน" ซึ่งในกรณีนี้
goat

1
มันจะดีกว่าที่จะใช้ "keydown" กว่า "keypress" เพราะปุ่มลูกศรไม่ถูกตรวจพบโดยเหตุการณ์ "keypress" ดังนั้นหากผู้ใช้นำทางหน้าโดยใช้ปุ่มลูกศรมันจะกลายเป็นไม่ได้ใช้งานต่อไป
aFerrer

13

คุณอาจจะแฮ็กบางอย่างด้วยกันโดยตรวจจับการเคลื่อนไหวของเมาส์บนเนื้อความของแบบฟอร์มและปรับปรุงตัวแปรทั่วโลกด้วยเวลาการเคลื่อนไหวล่าสุด จากนั้นคุณจะต้องมีตัวจับเวลาช่วงเวลาที่รันเป็นระยะเพื่อตรวจสอบเวลาการเคลื่อนไหวล่าสุดและทำบางสิ่งบางอย่างถ้ามันมีความยาวเพียงพอตั้งแต่ตรวจพบการเคลื่อนไหวของเมาส์ล่าสุด


สิ่งสำคัญที่ควรทราบว่าสคริปต์จะสามารถตรวจจับการเคลื่อนไหวบนเนื้อความของหน้าเท่านั้นไม่ใช่การป้อนข้อมูลของผู้ใช้ทั้งหมด ฉันไม่คิดว่าจะมีวิธีรับ CPU หรือข้อมูลกระบวนการจาก javascript
Dave Swersky

1
ฉันให้เสรีภาพในการใช้ความคิดของคุณใน jQuery
ปีเตอร์ J

9

ฉันเขียนคลาส ES6 ขนาดเล็กเพื่อตรวจจับกิจกรรมและมิฉะนั้นจะเริ่มการทำงานของเหตุการณ์ในช่วงเวลาที่ไม่ได้ใช้งาน มันครอบคลุมแป้นพิมพ์เมาส์และสัมผัสสามารถเปิดใช้งานและปิดการใช้งานและมี API ที่น้อยมาก:

const timer = new IdleTimer(() => alert('idle for 1 minute'), 1000 * 60 * 1);
timer.activate();

ไม่ได้ขึ้นอยู่กับ jQuery ถึงแม้ว่าคุณอาจจำเป็นต้องเรียกใช้ผ่าน Babel เพื่อรองรับเบราว์เซอร์รุ่นเก่า

https://gist.github.com/4547ef5718fd2d31e5cdcafef0208096

ฉันอาจปล่อยมันเป็นแพ็คเกจ npm เมื่อฉันได้รับคำติชม


8

หากคุณกำหนดเป้าหมายเป็นเบราว์เซอร์ที่รองรับ (Chrome หรือ Firefox ในเดือนธันวาคม 2018) คุณสามารถทดลองใช้requestIdleCallbackและรวมrequestIdleCallback shimสำหรับเบราว์เซอร์ที่ไม่รองรับ


และปล่อยให้เบราว์เซอร์อื่น ๆ อยู่คนเดียวเหรอ?
Frank Conijn

ชิมครอบคลุมทุกเบราว์เซอร์ และนี่คือคำตอบเดียว! คำตอบที่ช้าลงอื่น ๆ เกี่ยวกับเมาส์ ความสามารถในการโต้ตอบหรือซีพียูเป็นเพียงตัวอย่างเท่านั้น วิธีการตรวจสอบ CPU idle ด้วยเม้าส์

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

บวก 1 สำหรับการเป็นวานิลลา js
frostymarvelous

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 ไลบรารี่ในไฟล์ของคุณ!


4

ปัญหาเกี่ยวกับการแก้ปัญหาเหล่านี้แม้ว่าจะถูกต้อง แต่ก็ไม่สามารถทำได้เมื่อคำนึงถึงการหมดเวลาของเซสชั่นที่มีค่าโดยใช้ PHP, .NET หรือในไฟล์ Application.cfc สำหรับนักพัฒนา Coldfusion เวลาที่กำหนดโดยโซลูชันด้านบนจำเป็นต้องซิงค์กับการหมดเวลาเซสชันฝั่งเซิร์ฟเวอร์ หากทั้งสองไม่ซิงค์คุณสามารถพบกับปัญหาที่จะทำให้ผู้ใช้สับสนและสับสน ตัวอย่างเช่นการหมดเวลาเซสชันฝั่งเซิร์ฟเวอร์อาจถูกตั้งค่าเป็น 60 นาที แต่ผู้ใช้อาจเชื่อว่าตนปลอดภัยเนื่องจากการจับเวลาว่างของ JavaScript ทำให้จำนวนเวลาทั้งหมดที่ผู้ใช้สามารถใช้ในหน้าเดียวนั้นเพิ่มขึ้น ผู้ใช้อาจใช้เวลากรอกข้อมูลในแบบยาวแล้วไปส่ง การหมดเวลาของเซสชันอาจเริ่มก่อนที่การประมวลผลแบบฟอร์มจะถูกส่ง ฉันมักจะให้ผู้ใช้ของฉัน 180 นาที จากนั้นใช้ JavaScript เพื่อออกจากระบบผู้ใช้โดยอัตโนมัติ โดยพื้นฐานแล้วใช้รหัสด้านบนเพื่อสร้างตัวจับเวลาอย่างง่าย ๆ แต่ไม่มีส่วนเหตุการณ์การจับเมาส์ ด้วยวิธีนี้เวลาฝั่งไคลเอ็นต์และเซิร์ฟเวอร์ของฉันจะซิงค์อย่างสมบูรณ์แบบ ไม่มีความสับสนหากคุณแสดงเวลาให้กับผู้ใช้ใน UI ของคุณตามที่ลดลง ทุกครั้งที่มีการเข้าถึงหน้าใหม่ใน CMS ตัวจับเวลาเซสชัน & เซิร์ฟเวอร์ JavaScript จะถูกรีเซ็ต เรียบง่ายและสง่างาม หากผู้ใช้อยู่ในหน้าเดียวนานกว่า 180 นาทีฉันคิดว่ามีบางอย่างผิดปกติกับหน้าเว็บในตอนแรก ตามที่ช่วยลด ทุกครั้งที่มีการเข้าถึงหน้าใหม่ใน CMS ตัวจับเวลาเซสชัน & เซิร์ฟเวอร์ JavaScript จะถูกรีเซ็ต เรียบง่ายและสง่างาม หากผู้ใช้อยู่ในหน้าเดียวนานกว่า 180 นาทีฉันคิดว่ามีบางอย่างผิดปกติกับหน้าเว็บในตอนแรก ตามที่ช่วยลด ทุกครั้งที่มีการเข้าถึงหน้าใหม่ใน CMS ตัวจับเวลาเซสชัน & เซิร์ฟเวอร์ JavaScript จะถูกรีเซ็ต เรียบง่ายและสง่างาม หากผู้ใช้อยู่ในหน้าเดียวนานกว่า 180 นาทีฉันคิดว่ามีบางอย่างผิดปกติกับหน้าเว็บในตอนแรก


1
ใช่นั่นเป็นเหตุผลที่ฉันทำเช่นนี้หลังจากกำจัดเซสชันด้านเซิร์ฟเวอร์และโหลดทุกอย่างจากไฟล์ html เท่านั้น
Dan Parker

4

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

}());

4

(บางส่วนได้รับแรงบันดาลใจจากตรรกะหลักที่ดีของ Equiman ก่อนหน้าในหัวข้อนี้)

sessionExpiration.js


sessionExpiration.jsมีน้ำหนักเบา แต่มีประสิทธิภาพและปรับแต่งได้ เมื่อติดตั้งแล้วใช้งานในแถวเดียว:

sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
  • ส่งผลกระทบต่อแท็บทั้งหมดของเบราว์เซอร์ไม่ใช่เพียงเดียว
  • เขียนด้วยจาวาสคริปต์แท้โดยไม่มีการพึ่งพา ฝั่งไคลเอ็นต์อย่างเต็มที่
  • (หากต้องการเช่นนั้น)มีแบนเนอร์คำเตือนและนาฬิกานับถอยหลังซึ่งจะถูกยกเลิกโดยการโต้ตอบของผู้ใช้
  • เพียงรวมsessionExpiration.jsและเรียกใช้ฟังก์ชันพร้อมอาร์กิวเมนต์[1]จำนวนนาทีที่ไม่ได้ใช้งาน (ในแท็บทั้งหมด) จนกว่าผู้ใช้จะออกจากระบบ[2]จำนวนนาทีที่ไม่ได้ใช้งานจนกว่าจะมีคำเตือนและการนับถอยหลังปรากฏขึ้นและ[3] URL การออกจากระบบ
  • ใส่ CSS ลงในสไตล์ชีทของคุณ ปรับแต่งมันหากคุณต้องการ (หรือข้ามและลบแบนเนอร์หากคุณไม่ต้องการ)
  • ถ้าคุณทำต้องการแบนเนอร์เตือน แต่แล้วคุณจะต้องใส่ div ที่ว่างเปล่าที่มี ID sessExpirDivบนหน้าของคุณ(ข้อเสนอแนะที่มีการวางไว้ในส่วนท้าย)
  • ตอนนี้ผู้ใช้จะออกจากระบบโดยอัตโนมัติหากแท็บทั้งหมดไม่ได้ใช้งานในช่วงเวลาที่กำหนด
  • ทางเลือก: คุณอาจระบุอาร์กิวเมนต์ที่สี่ (URL เซิร์ฟเวอร์รีเฟรช) ให้กับฟังก์ชันเพื่อให้ตัวจับเวลาเซสชันฝั่งเซิร์ฟเวอร์นั้นได้รับการรีเฟรชเมื่อคุณโต้ตอบกับเพจ

นี่เป็นตัวอย่างของสิ่งที่ดูเหมือนว่าเป็นจริงถ้าคุณไม่เปลี่ยน CSS

demo_image


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

สคริปต์จะรับฟังเมาส์แป้นพิมพ์การสัมผัสและกิจกรรมอื่น ๆ ที่ไม่ได้ใช้งาน (ว่าง) และไฟกิจกรรม "กิจกรรม" และ "ไม่ทำงาน" ทั่วโลก

หวังว่าจะช่วย :)


มีความต้องการการหน่วงเวลาจริง ๆ ไม่เรียกเหตุการณ์ที่กำหนดเองจากตัวจัดการเหตุการณ์ที่กำหนดเองเพียงพอหรือไม่
Hibou57

2

เพียงไม่กี่ความคิดถนนหรือสองในการสำรวจ

เป็นไปได้ไหมที่จะใช้ฟังก์ชั่นทุกๆ 10 วินาทีและตรวจสอบตัวแปร "ตัวนับ" หรือไม่? หากเป็นไปได้คุณสามารถวางเมาส์โอเวอร์ไว้ที่หน้านั้นได้หรือไม่? ถ้าเป็นเช่นนั้นใช้เหตุการณ์การวางเมาส์เพื่อรีเซ็ตตัวแปร "ตัวนับ" หากฟังก์ชันของคุณถูกเรียกใช้และตัวนับอยู่เหนือช่วงที่คุณกำหนดไว้ล่วงหน้าให้ดำเนินการของคุณ

คิดอีกครั้ง ... หวังว่ามันจะช่วยได้


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

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)

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

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

1

คุณอาจตรวจพบการไม่ใช้งานบนหน้าเว็บของคุณโดยใช้เทคนิค mousemove ที่ระบุไว้ แต่จะไม่บอกคุณว่าผู้ใช้ไม่ได้อยู่ในหน้าอื่นในหน้าต่างหรือแท็บอื่นหรือผู้ใช้อยู่ใน Word หรือ Photoshop หรือ WOW และ ไม่ได้ดูหน้าของคุณในเวลานี้ โดยทั่วไปฉันจะทำ prefetch และพึ่งพาการทำงานแบบมัลติทาสกิ้งของลูกค้า หากคุณต้องการฟังก์ชั่นนี้จริงๆคุณทำบางอย่างด้วยตัวควบคุม activex ใน windows แต่มันก็น่าเกลียดที่สุด


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

1

เปิดตัวจริงเป็นความคิดที่ดี! รุ่นที่นี่สำหรับโครงการฟรี 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 ) 
}

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

0

คุณสามารถแนบเหตุการณ์ click หรือ mousemove เข้ากับเนื้อความเอกสารที่รีเซ็ตตัวจับเวลา มีฟังก์ชั่นที่คุณโทรตามช่วงเวลาที่กำหนดซึ่งจะตรวจสอบว่าตัวจับเวลาอยู่ในช่วงเวลาที่ระบุหรือไม่ (เช่น 1,000 มิลลิวินาที) และเริ่มต้นการโหลดล่วงหน้า


0

Javascript ไม่มีวิธีบอกการใช้งาน CPU การทำเช่นนี้จะทำให้จาวาสคริปต์จาวาสคริปต์ทำงานภายใน

นอกเหนือจากนั้นการเชื่อมโยงกิจกรรม onmouseover และ onkeydown ของหน้าอาจทำงานได้

นอกจากนี้คุณยังสามารถตั้งใช้ setTimeout ในเหตุการณ์ onload เพื่อกำหนดเวลาฟังก์ชั่นที่จะเรียกหลังจากล่าช้า

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

3
ฉันสงสัยว่าทำไม downvotes มากมายสำหรับคำตอบนี้ เท่าที่ฉันเห็นมันตอบคำถามที่ถามมาและถูกต้องตามความเป็นจริง ไม่เพียง แต่จะเผยแพร่ตัวอย่างโค้ดที่ซับซ้อนเท่านั้น
Ifedi Okonkwo

1
ตอนนี้เป็นไปได้ที่จะเรียกใช้ฟังก์ชันจาวาสคริปต์เมื่อ "มีเวลาว่างที่ท้ายเฟรมหรือเมื่อผู้ใช้ไม่ทำงาน" developers.google.com/web/updates/2015/08/…
สูงสุด

setTimeout 0 อาจจะถูกต้องมากขึ้นในการคำนวณด้วยความมั่นใจว่าบัฟเฟอร์เต็มโดยใช้เวลาระหว่าง FILO
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.