I am doing an online quiz application in PHP. I want to restrict the user from going back in an exam.
I have tried the following script, but it stops my timer.
Some of the solutions here will not prevent a back event from occurring - they let a back event happen (and data held about the page in the browsers memory is lost) and then they play a forward event to try and hide the fact that a back event just happened. Which is unsuccessful if the page held transient state.
I wrote this solution for React (when react router is not being used), which is based on vrfvr's answer.
It will truly stop the back button from doing anything unless the user confirms a popup:
const onHashChange = useCallback(() => {
const confirm = window.confirm(
'Warning - going back will cause you to loose unsaved data. Really go back?',
);
window.removeEventListener('hashchange', onHashChange);
if (confirm) {
setTimeout(() => {
window.history.go(-1);
}, 1);
} else {
window.location.hash = 'no-back';
setTimeout(() => {
window.addEventListener('hashchange', onHashChange);
}, 1);
}
}, []);
useEffect(() => {
window.location.hash = 'no-back';
setTimeout(() => {
window.addEventListener('hashchange', onHashChange);
}, 1);
return () => {
window.removeEventListener('hashchange', onHashChange);
};
}, []);
This is the way I could it accomplish it. Weirdly changing the window.location didn't worked out fine in chrome and safari. Happens that the location.hash doesn't create an entry in the history for chrome and safari. So you will have to use the pushstate. This is working for me in all browsers.
history.pushState({ page: 1 }, "title 1", "#nbb");
window.onhashchange = function (event) {
window.location.hash = "nbb";
};
Very simple and clean function to break the back arrow without interfering with the page afterward.
Benefits:
onbeforeunload
setInterval
so it doesn't break slow browsers and always works.unbeforeunload
which interrupts user with modal dialog.Note: some of the other solutions use onbeforeunload
. Please do not use onbeforeunload
for this purpose, which pops up a dialog whenever users try to close the window, hit backarrow, etc. Modals like onbeforeunload
are usually only appropriate in rare circumstances, such as when they've actually made changes on screen and haven't saved them, not for this purpose.
How It Works
That's it. No further messing around, no background event monitoring, nothing else.
Use It In One Second
To deploy, just add this anywhere on your page or in your JS:
<script>
/* break back button */
window.onload=function(){
var i=0; var previous_hash = window.location.hash;
var x = setInterval(function(){
i++; window.location.hash = "/noop/" + i;
if (i==10){clearInterval(x);
window.location.hash = previous_hash;}
},10);
}
</script>
In a modern browser this seems to work:
// https://developer.mozilla.org/en-US/docs/Web/API/History_API
let popHandler = () => {
if (confirm('Go back?')) {
window.history.back()
} else {
window.history.forward()
setTimeout(() => {
window.addEventListener('popstate', popHandler, {once: true})
}, 50) // delay needed since the above is an async operation for some reason
}
}
window.addEventListener('popstate', popHandler, {once: true})
window.history.pushState(null,null,null)
You simply cannot and should not do this. However, but this might be helpful
<script type = "text/javascript" >
history.pushState(null, null, 'pagename');
window.addEventListener('popstate', function(event) {
history.pushState(null, null, 'pagename');
});
</script>
Works in my chrome and firefox
None of the most-upvoted answers worked for me in Chrome 79. It looks like Chrome changed its behavior with respect to the Back button after Version 75, see here:
https://support.google.com/chrome/thread/8721521?hl=en
However, in that Google thread, the answer provided by Azrulmukmin Azmi at the very end did work. This is his solution.
<script>
history.pushState(null, document.title, location.href);
history.back();
history.forward();
window.onpopstate = function () {
history.go(1);
};
</script>
The problem with Chrome is that it doesn't trigger onpopstate event unless you make browser action ( i.e. call history.back). Thats why I've added those to script.
I don't entirely understand what he wrote, but apparently an additional history.back() / history.forward()
is now required for blocking Back in Chrome 75+.