点击返回按钮关闭弹出窗口

26

我希望在移动设备的“返回”按钮被点击时关闭弹出窗口。我使用onhashchange实现了这一点:

window.onhashchange = function (event) {

};
在这种情况下,如果弹出窗口被打开多次,那么在点击后退按钮时,它会打开和关闭模态弹出窗口。但是,我希望模态弹出窗口在第一次后退时关闭,并在下一次后退时导航到上一个页面。
我还尝试使用onbeforeunload,但它会显示另一个提示以离开或留在页面。
$(window).bind('beforeunload', function(e) {
    return false;
});

如何在按下后退按钮时关闭弹出窗口并重定向到上一个页面?


你是否正在使用Apache Cordova / Phonegap来加载你的Webview? - Liam
@Abhi 不,我没有在使用它。 - Yogesh
嗯,这个主题是最好的解决方案,网址为https://dev59.com/2XLYa4cB1Zd3GeqPb800。我尝试了一下,效果非常好。 - Md. Amanur Rahman
12个回答

18
if (window.history && window.history.pushState) {
    $('#myModal').on('show.bs.modal', function (e) {
        window.history.pushState('forward', null, './#modal');
    });

    $(window).on('popstate', function () {
        $('#myModal').modal('hide');
    });
}

在一些旧设备上,页面在onload时会收到一个错误的onpopstate - user5490177
我不得不在第二个函数中添加一个“return false;”以使其正常工作。 - Max
每次打开模态框都会创建一个新的历史记录。这会填满您的历史记录,如果您多次打开模态框并需要返回(到引荐页面),则需要按下与打开模态框相同次数的返回按钮才能实际导航到上一页。 - michal.jakubeczy

14

当我测试我的答案时,bootply.com网站挂了。请参阅下面代码底部的内联脚本和注释。其余部分只是Twitter Bootstrap样板,以便我可以轻松地在本地测试。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>modal.html</title>
    <!-- Bootstrap -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <p>If you press the back button now, you should return to whatever page you were on before this page.</p>
    <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">Show me the modal!</button>
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
            <h4 class="modal-title" id="myModalLabel">Modal title</h4>
          </div>
          <div class="modal-body">
            <p>If you press the web browser's back button OR the modal's close buttons, the modal will close and the hash will return to "modal.html#modalClosed".</p>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
          </div>
        </div>
      </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>

    <script type="text/javascript">
      // Immutable hash state identifiers. 
      var closedModalHashStateId = "#modalClosed";
      var openModalHashStateId = "#modalOpen";

      /* Updating the hash state creates a new entry
       * in the web browser's history. The latest entry in the web browser's
       * history is "modal.html#modalClosed". */
      window.location.hash = closedModalHashStateId;

      /* The latest entry in the web browser's history is now "modal.html#modalOpen".
       * The entry before this is "modal.html#modalClosed". */
      $('#myModal').on('show.bs.modal', function(e) {
        window.location.hash = openModalHashStateId;
      });  

      /* When the user closes the modal using the Twitter Bootstrap UI, 
       * we just return to the previous entry in the web 
       * browser's history, which is "modal.html#modalClosed". This is the same thing
       * that happens when the user clicks the web browser's back button. */
      $('#myModal').on('hide.bs.modal', function(e) {
        window.history.back();
      });      
    </script>
  </body>
</html>

2
@Kayace 如果模态框被打开和关闭多次,然后按下返回按钮。它会在之前和之后之间切换,而不是回到上一页。 - Yogesh
嗨@Yogesh。我明白你的意思。问题在于每次我们更新窗口哈希值时,该更新都会作为用户浏览历史记录中的新条目添加。让我考虑一下这个问题,然后再回复你。 - Kayce Basques
嗨@Yogesh。看看我的更新。我认为JavaScript代码中的注释已经足够解释了正在发生的事情,但如果有任何不清楚的地方,请告诉我,我会更新我的答案。 - Kayce Basques
@Kayace 非常感谢。window.history.back() 很好地解决了问题。此外,我移除了计时器并使用 onhashchange 来处理仅使用后退按钮关闭模态框的情况。window.onhashchange = function () { if(window.location.hash == "#before") { //closeModal(); } } - Yogesh
@KayceBasques 我问了一个类似的问题,如果你能看一下就太感激了。这是链接: https://stackoverflow.com/questions/75970812/closing-a-related-modal-when-the-user-clicks-the-browsers-back-button - Ali Ehyaie

3
这是我对Bootstrap模态框的解决方案。它增加了支持通过后退按钮关闭所有Bootstrap模态框的功能。您可以将其适应于非Bootstrap弹出窗口。
//Modal Closer With Back Button Support (Uses EventDelegation, so it works for ajax loaded content too.)
(function() {
    var activeOpenedModalId     = null;
    var isHidingModalByPopState = false;
    $(document).on('show.bs.modal', '.modal', function() {
        activeOpenedModalId  = $(this).attr('id');
        window.location.hash = activeOpenedModalId;
    }).on('hide.bs.modal', '.modal', function() {
        if(!isHidingModalByPopState) {
            window.history.back();
        }
        isHidingModalByPopState = false;
        activeOpenedModalId     = null;
    });
    $(window).on('popstate', function() {
        if(activeOpenedModalId && window.location.hash !== '#'+activeOpenedModalId) {
            isHidingModalByPopState = true;
            $("#" + activeOpenedModalId).modal('hide');
        }
    });
})();

3
我为自己的网站编写了这段代码,并在不同设备和浏览器上进行了多次测试。其中包括:Chromium 71、Chrome 67、FireFox 65、Android 4.1、Android 4.2 和 Android 7.1。
window.onload=function(){

    State=0;

    $(".modal").on("show.bs.modal",function(){
        path=window.location.pathname+window.location.search;
        history.pushState("hide",null,path);
        history.pushState("show",null,path);
        State="show";
    })
    .on("hidden.bs.modal",function(){
        if(!!State)
            history.go(State=="hide"?-1:-2);
    });

    setTimeout(function(){// fix old webkit bug
        window.onpopstate=function(e){
            State=e.state;
            if(e.state=="hide"){
                $(".modal").modal("hide");
            }
        };
    },999);

    $("#myModal").modal("show");
};

不要使用 $(document).ready 替代 window.onload

2

我问了这样的问题,如果你能看一下就感激不尽了。这是链接:https://stackoverflow.com/questions/75970812/closing-a-related-modal-when-the-user-clicks-the-browsers-back-button - Ali Ehyaie

2

只需要将以下代码添加到脚本中:

//update url to current url + #modal-open. example: https://your-url.test/home#modal-open
$('body').on('shown.bs.modal', '.modal', function () {
   location.hash = '#modal-open'
})

//remove #modal-open from current url, so the url back to: https://yoururl.test/home
$('body').on('hidden.bs.modal', '.modal', function () {
   location.hash = ''
})

//when user press back button
$(window).on('hashchange', function (e) {
   if(location.hash == ''){
      $('.modal').modal('hide')
   }
})

即使模态框被打开和关闭多次,上述代码仍然可以完美运行。

*注意: jQuery 3.^ Bootstrap 4.^


2

在返回按钮按下时,如果已经打开了任何模态框,我只想关闭模态框。我正在使用Bootstrap3模态框。谢谢。 - Niks Jain
@niks-jain function onBackKeyDown(e){ e.preventDefault(); $(".modal").modal("hide"); } - user5490177

2

点击返回按钮后,自动激活$('.modal').hide()函数。因此不需要隐藏模态框。在点击返回按钮后,我们可以看到灰色阴影背景。您可以使用以下任意一行代码来关闭模态弹出窗口。

  1. $('.modal' ).modal( 'hide' ).data( 'bs.modal', null ); [适用于 Bootstrap 3]

或者

  1. $('body').removeClass('modal-open');

    $('.modal-backdrop').remove();

当模态框处于活动状态时,请检查页面以查看这些类。如果此方法有误或存在其他简单的方法,请指正我。


0

我不喜欢哈希。而且这段代码中没有url中的哈希

  onModalMounted() => {
    if (isMobile) {
      history.pushState('modalShow', "", path); // add history point
      window.onpopstate = (e) => {
        e.stopPropagation()
        e.preventDefault()
        closeModalFn() // your func close modal
        history.replaceState('', "", path);
        window.onpopstate = () => {} // stop event listener window.onpopstate
      }
    } else {
      window.onpopstate = (e) => {
        e.stopPropagation()
        e.preventDefault()
        closeModalFn() // your func close modal
        window.onpopstate = () => {} // stop event listener window.onpopstate
      }
    }
  }

0

我的Angular解决方案

// push history state when a dialog is opened
dialogRef.afterOpened.subscribe((ref: MatDialogRef<any, any>) => {
  window.history.pushState(ref.id, '');
  // pop from history if dialog has not been closed with back button, and gurrent state is still ref.id
  ref.afterClosed().subscribe(() => {
    if (history.state === ref.id) {
      window.history.go(-1);
    }
  });
});

我问了这样一个问题,如果您能看一下就非常感激。这是链接:https://stackoverflow.com/questions/75970812/closing-a-related-modal-when-the-user-clicks-the-browsers-back-button - Ali Ehyaie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接