By
Kaido
Использую готовый плагин для модальных окон(от MaxGraph). Проблема в том, что когда у меня открыто два модальных окна, для примера Форма + Политика конфендициальности, и мне нужно закрыть политику вместе с ней закрывается и другое модальное окно. В JS я не сильно разбираюсь(собственно из за этого и использую готовый плагин), можете помочь кто работал с этим плагином? Я примерно понимаю как он работает, но реализовать чтобы закрывалось только одно не получается.
<div class="content">
<button class="modal-btn" data-path="first" data-animation="fadeInUp" data-speed="1500">Открыть окно 1</button>
</div>
<div class="modal">
<div class="modal__wrapp" data-target="first">
<div class="modal__content">
<button class="modal__close">Закрыть</button>
модальное окно
<button data-path="policy">Политика</button>
</div>
</div>
<div class="modal__wrapp" data-target="policy">
<div class="modal__content">
<button class="modal__close">Закрыть</button>
политика
</div>
</div>
</div>
.modal {
--transition-time: 0.3s;
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 1000;
cursor: pointer;
overflow-y: auto;
overflow-x: hidden;
text-align: center;
opacity: 0;
visibility: hidden;
transition: opacity var(--transition-time), visibility var(--transition-time);
}
.modal__wrapp {
display: none;
cursor: default;
width: fit-content;
height: fit-content;
}
.modal__content{
position: absolute;
left: 500px;
width: 500px;
height: 500px;
display: flex;
color: white;
flex-direction: column;
text-align: left;
background-color: #000;
}
.modal__content button{
width: 200px;
height: 50px;
margin: 50px 0;
}
.modal.is-open {
opacity: 1;
visibility: visible;
transition: opacity var(--transition-time), visibility var(--transition-time);
}
.modal__wrapp.modal-open {
display: flex;
}
.disable-scroll {
position: relative;
overflow: hidden;
height: 100vh;
position: fixed;
left: 0;
top: 0;
width: 100%;
}
.fade {
opacity: 0;
transition: opacity var(--transition-time);
}
.fade.animate-open {
opacity: 1;
transition: opacity var(--transition-time);
}
.fadeInUp {
opacity: 0;
transform: translateY(vw(-100));
transition: opacity var(--transition-time), transform var(--transition-time);
}
.fadeInUp.animate-open {
opacity: 1;
transform: translateY(0);
transition: opacity var(--transition-time), transform var(--transition-time);
}
.modal__wrapp[data-target="policy"] .modal__content{
left: 1050px;
background-color: #000;
opacity: .5;
}
class Modal {
constructor(options) {
let defaultOptions = {
isOpen: () => {},
isClose: () => {},
}
this.options = Object.assign(defaultOptions, options);
this.modal = document.querySelector('.modal');
this.speed = false;
this.animation = false;
this.isOpen = false;
this.modalContainer = false;
this.previousActiveElement = false;
this.fixBlocks = document.querySelectorAll('.fix-block');
this.focusElements = [
'a[href]',
'input',
'button',
'select',
'textarea',
'[tabindex]'
];
this.events();
}
events() {
if (this.modal) {
document.addEventListener('click', function(e){
const clickedElement = e.target.closest('[data-path]');
if (clickedElement) {
let target = clickedElement.dataset.path;
let animation = clickedElement.dataset.animation;
if (clickedElement.classList.contains('modal-close')) {
this.close();
}
let speed = clickedElement.dataset.speed;
this.animation = animation ? animation : 'fade';
this.speed = speed ? parseInt(speed) : 300;
this.modalContainer = document.querySelector(`[data-target="${target}"]`);
this.open();
return;
}
if (e.target.closest('.modal__close')) {
this.close();
return;
}
}.bind(this));
window.addEventListener('keydown', function(e) {
if (e.keyCode == 27) {
if (this.isOpen) {
this.close();
}
}
if (e.keyCode == 9 && this.isOpen) {
this.focusCatch(e);
return;
}
}.bind(this));
this.modal.addEventListener('click', function(e) {
if (!e.target.classList.contains('modal__wrapp') && !e.target.closest('.modal__wrapp') && this.isOpen) {
this.close();
}
}.bind(this));
}
}
open() {
this.previousActiveElement = document.activeElement;
this.modal.style.setProperty('--transition-time', `${this.speed / 1000}s`);
this.modal.classList.add('is-open');
this.disableScroll();
this.modalContainer.classList.add('modal-open');
this.modalContainer.classList.add(this.animation);
setTimeout(() => {
this.options.isOpen(this);
this.modalContainer.classList.add('animate-open');
this.isOpen = true;
this.focusTrap();
}, this.speed);
}
close() {
if (this.modalContainer) {
this.modalContainer.classList.remove('animate-open');
this.modalContainer.classList.remove(this.animation);
this.modal.classList.remove('is-open');
this.modalContainer.classList.remove('modal-open');
this.enableScroll();
this.options.isClose(this);
this.isOpen = false;
this.focusTrap();
}
}
focusCatch(e) {
const focusable = this.modalContainer.querySelectorAll(this.focusElements);
const focusArray = Array.prototype.slice.call(focusable);
const focusedIndex = focusArray.indexOf(document.activeElement);
if (e.shiftKey && focusedIndex === 0) {
focusArray[focusArray.length - 1].focus();
e.preventDefault();
}
if (!e.shiftKey && focusedIndex === focusArray.length - 1) {
focusArray[0].focus();
e.preventDefault();
}
}
focusTrap() {
const focusable = this.modalContainer.querySelectorAll(this.focusElements);
if (this.isOpen) {
focusable[0].focus();
} else {
this.previousActiveElement.focus();
}
}
disableScroll() {
let pagePosition = window.scrollY;
this.lockPadding();
document.body.classList.add('disable-scroll');
document.body.dataset.position = pagePosition;
document.body.style.top = -pagePosition + 'px';
}
enableScroll() {
let pagePosition = parseInt(document.body.dataset.position, 10);
this.unlockPadding();
document.body.style.top = 'auto';
document.body.classList.remove('disable-scroll');
window.scroll({ top: pagePosition, left: 0 });
document.body.removeAttribute('data-position');
}
lockPadding() {
let paddingOffset = window.innerWidth - document.body.offsetWidth + 'px';
this.fixBlocks.forEach((el) => {
el.style.paddingRight = paddingOffset;
});
document.body.style.paddingRight = paddingOffset;
}
unlockPadding() {
this.fixBlocks.forEach((el) => {
el.style.paddingRight = '0px';
});
document.body.style.paddingRight = '0px';
}
}
const modal = new Modal({
isOpen: (modal) => {
console.log(modal);
console.log('opened');
},
isClose: () => {
console.log('closed');
},
});
Question
Super_Saimon
Добрый день! Я с чисто теоретическим вопросом касательно верстки сайта. Столкнулся с одним нюансом, который вызывает затруднения. Лучше начну сразу с нудного и длинного)) примера, так станет в разы понятней в чем суть моего вопроса. Допустим, имеем часть сайта, отвечающую за основной контент... назовем "main". У main есть container, отвечающий за центровку контента. И main делится, в свою очередь, на две части- main__left(блок под меню с возможной рекламой), и main__right (блок с основным контентом). И вот почти добрался до сути. Далее в main__left я создаю блок для навигации и блок для рекламы, к примеру. А в main__right, допустим, еще две колонки. Так вот, вся моя верстка заключается в том, что я стараюсь не плодить кучу вложенных блоков. То есть, на конкретном примере, main__right- я добавлю еще "content__right", "content__left". И в этих двух блоках буду прописывать и позиционирование относительно родителя, и относительно соседа. А когда смотрю примеры, то там чуть-ли под каждое свойство отдельный вложенный блок.То есть, позиционирование относительно родителя-один блок, позиционирование относительно соседа-делаем вложенный в предыдущем... Я вот не пойму что дает такая модель верстки. И если этот метод, если можно так сказать, "канонический", то где можно про это прочитать чтобы до такого "додуматься")). Я, просто, немало уже перечитал на этот счет(и таких популярных источников как htmlacademy, "Большая книга CSS" и т.д.). И вроде ж все понятно, а как-то мыслить правильно, что-ли, не получается. Может кто сможет объяснить мне, непутевому, в чем суть, в чем соль? Извиняюсь за такой нелепый вопрос.
Link to comment
Share on other sites
8 answers to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.