Wie erkennt man die Leerlaufzeit in JavaScript elegant?

478

Ist es möglich, " Leerlauf " -Zeiten in JavaScript zu erkennen?
Mein primärer Anwendungsfall wäre wahrscheinlich das Vorabrufen oder Vorladen von Inhalten.

Leerlaufzeit: Zeitraum der Inaktivität des Benutzers oder ohne CPU-Auslastung

Cherian
quelle
7
Wie definieren Sie Leerlaufzeit?
Itay Moav-Malimovka
4
Überprüfen Sie github.com/kidh0/jquery.idle
apneadiving
74
Fast 50% der Antworten hier haben jQuery für eine so einfache Aufgabe für reines Javascript verwendet. Es ist mehr als dumm, zumal das OP Javascript wollte. Fragen Sie nach Erdbeereis, aber holen Sie sich stattdessen eine Doppelscheune.
TheCarver
4
das ist StackOverflow für Sie
robertmain
5
@TheCarver - Die Installation einer jQuery-Bibliothek für etwas so Einfaches ist in der Tat lächerlich, verlängert die Renderzeit und erhöht den Energieverbrauch. Die Leute sollten etwas weiter nach unten scrollen. Auch in Vanille-Javascript gibt es eine fast Copy-Paste-Lösung.
Frank Conijn

Antworten:

437

Hier ist ein einfaches Skript mit JQuery, das Mausbewegungs- und Tastendruckereignisse verarbeitet. Wenn die Zeit abgelaufen ist, wird die Seite neu geladen.

<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
quelle
16
Nach dem Text $ (document) .ready (function () fehlt ein Semikolon. Außerdem funktioniert es beim Aufruf von setInterval nicht mit Anführungszeichen um den Funktionsnamen und Sie benötigen keine Klammern danach. Nur: setInterval (timerIncrement, 60000)
Jesse Roper
9
@ Jesse: Ihre Vorschläge sind alle gut, so sollte der Code sein. Aber ich wollte nur darauf hinweisen, dass der Code auch ohne diese Änderungen voll funktionsfähig ist. Semikolons am Ende einer Ausdrucksanweisung sind optional, und Sie können tatsächlich eine Zeichenfolge an übergeben setInterval, die dann als JavaScript ausgewertet wird.
Felix Kling
6
Sie könnten einfach idleTime++;anstelle vonidleTime = idleTime + 1;
Mike Causer
7
Ist das nicht schwer für das System eines Benutzers? Angenommen, ein Benutzer mit einem ziemlich alten Browser auf einem nicht so schweren PC arbeitet einen halben Tag lang in einer Javascript-Anwendung und verarbeitet diese Funktionen jedes Mal, wenn der Benutzer seine Maus bewegt ... Ich frage mich, ob dies gewonnen hat. t beeinflussen die Benutzererfahrung ...
Sander
5
@PietBinnenbocht Wenn Sie mit der Optimierung solcher Dinge beginnen, können Sie auch jede Funktion ändern, für die Zeichenfolgen 'mousemove keydown click'Bit-Flags ( Event.MOUSEMOVE | Event.KEYDOWN | Event.CLICK) verwenden, da diese schneller als Zeichenfolgenoperationen sind. Aber willst du das wirklich tun?
Killah
361

Ohne Verwendung von jQuery nur Vanille-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
    }
};

Und starten Sie die Funktion dort, wo Sie sie benötigen (zum Beispiel: onPageLoad).

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

Sie können bei Bedarf weitere DOM-Ereignisse hinzufügen. Am häufigsten verwendet werden:

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

Oder registrieren Sie gewünschte Ereignisse mithilfe eines Arrays

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

Liste der DOM-Ereignisse : http://www.w3schools.com/jsref/dom_obj_event.asp

Denken Sie daran, verwenden windowoder documentnach Ihren Bedürfnissen. Hier sehen Sie die Unterschiede zwischen ihnen: Was ist der Unterschied zwischen Fenster, Bildschirm und Dokument in Javascript?

Mit @ frank-conijn und @daxchen aktualisierter Code verbessert: window.onscrollWird nicht ausgelöst, wenn sich das Scrollen in einem scrollbaren Element befindet, da Scroll-Ereignisse nicht sprudeln. window.addEventListener('scroll', resetTimer, true)Das dritte Argument weist den Hörer an, das Ereignis während der Erfassungsphase anstelle der Blasenphase abzufangen.

Equiman
quelle
58
Ich mag den einfachen Javascript-Ansatz viel besser.
Manatax
4
Das Zurücksetzen eines Timers ist definitiv ein direkterer / intuitiverer und genauerer Ansatz als das Ausführen einer Zeitüberschreitung, nur um eine ganzzahlige Zählung einer anderen Sache beizubehalten, wenn der Timer selbst der (hochpräzise) Zähler sein kann.
Josh Sutterfield
2
@mpsbhat fügen Sie einfach ein console.log oder eine Warnung hinzu und prüfen Sie, ob es funktioniert. Oder registrieren Sie diese Ereignisse:document.onload = function () { inactivityTime(); }; document.onmousedown = function () { inactivityTime(); }; document.onkeypress = function () { inactivityTime(); }; document.ontouchstart = function () { inactivityTime(); };
Equiman
2
Ja ... arbeiten. jsfiddle.net/mpsbhat/6b6mja5t/1 . Danke @equiman
mpsbhat
6
Wäre viel besser, eine Flagge var notidle zu haben; Setzen Sie dieses Flag = true nur für die Ereignisse. Testen Sie dann in der Funktion resetTimer, ob das Notidle-Flag wahr ist, ob der Timer zurückgesetzt wird, oder rufen Sie die Abmeldung auf. Dadurch entfällt der Komplexitätsaufwand für das ständige Zurücksetzen des Timers.
MartinWebb
75

Verbesserung der Antwort von 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();

.
Abgesehen von den Verbesserungen bei der Aktivitätserkennung und dem Wechsel von documentzu windowruft dieses Skript die Funktion tatsächlich auf, anstatt sie im Leerlauf stehen zu lassen.

Die CPU-Auslastung wird nicht direkt erfasst, dies ist jedoch nicht möglich, da die Ausführung einer Funktion die CPU-Auslastung verursacht. Und Inaktivität des Benutzers führt schließlich zu einer CPU-Auslastung von Null, sodass indirekt keine CPU-Auslastung erreicht wird.

Frank Conijn
quelle
3
Ich wollte nur darauf hinweisen, dass dies window.onscrollnicht ausgelöst wird, wenn sich das Scrollen in einem scrollbaren Element befindet, da Scroll-Ereignisse nicht sprudeln. Mit window.addEventListener('scroll', resetTimer, true)dem dritten Argument wird der Listener capturebubble
angewiesen
@DaxChen - Hat nicht document.onscrolldas gleiche Problem, wird nicht ausgelöst , wenn sich das Scrollen in einem scrollbaren Kind befindet?
Frank Conijn
2
Ja, der Punkt, den ich sagte, ist zu verwenden addEventListenerstatt onscroll.
DaxChen
@DaxChen - OK, ich habe mich gefragt, ob du das gemeint hast, um es zu umgehen, aber jetzt ist es klar. Ich habe die Antwort entsprechend bearbeitet. Danke für den Kommentar.
Frank Conijn
Ich werde meine Antwort mit diesen wichtigen Informationen aktualisieren, um andere Fehler zu vermeiden und einzufügen. Danke @DaxChen und Frank
Equiman
33

Ich habe vor einem Jahr eine kleine Bibliothek erstellt, die dies tut:

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

Beschreibung:

Winzige Javascript-Bibliothek, um die Aktivität des Benutzers im Browser zu melden (weg, inaktiv, keine Webseite betrachtend, in einem anderen Tab usw.). Das ist unabhängig von anderen Javascript-Bibliotheken wie jquery.

Visual Studio-Benutzer können es von NuGet erhalten, indem sie: PM> Install-Package Idle.js

Shawn Mclean
quelle
32

Hier ist eine grobe jQuery-Implementierung der Idee von 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.
   }

})
Peter J.
quelle
9
Diese Lösung berücksichtigt keine Tastaturereignisse.
Daniel Silveira
7
Übergeben Sie niemals setIntervaleine Schnur! Geben Sie einfach eine Funktion als Variable an!
Eric
1
Dies funktioniert nicht wirklich, da eine Zeichenfolge übergeben wird, setInterval()um den Ausdruck im globalen Bereich auszuwerten, und daher die timerIncrement()Funktion in der .ready-Handlerfunktion nicht gefunden wird. Dies ist ein weiterer Grund, NIEMALS Zeichenfolgen zu übergeben setInterval(). Übergeben Sie einfach eine tatsächliche Funktionsreferenz, und Sie werden dieses Problem nicht haben, da sie im aktuellen Bereich ausgewertet werden.
jfriend00
Vielen Dank, mir war nicht bewusst, dass NIEMALS Zeichenfolgen an setInterval übergeben werden müssen. Meine Antwort wurde aktualisiert.
Peter J
24

Ähnlich wie bei der obigen Lösung von Iconic (mit benutzerdefiniertem jQuery-Ereignis) ...

// 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)))
Tracker1
quelle
20

Sie können es eleganter mit Unterstrich und Abfrage tun -

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

Meine Antwort wurde von Vijays Antwort inspiriert , ist aber eine kürzere, allgemeinere Lösung, von der ich dachte, ich würde sie für jeden teilen, dem sie helfen könnte.

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

In der jetzigen Form wird dieser Code sofort ausgeführt und lädt Ihre aktuelle Seite nach 3 Minuten ohne Mausbewegung oder Tastendruck neu.

Dies verwendet einfaches Vanille-JavaScript und einen sofort aufgerufenen Funktionsausdruck , um Leerlaufzeitlimits sauber und in sich geschlossen zu behandeln.

johnnyRose
quelle
document.onclick berücksichtigt Javascript-Funktionen mit .trigger ('click'), die ich als automatisiert geschrieben habe. Es handelt sich also nicht wirklich um eine Benutzerinteraktion, aber in diesem Fall wird der idleCounter zurückgesetzt
Carmela
@ Carmela: Ich bin mir nicht sicher, warum ich das gerade sehe. Ich muss es verpasst haben. Vielen Dank, ich habe die onclickZuordnung entfernt, da dies wahrscheinlich nicht zusätzlich erforderlich ist onmousemove, aber offensichtlich werden alle diese Ereignisse, die programmgesteuert ausgelöst werden, weiterhin zurückgesetzt idleCounter. Ich bin mir nicht sicher, warum Sie Benutzerinteraktion simulieren würden, anstatt nur eine Funktion aufzurufen, aber wenn Sie dies aus irgendeinem Grund tun müssen, funktioniert diese Antwort offensichtlich nicht für Sie, und die meisten anderen Antworten, die ich habe, funktionieren nicht. Ich habe mir diese Frage angesehen.
Johnny Rose
15

Ich weiß, dass es eine relativ alte Frage ist, aber ich hatte das gleiche Problem und fand eine ziemlich gute Lösung.

Ich habe verwendet: jquery.idle und ich musste nur tun:

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

Siehe JsFiddle-Demo .

(Nur zur Info: siehe diese für Back-End - Event - Tracking - Leads browserload )

DDan
quelle
Wie kann ich diese Funktion stoppen? Sie haben ein Ereignis im Leerlauf angegeben: Stopp, aber ich weiß ehrlich gesagt nicht, wie ich das verwenden soll. Ich möchte, dass die Leerlauffunktion stoppt, wenn ich zur nächsten Seite gewechselt bin (Ajax-basiert, sodass nur ein Fragment der HTML-Seite aktualisiert wird). Wussten Sie, wie Sie dies erreichen können?
Mubasher
Hier heißt es: "idle: stop": stoppt und entfernt User Tracking
DDan
Ich habe bereits gelesen, konnte aber nicht herausfinden, wie ich das verwenden soll. Könnten Sie mir helfen?
Mubasher
Wenn Sie möchten, dass es nur einmal ausgelöst wird, können Sie die keepTrackingOption auf einstellen false. Wenn Sie zurücksetzen möchten, können Sie versuchen, neu zu initialisieren. Hier ist ein modifiziertes Beispiel, das nur einmal ausgelöst werden
DDan
Nein, ich feuere nicht einmal, keepTracking sollte wahr sein, aber bei der Navigation zu einer anderen Seite möchte ich dies stoppen
Mubasher
15

Alle vorherigen Antworten haben einen immer aktiven Mausbewegungs-Handler. Wenn der Handler jQuery ist, kann sich die zusätzliche Verarbeitung, die jQuery ausführt, summieren. Insbesondere wenn der Benutzer eine Gaming-Maus verwendet, können bis zu 500 Ereignisse pro Sekunde auftreten.

Diese Lösung vermeidet die Behandlung jedes Mausbewegungsereignisses. Dies führt zu einem kleinen Zeitfehler, den Sie jedoch an Ihre Bedürfnisse anpassen können.

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/

Sarsaparille
quelle
1
Funktioniert dies automatisch, wenn es auf einer Seite platziert wird, oder muss es sich in einem $ (document) .ready () -Wrapper befinden? Vielen Dank! Wo befindet sich der Teil, der eine Aktion ausführt, wenn der Timer abläuft?
Orangen13
1
Sie können dies jederzeit aufrufen, noch bevor das Dokument fertig ist. Sie übergeben eine Funktion 'Rückruf', die nach Ablauf des Timers aufgerufen wird.
Sarsaparilla
1
Das $(startTimer)entspricht $(document).ready(startTimer), sichergestellt , dass das DOM bereit ist , bevor Sie die mousemove- und keypress Ereignisse Haken.
Sarsaparilla
1
+1 Dies ist, was ich tue - Mausbewegungshandler tragen zu Trägheit und verkürzter Akkulaufzeit bei. Daher ist es nur eine gute Idee, sie nur regelmäßig einzuschalten, wenn Sie sich den kleinen Zeitfehler leisten können. Normalerweise verwende ich die Leerlaufzeiterkennung für automatische Warnungen zum Ablauf von Sitzungen (z. B. "Sind Sie noch da?"). Daher habe ich in der Regel viele Minuten Zeit, bevor ein Benutzer in den Leerlauf geht. In diesem Fall ist ein kleiner Zeitfehler völlig irrelevant.
Ziege
1
Es ist besser, "Tastendruck" als "Tastendruck" zu verwenden, da die Pfeiltasten vom Ereignis "Tastendruck" nicht erkannt werden. Wenn der Benutzer mit den Pfeiltasten auf der Seite navigiert, wird sie sowieso inaktiv.
aFerrer
13

Sie könnten wahrscheinlich etwas zusammen hacken, indem Sie die Mausbewegung im Hauptteil des Formulars erkennen und eine globale Variable mit der letzten Bewegungszeit aktualisieren. Dann müsste ein Intervall-Timer ausgeführt werden, der regelmäßig die letzte Bewegungszeit überprüft und etwas unternimmt, wenn es ausreichend lange her ist, seit die letzte Mausbewegung erkannt wurde.

Tvanfosson
quelle
Es ist wichtig zu beachten, dass das Skript nur Bewegungen auf dem Seitenkörper erkennen kann, nicht alle Benutzereingaben. Ich glaube nicht, dass es eine Möglichkeit gibt, CPU- oder Prozessinformationen aus Javascript abzurufen.
Dave Swersky
1
Ich habe mir erlaubt, Ihre Idee in jQuery umzusetzen.
Peter J
9

Ich habe eine kleine ES6-Klasse geschrieben, um Aktivitäten zu erkennen und ansonsten Ereignisse im Leerlauf auszulösen. Es deckt Tastatur, Maus und Touch ab , kann aktiviert und deaktiviert werden und verfügt über eine sehr schlanke API:

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

Es hängt nicht von jQuery ab, obwohl Sie es möglicherweise über Babel ausführen müssen, um ältere Browser zu unterstützen.

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

Ich könnte es als npm-Paket veröffentlichen, sobald ich Feedback bekomme.

Capi Etheriel
quelle
8

Wenn Sie auf einen unterstützten Browser abzielen (Chrome oder Firefox ab Dezember 2018), können Sie mit dem requestIdleCallback experimentieren und den requestIdleCallback-Shim für nicht unterstützte Browser einschließen .

Rajsite
quelle
Und die anderen Browser in Ruhe lassen?
Frank Conijn
Shim deckt alle Browser ab. Und das war die einzige Antwort! Andere langsame Antworten beziehen sich auf die Maus. Die Interaktivität oder CPU wurde nur als Beispiel genannt. Wie erkennt man einen CPU-Leerlauf mit einer Mauslösung?
6

Versuchen Sie diesen Code, es funktioniert perfekt.

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
quelle
plus 1 für Vanille 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> 

Ich denke, dieser Abfragecode ist perfekt, obwohl er von den obigen Antworten kopiert und modifiziert wurde !! Vergessen Sie nicht, die jquery-Bibliothek in Ihre Datei aufzunehmen!

SPidey
quelle
4

Das Problem mit all diesen Lösungen ist zwar korrekt, aber unpraktisch, wenn man das wertvolle Set für das Sitzungszeitlimit berücksichtigt, PHP, .NET oder die Datei Application.cfc für Coldfusion-Entwickler verwendet. Die von der obigen Lösung festgelegte Zeit muss mit dem Zeitlimit für die serverseitige Sitzung synchronisiert werden. Wenn die beiden nicht synchronisiert werden, können Probleme auftreten, die Ihre Benutzer nur frustrieren und verwirren. Beispielsweise kann das serverseitige Sitzungszeitlimit auf 60 Minuten festgelegt werden, der Benutzer kann jedoch davon ausgehen, dass er sicher ist, da durch die Erfassung der JavaScript-Leerlaufzeit die Gesamtzeit erhöht wurde, die ein Benutzer auf einer einzelnen Seite verbringen kann. Der Benutzer hat möglicherweise Zeit damit verbracht, ein langes Formular auszufüllen, und geht dann zum Senden. Das Sitzungszeitlimit wird möglicherweise aktiviert, bevor die Formularübermittlung verarbeitet wird. Ich neige dazu, meinen Benutzern nur 180 Minuten zu geben, Verwenden Sie dann JavaScript, um den Benutzer automatisch abzumelden. Verwenden Sie im Wesentlichen einen Teil des obigen Codes, um einen einfachen Timer zu erstellen, jedoch ohne den Teil des erfassenden Mausereignisses. Auf diese Weise wird meine clientseitige und serverseitige Zeit perfekt synchronisiert. Es gibt keine Verwirrung, wenn Sie dem Benutzer die Zeit in Ihrer Benutzeroberfläche anzeigen, da sie sich verringert. Bei jedem Zugriff auf eine neue Seite im CMS werden die serverseitige Sitzung und der JavaScript-Timer zurückgesetzt. Einfach und elegant. Wenn ein Benutzer länger als 180 Minuten auf einer einzelnen Seite bleibt, stimmt in erster Linie etwas mit der Seite nicht. wie es reduziert. Bei jedem Zugriff auf eine neue Seite im CMS werden die serverseitige Sitzung und der JavaScript-Timer zurückgesetzt. Einfach und elegant. Wenn ein Benutzer länger als 180 Minuten auf einer einzelnen Seite bleibt, stimmt in erster Linie etwas mit der Seite nicht. wie es reduziert. Bei jedem Zugriff auf eine neue Seite im CMS werden die serverseitige Sitzung und der JavaScript-Timer zurückgesetzt. Einfach und elegant. Wenn ein Benutzer länger als 180 Minuten auf einer einzelnen Seite bleibt, stimmt in erster Linie etwas mit der Seite nicht.

Charles Robertson
quelle
1
Ja, deshalb mache ich das erst, nachdem ich serverseitige Sitzungen entfernt und alles aus HTML-Dateien geladen habe.
Dan Parker
4

Reines JavaScript mit richtig eingestellter Rücksetzzeit und Bindungen über 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
quelle
4

(Teilweise inspiriert von der guten Kernlogik von Equiman weiter oben in diesem Thread.)

sessionExpiration.js


sessionExpiration.js ist leicht, aber effektiv und anpassbar. Einmal implementiert, in nur einer Zeile verwenden:

sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
  • Betrifft alle Registerkarten des Browsers, nicht nur eine.
  • Geschrieben in reinem JavaScript , ohne Abhängigkeiten. Voll Client-Seite.
  • (Wenn gewünscht.) Hat Warnbanner und Countdown- Uhr, die durch Benutzerinteraktion abgebrochen wird.
  • Fügen Sie einfach die Datei sessionExpiration.js hinzu und rufen Sie die Funktion mit den Argumenten [1] Anzahl der Leerlaufminuten (auf allen Registerkarten) auf, bis der Benutzer abgemeldet ist, [2] Anzahl der Leerlaufminuten, bis Warnung und Countdown angezeigt werden, und [3]. Abmelde-URL.
  • Fügen Sie das CSS in Ihr Stylesheet ein. Passen Sie es an, wenn Sie möchten. (Oder überspringen und löschen Sie das Banner, wenn Sie es nicht möchten.)
  • Wenn Sie das Warnbanner jedoch möchten, müssen Sie ein leeres div mit der ID sessExpirDiv auf Ihrer Seite einfügen (ein Vorschlag ist, es in die Fußzeile einzufügen ) .
  • Jetzt wird der Benutzer automatisch abgemeldet, wenn alle Registerkarten für die angegebene Dauer inaktiv waren.
  • Optional: Sie können der Funktion ein viertes Argument (URL serverRefresh) bereitstellen, damit ein serverseitiger Sitzungszeitgeber auch bei der Interaktion mit der Seite aktualisiert wird.

Dies ist ein Beispiel dafür, wie es in Aktion aussieht, wenn Sie das CSS nicht ändern.

demo_image

Fom
quelle
3

Ich habe ein einfaches jQuery-Plugin geschrieben, das genau das tut, wonach Sie suchen.

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

Das Skript wartet auf Inaktivität (Leerlauf) von Maus, Tastatur, Berührung und anderen benutzerdefinierten Ereignissen und löst globale "Aktivitäts" - und "Inaktivitäts" -Ereignisse aus.

Hoffe das hilft :)

Alexandros Filos Kaparelos
quelle
Ist wirklich eine Verzögerung erforderlich, reicht das Auslösen eines benutzerdefinierten Ereignisses von einem benutzerdefinierten Ereignishandler nicht aus?
Hibou57
2

Nur ein paar Gedanken, ein oder zwei Wege zum Erkunden.

Ist es möglich, dass alle 10 Sekunden eine Funktion ausgeführt wird und eine "Zähler" -Variable überprüft wird? Wenn das möglich ist, können Sie ein Mouseover für die Seite durchführen, nicht wahr? Verwenden Sie in diesem Fall das Mouseover-Ereignis, um die Variable "counter" zurückzusetzen. Wenn Ihre Funktion aufgerufen wird und der Zähler über dem von Ihnen festgelegten Bereich liegt, führen Sie Ihre Aktion aus.

Nochmals ein paar Gedanken ... Hoffe es hilft.

Mark Rullo
quelle
2

Ich habe diese Code-Arbeitsdatei getestet:

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

Hier ist die beste Lösung, die ich gefunden habe: http://css-tricks.com/snippets/jquery/fire-event-when-user-is-idle/

Hier ist der 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
quelle
2

Sie können die unten genannte Lösung verwenden

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

Ich verwende diesen Ansatz, da Sie die Zeit, zu der ein Ereignis ausgelöst wird, nicht ständig zurücksetzen müssen, sondern nur die Zeit aufzeichnen. Dadurch wird der Startpunkt im Leerlauf generiert.

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

Sie könnten wahrscheinlich mithilfe der aufgeführten Mausbewegungstricks Inaktivität auf Ihrer Webseite erkennen, aber das sagt Ihnen nicht, dass sich der Benutzer nicht auf einer anderen Seite in einem anderen Fenster oder einer anderen Registerkarte befindet oder dass sich der Benutzer in Word oder Photoshop oder WOW und befindet Sie sehen Ihre Seite derzeit nur nicht an. Im Allgemeinen würde ich nur den Prefetch durchführen und mich auf das Multitasking des Clients verlassen. Wenn Sie diese Funktionalität wirklich benötigen, tun Sie etwas mit einem ActiveX-Steuerelement in Windows, aber es ist bestenfalls hässlich.

Walden Leverich
quelle
1

Hier ist ein AngularJS-Dienst für die Ausführung in 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;
}]);

Beachten Sie, dass dieser Leerlaufprüfer für alle Routen ausgeführt wird. Daher sollte er beim .run()Laden der Winkel-App initialisiert werden . Dann können Sie idleChecker.secondsIdleinnerhalb jeder Route verwenden.

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

Debounce eigentlich eine tolle Idee! Hier Version für jQuery kostenlose Projekte:

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

Erkennen Sie so einfach wie möglich, wann sich nur die Maus bewegt:

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

Nun, Sie können dem Dokumentkörper ein Klick- oder Mausbewegungsereignis hinzufügen, das einen Timer zurücksetzt. Haben Sie eine Funktion, die Sie in zeitlich festgelegten Intervallen aufrufen, die prüft, ob der Timer eine bestimmte Zeit (z. B. 1000 Millis) überschreitet, und starten Sie das Vorladen.

Eric Wendelin
quelle
0

Javascript kann die CPU-Auslastung nicht ermitteln. Dies würde die darin enthaltenen Sandbox-Javascript-Läufe beschädigen.

Abgesehen davon würde es wahrscheinlich funktionieren, die Onmouseover- und Onkeydown-Ereignisse der Seite zu verknüpfen.

Sie können auch setTimeout im Ereignis onload festlegen, um eine Funktion zu planen, die nach einer Verzögerung aufgerufen werden soll.

// Call aFunction after 1 second
window.setTimeout(aFunction, 1000);
Powerlord
quelle
3
Ich frage mich, warum so viele Abstimmungen zu dieser Antwort. Soweit ich sehen kann, hat es die gestellte Frage beantwortet und ist sachlich korrekt. Nur wurden keine ausführlichen Codebeispiele eingeführt.
Ifedi Okonkwo
1
Jetzt ist es möglich, eine Javascript-Funktion aufzurufen, wenn "am Ende eines Frames freie Zeit ist oder wenn der Benutzer inaktiv ist". Developers.google.com/web/updates/2015/08/…
Max
setTimeout 0 ist wahrscheinlich korrekter, um im Durchschnitt zu berechnen, wie voll der Puffer ist, indem man sich die Zeit zwischen FILO