Idle timer within Vue Component - javascript

I am have some issues resetting my timer when no longer idle. I am using Vue Idle for this, which is a wrapper for idle.js.
So I have a modal with the id timeout-modal. When Vue Idle triggers the idle function, I call showWarningMessage.
Within this function, I first display my modal. I then create a timer which my modal uses to do a countdown. So this all works fine.
<script>
export default {
data() {
return {
timerId: 0,
remainingTimeoutSeconds: 10000
}
},
computed: {
second() {
return this.remainingTimeoutSeconds / 1000;
}
},
onIdle () {
this.showWarningMessage();
},
methods: {
showWarningMessage() {
this.$bvModal.show('timeout-modal');
this.warning = true;
this.timerId = setInterval(() => {
this.remainingTimeoutSeconds -= 1000;
}, 1000);
},
}
}
</script>
Now within the modal there is a continue button. When pressed, it should basically reset the above timer. At the moment I have
handleContinueButtonClick(response) {
if (response.data.success) {
console.log("IN")
this.$bvModal.hide('app-timeout-reminder-modal');
clearInterval(this.timerId);
return;
}
}
So what this should do is hide the modal, and then reset the timer back to 10 seconds. It is entering the above as the console is printing IN. The modal is also
hidden when I click OK.
However, the next time the modal is displayed, the timer is already near 0 as it did not reset back to 10.
Is there any reason why I cant get this back to 10 seconds? I thought clearInterval should reset the timer?
Thanks

I thought clearInterval should reset the timer?
Do you mean this.remainingTimeoutSeconds is set automatically when calling clearInterval?
The answer is no.
You need to reset that value as 10000 like blow;
handleContinueButtonClick(response) {
if (response.data.success) {
console.log("IN")
this.$bvModal.hide('app-timeout-reminder-modal');
this.remainingTimeoutSeconds = 10000;
clearInterval(this.timerId);
return;
}
}
or
showWarningMessage() {
this.$bvModal.show('timeout-modal');
this.warning = true;
this.remainingTimeoutSeconds = 10000;
this.timerId = setInterval(() => {
this.remainingTimeoutSeconds -= 1000;
}, 1000);
}

Related

Countdown timer not working in vue js pop up

I am trying to redirect to another website after countdown. The redirect works, however the countdown decrease only one time.
For example:
I have set the counter to 5. But when the pop up opens, its shows 4 and doesn't decrease further.
<p>Redirecting in {{ counter }}</p>
<script>
export default {
name: "modal",
data() {
return {
toggleModal: false,
counter: 5
}
},
methods: {
showModal() {
this.toggleModal = true;
this.countDown();
},
countDown() {
if(this.counter > 0) {
this.counter--;
setTimeout(() => {
window.location.href = 'https://www.google.com';
}, 5000);
}
},
}
};
</script>
Basically what your code is doing now is waiting 5 seconds and redirecting, one side effect of it redirecting is it decrements countdown by 1.
What you need to do is decrement the counter, every second until it becomes zero, then on the next tick you want to do the redirect.
We do this by first checking to see what the count down is at. If it is above zero we want to wait for a second, then decrement the counter by one, and check again.
countDown() {
//If the counter has not reached the end
if(this.counter > 0) {
//Wait 1 second, then decrement the counter
setTimeout(()=>{
this.counter--;
this.countDown();
},1000)
}
else
{
//Count down has reached zero, redirect
window.location.href = 'https://www.google.com';
}
},

Is it possible to prevent a Timer ends?

I'm trying to show a label when a user clicks a button. I've tried to use setTimeout to achieve this, but when you click the button multiple times before the timeout ends, this don't work properly.
This is what I got:
const [cameraLabelVisible, setCameraLabelVisible] = useState(false);
let labelTimer;
function labelVisible() {
setCameraLabelVisible(true);
labelTimer = setTimeout(() => {
setCameraLabelVisible(false);
clearTimeout(labelTimer);
}, 1500);
}
};
My question is: Is it posible reset the timer to the initial value (in this case 1500) by clicking the same button before the timer ends?
I want to show the label if the button is clicked multiple times before the time runs out.
You could clear the existing timer first:
const [cameraLabelVisible, setCameraLabelVisible] = useState(false);
let labelTimer;
function labelVisible() {
setCameraLabelVisible(true);
// clear the timer if there's another timer running
if(labelTimer) clearTimeout(labelTimer);
labelTimer = setTimeout(() => {
setCameraLabelVisible(false);
}, 1500);
}
My question is: Is it possible reset the timer to the initial value
(in this case 1500) by clicking the same button before the timer ends?
Yes, this can be achieved by clearing the existing timeout and creating a new timeout. This can be achieved as below:
const [cameraLabelVisible, setCameraLabelVisible] = useState(false);
let labelTimer;
function labelVisible() {
if(labelTimer) {
clearTimeout(labelTimer);
}
setCameraLabelVisible(true);
labelTimer = setTimeout(() => {
setCameraLabelVisible(false);
clearTimeout(labelTimer);
}, 1500);
}
};
I want to show the label if the button is clicked multiple times
before the time runs out.
This sounds like a different issue than what you asked above. If I'm understanding you correctly, the below will allow you to click the button multiple times within 1.5 seconds, and the label appear for only that amount of time before clearing.
const [cameraLabelVisible, setCameraLabelVisible] = useState(false);
let labelTimer = undefined;
function labelVisible() {
setCameraLabelVisible(true);
if(!labelTimer) {
labelTimer = setTimeout(() => {
setCameraLabelVisible(false);
labelTimer = undefined;
}, 1500);
}
};

how to destroy all the data of the current page

in my page , I have a real-time chart which updates every 3 seconds
I used setInterval(function(){...} , 3000) for make the chart updates.
but my problem is when I move to another page(by javascript) every thing are destroyed except my interval , so when I back to the chart page , it load every thing again and setInterval method works twice on every 3 seconds which makes duplicated points on mu chart.
this is destroy method
every line works except the myInterval one
destroy()
{ this.num=0;
this.c=0;
this.startLive = false;
clearInterval(this.myInterval); }
my problem appears just when I go to another page then back.
<template>
....
</template>
<script>
var charts = [];
export default {
data() {
return {
startLive: false,
num: 0,
c: 0,
myInterval: null,
}
},
methods: {
initChart(dataProvieded) {
charts[this.num] = AmCharts.makeChart("chart" + this.num, {...});
},
loadInitalData(limit) {
this.fetchDatafromServer(limit).then((response) => { ...
this.initChart(data);
this.num++;
this.setInt();
});
},
setInt() {
this.myInterval = setInterval(function() { .... } , 3000);
},
}
destroy() {
this.num = 0;
this.c = 0;
this.startLive = false;
clearInterval(this.myInterval);
}
</script>
It's strange, try to set debugger; before clearInterval to check variables.
By the way not all codepaths ok (looks like initializations doubled).
You should rewrite as
if (this.myInterval !== null) {
clearInterval(this.myInterval);
this.myInterval = null;
}
and add corresponding guard at setInt:
setInt() {
if (this.myInterval === null ) {
this.myInterval = setInterval(function() { .... } , 3000);
}
}
May you need one interval per graph, please check your logic.

How to run a function once after element has been found with Jquery/Javascript

Is there a way I can run a function once after a specific element has been found?
I tried this:
setInterval(function () {
if ($('.imagewrapper').length) {
self.carousel();
}
}, 1000)
So, it checks my page continiously if the .imagewrapper element exisit, and if so, it should run the self.carousel()function. The problem is, that this way, as soon the element exists, it runs the function continiously. Is there a way around?
ps: The setInterval-method needs to be there.
Try:
(function delay() {
if ($('.imagewrapper').length) {
self.carousel();
} else {
setTimeout(delay, 1000);
}
})();
or if you need setInterval:
var interval = setInterval(function() {
if ($('.imagewrapper').length) {
self.carousel();
clearInterval(interval);
}
}, 1000);
You looking for waitUntilExists https://gist.github.com/buu700/4200601
So, it will works something like that:
$(someselect).waitUntilExists(function(){
var that = $(this);
// do some code
})
It's easy:
// set ran to false when you load the page
ran = false;
setInterval(function () {
// only do your stuff when you haven't do yet (ran==false)
if (!ran && $('.imagewrapper').length) {
self.carousel();
// when you did it for the 1st time set ran to true, so next time you don't enter the if.
ran = true;
} }, 1000)
// but even better to stop the timer after you entered the if for the 1st time:
timer = setInterval(function () {
// only do your stuff when you haven't do yet (ran==false)
if ($('.imagewrapper').length) {
self.carousel();
// when you did it for the 1st time delete the timer
clearInterval(timer);
} }, 1000)

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