Using system clock for accurate idle timeout warning - javascript

I am working on a modal which will alert users of a pending logout due to idle time. Overall it works, but I notice the timer is not 100% accurate. I know there are issues with setInterval and accuracy. I still seeing discrepancies and will welcome a suggestion on how to improve my code.
var sessionTimeoutPeriod = 240;
var state = "L";
var timeoutPeriod = sessionTimeoutPeriod * 1000;
var logout = Math.floor(timeoutPeriod / 60000);
var idleInterval;
if (state == "L" || state == "O" || state == "C") {
var idleTime = 0;
$(document).ready(function() {
//Zero the idle timer on mouse movement.
$(this).mousemove(function(e) {
idleTime = 0;
console.log("The mouse moved, idle time = " + idleTime);
});
$(this).keypress(function(e) {
idleTime = 0;
console.log("A key was pressed, idle time = " + idleTime);
});
idleInterval = setInterval(timerIncrement, 60000); // 1 minute
});
function timerIncrement() {
idleTime++;
console.log("The total idle time is "+idleTime+ " minutes.");
if (idleTime >= 1) {
console.log("The modal will fire if idle time = " +idleTime);
var modal = new window.AccessibleModal({
mainPage: $('#main'),
overlay: $('#overlay').css('display', 'block'),
modal: $('#modal-session-timeout'),
prevFocus: $('#main')
});
modal.show();
$('#modal-overlay').removeClass('opened');
$('.js-timeout-refresh, .xClose').click(function() {
modal.hide();
$('#overlayTY').css('display', 'none');
idleTime = 0;
console.log("The total idle time is "+idleTime+ " minutes.");
});
$('.js-timeout-session-end').click(function() {
modal.hide();
$('#overlay').css('display', 'none');
endSession();
});
console.log(idleTime);
}
if (idleTime == logout) { // 9 minutes
endSession();
}
var endSession = function() {
document.location.replace(logoutPageUrl);
};
}
}

Instead of relying on the interval to determine how much time has passed, you could validate how much time has passed manually by comparing the current time against the time since last activity.
This way you can increase the checking interval without having to modify the code. The discrepancy will never be higher then then the interval timeout now, the discrepancy will also not change incrementally, it will always be lower or equal to the interval ( in worst case scenario ).
Here is a basic example.
var sessionTimeoutPeriod = 240;
var timeoutPeriod = sessionTimeoutPeriod * 1000;
var oneMinute = 60000;
var showIdlePopUpTimeOut = oneMinute * 2;
var lastActivity = new Date();
function getIdleTime() {
return new Date().getTime() - lastActivity.getTime();
}
$(document).ready(function () {
//Zero the idle timer on mouse movement.
$(this).mousemove(function (e) {
console.log("The mouse moved, idle time = " + getIdleTime());
lastActivity = new Date();
});
$(this).keypress(function (e) {
console.log("A key was pressed, idle time = " + getIdleTime());
lastActivity = new Date();
});
setInterval(checkIdleTime, 5000);
});
function endSession() {
document.location.replace(logoutPageUrl);
};
function checkIdleTime() {
var idleTime = getIdleTime();
console.log("The total idle time is " + idleTime / oneMinute + " minutes.");
if (idleTime > showIdlePopUpTimeOut) {
var modal = new window.AccessibleModal({
mainPage: $('#main'),
overlay: $('#overlay').css('display', 'block'),
modal: $('#modal-session-timeout'),
prevFocus: $('#main')
});
modal.show();
$('#modal-overlay').removeClass('opened');
$('.js-timeout-refresh, .xClose').click(function () {
modal.hide();
$('#overlayTY').css('display', 'none');
lastActivity = new Date();
});
$('.js-timeout-session-end').click(function () {
modal.hide();
$('#overlay').css('display', 'none');
endSession();
});
console.log(lastActivity);
}
if (idleTime > timeoutPeriod) { // 4 minutes
endSession();
}
}

The problem is that your function "timerIncrement" checks the difference every minute after loading the page, so you will never get exact 1 minute after last activity.Changing interval from 60000 to 1000 will solve the issue.
You don't even need to calculate diff, you can just reset timeout every time there is activity. like this:
$(this).on("mousemove keypress", function(e) {
clearInterval(idleInterval);
idleInterval = setTimeout(functionThatExecutesAfter1minInactivity, 60000);
});

Related

swal alert after 10 minutes of inactivity

How can I make a swal alert that gets triggered after 10 minutes of inactivity on my laravel app?
Also, there should be a logout button in the swal alert. Is it possible?
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 > 10) { // ten minute
alert("enter your html code for logout")
}
}

Cannot understand why event is undefined

I'm sorry, I feel this is a really classic issue but since I'm learning I don't know why it's not working in my case.
I'm trying to have a script that detect your idle time and if so, execute a function that get your mouse position.
In order to do that, I have the function TimerIncrement() that can check 2 seconds of inactivity, if so I would like to execute another function called GetMousePos in order to get the mouse position and to have a console.log of it.
I've tried looking online and on the forums but nothing I have been doing is helping.
Thanks for the precious help.
var idleTime = 0;
$(document).ready(function () {
//Increment the idle time counter every minute.
var idleInterval = setInterval(timerIncrement, 1000); // 1s
//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 > 2) { // 2sec
getMousePos();
idleTime = 0; // reset timer
}
}
function getMousePos(event) {
x = event.pageX;
y = event.pageY;
console.log(x);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
So you're calling getMousePos which takes a parameter of event and you are not passing anything to it hence the Cannot read property 'pageX' as event.pageX (event not defined). You can only get to the event object ON a event callback so I am assuming you want to get the last event you have seen if any.
The below should work for you, storing the lastEvent seen you should then be able to get the info you want. Hopefully, this code example makes you understand what you were missing.
var idleTime = 0;
var lastEvent = undefined;
$(document).ready(function () {
//Increment the idle time counter every minute.
var idleInterval = setInterval(timerIncrement, 1000); // 1s
//Zero the idle timer on mouse movement.
$(this).mousemove(function (e) {
idleTime = 0;
lastEvent = e;
});
$(this).keypress(function (e) {
idleTime = 0;
lastEvent = e;
});
});
function timerIncrement() {
idleTime = idleTime + 1;
if (idleTime > 2) { // 2sec
getMousePos(lastEvent);
idleTime = 0; // reset timer
}
}
function getMousePos(event) {
if (!event) {
console.log("No mouse or keypress has been executed yet");
return;
}
x = event.pageX;
y = event.pageY;
console.log(x);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You can't get the mouse position without an event, so we need to track the mousemove and save the latest position.
$(function() {
let idleTime = 0
let pos = []
let timer = window.setInterval(incTime, 1000)
function incTime() {
idleTime++
checkTime()
$('.time span')[0].innerText = idleTime
}
function checkTime() {
if (idleTime > 2) {
resetTime()
$('.x span')[0].innerText = pos[0]
$('.y span')[0].innerText = pos[1]
}
}
$(document).on('mousemove', e => {
window.clearInterval(timer)
resetTime()
pos[0] = e.pageX
pos[1] = e.pageY
timer = window.setInterval(incTime, 1000)
})
function resetTime() {
idleTime = 0
$('.time span')[0].innerText = idleTime
}
})
<div class="time">Idle time: <span>0</span></div>
<div class="x">X: <span></span></div>
<div class="y">Y: <span></span></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

How to catch events to clear cookies?

I have developed a login page. I am saving sessionId in local storage on login and I want to clear it after some time. But that to be if someone(logged-user) not active for some time. If he is active, I don't want to clear. But I did that even he is active also, I am clearing the local storage. Please help to know how to catch he is active or not.
localStorage.setItem('userId', data.id);
localStorage.setItem('user', data.phone);
localStorage.setItem('sessionId', (Math.random()*1e64).toString(36));
var interval = setInterval(function(){
console.log('In localStorage');
localStorage.removeItem('sessionId');
clearInterval(interval);
alert('Session expired!!')
}, (30*60*1000));
You can just check use a setInterval:
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
localStorage.removeItem('sessionId');
}
}
Answer borrowed from here

Start timer every 1 minute Jquery

Trying to start my timer if the app is in idle start for 1 minute.
My timer is starting initially, how do I check whether my app is idle or not.
And also if the timer starts and interrupts in between then the timer should disappear and stay on the same page.
else redirect to home page.
JS:
var interval = setInterval(function() {
var timer = $('span').html();
var seconds = parseInt(timer,10);
seconds -= 1;
if (seconds < 0 ) {
seconds = 59;
}
else if (seconds < 10 && length.seconds != 2) seconds = '0' + seconds;
$('span').html(seconds);
if (seconds == 0)
clearInterval(interval);
}, 1000);
This is what I have tried:
Demo
$(document).ready(function(){
var idleInterval = setInterval(timerIncrement, 60000); // 1 minute
idleTime = 0;
//Zero the idle timer on mouse movement.
$(this).mousemove(function (e) {
idleTime = 0;
});
$(this).keypress(function (e) {
idleTime = 0;
});
});
//after every one minute this function will call and it check idleTime is
//increment if it is one then reload the page
function timerIncrement() {
idleTime = idleTime + 1;
if (idleTime > 1) { // 1 minutes
//alert();
window.location.reload();
}
}

Countdown timer for use in several places at same page

I want to make a countdown timer, that can be used on several places in the same page - so I think it should be a function in some way.
I really want it to be made with jQuery, but I cant quite make it happen with my code. I have e.g. 10 products in a page, that I need to make a countdown timer - when the timer is at 0 I need it to hide the product.
My code is:
$(document).ready(function(){
$(".product").each(function(){
$(function(){
var t1 = new Date()
var t2 = new Date()
var dif = t1.getTime() - t2.getTime()
var Seconds_from_T1_to_T2 = dif / 1000;
var Seconds_Between_Dates = Math.abs(Seconds_from_T1_to_T2);
var count = Seconds_Between_dates;
var elm = $(this).attr('id');
alert(elm);
countdown = setInterval(function(){
$(elm + " .time_left").html(count + " seconds remaining!");
if (count == 0) {
$(this).css('display','none');
}
count--;
}, 1000);
});
});
});
EDIT 1:
$(document).ready(function(){
$(".product").each(function(){
var elm = $(this).attr('id');
$(function(){
var t1 = new Date()
var t2 = new Date()
var dif = t1.getTime() - t2.getTime()
var Seconds_from_T1_to_T2 = dif / 1000;
var Seconds_Between_Dates = Math.abs(Seconds_from_T1_to_T2);
var count = Seconds_Between_dates;
alert(elm);
countdown = setInterval(function(){
$(elm + " .time_left").html(count + " seconds remaining!");
if (count == 0) {
$(this).css('display','none');
}
count--;
}, 1000);
});
});
});
Do you have any solutions to this?
I'd probably use a single interval function that checks all the products. Something like this:
$(function() {
/* set when a product should expire.
hardcoded to 5 seconds from now for demonstration
but this could be different for each product. */
$('.product').each(function() {
$(this).data('expires', (new Date()).getTime() + 5000);
});
var countdown_id = setInterval(function() {
var now = (new Date()).getTime();
$('.product').each(function() {
var expires = $(this).data('expires');
if (expires) {
var seconds_remaining = Math.round((expires-now)/1000);
if (seconds_remaining > 0) {
$('.time-left', this).text(seconds_remaining);
}
else {
$(this).hide();
}
}
});
}, 1000);
});
You could also cancel the interval function when there is nothing left to expire.
Your problem seems to be that this doesn't refer to the current DOM element (from the each), but to window - from setTimeout.
Apart from that, you have an unnecessary domReady wrapper, forgot the # on your id selector, should use cached references and never rely on the timing of setInterval, which can be quite drifting. Use this:
$(document).ready(function(){
$(".product").each(function(){
var end = new Date(/* from something */),
toUpdate = $(".time_left", this);
prod = $(this);
countDown();
function countdown() {
var cur = new Date(),
left = end - cur;
if (left <= 0) {
prod.remove(); // or .hide() or whatever
return;
}
var sec = Math.ceil(left / 1000);
toUpdate.text(sec + " seconds remaining!"); // don't use .html()
setTimeout(countdown, left % 1000);
}
});
});

Categories

Resources