I have a exam application using React. I need to run this application in IE11. In this exam app I have added the onblur event that will run when the user switches away from the tab, and when this event is triggered the user is alerted with a popup and the user's lockCount in DB is incremented. The user's exam will be blocked if the LockCount exceeds the limit defined for the exam.
The problem is that the onblur event is triggered when the page is momentarily frozen. Usually this freezing problem occurs when it takes a long time to rerender the page or call any API service. It is working without any problem in Chrome.
I also tried the onBlur event with Mouseleave event, but when the page freezes the mouseleave event also triggers.
How can I prevent the onBlur event from triggering when the page freezes in IE11?
Code for the onBlur and onFocus events:
const onFocus = () => {
setIsOnblur(false);
};
const onBlur = () => {
increaseCount();
setIsOnblur(true);
};
useEffect(() => {
if (props.location.pathname.includes("/Exam/")) {
window.addEventListener("focus", onFocus);
window.addEventListener("blur", onBlur);
return () => {
window.removeEventListener("focus", onFocus);
window.removeEventListener("blur", onBlur);
};
}
}, []);
I solved the problem with this(https://stackoverflow.com/a/9502074/9938582) answer. This answer tells that you can use 3 different methods to detect that user lost focus from the webpage.
In my case, I solved the problem with user's mouse activity and timeout.
First case: It works when user changes the screen completely from webpage to another page or something. Page Visibility API allows us to detect when page is hidden to the user. It doesn't catch the lost focus when the page is minimized but the page is not hidden completely. It doesn't count.
Second case: Focus-Blur events are working perfectly in normal conditions. But Internet Explorer issue misleads that.
Third case: Mouse events(mouseout,mousein,mouseover) don't work due to this issue above. But if I use all events and especially mouse events with timeout, onBlur event doesn't trigger when the page freezes.
Here is the code:
useEffect(() => {
if (props.location.pathname.includes("/Exam/")) {
var doc = document as any;
// register to the W3C Page Visibility API
var hidden: any = null;
var visibilityChange: any = null;
if (typeof doc.mozHidden !== "undefined") {
hidden = "mozHidden";
visibilityChange = "mozvisibilitychange";
} else if (typeof doc.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof doc.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
// } else if (typeof document.hidden !== "hidden") {
} else if (doc.hidden) {
hidden = "hidden";
visibilityChange = "visibilitychange";
}
if (hidden != null && visibilityChange != null) {
addEvent(doc, visibilityChange, function (event: any) {
if (doc[hidden]) {
onBlur();
}
});
}
// register to the potential page visibility change
addEvent(doc, "potentialvisilitychange", function (event: any) {
if (doc.potentialHidden && !doc[hidden]) {
onBlur();
}
});
var potentialPageVisibility = {
pageVisibilityChangeThreshold: 3 * 3600, // in seconds
init: function () {
var lastActionDate: any = null;
var hasFocusLocal: any = true;
var hasMouseOver: any = true;
doc.potentialHidden = false;
doc.potentiallyHiddenSince = 0;
var timeoutHandler: any = null;
function setAsNotHidden() {
var dispatchEventRequired = doc.potentialHidden;
doc.potentialHidden = false;
doc.potentiallyHiddenSince = 0;
if (dispatchEventRequired) dispatchPageVisibilityChangeEvent();
}
function initPotentiallyHiddenDetection() {
if (!hasFocusLocal) {
// the window does not has the focus => check for user activity in the window
lastActionDate = new Date();
if (timeoutHandler != null) {
clearTimeout(timeoutHandler);
}
timeoutHandler = setTimeout(checkPageVisibility, potentialPageVisibility.pageVisibilityChangeThreshold * 1000 + 100); // +100 ms to avoid rounding issues under Firefox
}
}
function dispatchPageVisibilityChangeEvent() {
var evt = doc.createEvent("Event");
evt.initEvent("potentialvisilitychange", true, true);
doc.dispatchEvent(evt);
}
function checkPageVisibility() {
var potentialHiddenDuration = (hasFocusLocal || lastActionDate == null ? 0 : Math.floor((new Date().getTime() - lastActionDate.getTime()) / 1000));
doc.potentiallyHiddenSince = potentialHiddenDuration;
if (potentialHiddenDuration >= potentialPageVisibility.pageVisibilityChangeThreshold && !doc.potentialHidden) {
// page visibility change threshold raiched => raise the even
doc.potentialHidden = true;
dispatchPageVisibilityChangeEvent();
}
}
addEvent(doc, "mousemove", function (event: any) {
lastActionDate = new Date();
});
addEvent(doc, "mouseover", function (event: any) {
hasMouseOver = true;
setAsNotHidden();
});
addEvent(doc, "mouseout", function (event: any) {
hasMouseOver = false;
initPotentiallyHiddenDetection();
});
addEvent(window, "blur", function (event: any) {
hasFocusLocal = false;
initPotentiallyHiddenDetection();
});
addEvent(window, "focus", function (event: any) {
hasFocusLocal = true;
setAsNotHidden();
});
setAsNotHidden();
}
}
potentialPageVisibility.pageVisibilityChangeThreshold = 1; // 4 seconds for testing
potentialPageVisibility.init();
}
}, []);