Sawant Akshay
Sawant Akshay

Reputation: 2814

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?

Upvotes: 254

Views: 869835

Answers (30)

Gajender Singh
Gajender Singh

Reputation: 1313

<script>
history.pushState(null, null, location.href);
window.onpopstate = function () {
    history.go(1);
};
</script>

Use this code in yr html to prevent back button

Upvotes: 0

Tel
Tel

Reputation: 91

If you link to your exam page using window.location.replace("ExamPage.html") this will remove anything for the back button to go back to.

Example button link... input type="button" onClick="window.location.replace('ExamPage.html');" value="Exam Page"

Sorry the chevrons are missing around the button example. When I add them, the example is not shown.

Upvotes: 0

RandomX
RandomX

Reputation: 199

If you use React, you can use NPM module: use-history-back-trap. This is a custom React hook which intercepts back navigation and allows to resume it later if needed.

Usage is super simple:

const SomeFunctionalReactComponent = () => {
   useHistoryBackTrap(approveNavigation)
   // ...
}

where approveNavigation is your function which returns true (or Promise) when you want to proceed with back navigation.

Upvotes: 0

owino
owino

Reputation: 153

Having gone through most of the existing answers, there is no solution that works in chrome.

The idea is make the browser to move forward one page in the session history, effectively preventing leaving this page using the back browser button. You do this by invoking the History.forward() method, by placing the following line in the page.

window.history.forward();

I found this solution at mdn web docs and it works in chrome.

Upvotes: 1

Neo Sono
Neo Sono

Reputation: 196

If you are using angular just use *ngIf=loggedout within a div or container div.

Set variable in component. If it's true show else router will redirect to home page. As per your configuration on router file.

This work for login and log out using username for example. As for other account related pages or internal pages it will be a bit hard to prevent. You might need to disable the whole browser nav tab.

Upvotes: 0

user5583316
user5583316

Reputation:

Try with this: Suppose there are two pages Page1 and Page2 and Page1 redirects to Page2

to prevent user from visiting Page1 using the back button you will need to place the above script in the Page1

$(document).ready(async function (){
    history.pushState(null, null, location.href);
    window.onpopstate = function () {
        history.go(1);
    };
})

Upvotes: 2

alexrnov
alexrnov

Reputation: 2534

Based on answer @Franklin Innocent F

Solution for Kotlin/JS (React):

import org.w3c.dom.events.Event
import kotlin.browser.document
import kotlin.browser.window

...
override fun componentDidMount() {
    window.history.pushState(null, "", window.location.href)
    window.history.back()
    window.history.forward()
    window.addEventListener("popstate", browserBackButtonHandler)
}

...
private val browserBackButtonHandler: (Event?) -> Unit = {
    window.history.go(1)
}

Upvotes: 0

Eng Mahmoud El Torri
Eng Mahmoud El Torri

Reputation: 503

How to block coming backwards functionality:

history.pushState(null, null, location.href);
window.onpopstate = function () {
  history.go(1);
};

Upvotes: 39

Abdelqoddous Rifai
Abdelqoddous Rifai

Reputation: 21

It's basically assigning the window's "onbeforeunload" event along with the ongoing document 'mouseenter' / 'mouseleave' events so the alert only triggers when clicks are outside the document scope (which then could be either the back or forward button of the browser)

    $(document).on('mouseenter', function(e) { 
            window.onbeforeunload = null; 
        }
    );
    
    $(document).on('mouseleave', function(e) { 
            window.onbeforeunload = function() { return "You work will be lost."; };
        }
    );

Upvotes: 1

John
John

Reputation: 3996

This is the first hit I get for the Google query "disable back button". My use case is a little different than the original posted question. I need to "disable the back button" for a user that has logged of of a secured web site (i.e. prevent a user from logging off and then another user being able to view information from the previous user by hitting the back button).

In short, the goal here is to prevent a user from seeing the applications page after the logged in user has logged off.

This can be achieved by adding the code shown below to the pages in the authenticated application.

A full example using Apache Shiro is available here:

https://github.com/NACHC-CAD/web-security-example/releases/tag/v2.0.0

<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="CACHE-CONTROL" content="NO-CACHE" />

<script>
    if(performance.navigation.type == 2){
        console.log("Doing reload");   
        location.reload(true);
        console.log("Done with reload");
    }
    console.log("Script loaded.")
</script>

Upvotes: 0

user9384
user9384

Reputation: 25

This code is full javascript. Put this on your home page or whatever you need when someon goes back it brings them to the page they were previously on.

<script type="text/javascript"> 
        function preventBack() { 
            window.history.forward();  
        } 
          
        setTimeout("preventBack()", 0); 
          
        window.onunload = function () { null }; 
    </script>

Upvotes: 0

Saksham Chaudhary
Saksham Chaudhary

Reputation: 637

Just run code snippet right away and try going back

history.pushState(null, null, window.location.href);
history.back();
window.onpopstate = () => history.forward();

Upvotes: 2

user14415508
user14415508

Reputation:

React

For modal component in React project, the open or close of the modal, controlling browser back is a necessary action.

  • The stopBrowserBack: the stop of the browser back button functionality, also get a callback function. This callback function is what you want to do:

    const stopBrowserBack = callback => {
      window.history.pushState(null, "", window.location.href);
      window.onpopstate = () => {
        window.history.pushState(null, "", window.location.href);
        callback();
      };
    };
    
  • The startBrowserBack: the revival of the browser back button functionality:

    const startBrowserBack = () => {
      window.onpopstate = undefined;
      window.history.back();
    };
    

The usage in your project:

handleOpenModal = () =>
  this.setState(
    { modalOpen: true },
    () => stopBrowserBack(this.handleCloseModal)
  );

handleCloseModal = () =>
  this.setState(
    { modalOpen: false },
    startBrowserBack
  );

Upvotes: 18

Wolden
Wolden

Reputation: 333

Here is another way to proceed. Instead of just trying to avoid the Back button functionality (which doesn't work reliably) we can add short SessionStorage conditions.

Say we have three different pages (page1, page2, and page3). On each page we got a link to click to acceed to the next one and we don't want the user to be able to go back to the previous page.

On the first page (page1.html) we create an SI (sessionStorage Item) with a dummy "prev" code and another one with "page1" code (SI "now"):

  PAGE 1  <button onclick="goto()">PAGE 2</button>

  -------------------

  let thispage = '1' // Or 123456 if preferred or make sense

  // You can replace this fixed 'thispage' value on each page with a script counting the clicks
  // or any other way to increase its value, i.e., thispage++
  // or what you want, even counting the url.length (lol)

  sessionStorage.setItem('prev', '0') // Dummy code
  sessionStorage.setItem('now', thispage)

  // You can here make this page unreachable with page2/page3 SI same conditions

  function goto(){
      window.location = "page2.html"
  }

On page2.html we use the usual NoBack script (if it works) and update SIs only if we're coming from page1:

  PAGE 2  <button onclick="goto()">PAGE 3</button>

  -------------------

  // If it works, let it work :-)

  history.pushState(null, null, location.href);
  history.back();
  history.forward();
  window.onpopstate = function () {
      history.go(1);
  };

  // else

  let thispage = '2' // 456789
  let thisprev = sessionStorage.getItem('now')
  if(sessionStorage.getItem('prev')==thispage) {
      console.log('USER is back on PAGE 2')
      setTimeout(function() { goto() }, 1000); // Remove log + setTimeout
  }
  if(thisprev !== thispage) {
      if(thisprev < thispage) {
          console.log('USER is coming from PAGE 1')
          sessionStorage.setItem('prev', thisprev)
          sessionStorage.setItem('now', thispage)
      }
      else {
          console.log('USER try to reload this page')
          setTimeout(function() { goto() }, 1000);
      }
  }

  function goto(){
      window.location = "page3.html"
  }

And on page3.html:

  PAGE 3  <button onclick="goto()">BACK TO PAGE 1</button>

  -------------------

  history.pushState(null, null, location.href);
  history.back();
  history.forward();
  window.onpopstate = function () {
      history.go(1);
  };

  let thispage = '3' // 999999
  let thisprev = sessionStorage.getItem('now')
  if(sessionStorage.getItem('prev') == thispage) {
      goto()
  }
  if(thisprev !== thispage) {
      if(thisprev < thispage) {
          sessionStorage.setItem('prev', thisprev)
          sessionStorage.setItem('now', thispage)
      }
      else {
          goto()
      }
  }
  function goto(){
      window.location = "page1.html" // Reinit test
  }

The advantage is that even if the user manually reloads the previous page (if he had time to see and remember the URL) it still works. It was not tested on all devices, but seems to work fine on Firefox + Chrome + Edge Windows 10 and Firefox + Chrome on OS X.

Upvotes: -1

gene b.
gene b.

Reputation: 12034

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). That's 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+.

Upvotes: 22

Franklin Innocent F
Franklin Innocent F

Reputation: 261

This code was tested with the latest Chrome and Firefox browsers.

<script type="text/javascript">
    history.pushState(null, null, location.href);
    history.back();
    history.forward();
    window.onpopstate = function () { history.go(1); };
</script>

Upvotes: 9

Fezal halai
Fezal halai

Reputation: 784

For restricting the browser back event:

window.history.pushState(null, "", window.location.href);
window.onpopstate = function () {
    window.history.pushState(null, "", window.location.href);
};

Upvotes: 45

Surajit Mitra
Surajit Mitra

Reputation: 414

history.pushState(null, null, document.URL);
window.addEventListener('popstate', function () {
    history.pushState(null, null, document.URL);
});

This JavaScript code does not allow any user to go back (works in Chrome, Firefox, Internet Explorer, and Edge).

Upvotes: 11

fatal_error
fatal_error

Reputation: 5973

Very simple and clean function to break the back arrow without interfering with the page afterward.

Benefits:

  • Loads instantaneously and restores original hash, so the user isn't distracted by URL visibly changing.
  • The user can still exit by pressing back 10 times (that's a good thing), but not accidentally
  • No user interference like other solutions using onbeforeunload
  • It only runs once and doesn't interfere with further hash manipulations in case you use that to track state
  • Restores original hash, so almost invisible.
  • Uses setInterval, so it doesn't break slow browsers and always works.
  • Pure JavaScript, does not require HTML5 history, works everywhere.
  • Unobtrusive, simple, and plays well with other code.
  • Does not use unbeforeunload which interrupts user with modal dialog.
  • It just works without fuss.

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

  1. Executes on page load
  2. Saves your original hash (if one is in the URL).
  3. Sequentially appends #/noop/{1..10} to the hash
  4. Restores the original hash

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 JavaScript code:

<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>

Upvotes: 3

Lakhan
Lakhan

Reputation: 13276

Try it with ease:

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

Upvotes: 5

JonBrave
JonBrave

Reputation: 4280

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.

Upvotes: 173

jgabb
jgabb

Reputation: 554

This seems to have worked for us in disabling the back button on the browser, as well as the backspace button taking you back.

history.pushState(null, null, $(location).attr('href'));
window.addEventListener('popstate', function () {
    history.pushState(null, null, $(location).attr('href'));
});

Upvotes: 2

Ajit Kamble
Ajit Kamble

Reputation: 153

Try this to prevent the backspace button in Internet Explorer which by default acts as "Back":

<script language="JavaScript">
    $(document).ready(function() {
    $(document).unbind('keydown').bind('keydown', function (event) {
        var doPrevent = false;

        if (event.keyCode === 8 ) {
            var d = event.srcElement || event.target;
            if ((d.tagName.toUpperCase() === 'INPUT' &&
                 (
                     d.type.toUpperCase() === 'TEXT'     ||
                     d.type.toUpperCase() === 'PASSWORD' ||
                     d.type.toUpperCase() === 'FILE'     ||
                     d.type.toUpperCase() === 'EMAIL'    ||
                     d.type.toUpperCase() === 'SEARCH'   ||
                     d.type.toUpperCase() === 'DATE' )
                ) ||
                d.tagName.toUpperCase() === 'TEXTAREA') {

                     doPrevent = d.readOnly || d.disabled;
                }
                else {
                    doPrevent = true;
                }
            }

            if (doPrevent) {
                event.preventDefault();
            }

            try {
                document.addEventListener('keydown', function (e) {
                    if ((e.keyCode === 13)) {
                        //alert('Enter keydown');
                        e.stopPropagation();
                        e.preventDefault();
                    }
                }, true);
            }
            catch (err) {
            }
        });
    });
</script>

Upvotes: 1

Valamas
Valamas

Reputation: 24759

In my case this was a shopping order. So I disabled the button. When the user clicked back, the button was disabled still. When they clicked back one more time, and then clicked a page button to go forward. I knew their order was submitted and skipped to another page.

In the case when the page actually refreshed which would make the button (theoretically), available; I was then able to react in the page load that the order was already submitted and redirected then too.

Upvotes: 0

hacker1033
hacker1033

Reputation: 1

I create one HTML page (index.html). I also create a one (mechanism.js) inside a script folder / directory. Then, I lay all my content inside of (index.html) using form, table, span, and div tags as needed. Now, here's the trick that will make back / forward do nothing!

First, the fact that you have only one page! Second, the use of JavaScript with span / div tags to hide and display content on the same page when needed via regular links!

Inside 'index.html':

<td width="89px" align="right" valign="top" style="letter-spacing:1px;">
    <small>
        <b>
            <a href="#" class="traff" onClick="DisplayInTrafficTable();">IN</a>&nbsp;
        </b>
    </small>
    [&nbsp;<span id="inCountSPN">0</span>&nbsp;]
</td>

Inside 'mechanism.js':

function DisplayInTrafficTable()
{
    var itmsCNT = 0;
    var dsplyIn = "";
    for (i=0; i<inTraffic.length; i++)
    {
        dsplyIn += "<tr><td width='11'></td><td align='right'>" + (++itmsCNT) + "</td><td width='11'></td><td><b>" + inTraffic[i] + "</b></td><td width='11'></td><td>" + entryTimeArray[i] + "</td><td width='11'></td><td>" + entryDateArray[i] + "</td><td width='11'></td></tr>";
    }
    document.getElementById('inOutSPN').innerHTML =
        "" +
        "<table border='0' style='background:#fff;'><tr><th colspan='21' style='background:#feb;padding:11px;'><h3 style='margin-bottom:-1px;'>INCOMING TRAFFIC REPORT</h3>" +
        DateStamp() +
        "&nbsp;&nbsp;-&nbsp;&nbsp;<small><a href='#' style='letter-spacing:1px;' onclick='OpenPrintableIn();'>PRINT</a></small></th></tr><tr style='background:#eee;'><td></td><td><b>###</b></td><td></td><td><b>ID #</b></td><td></td><td width='79'><b>TYPE</b></td><td></td><td><b>FIRST</b></td><td></td><td><b>LAST</b></td><td></td><td><b>PLATE #</b></td><td></td><td><b>COMPANY</b></td><td></td><td><b>TIME</b></td><td></td><td><b>DATE</b></td><td></td><td><b>IN / OUT</b></td><td></td></tr>" +
        dsplyIn.toUpperCase() +
        "</table>" +
        "";
    return document.getElementById('inOutSPN').innerHTML;
}

It looks hairy, but note the function names and calls, embedded HTML, and the span tag id calls. This was to show how you can inject different HTML into same span tag on same page! How can Back/Forward affect this design? It cannot, because you are hiding objects and replacing others all on the same page!

How can we hide and display? Here goes:

Inside functions in ' mechanism.js ' as needed, use:

document.getElementById('textOverPic').style.display = "none"; //hide
document.getElementById('textOverPic').style.display = "";     //display

Inside ' index.html ' call functions through links:

<img src="images/someimage.jpg" alt="" />
<span class="textOverPic" id="textOverPic"></span>

and

<a href="#" style="color:#119;font-size:11px;text-decoration:none;letter-spacing:1px;" onclick="HiddenTextsManager(1);">Introduction</a>

Upvotes: 0

Shailendra Sharma
Shailendra Sharma

Reputation: 6992

You simply cannot and should not do this. However, this might be helpful:

<script type = "text/javascript" >
    history.pushState(null, null, 'pagename');
    window.addEventListener('popstate', function(event) {
        history.pushState(null, null, 'pagename');
    });
</script>

This works in my Google Chrome and Firefox.

Upvotes: 2

user3789888
user3789888

Reputation: 123

<script src="~/main.js" type="text/javascript"></script>

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

    function noBack() {
        window.history.forward();
    }
</script>

Upvotes: 1

Sanchitos
Sanchitos

Reputation: 8589

This is the way I could it accomplish it.

Weirdly, changing window.location didn't work out fine in Google Chrome and Safari.

It happens that 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";
};

Upvotes: 14

vrfvr
vrfvr

Reputation: 845

<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>

Upvotes: 82

kohloth
kohloth

Reputation: 914

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);
    };
  }, []);

Upvotes: 0

Related Questions