You can use the Page Visibility API to detect when the page is hidden or visible. For example, if the user navigates away from the browser and back again or the screen turns off and on.
I used this answer to help create by solution.
You will need to store the time you set your interval. Then when the visibilityChange event listener indicates the document is visible again, you can calculate the amount of time that has passed since you first started the interval and update your data as needed.
In my case I was creating a count down timer in my Angular2 project. My page was running on an iPad and the timer was pausing whenever the screen turned off. So I added the event listener in my ngOnInit()
. Then when the screen turned back on I could update my timer to show the correct time left since it was started.
I am using the moment npm package to handle my date time.
The timerInfo
object is a class variable that gets updated by the interval callback. self.zone.run()
is used to propagate the changes to the DOM so that the updated time gets displayed.
Written in typescript:
private timerInfo:{
days?:number,
hours?:number,
minutes:number,
seconds:number
};
private startTime:Moment = moment();
private timerDuration:number = 20; // in minutes
private timerHandle:any;
ngOnInit() {
this.setVisibilityListener();
}
private setVisibilityListener():void {
var self = this;
var hidden, visibilityState, visibilityChange;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
visibilityState = "visibilityState";
}
var document_hidden = document[hidden];
document.addEventListener(visibilityChange, function () {
if (document_hidden != document[hidden]) {
if (document[hidden]) {
// Document hidden
console.log("document hidden");
} else {
// Document shown
console.log("document shown; setCountDownTimer()");
self.setCountDownTimer();
}
document_hidden = document[hidden];
}
});
}
private setCountDownTimer():void {
var self = this;
if (self.startTime) {
var startMoment = moment(self.startTime);
var endMoment = startMoment.add(self.timerDuration, "minutes");
console.log("endMoment: ", endMoment.toISOString());
self.clearTimer();
var eventTime = endMoment.unix();
var currentTime = moment().unix();
var diffTime = eventTime - currentTime;
var duration = moment.duration(diffTime * 1000, 'milliseconds');
var interval = 1000;
// if time to countdown
if (diffTime > 0) {
self.timerHandle = setInterval(() => {
self.zone.run(() => {
var diff = duration.asMilliseconds() - interval;
if (diff < 0) {
self.clearTimer();
self.timerComplete();
} else {
duration = moment.duration(duration.asMilliseconds() - interval, 'milliseconds');
self.timerInfo = {
days: moment.duration(duration).days(),
hours: moment.duration(duration).hours(),
minutes: moment.duration(duration).minutes(),
seconds: moment.duration(duration).seconds()
};
// console.log("timerInfo: ", JSON.stringify(self.timerInfo));
}
});
}, 1000);
} else {
self.timerComplete();
}
}
}
private clearTimer():void {
if (this.timerHandle) {
clearInterval(this.timerHandle);
this.timerHandle = null;
}
}