Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tdsymonds/23917215f591a9e1442a38783c77f0f0 to your computer and use it in GitHub Desktop.
Save tdsymonds/23917215f591a9e1442a38783c77f0f0 to your computer and use it in GitHub Desktop.
Cause back button to close Bootstrap modal windows
// For the below to work with the escape key
// I needed to add data-keyboard="false" to the modal
// in the HTML so that the standard bootstrap function
// doesn't fire, the below fires instead
$('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();
}
});
@tdsymonds
Copy link
Author

One caveat to note with the above is that if you go to a page with a modal, open the modal then press back, back, this will work as expected (it will close the modal and then navigate back to the previous page), however if the user presses forward, forward now the url will now show something like this:

http://example.co.uk/#modal

This messes up the history.

The way that I've got around this problem, is if you navigate to the url I've that I've described above, it will open the modal on the page load by adding the below snippet:

var hash = window.location.hash;
if (hash != ''){
    $(hash).modal('show');
}

This now provides a fully working solution. It also allows a user to share the modal and it everything should work as expected.

@jsoftwareengineering
Copy link

jsoftwareengineering commented Mar 12, 2017

This doesn't quite work on forward as navigating forward doesn't refresh the page (at least on macOS in Chrome and Safari this seems to be the case).

To fix this, add

else {
    $(modal).modal('show');
}

to the onhashchange function.

There does seem to be some remaining history bug using my solution here where after pressing forward, sometimes one must now press back twice to get back.

@rproenca
Copy link

rproenca commented Jul 5, 2017

Line 18 can be removed, right?
var hash = this.id;

@FynnZW
Copy link

FynnZW commented Jul 9, 2019

Works great, thanks!
My only problem was that clicks next to the modal closed it, but did not clear the history entry, so I had to click through several empty history entries.
My solution was to listen to the hide.bs.modal-event (instead of the different close-triggers individually) and using history.back() if the hash-fragment is still there (user did not use back button, but close icon, overlay, etc).
Might be helpful to someone else:

$('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('hide.bs.modal', function(e) {
  // hash fragment is still there? User did not use back-button, reset browser history manually now
  // check referrer to disable this for links that where copied and opened with the hash
  if (location.hash && document.referrer.includes(location.host)) {
    window.history.back();
  } 
});

edit: Added a referrer-check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment