Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript - close popup with back button

I have a custom popup functionality. What I want is for the browser back button to close this popup.

My ideal scenario would be to NOT show a hashtag in the URL bar.

I have tried putting window.history.pushState('forward', null, ''); in my showPopup() function and then doing the following:

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

This does work but the problem is when I manually close the popup I have to press the back button twice to navigate back to the previous page (obviously because a browser history entry was added when the popup was opened).

What is the best way of doing this? Can it be done without adding a browser history entry? Essentially what I am trying to do is replicate the behaviour of a mobile app. Press the back button in a mobile app will usually dismiss any open modals or context menus.

$('.popup-link').click(function() {
    showPopup();
});

$('.popup-close').click(function() {
    hidePopup();
});

function showPopup() {
    $('.popup').addClass('active');
}

function hidePopup() {
    $('.popup').removeClass('active');
}
.popup {
  background-color: #ccc;
  width: 300px;
  height: 300px;
  display: none;
}

.popup.active {
    display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="popup-link">Click</button>

<div class="popup">
    <button class="popup-close">x</button>
    <!-- popup content here -->
</div>
like image 368
MAX POWER Avatar asked Mar 24 '19 19:03

MAX POWER


People also ask

How to close modal when click back button?

When the modal dialog is open, pressing the back button closes it. On a multi-step modal dialog, the back button can even navigate backwards through the steps! On most web apps, pressing the back button while a modal dialog is open will navigate to the previous page, rather than closing the modal.

How to hide modal popup on browser back button?

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


3 Answers

It is not possible to do it without adding browser history entries since you cannot override the back button behaviour, see Intercepting call to the back button in my AJAX application: I don't want it to do anything

Sujumayas answer is a good option, you should introduce some additional variable though to avoid problems with the history when opening multiple popups (e.g. when clicking the button multiple times)

Here is some possible sample code:

let popupOpen = false;

$(".popup-link").click(function() {
    showPopup();
});

$(".popup-close").click(function() {
    window.history.back();
});

function showPopup() {
    if (popupOpen) {
        window.history.back();
    }
    popupOpen = true;
    window.history.pushState("forward", null, "");
    $(".popup").addClass("active");
}

function hidePopup() {
    popupOpen = false;
    $(".popup").removeClass("active");
}

$(window).on("popstate", function() {
    hidePopup();
});

Additionally please note that you might have problems with Opera Mini: https://caniuse.com/#search=history

like image 53
Stefan Blamberg Avatar answered Oct 29 '22 19:10

Stefan Blamberg


Altho I don't recommend to override regular browser history managment (back button) to use it as you please....

I think that the only thing you missed in your example is that the close button should not close the modal by itself, but instead just execute a backbutton event (which will eventually close the modal).

That simple fix and it will work as you wanted.

like image 30
sujumayas Avatar answered Oct 29 '22 19:10

sujumayas


I am doing already something like this, and it works nicely with the browser back-button and by pushing the android back-button as well. I am also not showing a hashtag in the URL bar.

Here is the stub (I just tried to apply that to Your scenario):

function freezeHistory() {
  window.history.pushState({}, window.document.title, window.location.href);
}

function goBack() {
  /*
    Custom history back actions: close panel, close popup, close drop-down menu
  */
  var popupOpen = $(".popup.active").length > 0;
  if(popupOpen) {
    hidePopup();
    return false;
  }
  window.history.back();
  return true;
}

function showPopup() {
  $('.popup').addClass('active');
  freezeHistory();
}

function hidePopup() {
  $('.popup').removeClass('active');
}

$(window).on("popstate", function(e) {
  /* 
     Browsers tend to handle the popstate event differently on page load. 
     Chrome (prior to v34) and Safari always emit a popstate event on page load, 
     but Firefox doesn’t.
  */
  goBack();
})

If this won't work for You out-of-the box, it is because IMHO You may need to clarify a little bit how do You expect to manage the page history. Feel free to add more detail to Your question if this isn't working as You'd expect now, but anyway, I strongly believe You got the idea and You are able to apply it inside the scenario of Your web-app.

like image 39
deblocker Avatar answered Oct 29 '22 19:10

deblocker