JavaScript - закрыть всплывающее окно с кнопкой назад - PullRequest
6 голосов
/ 24 марта 2019

У меня есть пользовательские всплывающие функции.Мне нужно, чтобы кнопка возврата браузера закрывала это всплывающее окно.

Мой идеальный сценарий - НЕ показывать хэштег в строке URL.

Я пытался вставить window.history.pushState('forward', null, ''); в свойshowPopup(), а затем выполните следующие действия:

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

Это работает, но проблема в том, что когда я закрываю всплывающее окно вручную, мне нужно дважды нажать кнопку «Назад», чтобы вернуться на предыдущую страницу (очевидно, потому чтозапись истории браузера была добавлена ​​при открытии всплывающего окна).

Каков наилучший способ сделать это?Можно ли это сделать без добавления записи истории браузера?По сути, я пытаюсь повторить поведение мобильного приложения.Нажатие кнопки «Назад» в мобильном приложении обычно отменяет любые открытые модальные или контекстные меню.

$('.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>

Ответы [ 7 ]

10 голосов
/ 27 марта 2019

Невозможно сделать это без добавления записей истории браузера, поскольку вы не можете переопределить поведение кнопки «Назад», см. Перехват вызова кнопки «Назад» в моем приложении AJAX: я не хочу, чтобы он что-либо делал

Sujumayas ответ является хорошим вариантом, хотя вы должны ввести некоторую дополнительную переменную, чтобы избежать проблем с историей при открытии нескольких всплывающих окон (например, при многократном нажатии кнопки)

Вот некоторые возможныепример кода:

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();
});

Кроме того, обратите внимание, что у вас могут быть проблемы с Opera Mini: https://caniuse.com/#search=history

4 голосов
/ 24 марта 2019

Хотя я не рекомендую переопределять обычное управление историей браузера (кнопка назад), чтобы использовать его по своему усмотрению ....

Я думаю, что единственное, что вы пропустили в своем примере, это то, что кнопка закрытия не должна закрывать модальное само по себе, а вместо этого просто выполнять событие backbutton (которое в конечном итоге закроет модальное).

Это простое исправление, и оно будет работать так, как вы хотели.

1 голос
/ 02 апреля 2019

У вас будет два варианта для реализации этого:

Опция 1: Использование события window.beforeunload. ссылка

$('.popup-link').click(function() {
  showPopup();
  $(window).on("beforeunload", hidePopup);
});

$('.popup-close').click(hidePopup);

function hidePopup() {
  $(window).off("beforeunload", hidePopup);
  $('.popup').removeClass('active');
}

Демонстрация


Опция 2: Использование API истории HTML5. ссылка

$('.popup-link').click(function() {
  showPopup();
  window.history.pushState('popup-open', null, '');
  $(window).on('popstate', hidePopup);
});

$('.popup-close').click(function() {
  if(history.state == 'popup-open')  {
    window.history.back();
  }
  hidePopup();
});

function hidePopup() {
    $(window).off('popstate', hidePopup);
    $('.popup').removeClass('active');
}

Демо


Редактировать : идея Суджумая такжедовольно хороший Демо

Кроме того, я рекомендую регистрировать события popstate / beforeunload только при необходимости и отменять их регистрацию, когда они вам больше не нужны, чтобы избежать накладных расходов.

0 голосов
/ 02 апреля 2019

Просто запустите window.history.back ();при закрытии всплывающего окна.

$('.popup-close').click(function() {
    hidePopup();
    window.history.back();
});
0 голосов
/ 01 апреля 2019

Вы можете добавить window.history.go (-2) к вашему popstate.Это должно вернуть вас дважды, что будет вашей исходной страницей до того, как модал добавит pushState запись в ваш объект истории.

И наоборот, вы можете использовать history.back (2) Использовать window.location.href, чтобы вернуться на 2 страницы назад и перезагрузить

0 голосов
/ 29 марта 2019

Откройте всплывающее окно и попробуйте перейти назад и вперед с помощью кнопок истории браузера

$(document).ready(function () {
    // manage popup state
    var poped = false;
    $('.popup-link').click(function () {
        // prevent unwanted state changtes
        if(!poped){
            showPopup();
        }
    });

    $('.popup-close').click(function () {
        // prevent unwanted state changtes
        if(poped){
            hidePopup();
        }
    });

    function showPopup() {
        poped = true;
        $('.popup').addClass('active');
        // push a new state. Also note that this does not trigger onpopstate
        window.history.pushState({'poped': poped}, null, '');
    }

    function hidePopup() {
        poped = false;
        // go back to previous state. Also note that this does not trigger onpopstate
        history.back();
        $('.popup').removeClass('active');
    }
});

// triggers when browser history is changed via browser
window.onpopstate = function(event) {
    // show/hide popup based on poped state
    if(event.state && event.state.poped){
        $('.popup').addClass('active');
    } else {
        $('.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>
0 голосов
/ 28 марта 2019

Я уже делаю что-то подобное, и это прекрасно работает с кнопкой возврата браузера и нажатием кнопки возврата Android.Я также не показываю хэштег в строке URL.

Вот заглушка (я только что попытался применить ее к вашему сценарию):

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();
})

Если это не будет работать дляВы из коробки, это потому, что ИМХО Вам, возможно, потребуется немного уточнить, как вы ожидаете управлять историей страниц.Не стесняйтесь добавлять больше деталей к вашему вопросу, если это не работает так, как вы ожидаете сейчас, но в любом случае, я твердо верю, что у вас есть идея и вы можете применить ее в сценарии вашего веб-приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...