How can I stop the browser back button using JavaScript?

前端 未结 30 3299
没有蜡笔的小新
没有蜡笔的小新 2020-11-22 00:07

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.

相关标签:
30条回答
  • 2020-11-22 00:46

    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);
        };
      }, []);
    
    0 讨论(0)
  • 2020-11-22 00:48

    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";
    
        };
    
    0 讨论(0)
  • 2020-11-22 00:51

    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.
    • Unobrusive, 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 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>
    
    0 讨论(0)
  • 2020-11-22 00:52

    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)
    
    0 讨论(0)
  • 2020-11-22 00:52

    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

    0 讨论(0)
  • 2020-11-22 00:55

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

    0 讨论(0)
提交回复
热议问题