8

I just want to create a modal page which behaves the same either pushing the browser back button or the close button inside the modal, using bootstrap 3. I found a script which does that, but there is a problem. let's say I start off with a google.com, go to this modal page, then push the "Modal!" button, then push the browser back button, it will close the modal, if I push the back button again, it will take me back to google.com (all is good). But this time, if I open the modal page and close the modal using the "close" button instead. But now, I would have to push the back button twice to go back to google.com. If I open and close the modal with the close button inside of modal for like 10x. I found that I have to push the browser back button 10 more times to get back to google.com page. How to fix this problem? TIA

<!--html, bootstrap 3.2.0-->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
  <div class="modal-body">
    <p>If you press the web browser's back button not the modal's "close" button, the modal will close and the hash "#myModal" will be removed for the URL</p>
  </div>
  <div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal">Close</button></div>
</div>
</div>
</div>

<!--jquery-->
$('#myModal').on('show.bs.modal', function (e) {
    window.history.pushState('forward', null, '#modal');
});

$('#myModal').on('hide.bs.modal', function (e) {
    //pop the forward state to go back to original state before pushing the "Modal!" button
});

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

jsfiddle source

xam
  • 452
  • 2
  • 7
  • 15
  • Have you tried `window.history.back();` in modal hide event? – H. Jabi Oct 29 '16 at 00:02
  • i tried, instead of closing the modal, it goes to google.com entirely. – xam Oct 29 '16 at 00:08
  • I think that happens because when you close the modal, `window.history.back();` triggers a popstate, which triggers the modal to close again, which triggers another `window.history.back()` – Cave Johnson Oct 29 '16 at 00:13
  • So, it's firing. Maybe, using it with some conditions can bring up your result. Try debugging the history. You can also have a look here: http://html5doctor.com/history-api/ – H. Jabi Oct 29 '16 at 00:33
  • Thanks for all of your comment, which clear up what was going on. It took some time, but helped me to derived my solution. Thank you! – xam Nov 01 '16 at 16:48
  • i write my code here https://stackoverflow.com/a/54969370 –  Mar 03 '19 at 14:08
  • I answered a similar question and I think it will work for you: https://stackoverflow.com/a/60225289/5950111 – Amin Hemati Nik Feb 14 '20 at 11:25
  • Does this answer your question? [Close pop up on back button](https://stackoverflow.com/questions/25377383/close-pop-up-on-back-button) – node_modules Sep 26 '22 at 07:42

5 Answers5

9

I know this question was asked in 2016 and now it's 2022, but still I am answering this for the sake of those people who might be searching it in the future (I am sure people will).

Just copy and paste the below code to your site's .js file like custom.js or simply in the footer within $(document).ready(function(){}) like:

$(document).ready(function(){
  $('div.modal').on('show.bs.modal', function() {
    var modal = this;
    var hash = modal.id;
    window.location.hash = hash;
    window.onhashchange = function() {
      if (!location.hash){
        $(modal).modal('hide');
      }
    }
  });
  $('div.modal').on('hidden.bs.modal', function() {
    var hash = this.id;
    history.replaceState('', document.title, window.location.pathname);
  });
  // when close button clicked simulate back
  $('div.modal button.close').on('click', function(){
    window.history.back();
  })
  // when esc pressed when modal open simulate back
  $('div.modal').keyup(function(e) {
    if (e.keyCode == 27){
      window.history.back();          
    }
  });
});

I have seen a lot of people searching a solution to this and now I am applying a full stop to the searches. This should be doing the exact job that we have all been waiting for "Closing bootstrap modal on click of back button on PC and Mobile and on back swipe gesture on mobile too (tested)". Feel free to customize it as per your needs.

Happy day :)

node_modules
  • 4,790
  • 6
  • 21
  • 37
  • 3
    Awesome but instead of replacing the entire path with `window.location.pathname` you should replace the full URL instead like `window.location.href` to avoid loss of GET params in the URL – Emmanuel Jul 29 '20 at 23:22
  • If you are working with a Ruby on Rails application you should use `$(document).on('turbolinks:load', function() {` as the first line – Sara Fuerst Jan 03 '21 at 21:46
  • This only appears to work correctly the first time you click the back button to close a modal. If you open modals multiple times on the same page, it requires clicking back multiple times to close the modal? I also get this behavior with @a55 solution below – Digital Fusion Feb 02 '21 at 19:08
  • This doesn't work. After I open and close many times, I have to click back button many times to exit the page. thanks for trying. – xam Sep 14 '21 at 23:41
3

You can use the following code in order to just get rid of the modal window which is open and not move to the previous page of the browser accidentally.

//When ever the modal is shown the below code will execute.
$(".modal").on("shown.bs.modal", function()  {
    var urlReplace = "#" + $(this).attr('id'); 
    history.pushState(null, null, urlReplace); 
  });

  // This code gets executed when the back button is clicked, hide any/open modals.
  $(window).on('popstate', function() { 
    $(".modal").modal('hide');
  });

EDIT:- From the reply solutions

$(".modal").on("hidden.bs.modal",function(){history.back(1);});
Aamir Iqubal
  • 300
  • 2
  • 11
  • 1
    This have the same problem as my original question, where I open and close the modal 4 times, I have to click the back buttons 4 more times to get back to the initial page, so this is not good. Thanks for trying. – xam Jun 09 '17 at 18:06
  • You can make this solution better by setting a counter, and using history.forward() – Shehroz Ahmed Feb 06 '18 at 12:44
  • 1
    _thanks_, add `$(".modal").on("hidden.bs.modal",function(){history.back(1);});` –  Mar 03 '19 at 11:44
  • 1
    Much better. Cheers @ShehrozAhmed – Aamir Iqubal May 15 '19 at 12:51
  • This doesn't work. After I open and close many times, I have to click back button many times to exit the page. thanks for trying. – xam Sep 14 '21 at 23:40
1

I use this code for my own website

window.onload=function(){

    State=popset=0;
    setpops=function(){
        if(popset) return;popset=1;// dont set event multiple times
        window.onpopstate=function(e){
            State=e.state;
            if(e.state=="hide"){
                $(".modal").modal("hide").removeClass("in show");
                $(".modal-backdrop").remove();// force hide bg
                /* in some old devices .modal("hide") is not enough */
            }
        };
    };

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

    window.onpopstate=function(){setpops();};

    setTimeout(function(){setpops();},2000);// fix old webkit bug

};
  • dont use $(document).ready instead of window.onload

Tested on Chrome 87 ,   FireFox 84 ,   Chromium 88 ,   Android 4.1 / 4.2 / 7.1 / 9.0

(i am user5490177 deleted account which answer same question, this is a new improved version)

a55
  • 376
  • 3
  • 13
  • This only appears to work correctly the first time you click the back button to close a modal. If you open modals multiple times on the same page, it requires clicking back multiple times to close the modal? – Digital Fusion Feb 02 '21 at 19:05
  • @digital-fusion because of `$(".modal")` include all modal classes on the page, then it will close all modals if back button pressed 1 time – a55 Feb 02 '21 at 19:34
  • Sorry, I was not referring to multiple modals. If I load a page with this code and open the modal, then click back button, the modal closes. If I then open the modal again and click back button, the modal does not close (goes completely blank). I have to then click the back button a second time to get it to close. – Digital Fusion Feb 02 '21 at 19:48
  • This behavior appears to be due to using an iframe within the modal, and loading a URL into the iframe via an onClick event in the button that opens the modal. When the modal is closed, the iframe source is set back to about:blank. It confusing why this works the first time you open a modal, and then all subsequent openings require clicking back twice to close it – Digital Fusion Feb 02 '21 at 20:19
  • @digital-fusion i used this code in a website with ~100K users about 6 months, no body report us such behavior, we dont observe in different devices too – a55 Feb 03 '21 at 20:10
  • 1
    bravo! even though I couldn't fully understand your logic, but this solution works, even on jsfiddle! Finally a working solution that I could give my "check" mark to, after all these years. my thank you! – xam Sep 14 '21 at 23:53
0

I found a solution. Feel free to post any other elegant solutions.

$('#myModal').on('hide.bs.modal', function (e) {
    if(location.hash=='#modal')window.history.back();
});

$(window).on('popstate', function (event) {  //pressed back button
    if(event.state!==null)$('.modal').modal('hide');
});
xam
  • 452
  • 2
  • 7
  • 15
  • notice, this solution would not work on jsfiddle, because jsfiddle doesn't do hash. It will work on regular page. I also hope someone would come up more elegant solutions, which don't required any additional plugins and works on anything, even on jsfiddle. That's why I did not accept my own solution even it works. – xam Nov 01 '16 at 16:57
0

On button click popup will come up.

$(document).ready(function(){
      $(".popup-btn").click(function () {
          location.hash = "popup";
          $(".popup-panel").show();
      });
});

On location change it would get hidden:

$(window).bind('hashchange', function () {
      if (location.hash == null || location.hash == "") {
          $(".popup-panel").hide();
      }
});
Community
  • 1
  • 1
arush
  • 11
  • 2
  • I thought this work, but the browser back button would exit the page entirely, instead of just closing the modal. I need the browser back button to close the modal as if pushing the modal "Close" button, without leaving the page. Thanks for trying. – xam Jun 09 '17 at 18:16