как сказать addEventListener('click') что бы закрывал окно

У меня два модальных окна. Внутри каждого модального окна есть кнопка закрыть с классом close. Окна я получаю через querySelectorAll

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

let modal = document.querySelectorAll('.modal')
let btnHistory = document.getElementById('modal-btn-history')
let btnExpenses = document.getElementById('modal-btn-expenses')
let modalHistory = document.getElementById('modal-history')
let modalExpenses = document.getElementById('modal-expenses')
let btnClose = document.querySelectorAll('.close')

btnHistory.addEventListener('click', function(e) {
  e.preventDefault();
  modalHistory.style.display = 'flex';
})
btnExpenses.addEventListener('click', function(e) {
  e.preventDefault();
  modalExpenses.style.display = 'flex';
})
btnClose.addEventListener('click', function(e) {
  e.preventDefault();
  console.log(modal.length)
  for (let i = 0; i < modal.length; i++) {
    modal[i].style.display = 'none';
  }
})
<!-- header -->
<header class="header">
  <a href="" id="modal-btn-history" class="header-btn bg-info">История</a>
  <a href="" id="modal-btn-expenses" class="header-btn bg-danger">Расход</a>
</header>

<div class="modal fade" id="modal-history">
  <div class="modal-head bg-info">
    История
  </div>
  <div class="modal-body">

  </div>
  <div class="modal-footer">
    <a href="#" class="close w-block btn bg-secondary">Закрыть</a>
  </div>
</div>
<div class="modal fade" id="modal-expenses">
  <div class="modal-head bg-info">
    Расход
  </div>
  <div class="modal-body">

  </div>
  <div class="modal-footer">
    <a href="#" class="close w-block btn bg-secondary">Закрыть</a>
  </div>
</div>

Но у меня проблема с btnClose.addEventListener, потому что передаю список, а не конкретный элемент. А если передам конкретный, то закроется только первое окно.


Ответы (1 шт):

Автор решения: meine

class ModalManager {
  constructor() {
    this.actions = {
      'open-modal': 'open',
      'close-modal': 'close'
    };
    
    this.onClick = this.onClick.bind(this);
    
    document.addEventListener('click', this.onClick, false);
  }
  
  onClick(e) {
    const target = e.target.closest('[data-action]');
    
    if (e.target.closest('.modal__inner') && !target) return;
    
    if (!!this.current && !target) this.close();
    
    if (!target) return;
    
    const name = target.getAttribute('data-name');
    
    if (!name) console.error('Missing required parameter "data-name"');
    
    const action = target.getAttribute('data-action');
    
    if (!this.actions[action]) return;
    
    this[this.actions[action]](name);
  }
  
  open(name) {
    const modal = document.querySelector(`.modal[data-name="${name}"]`);
    
    if (!modal) console.error(`Modal with name ${name} does not exist on the current page`);
    
    modal.classList.add('modal--active');
    
    this.current = name;
  }
  
  close() {
    if (!this.current) return;
    
    const modal = document.querySelector(`.modal[data-name="${this.current}"]`);
    
    modal.classList.remove('modal--active');
    
    this.current = null;
  }
}

new ModalManager();
.modal {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100%;
  display: none;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, .3);
}

.modal__inner {
  width: 20vw; height: 20vw;
  background-color: #fff;
}

.modal--active { display: flex; }

[data-action] { cursor: pointer; }
<div data-name="first-modal" data-action="open-modal">First modal</div>
<div data-name="second-modal" data-action="open-modal">Second modal</div>

<div class="modal" data-name="first-modal">
  <div class="modal__inner">
    <h2 class="modal__title">First modal</h2>
    
    <div class="modal__close" data-name="first-modal" data-action="close-modal">Close modal</div>
  </div>
</div>

<div class="modal" data-name="second-modal">
  <div class="modal__inner">
    <h2 class="modal__title">Second modal</h2>
    
    <div class="modal__close" data-name="second-modal" data-action="close-modal">Close modal</div>
  </div>
</div>

→ Ссылка