How can I stop the browser back button using JavaScript?

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.

What should I do?

The timer is stored in file cdtimer.js.

<script type="text/javascript">
    window.history.forward();
    function noBack()
    {
        window.history.forward();
    }
</script>

<body onLoad="noBack();" onpageshow="if (event.persisted) noBack();" onUnload="">

I have the exam timer which takes a duration for the exam from a MySQL value. The timer starts accordingly, but it stops when I put the code in for disabling the back button. What is my problem?


Solution 1:

There are numerous reasons why disabling the back button will not really work. Your best bet is to warn the user:

window.onbeforeunload = function() { return "Your work will be lost."; };

This page does list a number of ways you could try to disable the back button, but none are guaranteed:

http://www.irt.org/script/311.htm

Solution 2:

It is generally a bad idea overriding the default behavior of the web browser. A client-side script does not have the sufficient privilege to do this for security reasons.

There are a few similar questions asked as well,

  • How can I prevent the backspace key from navigating back?

  • How can I prevent the browser's default history back action for the backspace button with JavaScript?

You can-not actually disable the browser back button. However, you can do magic using your logic to prevent the user from navigating back which will create an impression like it is disabled. Here is how - check out the following snippet.

(function (global) {

    if(typeof (global) === "undefined") {
        throw new Error("window is undefined");
    }

    var _hash = "!";
    var noBackPlease = function () {
        global.location.href += "#";

        // Making sure we have the fruit available for juice (^__^)
        global.setTimeout(function () {
            global.location.href += "!";
        }, 50);
    };

    global.onhashchange = function () {
        if (global.location.hash !== _hash) {
            global.location.hash = _hash;
        }
    };

    global.onload = function () {
        noBackPlease();

        // Disables backspace on page except on input fields and textarea..
        document.body.onkeydown = function (e) {
            var elm = e.target.nodeName.toLowerCase();
            if (e.which === 8 && (elm !== 'input' && elm  !== 'textarea')) {
                e.preventDefault();
            }
            // Stopping the event bubbling up the DOM tree...
            e.stopPropagation();
        };
    }
})(window);

This is in pure JavaScript, so it would work in most of the browsers. It would also disable the backspace key, but that key will work normally inside input fields and textarea.

Recommended Setup:

Place this snippet in a separate script and include it on a page where you want this behavior. In the current setup it will execute the onload event of the DOM which is the ideal entry point for this code.

Working DEMO!

It was tested and verified in the following browsers,

  • Chrome.
  • Firefox.
  • Internet Explorer (8-11) and Edge.
  • Safari.

Solution 3:

I came across this, needing a solution which worked correctly and "nicely" on a variety of browsers, including Mobile Safari (iOS 9 at time of posting). None of the solutions were quite right. I offer the following (tested on Internet Explorer 11, Firefox, Chrome, and Safari):

history.pushState(null, document.title, location.href);
window.addEventListener('popstate', function (event)
{
  history.pushState(null, document.title, location.href);
});

Note the following:

  • history.forward() (my old solution) does not work on Mobile Safari --- it seems to do nothing (i.e., the user can still go back). history.pushState() does work on all of them.
  • the third argument to history.pushState() is a url. Solutions which pass a string like 'no-back-button' or 'pagename' seem to work OK, until you then try a Refresh/Reload on the page, at which point a "Page not found" error is generated when the browser tries to locate a page with that as its URL. (The browser is also likely to include that string in the address bar when on the page, which is ugly.) location.href should be used for the URL.
  • the second argument to history.pushState() is a title. Looking around the web most places say it is "not used", and all the solutions here pass null for that. However, in Mobile Safari at least, that puts the page's URL into the history dropdown the user can access. But when it adds an entry for a page visit normally, it puts in its title, which is preferable. So passing document.title for that results in the same behaviour.

Solution 4:

<script>
    window.location.hash = "no-back-button";

    // Again because Google Chrome doesn't insert
    // the first hash into the history
    window.location.hash = "Again-No-back-button"; 

    window.onhashchange = function(){
        window.location.hash = "no-back-button";
    }
</script>