我正在用PHP做一个在线测试应用程序。我想限制用户在考试中返回。

我尝试了下面的脚本,但它停止了我的计时器。

我该怎么办?

定时器存储在cdtimer.js文件中。

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

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

我有一个考试计时器,它从一个MySQL值中获取考试的持续时间。计时器随之启动,但当我输入禁用后退按钮的代码时,它就停止了。我有什么问题?


当前回答

在Chrome 79中,被点赞最多的答案没有一个对我有效。看起来Chrome在75版之后改变了后退按钮的行为。在这里看到的:

https://support.google.com/chrome/thread/8721521?hl=en

然而,在谷歌的帖子中,Azrulmukmin Azmi在最后提供的答案确实起作用了。这是他的解。

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

Chrome的问题是它不会触发onpopstate事件 除非你做出浏览器动作(即调用history.back)。这就是为什么 我已经将这些添加到脚本中。

我不完全明白他写了什么,但显然现在需要一个额外的history.back() / history.forward()来阻止Chrome 75+中的返回。

其他回答

//"use strict";
function stopBackSpace(e) {
    var ev = e || window.event;
    var obj = ev.target || ev.srcElement;
    var t = obj.type || obj.getAttribute('type');

    var vReadOnly = obj.getAttribute('readonly');
    var vEnabled = obj.getAttribute('enabled');
    // null
    vReadOnly = (vReadOnly == null) ? false : vReadOnly;
    vEnabled = (vEnabled == null) ? true : vEnabled;
    // when click Backspace,judge the type of obj.

    var flag1 = ((t == 'password' || t == 'text' || t == 'textarea') && ((vReadOnly == true || vReadOnly == 'readonly') || vEnabled != true)) ? true : false;

    var flag2 = (t != 'password' && t != 'text' && t != 'textarea') ? true : false;

    if (flag2) {
        e.keyCode = 0;
        e.cancelBubble = true;
        return false;
    }
    if (flag1) {
        e.keyCode = 0;
        e.cancelBubble = true;
        return false;
    }
}
if (typeof($) == 'function') {
    $(function() {
        $(document).keydown(function(e) {
            if (e.keyCode == 8) {
                return stopBackSpace(e);
            }
        });
    });
} else {
    document.onkeydown = stopBackSpace;
}

这是另一种方法。我们可以添加简短的SessionStorage条件,而不是仅仅尝试避免Back按钮功能(它不可靠地工作)。

假设我们有三个不同的页面(page1、page2和page3)。在每个页面上,我们都有一个链接,点击进入下一个页面,我们不希望用户能够回到上一页。

在第一个页面(page1.html),我们创建了一个SI (sessionStorage Item)与一个虚拟的“prev”代码和另一个与“page1”代码(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"
  }

在page2.html上,我们使用通常的NoBack脚本(如果它有效的话),只在来自page1时更新si:

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

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

这样做的好处是,即使用户手动重新加载前一个页面(如果他有时间查看并记住URL),它仍然可以工作。它没有在所有设备上进行测试,但似乎在Firefox + Chrome + Edge Windows 10和Firefox + Chrome在OS X上运行良好。

你可以放一个小脚本,然后检查。它将不允许您访问前一页。

这是用JavaScript完成的。

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

窗外。Onunload函数当您试图通过浏览器访问返回或上一页时触发。

这段代码是完整的javascript。 把这个放在你的主页或者其他你需要的地方当有人返回时,它会把他们带到他们之前所在的页面。

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

如果你使用React,你可以使用NPM模块:use-history-back-trap。这是一个自定义的React钩子,它拦截向后导航,并允许在需要时恢复它。

用法超级简单:

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

其中approveNavigation是你的函数,当你想继续向后导航时,它返回true(或Promise)。