How can I override a JavaScript variable when page is visible again? - javascript

When visiting a web page I want to declare a start time and send an AJAX request when the user leaves the site. It works like expected but when changing the tab or minimizing the browser the start time remains the same as when the user accessed the web page. I thought I could override the start time by declaring it within a function which is fired when the tab is active again but with no success.
Here is my code so far:
$(document).ready(function() {
var starts = Math.ceil(Date.now() / 1000);
//declare new start time when user returns
document.addEventListener('visibilitychange', function() {
if(!document.hidden) {
var starts = Math.ceil(Date.now() / 1000);
}
});
//AJAX
//value of old starts is used here instead of new declared starts
...
});
Does anyone have a solution for this?

Try document.visibilityState === 'visible' so your code will look like this:
$(document).ready(function() {
var starts = Math.ceil(Date.now() / 1000);
//declare new start time when user returns
document.addEventListener('visibilitychange', function() {
if(document.visibilityState === 'visible') {
var starts = Math.ceil(Date.now() / 1000);
}
});
});
Read more about it here:
https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilitychange_event

const timer = document.querySelector("#timer");
window.addEventListener('DOMContentLoaded', () => {
startTimer(); // starttime on load
});
let intervalID = null;
let timerValue = 0;
const startTimer = () => {
intervalID = setInterval(() => {
timerValue++;
timer.innerText = timerValue;
}, 1000);
}
const stopTimer = () => {
clearInterval(intervalID);
}
document.addEventListener('visibilitychange', () => {
if (document.hidden) { // codition for browser tabs is active or minimize
stopTimer(); // stop timer when you leave tab minimize it on
return;
}
startTimer(); // start timer when you comback to tab maximize it
})
<div class="container">
<h2>time spend in seconds:<span id="timer">0</span>
<h2>
</div>

Related

How to execute an event in a loop until the event is true

I'm stuck in Javascript at looping a piece of code when an event listener is being
placed.
For example, let's say I have a div:
<div id="option">
</div>
and I added a Javascript mouseenter event listener:
const divItem = document.getElementById("option")
divItem.addEventListner("mouseenter", () => {
console.log("Mouse is entered")
})
Now the console log happens once and after I hover the mouse, but I want it to happen every after 4 seconds
and log the same message in the console until the mouse is moving out of the div.
I tried using setTimeout:
divItem.addEventListner("mouseenter", () => {
const timeoutEvent = () => {
console.log("Mouse is entered")
setTimeout( () => { timeoutEvent() }, 4000 )
}
timeoutEvent()
})
but it is logging even after the mouse left the div,
so how can I solve this?
You're on the right track. If you want every four seconds, you want to:
Use setInterval (or set a new setTimeout every time), and
Cancel it when you see mouseleave
const divItem = document.getElementById("option")
// The timer handle so we can cancel it
let timer = 0; // A real timer handle is never 0, so we can use it as a flag
divItem.addEventListener("mouseenter", () => {
console.log("Mouse is entered");
timer = setInterval(() => {
if (timer) {
console.log("Mouse is still here");
}
}, 1000);
})
divItem.addEventListener("mouseleave", () => {
console.log("Mouse left");
clearInterval(timer);
timer = 0;
});
<div id="option">
this is the div
</div>
(I've used one second in that example instead of four so it's easier to see it working.)
Or using setTimeout rescheduling itself instead:
const divItem = document.getElementById("option")
// The timer handle so we can cancel it
let timer = 0; // A real timer handle is never 0, so we can use it as a flag
const timerInterval = 1000;
function tick() {
if (timer) {
console.log("Mouse is still here");
timer = setTimeout(tick, timerInterval);
}
}
divItem.addEventListener("mouseenter", () => {
console.log("Mouse is entered");
timer = setTimeout(tick, timerInterval);
})
divItem.addEventListener("mouseleave", () => {
console.log("Mouse left");
clearTimeout(timer);
timer = 0;
});
<div id="option">
this is the div
</div>
You should use setInterval instead of setTimeout.
You can define your 'interval' function and the interval in global scope and then use them to set and start the interval execution and clearInterval ( stop de execution ) on mouseenter/mouseleave events.
const divItem = document.getElementById("option")
let myInterval;
const timeoutEvent = () => {
console.log("Mouse is entered")
}
divItem.addEventListener("mouseenter", () => {
myInterval = setInterval(timeoutEvent, 1000);
})
divItem.addEventListener("mouseleave", () => clearInterval(myInterval))
<div id="option">
My Option
</div>
divItem.addEventListener("mouseenter", () => {
console.log("Mouse is entered");
timer = setInterval(() => {
console.log("Mouse is still here");
}
}, 4000);
})

Chrome Extensions: Javascript not not running clearInterval();

I'm trying the make a chrome extension in javascript. So far, my popup.js looks like this:
let bg;
let clock;
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('button1').addEventListener('click', butClicked);
bg = chrome.extension.getBackgroundPage();
//clock = document.getElementById("label1");
});
let timeStamp;
let isClockRunning = false;
function butClicked() {
let test = bg.getURL();
document.getElementById('test').innerHTML = test;
timeStamp = new Date();
isClockRunning = !isClockRunning;
runCheckTimer();
}
function runCheckTimer() {
var handle;
if(isClockRunning == true) {
handle = setInterval(updateClock, 1000);
}
else if(isClockRunning == false) {
clearInterval(handle);
handle = 0;
}
}
function updateClock() {
let seconds = bg.returnTimeSince(timeStamp);
document.getElementById("label1").innerHTML = "Seconds: " + seconds;
}
The program works just fine when I click the button once; it starts the timer. But when I click the button the second time, timeStamp gets set to 0, but the updateClock keeps running at the same interval; the interval doesn't get cleared even though I'm toggling the isClockRunning boolean. It's almost as if javascript is forgetting to run the else if part in runCheckTimer(). How can I fix this?
EDIT: On a sidenote, am I doing the timer thing the right way? Or is there a better way to do it? I basically want a timer to keep ticking every second since you've pressed the button, and then when you click it again it'll stop and reset to 0.
You have scoped handle to runCheckTimer. When runCheckTimer starts, it will create a new handle every time.
Move handle outside of the function.
var handle;
function runCheckTimer() {
if(isClockRunning == true) {
handle = setInterval(updateClock, 1000);
}
else if(isClockRunning == false) {
clearInterval(handle);
handle = 0;
}
}

Global Javascript timer not resetting from button click

I'm working in an MVC app and I'm having an issue with a global javascript timer that will send the user to the login page if their session expires. Setting the timer and having it execute the logoff function works fine, but I've tried to set that a click function should reset the timer (to try and prevent the timer from closing a user's session prematurely) I'm not sure what I've done incorrectly.
Code in _Layout.csthml
<script>
//session end
var sessionTimer = 0;
var sessionTimeoutWarning = #Session.Timeout- 1;
var sTimeout = parseInt(sessionTimeoutWarning) * 60 * 1000;
function SessionEnd() {
document.getElementById('logoutForm').submit();
}
function SetTimer() {
ClearTimer();
sessionTimer = setInterval('SessionEnd()', sTimeout);
};
function ClearTimer() {
clearInterval(sessionTimer);
};
$('body').on('click', function () {
ClearTimer();
});
$(document).ready(function () {
SetTimer();
});
Relevant Code in Web.config:
<sessionState timeout="2"></sessionState>
EDIT: I realize right now it shows that I'm just clearing the timer on button click. I just wanted to see if it would actually clear it before I try resetting it each time.
Looks like the issue was having this in _Layout and using $('document').ready for triggering the SetTimer. Code is in _Index_Layout and is as follows:
<script>
//session end
if (sessionTimer === undefined)
var sessionTimer = 0;
var sessionTimeoutWarning = #Session.Timeout- 1;
var sTimeout = parseInt(sessionTimeoutWarning) * 60 * 1000;
SetTimer();
function SessionEnd() {
document.getElementById('logoutForm').submit();
}
function SetTimer() {
ClearTimer();
sessionTimer = setTimeout('SessionEnd()', sTimeout);
};
function ClearTimer() {
clearTimeout(sessionTimer);
};
$('body').on('click', function () {
ClearTimer();
});
</script>

Repeat code every x seconds but not if [insert check here]

This is a followup to this question, where I found out how to make code be repeated every x seconds. Is it possible to make an event that can change this? I.e. I have a checkbox which is meant to control whether this is repeated or not, so I figured I'd need something like this:
$(checkbox).bind("change", function() {
switch(whether if it is ticked or not) {
case [ticked]:
// Make the code repeat, while preserving the ability to stop it repeating
case [unticked]:
// Make the code stop repeating, while preserving the ability to start again
}
});
I have no idea what I could put in the cases.
You can do it by assigning your setInterval function to a variable.
var interval = setInterval(function() { }, 1000);
and then you can stop setInterval by
clearInterval(interval);
p.s.
to start your interval you need to call var interval = setInterval(function() { }, 1000); again
You can either stop and start the interval:
var timer;
function start() {
timer = window.setInterval(function(){
// do something
}, 1000);
}
function stop() {
window.clearInterval(timer);
}
start();
$(checkbox).bind("change", function() {
if ($(this).is(':checked')) {
start();
} else {
stop();
}
});
Or you can have a flag causing the interval to skip the code:
var enabled = true;
var timer = window.setInterval(function(){
if (!enabled) {
// do something
}
}, 1000);
$(checkbox).bind("change", function() {
enabled = $(this).is(':checked');
});
function fooFunc() {
$('#foo').text(+new Date());
}
var id;
var shouldBeStopped = false;
$('input').change(function() {
if (shouldBeStopped)
clearInterval(id);
else
id = setInterval(fooFunc, 200);
shouldBeStopped = !shouldBeStopped;
});​
Live DEMO

Implement a timer into js function

I have already this function I'm trying to add a timer like this: when value >= 1 and user doesn't move mouse for 1 minute or 60 seconds timer starts and redirect user to a new page but if user moves mouse before 60 seconds end the timer resets again.
function pagar(){
var textarea = document.getElementById ("textarea");
/*if (event.propertyName.toLowerCase () == "value") {
alert ("NUEVO VALOR EN EL CAMPO TOTAL: " + event.srcElement.value);
}*/
if (event.srcElement.value>=1)
{
var bottomMenu = $("#main_footer").bottomMenu([
{name:"backward","class":"red", text:getStr("menu_backward")},
{name:"menu","class":"green", text:getStr("menu_menu"), func:function(){parent.location = "./index.html";}, enabled:false},
{name:"forward","class":"green", text:getStr("menu_pay"), func:forward, enabled:true}
]);
}
else
{
var bottomMenu = $("#main_footer").bottomMenu([
{name:"backward","class":"red", text:getStr("menu_backward")},
{name:"menu","class":"green", text:getStr("menu_menu"), func:function() {parent.location = "./index.html";}, enabled:true},
{name:"forward","class":"green", text:getStr("menu_pay"), func:forward, enabled:false}
]);
}
}
I want to add a timer after this:
if (event.srcElement.value>=1)
{
You'll want to attach a mousemove event listener to the window which clears and resets a timer upon movement.
function MouseMoveTimeout() {
// Whatever you want the timeout to do
}
var TimerID;
function InstallMouseMoveTimeout(Install) {
var Timeout = 60000;
var MouseMoveDetector = function(e) {
clearTimeout(TimerID);
TimerID = setTimeout(MouseMoveTimeout, Timeout);
}
if(Install && TimerID == undefined) {
TimerID = setTimeout(MouseMoveTimeout, Timeout);
window.addEventListener('mousemove', MouseMoveDetector, true);
} else {
clearTimeout(TimerID);
window.removeEventListener('mousemove', MouseMoveDetector, true);
TimerID = undefined;
}
}
To use this in your code you would:
if (event.srcElement.value>=1) {
InstallMouseMoveTimeout(true); // Install mouse move timeout
...
} else {
InstallMouseMoveTimeout(false); // Cancel mouse move timeout
...
}
var idleTimer = null; // do this in the global scope
// do the following at the location where you want to reset the timer:
if(idleTimer) window.clearTimeout(idleTimer);
idleTimer = window.setTimeout(function() {
location.href = 'other-site';
}, 60000);
So whenever the second block of code is called the old timer is reset and a new one is started. However, since mousemove events trigger very often, this might screw up performance. In this case create an interval (setInterval()) which triggers e.g. every 10 seconds and only set the current date in your mousemove handler. Then you can simply check in your timer callback if enough time since the last mousemove has exceeded and in this case execute an action.
Sounds like a crazy UI idea! But if you want to do that, you need to declare this somewhere:
var timer;
When you want to start the timer running, do this:
timer = setTimeout(function() { timer = -1; doStuff(); }, seconds * 1000);
That will call doStuff after seconds has elapsed.
If you want to cancel the timer:
if (timer != -1) {
clearTimeout(timer);
timer = -1;
}
By combining these appropriately, you can solve your problem.

Categories