26

I want to close pop up on click of back button for mobile. I implemented this using onhashchange:

window.onhashchange = function (event) {

};

In this case, if pop up is opened multiple times then on click of back button, it opens and closes the modal pop up. But, I want modal pop up to close on first back and navigate to prev page on next back.

I also tried using onbeforeunload, but it will show another alert to leave or stay on the page.

$(window).bind('beforeunload', function(e) {
    return false;
});

What is the best way to close the pop up on back button and redirect to prev page on next back?

Yogesh
  • 3,394
  • 9
  • 31
  • 46
  • are you using Apache Cordova / Phonegap to load your webview? – Liam Aug 27 '14 at 02:43
  • @Abhi NO, I am not using it – Yogesh Aug 27 '14 at 06:20
  • Well, This topic is the best solution here http://stackoverflow.com/questions/16870007/how-to-close-a-bootstrap-modal-with-the-browser-back-button-instead-of-going-back. I tried it and works great – Md. Amanur Rahman May 30 '15 at 14:04
  • Try this link [Solution with code snippet][1] [1]: http://stackoverflow.com/questions/23685304/close-jquery-dialog-when-the-user-presses-browsers-back-button/32793335#32793335 – pro Sep 26 '15 at 03:38

12 Answers12

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');
    });
}
kjetils
  • 191
  • 1
  • 3
  • on some old devices page will recieve an incorrect `onpopstate` while page `onload` –  Dec 08 '19 at 11:10
  • I had to add a return false; to the second function to make it work properly – Max Feb 12 '20 at 15:51
  • every time you open a modal a new history record is created. This fills your history up and if you open modal multiple times and need to navigate back (to the referral page), you need to hit back as many times as you opened modal to actually navigate to the previous page. – michal.jakubeczy Jun 18 '20 at 05:34
14

bootply.com was down when I was testing my answer. See the inline script and comments at the bottom of the code below. The rest is just Twitter Bootstrap boilerplate so that I could easily test it locally.

<!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>
Kayce Basques
  • 23,849
  • 11
  • 86
  • 120
  • 2
    @Kayace If modal opened and closed multiple time and then back button is pressed. It is toggling between before and after and not going to prev page. – Yogesh Aug 26 '14 at 14:06
  • Hi @Yogesh. I see what you mean. The problem is that every time we update the window hash value, that update is getting added as a new entry in the user's browsing history. Let me think about this one and get back to you. – Kayce Basques Aug 26 '14 at 22:46
  • Hi @Yogesh. Check out my update. I think the comments in the JavaScript code sufficiently explain what's going on, but let me know if anything is unclear and I'll update my answer. – Kayce Basques Aug 26 '14 at 23:42
  • @Kayace Thanks a lot. window.history.back() did the trick well. Also, I removed the timer and used onhashchange to handle when only back button is used to close modal. window.onhashchange = function () { if(window.location.hash == "#before") { //closeModal(); } } – Yogesh Aug 27 '14 at 07:41
  • @KayceBasques I asked a question like this and I would be so appreciative if you could take a look at it. Here is the link: https://stackoverflow.com/questions/75970812/closing-a-related-modal-when-the-user-clicks-the-browsers-back-button – Ali Ehyaie Apr 09 '23 at 18:00
3

This is my solution for bootstrap modals. It adds support closing with back button to all bootstrap modals. You can adapt it for your non-bootstrap popups.

//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');
        }
    });
})();
Fatih K.
  • 393
  • 3
  • 6
3

I write this code for my own website

and tested too many times with different devices and browsers

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");
};
  • dont use $(document).ready instead of window.onload
2

This could be done easily using Apache Cordova but not sure if you are using it to show your page in webview.

function onBackKeyDown(e) {
  e.preventDefault();

}
document.addEventListener("backbutton", onBackKeyDown, false);

http://cordova.apache.org/docs/en/2.4.0/cordova_events_events.md.html#backbutton

Liam
  • 2,837
  • 23
  • 36
  • On Back button press, I just wanted to close modal if any modal already opened. I'm using Bootstrap3 modal. Thanks – Niks Jain Apr 04 '16 at 13:23
  • @niks-jain `function onBackKeyDown(e){ e.preventDefault(); $(".modal").modal("hide"); }` –  Dec 08 '19 at 11:15
2

according to http://www.mylearning.in/2015/06/close-modal-pop-up-on-back-button.html

    $('#myModal').on('show.bs.modal', function(e) {
        window.location.hash = "modal";
    });

    $(window).on('hashchange', function (event) {
        if(window.location.hash != "#modal") {
            $('#myModal').modal('hide');
        }
    });
Raymond Ativie
  • 1,747
  • 2
  • 26
  • 50
  • I asked a question like this and I would be so appreciative if you could take a look at it. Here is the link: https://stackoverflow.com/questions/75970812/closing-a-related-modal-when-the-user-clicks-the-browsers-back-button – Ali Ehyaie Apr 10 '23 at 05:56
2

By clicking back, automatically $('.modal').hide() function get activated. So no need to hide modal. We can see grey shaded background after back button.You can use either of these line of code to close modal pop up.

  1. $('.modal' ).modal( 'hide' ).data( 'bs.modal', null ); [work on bootstrap 3]

Or

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

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

Inspect the page when modal is active you can see these classes. Do correct me if this method is wrong or other simple way exist.

Himanshu Shekhar
  • 1,196
  • 1
  • 16
  • 35
2

Just add this code to script:

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

and the above code works perfectly even though the modal is opened and closed several times.

*note: jQuery 3.^ Bootstrap 4.^

ARGVN
  • 41
  • 5
0

My Solution in 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);
    }
  });
});
wutzebaer
  • 14,365
  • 19
  • 99
  • 170
  • I asked a question like this and I would be so appreciative if you could take a look at it. Here is the link: https://stackoverflow.com/questions/75970812/closing-a-related-modal-when-the-user-clicks-the-browsers-back-button – Ali Ehyaie Apr 10 '23 at 05:55
0

Issue : When a modal is open and the user clicks browser's back button, the page navigates (backwards or forward) but the modal remains open.

Solution :

In Javascript :

$(window).on('popstate', function() {
  $('.modal').click();     
});

In Angular :

  ngAfterViewInit() {
$(window).on('popstate', function() {
  $('.modal').click();     
});}
pkp
  • 21
  • 3
0

I don't like hash. And this code without hash in 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
      }
    }
  }
-1

I'll did it like this :

// 2.0 and above
@Override
public void onBackPressed(evt) {
    evt.preventDefault();
    closeTab();
}

// Before 2.0
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        evt.preventDefault();
        closeTab();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

--> These are handlers btw, need addEventListener =)

I've done it by memory, i'll check it later when i find it in my 'code mess' folder

Hotted24
  • 502
  • 3
  • 8