0

An existing refresh function that I don't wan't to touch (if possible). It refreshes a table in page.

I need to suspend the refresh function if the client is idle / inactive.

If the client is active the original refresh function returns to the way it was before being suspended.

//SUSPEND THIS FUNCTION IF CLIENT IS IDLE
//ENABLE THIS FUNCTION WHEN CLIENT IS ACTIVE
    function refreshTable() {

        window.clearTimeout(timer);

        timer = window.setTimeout(refreshTable, 5000);

        $("body").append("<p>refreshTable every 5 seconds.</p>");
    }
    var timer = window.setTimeout(refreshTable, 0);



    function idleClientCheck() {
        var t;
        window.onload = resetTimer;
        window.onmousemove = resetTimer;
        window.onmousedown = resetTimer;
        window.onclick = resetTimer;
        window.onscroll = resetTimer;
        window.onkeypress = resetTimer;


        function isNotIdle() {
            setTimeout(timer);
            //alert('isNotIdle');
        }

        function isIdle() {
            clearTimeout(timer);
            alert('isIdle');
        }

        function resetTimer() {
            clearTimeout(t);
            //MY LOGIC ERROR
            t = setInterval(isNotIdle, 9999);

            //THIS WORKS LIKE I WANT. BUT refreshTable() DOES NOT
            //RESTART AGAIN WHEN CLIENT IS ACTIVE
            t = setInterval(isIdle, 15000);
        } 
    }
    idleClientCheck();

Codepen

Kerry7777
  • 4,246
  • 1
  • 18
  • 28
  • You can use `clearInterval()` to stop the interval running, but what do you consider an 'active' user? – Rory McCrossan Sep 14 '17 at 06:32
  • If the client has moved mouse, clicked etc within 15 seconds I consider them 'active' or 'not idle'. 15 seconds will be changed to 15 - 30 minutes later (in production). – Kerry7777 Sep 14 '17 at 06:58

2 Answers2

1

Your code can be easily refactored into something that makes a bit more sense, when you realized that all your need is two timers:

  1. Timer 1, say refreshTimer, simply iteratively invokes itself to refresh the table
  2. Timer 2, say idleTimer, checks how long the user has been idle. This timer is reset whenever a specific event is fired from the window object, as per your question's requirements

Basic timer settings

With that in mind, we can set up two global timers:

// Global timers
var refreshTimer = null,
    idleTimer = null;

We can also store the timeouts somewhere, so that they don't clutter our functions with magic constants :) refreshDuration is the interval you want to call the refresh function, while idleDuration is the duration you use to determine if the user is inactive:

// Some settings
var refreshDuration = 5000,  // You can change this!
    idleDuration = 3000;     // You can change this!

p/s: You have noted in your question that you wanted to wait for 15s (i.e. 15000ms), but for testing purposes I have reduced it.


The refresh timer: self-invoking function that refreshes content

To mimic a window.setInterval function for the freshTimer callback, we simply define a refresh() function, which within itself starts a new timeout and invokes itself again:

var refresh = function() {
  $("body").append("<p>refreshTable every 5 second.</p>");

  // Call itself
  refreshTimer = window.setTimeout(refresh, refreshDuration);
};

The idle timer: checking for user (in)activity

For the idle timer, what you want to do is not to use window.onload to bind events. That is because this can only be run once, and if you have other window.onload statements on your page, you will risk overwriting them. Use .addEventListener instead. So, what we can do is store all the events you want to listen to in an array, and bind them iteratively using IIFE.

In each of these event callbacks, you want to clear both global timers, because:

  1. You want to cancel the self-invoking refresh function, and
  2. You want to restart the countdown towards a "user is idle" state

And then you simply restart the idleTimer in the same callback. The idleTimer will simply restart the self-invoking refresh function when it times out:

var idleClientCheck = function() {

  // These events will trigger a new countdown
  var events = ['load', 'mousemove', 'mousedown', 'click', 'scroll', 'keypress'];
  for (var i = 0; i < events.length; i++) {

    // Use IIFE to bind correct event on the fly
    (function() {
      var e = events[i];
      window.addEventListener(e, function() {
        // When these events are triggered, we cancel refreshTimer and idleTimer
        window.clearTimeout(refreshTimer);
        window.clearTimeout(idleTimer);

        console.log('Refresh timer cancelled by ' + e + ', will restart in ' + idleDuration + 'ms');

        // We restart idleTimer
        // idleTimer simply fires refresh() when time runs out
        idleTimer = window.setTimeout(refresh, idleDuration);
      });
    })(i);

  }
};

idleClientCheck();

Combining all these at once, and you get a functional snippet:

// Global timers
var refreshTimer = null,
    idleTimer = null;
    
// Some settings
var refreshDuration = 5000,
    idleDuration = 3000;

// refresh() is simply a method with a self-invoking to mimic window.setInterval
var refresh = function() {
  $("body").append("<p>refreshTable every 5 second.</p>");
  
  // Call itself
  refreshTimer = window.setTimeout(refresh, refreshDuration);
};

// idleClientCheck() runs its own timer to check for idle client
var idleClientCheck = function() {

  // These events will trigger a new countdown
  var events = ['load', 'mousemove', 'mousedown', 'click', 'scroll', 'keypress'];
  for (var i = 0; i < events.length; i++) {
  
    // Use IIFE to bind correct event on the fly
    (function() {
      var e = events[i];
      window.addEventListener(e, function() {
        // When these events are triggered, we cancel refreshTimer and idleTimer
        window.clearTimeout(refreshTimer);
        window.clearTimeout(idleTimer);

        console.log('Refresh timer cancelled by ' + e + ', will restart in ' + idleDuration + 'ms');

        // We restart idleTimer
        // idleTimer simply fires refresh() when time runs out
        idleTimer = window.setTimeout(refresh, idleDuration);
      });
    })(i);
    
  }
};

idleClientCheck();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Terry
  • 63,248
  • 15
  • 96
  • 118
  • Very thorough answer. Although I wanted the other way around so if the client is (in)active / idle for 15 seconds or more the refresh stops until the client moves mouse, clicks etc. The timer idea is a good one. – Kerry7777 Sep 14 '17 at 22:36
0

its work for me ..I have checked and you can also check this in "TryitEditor" of W3Schools

<script>
 //SUSPEND THIS FUNCTION IF CLIENT IS IDLE
//ENABLE THIS FUNCTION WHEN CLIENT IS ACTIVE
    function refreshTable() {

        window.clearTimeout(timer);

        timer = window.setTimeout(refreshTable, 5000);

        $("body").append("<p>refreshTable every 5 seconds.</p>");
    }
    var timer = window.setTimeout(refreshTable, 0);



    function idleClientCheck() {
        var t1;
         var t2;
        window.onload = resetTimer;
        window.onmousemove = resetTimer;
        window.onmousedown = resetTimer;
        window.onclick = resetTimer;
        window.onscroll = resetTimer;
        window.onkeypress = resetTimer;


        function isNotIdle() {

            timer = window.setTimeout(refreshTable, 5000);
            //setTimeout(timer);
            //alert('isNotIdle');
             $("body").append("<p>isNotIdle</p>");
        }

        function isIdle() {
        clearTimeout(t1);
            //timer = null;
            window.clearTimeout(timer);
            timer = null;
             $("body").append("<p>isIdle</p>");
            //alert('isIdle');
        }

        function resetTimer() {
            clearTimeout(t1);
            clearTimeout(t2);
            t1 = setInterval(isNotIdle, 9999);
            t2 = setInterval(isIdle, 15000);
        } 
    }
    idleClientCheck();
</script>
Hiren Patel
  • 125
  • 11