Jak elegancko wykryć czas bezczynności w JavaScript?

478

Czy w JavaScript można wykryć czas „ bezczynności ”?
Moim podstawowym zastosowaniem prawdopodobnie byłoby pobranie lub wstępne załadowanie treści.

Czas bezczynności: okres bezczynności użytkownika lub bez użycia procesora

Cherian
źródło
7
Jak definiujesz CZAS BEZCZYNNOŚCI?
Itay Moav-Malimovka
4
sprawdź github.com/kidh0/jquery.idle
apneadiving
74
Prawie 50% odpowiedzi tutaj użyło jQuery do tak prostego zadania dla czystego Javascript. To jest głupsze, zwłaszcza że OP chciał Javascript. Poproś o lody Truskawkowe, ale zamiast tego weź stodołę w zabudowie bliźniaczej.
TheCarver
4
to StackOverflow dla ciebie
robertmain
5
@TheCarver - Konieczność zainstalowania biblioteki jQuery dla czegoś tak prostego jest w rzeczywistości niedorzeczna i wydłuża czas renderowania oraz zwiększa zużycie energii. Ludzie powinni przewinąć nieco dalej. W waniliowym JavaScripcie istnieje również rozwiązanie prawie kopiuj-wklej.
Frank Conijn

Odpowiedzi:

437

Oto prosty skrypt używający JQuery, który obsługuje zdarzenia ruchów myszy i naciśnięć klawiszy. Po upływie czasu strona zostanie ponownie załadowana.

<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>   
Freddoo
źródło
16
Brakuje średnika po treści $ (document) .ready (function (). Ponadto w wywołaniu setInterval nie będzie działać z cudzysłowami wokół nazwy funkcji i nie będzie po niej nawiasów. Po prostu: setInterval (timerIncrement, 60000)
Jesse Roper
9
@Jesse: Twoje sugestie są dobre, taki powinien być kod. Chciałem tylko zaznaczyć, że nawet bez tych zmian kod jest w pełni funkcjonalny. Średniki na końcu instrukcji wyrażenia są opcjonalne i w rzeczywistości można przekazać ciąg znaków setInterval, który następnie jest oceniany jako JavaScript.
Felix Kling
6
Możesz po prostu użyć idleTime++;zamiastidleTime = idleTime + 1;
Mike Causer
7
Czy to nie jest ciężkie w systemie użytkownika? Załóżmy, że użytkownik z dość starą przeglądarką na niezbyt ciężkim komputerze pracuje przez pół dnia w aplikacji javascript i przetwarza te funkcje za każdym razem, gdy użytkownik porusza myszką ... Ciekawe, czy to wygrało wpływają na wrażenia użytkownika ...
Sander
5
@PietBinnenbocht Ponadto, jeśli zaczniesz optymalizować takie rzeczy, możesz również zmienić każdą funkcję, która pobiera ciągi, takie jak 'mousemove keydown click'użycie bit flagi ( Event.MOUSEMOVE | Event.KEYDOWN | Event.CLICK), ponieważ są one o wiele szybsze niż operacje na łańcuchach. Ale czy naprawdę chcesz to zrobić?
Killah
361

Bez użycia jQuery, tylko waniliowy 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
    }
};

I uruchom funkcję tam, gdzie jej potrzebujesz (na przykład: onPageLoad).

window.onload = function() {
  inactivityTime(); 
}

W razie potrzeby możesz dodać więcej zdarzeń DOM. Najczęściej używane są:

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

Lub zarejestruj pożądane zdarzenia za pomocą tablicy

window.addEventListener('load', resetTimer, true);
var events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'];
events.forEach(function(name) {
 document.addEventListener(name, resetTimer, true); 
});

Lista wydarzeń DOM : http://www.w3schools.com/jsref/dom_obj_event.asp

Pamiętaj o użyciu windowlub documentzgodnie z własnymi potrzebami. Tutaj możesz zobaczyć różnice między nimi: Jaka jest różnica między oknem, ekranem i dokumentem w JavaScript?

Kod zaktualizowany o @ frank-conijn i @daxchen ulepsz: window.onscrollnie będzie uruchamiany, jeśli przewijanie znajduje się w przewijalnym elemencie, ponieważ zdarzenia przewijania nie pękają. window.addEventListener('scroll', resetTimer, true), trzeci argument mówi słuchaczowi, aby złapał zdarzenie podczas fazy przechwytywania zamiast fazy bąbelkowej.

Equiman
źródło
58
Bardziej podoba mi się proste podejście do javascript.
Manatax,
4
definitywne zresetowanie timera jest bardziej bezpośrednie / intuicyjne i dokładne podejście niż przekroczenie limitu czasu, tylko po to, aby zachować liczbę całkowitą innej rzeczy, gdy sam timer może być licznikiem (o wysokiej precyzji).
Josh Sutterfield
2
@mpsbhat wystarczy dodać plik console.log lub alert i sprawdzić, czy działa. Lub zarejestruj te wydarzenia:document.onload = function () { inactivityTime(); }; document.onmousedown = function () { inactivityTime(); }; document.onkeypress = function () { inactivityTime(); }; document.ontouchstart = function () { inactivityTime(); };
equiman
2
Tak ... Pracuję. jsfiddle.net/mpsbhat/6b6mja5t/1 . Dzięki @equiman
mpsbhat
6
O wiele lepiej byłoby mieć flag var notidle; ustaw tę flagę = true tylko na zdarzenia. Następnie w teście funkcji resetTimer, czy flaga notidle jest prawdziwa, czy jest resetowany timer ich, czy wyloguj się. To usunie narzut związany z ciągłym resetowaniem timera.
MartinWebb
75

Poprawa odpowiedzi Equimana:

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

.
Oprócz ulepszeń w zakresie wykrywania aktywności i zmiany z documentna window, ten skrypt faktycznie wywołuje funkcję, a nie pozwala jej pozostać bezczynnym.

Nie wychwytuje bezpośrednio zerowego użycia procesora, ale jest to niemożliwe, ponieważ wykonanie funkcji powoduje użycie procesora. Bezczynność użytkownika ostatecznie prowadzi do zerowego użycia procesora, więc pośrednio łapie zerowe użycie procesora.

Frank Conijn
źródło
3
Chciałem tylko zaznaczyć, że window.onscrollnie uruchomi się, jeśli przewijanie znajduje się w przewijalnym elemencie, ponieważ zdarzenia przewijania nie pękają. Używając window.addEventListener('scroll', resetTimer, true), trzeci argument mówi słuchaczowi, aby złapał zdarzenie podczas capturefazy zamiast bubblefazy (IE> 8), zobacz tę odpowiedź
DaxChen,
@DaxChen - Nie document.onscrollma tego samego problemu, nie uruchamia się, jeśli przewijanie znajduje się w przewijalnym dziecku?
Frank Conijn
2
Tak, chodziło mi o użycie addEventListenerzamiast onscroll.
DaxChen
@DaxChen - OK, zastanawiałem się, czy miałeś na myśli to obejście, ale teraz jest jasne. Odpowiednio zredagowałem odpowiedź. Dziękuję za komentarz.
Frank Conijn
Zaktualizuję moją odpowiedź tymi ważnymi informacjami, aby uniknąć innej kopii i wkleić mój błąd. Dzięki @DaxChen i Frank
equiman
33

Stworzyłem małą bibliotekę, która robi to rok temu:

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

Opis:

Mała biblioteka javascript do zgłaszania aktywności użytkownika w przeglądarce (poza domem, bezczynnie, nie patrząc na stronę, na innej karcie itp.). który jest niezależny od innych bibliotek javascript, takich jak jquery.

Użytkownicy programu Visual Studio mogą uzyskać go z NuGet poprzez: PM> Install-Package Idle.js

Shawn Mclean
źródło
32

Oto przybliżona implementacja pomysłu tvanfosson przez 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.
   }

})
Peter J.
źródło
9
To rozwiązanie nie uwzględnia zdarzeń klawiatury.
Daniel Silveira
7
Nigdy nie podawaj setIntervalsznurka! Po prostu podaj funkcję jako zmienną!
Eric,
1
To tak naprawdę nie zadziała, ponieważ przekazanie ciągu do setInterval()oceny wyrażenia w zasięgu globalnym, a zatem nie znajdzie timerIncrement()funkcji, która znajduje się w funkcji obsługi .ready. Jest to kolejny powód, dla którego NIGDY nie należy przekazywać ciągów znaków setInterval(). Wystarczy przekazać rzeczywiste odwołanie do funkcji i nie będzie tego problemu, ponieważ są one oceniane w bieżącym zakresie.
jfriend00
Dzięki, nie byłem świadomy potrzeby, aby NIGDY nie przekazywać ciągów do setInterval. Zaktualizowałem moją odpowiedź.
Peter J
24

Podobne do powyższego rozwiązania Iconic (z niestandardowym zdarzeniem 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)))
Tracker 1
źródło
20

Możesz to zrobić bardziej elegancko dzięki podkreśleniu i jquery -

$('body').on("click mousemove keyup", _.debounce(function(){
    // do preload here
}, 1200000)) // 20 minutes debounce
Kruttik
źródło
16

Moja odpowiedź została zainspirowana odpowiedzią vijay , ale jest krótszym, bardziej ogólnym rozwiązaniem, które, jak sądzę, podzieliłbym się z każdym, komu może pomóc.

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

W obecnej postaci ten kod zostanie wykonany natychmiast i ponownie załaduje bieżącą stronę po 3 minutach braku ruchu myszy lub naciskania klawiszy.

Wykorzystuje zwykły waniliowy JavaScript i natychmiast wywoływane wyrażenie funkcyjne, aby obsłużyć limity czasu bezczynności w czysty i samodzielny sposób.

Johnny Rose
źródło
document.onclick uważa funkcje javascript za pomocą .trigger („kliknięcie”), który napisałem jako automatyczny. Więc to nie jest interakcja użytkownika, ale w tym przypadku zresetuje licznik idleCounter
Carmela
@Carmela: Nie jestem pewien, dlaczego to widzę; Musiałem to przeoczyć. Dzięki, usunąłem onclickprzypisanie, ponieważ prawdopodobnie nie jest to konieczne onmousemove, ale oczywiście każde z tych zdarzeń, które są uruchamiane programowo, będzie nadal resetowane idleCounter. Nie jestem pewien, dlaczego symulowałbyś interakcję użytkownika zamiast po prostu wywoływać funkcję, ale jeśli jest to coś, co musisz zrobić z jakiegoś powodu, ta odpowiedź oczywiście nie zadziała dla ciebie, podobnie jak większość innych odpowiedzi spojrzałem na to pytanie.
johnnyRose
15

Znam to stosunkowo stare pytanie, ale miałem ten sam problem i znalazłem całkiem dobre rozwiązanie.

Użyłem: jquery.idle i potrzebowałem tylko:

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

Zobacz demo JsFiddle .

(Tylko dla informacji: zobacz to w celu śledzenia zdarzeń zaplecza prowadzi do ładowania przeglądarki )

DDan
źródło
Jak mogę zatrzymać tę funkcję? Podali zdarzenie bezczynności: stop, ale szczerze mówiąc nie wiem, jak z tego korzystać. Chcę, aby po przejściu na następną stronę (opartą na ajax, więc zaktualizowano tylko fragment strony HTML), funkcja bezczynności zatrzyma się. Czy wiesz, jak to osiągnąć?
Mubasher
Tutaj napisano: „idle: stop”: zatrzyma i usunie śledzenie użytkowników
DDan
Już przeczytałem, ale nie mogłem wymyślić, jak tego użyć. Czy możesz mi pomóc?
Mubasher
Jeśli chcesz, aby strzelał tylko raz, możesz ustawić keepTrackingopcję na false. Jeśli chcesz zresetować, możesz spróbować ponownie zainicjować. Oto zmodyfikowany przykład, który uruchomiłby się tylko raz: jsfiddle.net/f238hchm/12
DDan
Nie, nie strzelam raz, KeepTracking powinien być prawdziwy, ale w nawigacji do innej strony chcę to zatrzymać
Mubasher
15

Wszystkie poprzednie odpowiedzi mają zawsze aktywny moduł obsługi myszy. Jeśli procedura obsługi to jQuery, dodatkowe przetwarzanie wykonywane przez jQuery może się sumować. Zwłaszcza jeśli użytkownik korzysta z myszy do gier, może wystąpić nawet 500 zdarzeń na sekundę.

To rozwiązanie pozwala uniknąć obsługi każdego zdarzenia myszy. Powoduje to niewielki błąd synchronizacji, który można dostosować do własnych potrzeb.

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/

Sarsaparilla
źródło
1
Czy to zadziała automatycznie, jeśli zostanie umieszczone na stronie, czy też musi znajdować się w opakowaniu $ (document) .ready ()? Dziękuję Ci! Gdzie jest także część, która wykonuje akcję po upływie czasu?
Pomarańcze
1
Możesz to zrobić w dowolnym momencie, nawet zanim dokument będzie gotowy. Przekazujesz funkcję „callback”, która zostanie wywołana po upływie czasu.
Sarsaparilla,
1
Jest $(startTimer)to równoważne z $(document).ready(startTimer), gwarantuje, że DOM jest gotowy, zanim zaczepisz zdarzenia myszy i naciśnięcia klawisza.
Sarsaparilla,
1
+1 To właśnie robię - programy obsługi myszy powodują spowolnienie i skracają żywotność baterii, więc tylko okresowe włączanie to świetny pomysł, jeśli możesz sobie pozwolić na drobny błąd synchronizacji. Zazwyczaj używam wykrywania czasu bezczynności do automatycznego ostrzegania o wygaśnięciu sesji (np. „Czy nadal tam jesteś?”), Więc zwykle mam wiele minut, zanim użytkownik przejdzie w stan „bezczynności”, w którym to przypadku mały błąd taktowania jest całkowicie nieistotny.
koza
1
Lepiej jest użyć opcji „keydown” niż „keypress”, ponieważ klawisze strzałek nie są wykrywane przez zdarzenie „keypress”. Jeśli użytkownik porusza się po stronie za pomocą klawiszy strzałek, i tak stanie się bezczynny.
aFerrer
13

Prawdopodobnie możesz zhakować coś razem, wykrywając ruch myszy na treści formularza i aktualizując zmienną globalną o czasie ostatniego ruchu. Potrzebny byłby wtedy licznik interwałowy, który okresowo sprawdza czas ostatniego ruchu i robi coś, jeśli minęło wystarczająco dużo czasu od wykrycia ostatniego ruchu myszy.

tvanfosson
źródło
Ważne jest, aby pamiętać, że skrypt będzie w stanie wykryć ruch w treści strony, a nie wszystkie dane wprowadzone przez użytkownika. Nie sądzę, że istnieje sposób na uzyskanie informacji o procesorze lub procesie z javascript.
Dave Swersky
1
Pozwoliłem sobie na wdrożenie twojego pomysłu w jQuery.
Peter J
9

Napisałem małą klasę ES6, aby wykrywać aktywność i w inny sposób uruchamiać zdarzenia w czasie bezczynności. Obejmuje klawiaturę, mysz i dotyk , może być aktywowany i dezaktywowany oraz ma bardzo uproszczony interfejs API:

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

To nie nie zależą od jQuery, choć być może trzeba go uruchomić poprzez Babel do wspierania starszych przeglądarek.

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

Mogę wydać go jako pakiet npm, gdy otrzymam jakieś uwagi.

Capi Etheriel
źródło
8

Jeśli kierujesz reklamy na obsługiwaną przeglądarkę (Chrome lub Firefox od grudnia 2018 r.), Możesz eksperymentować z requestIdleCallback i dołączyć podkładkę requestIdleCallback dla nieobsługiwanych przeglądarek.

rajsite
źródło
I zostawić inne przeglądarki w spokoju?
Frank Conijn,
Podkładka obejmuje wszystkie przeglądarki. To była jedyna odpowiedź! Inne spowolnione odpowiedzi dotyczą myszy. Interaktywność lub procesor podano tylko jako przykład. Jak wykryć bezczynność procesora za pomocą myszy?
6

Wypróbuj ten kod, działa idealnie.

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";
    }
}
Vijay
źródło
plus 1 za bycie waniliowym 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> 

Myślę, że ten kod jquery jest idealny, choć skopiowany i zmodyfikowany z powyższych odpowiedzi !! nie zapomnij dołączyć biblioteki jquery do swojego pliku!

SPidey
źródło
4

Problem ze wszystkimi tymi rozwiązaniami, choć poprawnymi, są niepraktyczne, biorąc pod uwagę cenny zestaw limitów czasu sesji, używając PHP, .NET lub w pliku Application.cfc dla programistów Coldfusion. Czas ustawiony w powyższym rozwiązaniu musi zostać zsynchronizowany z limitem czasu sesji po stronie serwera. Jeśli te dwie nie zostaną zsynchronizowane, możesz napotkać problemy, które po prostu sfrustrują i wprowadzą użytkowników w błąd. Na przykład limit czasu sesji po stronie serwera może być ustawiony na 60 minut, ale użytkownik może uważać, że jest bezpieczny, ponieważ przechwytywanie czasu bezczynności JavaScript zwiększyło całkowity czas, jaki użytkownik może spędzić na jednej stronie. Użytkownik mógł spędzić czas na wypełnianiu długiego formularza, a następnie przechodzi do jego przesłania. Upłynął limit czasu sesji przed przetworzeniem formularza. Daję moim użytkownikom 180 minut, a następnie użyj JavaScript, aby automatycznie wylogować użytkownika. Zasadniczo, używając części powyższego kodu, aby utworzyć prosty licznik czasu, ale bez części zdarzenia myszy przechwytującej. W ten sposób czas mojej strony klienta i serwera doskonale się synchronizuje. Nie ma zamieszania, jeśli pokażesz czas użytkownikowi w interfejsie użytkownika, ponieważ zmniejsza się. Za każdym razem, gdy otwierana jest nowa strona w CMS, sesja po stronie serwera i zegar JavaScript są resetowane. Prosty i elegancki. Jeśli użytkownik pozostaje na jednej stronie przez ponad 180 minut, to na pierwszym miejscu wydaje mi się, że coś jest nie tak. jak to zmniejsza. Za każdym razem, gdy otwierana jest nowa strona w CMS, sesja po stronie serwera i zegar JavaScript są resetowane. Prosty i elegancki. Jeśli użytkownik pozostaje na jednej stronie przez ponad 180 minut, to na pierwszym miejscu wydaje mi się, że coś jest nie tak. jak to zmniejsza. Za każdym razem, gdy otwierana jest nowa strona w CMS, sesja po stronie serwera i zegar JavaScript są resetowane. Prosty i elegancki. Jeśli użytkownik pozostaje na jednej stronie przez ponad 180 minut, to na pierwszym miejscu wydaje mi się, że coś jest nie tak.

Charles Robertson
źródło
1
Tak, dlatego robię to dopiero po pozbyciu się sesji po stronie serwera i załadowaniu wszystkiego z plików HTML.
Dan Parker
4

Czysty JavaScript z odpowiednio ustawionym czasem resetowania i powiązaniami za pośrednictwem 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);
  });

}());
JackTheKnife
źródło
4

(Częściowo zainspirowany dobrą podstawową logiką Equimana wcześniej w tym wątku.)

sessionExpiration.js


sessionExpiration.js jest lekki, ale skuteczny i konfigurowalny. Po wdrożeniu użyj w jednym rzędzie:

sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
  • Wpływa na wszystkie karty przeglądarki, nie tylko jedną.
  • Napisane w czystym JavaScript , bez żadnych zależności. W pełni po stronie klienta.
  • (W razie potrzeby.) Ma baner ostrzegawczy i zegar odliczający , który jest anulowany przez interakcję użytkownika.
  • Wystarczy dołączyć sessionExpiration.js i wywołać funkcję z argumentami [1] liczba bezczynnych minut (na wszystkich kartach) do wylogowania użytkownika, [2] liczba bezczynnych minut do wyświetlenia ostrzeżenia i odliczania oraz [3] wyloguj się
  • Umieść CSS w swoim arkuszu stylów. Dostosuj go, jeśli chcesz. (Lub pomiń i usuń banner, jeśli go nie chcesz).
  • Jeśli zrobić jednak chcą baner ostrzegawczy, a następnie należy umieścić pusty div z ID sessExpirDiv na swojej stronie (sugestia jest umieszczenie go w stopce) .
  • Teraz użytkownik zostanie automatycznie wylogowany, jeśli wszystkie zakładki były nieaktywne przez określony czas.
  • Opcjonalne: Możesz podać czwarty argument (URL serverRefresh) dla funkcji, aby zegar sesji po stronie serwera był odświeżany również podczas interakcji ze stroną.

To jest przykład tego, jak to wygląda w akcji, jeśli nie zmienisz CSS.

demo_image

Fom
źródło
3

Napisałem prostą wtyczkę jQuery, która zrobi to, czego szukasz.

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

Skrypt będzie nasłuchiwał nieaktywności myszy, klawiatury, dotyku i innych niestandardowych zdarzeń (bezczynności) oraz wyzwalał globalne zdarzenia „aktywności” i „braku aktywności”.

Mam nadzieję że to pomoże :)

Alexandros Filos Kaparelos
źródło
Czy naprawdę istnieje potrzeba opóźnienia, czy wyzwalanie niestandardowego zdarzenia z niestandardowej procedury obsługi zdarzeń nie jest wystarczające?
Hibou57
2

Tylko kilka myśli, aleja lub dwie do odkrycia.

Czy możliwe jest uruchamianie funkcji co 10 sekund i sprawdzanie zmiennej „licznik”? Jeśli to możliwe, możesz najechać kursorem myszy na stronę, prawda? Jeśli tak, użyj zdarzenia mouseover, aby zresetować zmienną „counter”. Jeśli twoja funkcja jest wywoływana, a licznik znajduje się powyżej zakresu, który wcześniej ustaliłeś, zrób to.

Ponownie, tylko kilka myśli ... Mam nadzieję, że to pomaga.

Mark Rullo
źródło
2

Przetestowałem ten plik roboczy kodu:

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);
    });
Vishal Jaura
źródło
2

Oto najlepsze rozwiązanie, jakie znalazłem: http://css-tricks.com/snippets/jquery/fire-event-when-user-is-idle/

Oto 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)
Casey
źródło
2

Możesz użyć niżej wymienionego rozwiązania

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);
}
Abhishek
źródło
2

Korzystam z tego podejścia, ponieważ nie trzeba ciągle resetować czasu, w którym wydarzenie się uruchamia, zamiast tego rejestrujemy tylko czas, co generuje bezczynny punkt początkowy.

           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);    
        },
MartinWebb
źródło
1

Prawdopodobnie możesz wykryć brak aktywności na swojej stronie internetowej, korzystając z podanych sztuczek myszy, ale to nie powie, że użytkownika nie ma na innej stronie w innym oknie lub karcie, lub że jest on w programie Word lub Photoshop lub WOW i po prostu nie patrzy teraz na twoją stronę. Generalnie po prostu wykonuję pobieranie wstępne i polegam na wielozadaniowości klienta. Jeśli naprawdę potrzebujesz tej funkcji, robisz coś z kontrolką ActiveX w systemie Windows, ale w najlepszym razie jest brzydka.

Walden Leverich
źródło
1

Oto usługa AngularJS do realizacji w 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;
}]);

Pamiętaj, że ten kontroler bezczynności będzie działał na wszystkich trasach, dlatego należy go zainicjować .run()po załadowaniu aplikacji kątowej. Następnie możesz korzystać z idleChecker.secondsIdlekażdej trasy.

myApp.run(['idleChecker',function(idleChecker){
    idleChecker.init();
}]);
steampowered
źródło
1

Zapowiedź naprawdę świetny pomysł! Oto wersja dla darmowych projektów 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 ) 
}
Gleb Dolzikov
źródło
1

Tak proste, jak to tylko możliwe, wykrywaj tylko ruchy myszy:

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');
}
lucss
źródło
0

Cóż, możesz dołączyć zdarzenie kliknięcia lub przesunięcia myszy do treści dokumentu, która resetuje stoper. Mieć funkcję, którą wywołujesz w odstępach czasowych, która sprawdza, czy czas przekroczył określony czas (np. 1000 milis) i rozpoczyna wstępne ładowanie.

Eric Wendelin
źródło
0

JavaScript nie ma sposobu na określenie wykorzystania procesora. Spowodowałoby to uszkodzenie javascript w piaskownicy.

Poza tym zaczepienie zdarzeń onmouseover i onkeydown strony prawdopodobnie działałoby.

Można również ustawić użycie setTimeout w zdarzeniu onload, aby zaplanować funkcję, która będzie wywoływana z opóźnieniem.

// Call aFunction after 1 second
window.setTimeout(aFunction, 1000);
Władca
źródło
3
Zastanawiam się, dlaczego tak wiele głosów negatywnych na temat tej odpowiedzi. O ile widzę, odpowiedziała na zadane pytanie i jest zgodna ze stanem faktycznym. Tylko nie udało mi się wprowadzić skomplikowanych przykładów kodu.
Ifedi Okonkwo
1
Teraz można wywołać funkcję javascript, gdy „na końcu ramki jest wolny czas lub gdy użytkownik jest nieaktywny”. Developers.google.com/web/updates/2015/08/…
Maks.
setTimeout 0 jest prawdopodobnie bardziej poprawny, aby obliczyć w średnim stopniu, jak pełny jest bufor, poświęcając czas między FILO