0

I want to track IDLE time (no mouse or keyboard movement) of a user on my page. I want a running tally because when the user submits via ajax the call will subtract that time from the time spent on the page.

time on page =  (Date.now() - startTime) - idleTime.

should be easy I would think to stick something in function() for the custom javascript but not getting how to just tally.

Mike Q
  • 6,716
  • 5
  • 55
  • 62
  • How would you define idle time? Is it the time it takes to complete a server side function, is it because the user is not moving his mouse or not interacting with the website? – Icepickle Aug 21 '17 at 16:26
  • This post has the answer: https://stackoverflow.com/questions/9564602/how-to-know-browser-idle-time – Airwavezx Aug 21 '17 at 16:27
  • Possible duplicate of [Detecting idle time in JavaScript elegantly](https://stackoverflow.com/questions/667555/detecting-idle-time-in-javascript-elegantly) – Nisarg Shah Aug 21 '17 at 16:27
  • I've looked at these other examples but none of them seem to keep track of the time that the user is not doing anything AS A TALLY.. – Mike Q Aug 21 '17 at 16:30
  • idle time meaning no mouse/keyboard movement but keep it as a running tally ... when the user clicks to submit their email I want it to subtract that idle time .. All I need is the time after the page loads when the perform some particular action .. – Mike Q Aug 21 '17 at 16:32

1 Answers1

1

I guess you could do it like that. You can get the total time it took from the getIdleTime method, and if you want to track some more events, you could do that through the actionsToTrack const

function TimeKeeper(selector) {
  const timeKeeper = document.querySelector(selector);
  const actionsToTrack = ['mousemove', 'mouseenter', 'mouseleave', 'keyup', 'keydown', 'keypress'];

  let lastMoveTime = new Date();
  let idleTime = 0;
  
  // this updates the time and updates the element showing the inactive time
  let update = (newTime) => {
    idleTime += newTime;
    timeKeeper.innerHTML = `${idleTime} ms`;
  };

  // will execute for every different kind of action
  // you could potentially log the action to see if it got caught or not
  const trackAction = (action) => function() {
    lastMoveTime = new Date();
  };

  setInterval(() => {
    let moveTime = new Date();
    let diff = moveTime - lastMoveTime;
    // i don't see 100 ms of inactivity necessarily as idle, but okay
    if (diff >= 100) {
      update(diff);
      lastMoveTime = moveTime;
    }
  }, 100);

  // attaches the handlers
  Object.keys( actionsToTrack ).forEach(action => 
    document.body.addEventListener(actionsToTrack[action], trackAction( actionsToTrack[action] ) )
  );

  // returns the idle time
  this.getIdleTime = () => {
    return idleTime;
  };

  // resets the idle time
  this.reset = () => {
    idleTime = 0;
  };
}

var tk = new TimeKeeper('#idleTime');
html,
body {
  position: absolute;
  padding: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.timekeeper {
  position: absolute;
  top: 0;
  right: 0;
}
<div id="idleTime" class="timekeeper"></div>

Note that for a mousemove, the cursor has to pass the body itself, since I don't have any content i just stretched it...

Icepickle
  • 12,689
  • 3
  • 34
  • 48