0

I am working on a php page with tests. The max time for a test is 1 hour, but the session times out after 10 mins of inactivity. At timeout, the tests page doesn't refresh or redirect... It stays the same, but when the user hits the "see the results" button at the end of the test, he is logged out and his results are not registred.

I just need - [after 3 mins of inactivity on the page] - to diplay a warning message. if after displaying the message the user makes a mouse movement - or click - anywhere on the page, the timer resets without refreshing the page.

If even after displaying the warning message the user didn't moved his mouse or clicked for 7 mins, the message shows "you have been logged out".

I am a beginner in progrmming, but I guess it's pretty simple stuff, displaying 2 messages after 3 and 10 mins of inactivity, both timer reset at mouse movement or click.

Could somebody help me with a nice solution to this? Thanks!

bwoebi
  • 23,637
  • 5
  • 58
  • 79
Klausss
  • 7
  • 1
  • 1
  • 4
  • 2
    `window.setTimeout(function() { alert('3 minute warning') }, 30000);` Detecting activity is left as an exercise to the reader. – Marc B Apr 22 '13 at 15:43
  • 2
    @Marc B this is not 3 minutes of inactivity – Elzo Valugi Apr 22 '13 at 15:43
  • Try this post: http://stackoverflow.com/questions/667555/detecting-idle-time-in-javascript-elegantly – jbolanos Apr 22 '13 at 15:44
  • It may be close though, have this timer attached to an event that listens for keyboard presses and mouse movement and it might do the job. – Useless Intern Apr 22 '13 at 15:45
  • To be able to detect any mouse/key activity you'll need to add listeners to the whole page for activity and track the last time the user had any action. That *could* have a rather large performance hit. But if you get that working pretty well in the background you can tie it into something to warn the user after 3 minutes of inactivity. – BlargleMonster Apr 22 '13 at 15:45
  • 1
    FYI. activity in HTTP means a server request – Elzo Valugi Apr 22 '13 at 15:53

4 Answers4

4
var timeout;

document.onmousemove = resetTimer;
document.onclick = resetTimer;

function resetTimer = function() {
  clearTimeout(timeout);
  timeout = setTimeout(function(){alert("3 minute warning");}, 3*60*1000);
}

As @Elzo Valugi noted, your server will not be able to verify anything you do client side, so if that is important you will need to add server-side code as well.

Jonah
  • 15,806
  • 22
  • 87
  • 161
1
var timeoutWarn;
var timeoutLogout;

// Set the timer
resetTimer();

// Reset the timer
document.onmousemove = resetTimer();
document.onclick = resetTimer();

function resetTimer = function() {
    timeoutWarn = window.setTimeout(function() { 
        // create warning element.
    }, 180000);

    timeoutLogout = window.setTimeout(function() { 
        // ajax to process logout
        alert('You have been logged out');
    }, 420000);
}
Ian Brindley
  • 2,197
  • 1
  • 19
  • 28
0

If you really care to be correct go with the assumption that anything client side is fakeable and forget about JS solutions. The only correct way to do this is server side. BUT, unfortunately, HTTP requests are stateless, which means you dont know exactly what the client is doing and if he is still active. What you can do is to update the session information server side on each request and once every minute you have a cron job that works as a garbage collector for the expired sessions.

Elzo Valugi
  • 27,240
  • 15
  • 95
  • 114
0

This should allow you to tweak the area and actual milliseconds/actions without modifying the core timer logic

var $area = $(document),
    idleActions = [
        {
            milliseconds: 3000, // 3 seconds
            action: function () { alert('Warning'); }
        },
        {
            milliseconds: 3000, // 3 + 3 = 6 seconds
            action: function () { alert('Logout'); }
        }
    ];


function Eureka (event, times, undefined) {
    var idleTimer = $area.data('idleTimer');
    if (times === undefined) times = 0;
    if (idleTimer) {
        clearTimeout($area.data('idleTimer'));
    }
    if (times < idleActions.length) {
        $area.data('idleTimer', setTimeout(function () {
            idleActions[times].action(); // run the first action
            Eureka(null, ++times); // setup the next action
        }, idleActions[times].milliseconds));
    } else {
        // final action reached, prevent further resetting
        $area.off('mousemove click', Eureka);
    }
};

$area
    .data('idle', null)
    .on('mousemove click', Eureka);

Eureka(); // start the first time

jsFiddle: http://jsfiddle.net/terryyounghk/wMZJA/

Terry Young
  • 3,531
  • 1
  • 20
  • 21
  • Thanks, Terry! This seems to work somehow, but it's firing even if I move the mouse or scroll. If I move the mouse after "Warning", "Logout" triggers, which should trigger only if i dont move the mouse after "warning". If after warning i retake activity and then stop again, it should trigger "Warning" again. – Klausss Apr 22 '13 at 17:44
  • While I'm giving this some more thought, does the situation also happen in my demo link (which I can't seem to reproduce)? And could it be possible you have certain elements in the document that stops event propagation, preventing the event to reach `document` (hence `$area`)? If that's the case, tweak the selector for `$area`, I kind of anticipated that. – Terry Young Apr 22 '13 at 18:03
  • For example: `var $area = $([document, 'body', '.SomeElementThatPreventedEventPropagation'])` – Terry Young Apr 22 '13 at 18:06
  • And I think `scroll` events won't trigger `mousemove` events. Whatever event(s) you might want to add, there's just two places to modify (or abstract that into a variable if you want) – Terry Young Apr 22 '13 at 18:08