Введение
Итак, из того, что я понимаю (я пояснил это с помощью OP в комментариях к вопросу), мы хотим изменить URL-адрес всякий раз, когда пользователь открывает модальное окно / закрывает модальное, чтобы предоставить ссылку наэтот модальный.Google Chrome делает то же самое на своей странице настроек, и я также вижу несколько других вариантов использования для этого.
Мы могли бы использовать window.history
API, так как он предназначен для этого.за.Однако это, вероятно, дает нам дополнительную работу - если кто-то вводит один из этих URL-адресов, вам нужны серверные правила для работы с ним (например, .htaccess), и я бы предпочел, чтобы этот работал для максимально возможного числа людей.
Поэтому я собираюсь использовать часть URL #
.Идея состоит в том, что, если пользователь открывает модальное окно, конец URL-адреса может измениться на #modalOne
(например) и вернуться к #
, когда пользователь закроет его.Если пользователь вручную вводит #
или щелкает по ссылке в ссылке, появится соответствующий модал (если такой модал существует).
Это будет сделано в двух частях: добавление модалов /удалите URL-адреса #
и отобразите модалы, основанные на URL-адресе.
Код
Я хочу, чтобы это было максимально простым и расширяемым для вас - его легко масштабировать сиспользование его для 1 модального до 100 без написания дополнительного кода.
Метод, который, кажется, работает лучше всего, использует атрибут данных на модале, чтобы указать его #
заголовок URL.Атрибут данных - это просто пользовательский атрибут HTML, который вы можете поместить в любой элемент.В нашем случае это будет тот же элемент с атрибутом UIKit uk-modal
.Я решил назвать это data-modal
, но вы можете называть это как угодно, если вы везде непротиворечивы, мы ссылаемся на него и начинаем имя с data-
.
Вот как модальное определение можетпосмотрите:
<div id="modal" uk-modal data-modal="test">
<div class="uk-modal-dialog uk-modal-body">
<h2 class="uk-modal-title">Modal</h2>
Some modal window<br>
<button class="uk-modal-close" type="button">Close</button>
</div>
</div>
Этот модал имеет атрибут data-modal
, равный test
- это означает, что при открытии он изменит URL-адрес на #test
.
Теперь,нам нужно на самом деле реализовать это.Вам нужно добавить следующий код JS где-нибудь на вашей странице:
let isChangingModal = false;
window.addEventListener("load", ()=>{
for (let modal of document.querySelectorAll("[data-modal]")) {
modal.addEventListener("beforeshow", ()=>{
isChangingModal = true;
window.location.hash = "#" + modal.getAttribute("data-modal");
});
modal.addEventListener("beforehide", ()=>{
isChangingModal = true;
window.location.hash = "#";
});
}
showModalFromURL();
});
function showModalFromURL() {
if (isChangingModal) {
isChangingModal = false;
return;
}
let modal = document.querySelector(`[data-modal="${window.location.hash.slice(1)}"]`);
if (modal) {
UIkit.modal(modal).show();
}
}
window.onhashchange = showModalFromURL;
Ниже я объясню, как это работает.
Как это работает
Когда страница загружается,нам нужно добавить обработчики событий во все модалы с атрибутами data-modal
- нам нужно обработать события onbeforeshow
и onbeforehide
.Это позволяет нам вызывать код, когда эти модалы показаны или скрыты.Обратите внимание, что это означает, что вы можете исключить модальное из этой схемы, просто не добавляя к нему атрибут data-modal
.
Мы делаем это путем зацикливания всех модальных атрибутов с атрибутом при загрузке страницы.
Примечание: предполагается, что вы не добавляете модалы через JS после загрузки страницы.Если вы это сделаете, просто измените это на функцию и вызывайте ее как при загрузке страницы, так и всякий раз, когда добавляете новый модал.
document.querySelectorAll("[data-modal]")
дает вам все DOM-узлы для элементов, которые имеют этот атрибут -посмотрите дополнительную документацию (селекторы атрибутов CSS и MDN для querySelector).Затем мы последовательно перебираем их и добавляем к ним оба события.
В каждом обработчике событий мы хотим изменить часть URL #
, что мы и делаем.Когда вы открываете модальное значение, мы меняем его на "#" + modal.getAttribute("data-modal")
- это означает #
перед любым значением, которое вы установили для этого атрибута.Для закрытия мы просто устанавливаем его в хэш.
Это все, что нам нужно для первой части.Для второй части я написал функцию, которая проверяет, что находится в хэше, пытается найти модал с атрибутом data-modal
с тем же значением, и, если это так, показывает его.Это должно происходить как при загрузке страницы (они щелкали по внешней ссылке), так и всякий раз, когда хэш-часть URL-адреса изменяется (они щелкали ссылку на странице, редактировали URL-адрес, вы изменяли ее с помощью кода в другом месте и т. Д.).
Конечно, была только одна проблема - сами модали изменяют хеш - мы не хотим, чтобы открытие модала вызывало его открытие, которое затем вызывало бы его открытие, которое затем .........
Вот почему у нас есть isChangingModal
логическое значение.Если это так, это означает, что мы меняем модальное состояние, и последующее изменение хеш-функции не должно использоваться в качестве события.
В противном случае мы используем querySelector, чтобы найти модальное, а затем UIKit, чтобы открыть его..
Дайте мне знать, если что-то не так / у вас есть какие-либо проблемы с этой реализацией.
Дальнейшее чтение
Использованиес UIKit 2.25
UIKit имеет только события hide
и show
(вместо beforehide
и `beforeshow) - разница в том, что они запускают после анимаций, а не перед ними.Это не должно быть большой проблемой для портирования.
Большая проблема в том, что они не работают изначально, только с jQuery.Если у вас все в порядке, вот небольшая часть моего кода, ранее измененного для работы с этими различными событиями - замените аналогичную часть в этом скрипте на это, и вы должны быть в порядке:
window.addEventListener("load", ()=>{
for (let modal of document.querySelectorAll("[data-popup]")) {
$(modal).on({
"show.uk.modal" : ()=>{
isChangingModal = true;
window.location.hash = "#" + modal.getAttribute("data-popup");
},
"hide.uk.modal" : ()=>{
isChangingModal = true;
window.location.hash = "#";
}
});
}
showModalFromURL();
});