我正在用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+中的返回。

其他回答

这就是我实现它的方法。

奇怪的是,换窗口。在谷歌Chrome和Safari浏览器中,location无法正常工作。

它发生在那个位置。hash不会在Chrome和Safari的历史记录中创建条目。所以你必须使用推力器。

这在所有浏览器中都适用。

history.pushState({ page: 1 }, "title 1", "#nbb");
window.onhashchange = function (event) {
    window.location.hash = "nbb";
};

非常简单和干净的函数打破向后箭头,而不干扰页面之后。

好处:

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.

注意:其他一些解决方案使用onbeforeunload。请不要为此目的使用onbeforeunload,当用户试图关闭窗口、点击反向箭头等时,onbeforeunload会弹出一个对话框。像onbeforeunload这样的情态动词通常只适用于很少的情况,比如当它们实际上在屏幕上做了更改并且没有保存它们时,不是为了这个目的。

工作原理

在页面加载时执行 保存您的原始散列(如果URL中有一个)。 依次追加#/noop/{1..10}到哈希 恢复原始哈希

就是这样。没有更多的混乱,没有后台事件监控,没有其他。

在一秒钟内使用它

要部署,只需在页面或JavaScript代码中添加这个:

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

基于@Franklin Innocent F的回答

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

如何阻止反向功能:

历史。pushState(null, null, location.href); 窗口。Onpopstate = function () { history.go (1); };

这是另一种方法。我们可以添加简短的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上运行良好。