Как исправить «Одна кнопка закрытия закрывает все модалы» - PullRequest
2 голосов
/ 23 сентября 2019

Я пытаюсь создать модальный vanilla JavaScript , который может настраиваться пользователем при создании экземпляра из файла HTML (или файла JS).Однако, когда дело доходит до работы с функцией close () для закрытия модального режима, вместо того, чтобы закрывать ОДИН модальный за раз, используя кнопку закрытия, кнопка закрытия FIRST-модального режима закрывает ВСЕ модальные страницы.Я не уверен, что я делаю не так ...

Я исследовал другие подобные ванильные JavaScript, настраиваемые модальные библиотеки, но большинство из них используют либо jQuery, некоторые фреймворки, либо содержат много сложностей.что я не знаком с (я все еще начинающий).Я исследовал GitHub, CodePen, Google и здесь;но мне еще предстоит найти решение, которое бы удовлетворяло тому, что мне нужно.

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

https://codepen.io/jdriviere/pen/zYOyJvv?editors=0011

Но вот моя функция close ():

Modal.prototype.close = function() {
  let modal = document.getElementById(this.options.id);
  let modalBody = modal.children[0];

  // Delete elements from Modal Body
  for (let i = 0; i < modalBody.children.length; i++) {
    modalBody.removeChild(modalBody.children[i]);
  } // End of LOOP

  // Delete Modal Body from Modal
  modal.removeChild(modalBody);

  // Delete Modal from DOM
  modal.style.display = 'none';
  document.body.removeChild(modal);

  return this;
};

Я ожидаю, что код закроет ОДИН модальный за раз, и предпочтительно модал, который имеетправильный идентификатор (который должен быть назначен пользователем или по умолчанию иметь идентификатор «NoID»).Вместо этого, если я закрываю последующие модалы, он закрывает их;но если я закрою ПЕРВУЮ, она закроет ВСЕ из них.Кроме того, есть ли способ init () модальные функциональные возможности, как только вы создаете модальный экземпляр (я ненавижу инициировать их вручную)?Если это так, пожалуйста, включите ваше решение здесь, если не так много.

Занимался этим уже довольно давно.Ваша помощь будет принята с благодарностью.

Спасибо.:)

Ответы [ 2 ]

0 голосов
/ 23 сентября 2019

Проблема в функции init:

/**
* Initializes the inner functions of the modal, such as the closing capacity.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.init = function() {
  // let closeBtnAll = document.querySelectorAll('.modal-close');
  let modal = document.getElementById(this.options.id);
  let closeBtn = modal.querySelector('.modal-close'); 
  
  // Assign close() function to all close buttons
  closeBtn.addEventListener('click', () => {
    console.log(this.options);
    if (this.options.closable) {
      this.close();
    }
  })
  
  // Press ESC to close ALL modals
  
  return this;
};

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

0 голосов
/ 23 сентября 2019

В вашем коде есть пара ошибок:

  1. Всегда используйте правильный шаблон идентификатора для элемента HTML.Вы использовали n/a для модального объекта, у которого нет свойства id в их объекте options.Использование таких id сломает селектор запросов при использовании jQuery.
  2. Поскольку вы вызываете функцию init() дважды, и в каждом вызове для init() closeBtn выбирает обе кнопки закрытия.из двух модальных и присвоение обработчика события клика для каждого из них дважды.По этой причине, когда вы нажимали одну кнопку, событие нажатия для другой кнопки выполнялось само собой.Таким образом, вы можете только один раз связать функцию щелчка только с той кнопкой закрытия модального окна, для которой была вызвана функция init().Я использовал let closeBtn = document.querySelector('#'+this.options.id + ' .modal-close');, чтобы выбрать конкретную кнопку закрытия внутри этой функции init().

В целом ваш код JS будет выглядеть следующим образом:

/**
* Blueprint function (class) that describes a Modal object.
* @param {Object} options Object parameter containing elements that describe the Modal.
* @returns {Object} options Returns options from current modal object.
*/
function Modal(options) {
    // If constructor params is available
    if (options) {
    this.options = options;
  } else {
    this.options = {};

  } // End of IF-ELSE

  // Add to options object
  if (options.id) {
    // Check type of ID entry
    if (typeof options.id === 'number') {
      this.options.id = options.id.toString();
    } else {
      this.options.id = options.id;
    } // End of IF-ELSE
  } else if (options.id === undefined) {
    this.options.id = 'NA';
  } // End of IF-ELSE
  if (options.name) {
    this.options.name = options.name;
  } // End of IF
  if (options.closable) {
    this.options.closable = options.closable;
  } // End of IF

  return this;
};

// Prototypes
/**
* Displays some information concerning the current Modal object.
* @returns {Object} this Returns current modal object.
*/
Modal.prototype.open = function() {
    let demo = document.getElementById('demo');

  return this;
};

/**
* Creates an instance of a Modal object with the specified object elements.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.create = function() {
  // Create Modal Element
  let modal = document.createElement('div');
  let modalBody = document.createElement('div');

  // Create Modal
  !modal.classList.contains('modal') ?
    modal.classList.add('modal') :
    modal.classList.add('');
  modal.id = this.options.id || 'noID';

  // Create modal body element
  !modalBody.classList.contains('modal-body') ?
    modalBody.classList.add('modal-body') :
    modalBody.classList.add('');document.querySelector('#' + this.options.id + ' .modal-close');
  modal.appendChild(modalBody);

  // Adding modal sub-elements  
  if (this.options.title) {
    let modalTitle = document.createElement('h2');
    !modalTitle.classList.contains('modal-title') ?
      modalTitle.classList.add('modal-title') :
      modalTitle.classList.add('');
    modalTitle.textContent = this.options.title;
    modalBody.appendChild(modalTitle);
    console.log('Added title!');
  } // End of IF

  if (this.options.subtitle) {
    let modalSubtitle = document.createElement('h4');
    !modalSubtitle.classList.contains('modal-subtitle') ?
      modalSubtitle.classList.add('modal-subtitle') :
      modalSubtitle.classList.add('');
    modalSubtitle.textContent = this.options.subtitle;
    modalBody.appendChild(modalSubtitle);
    console.log('Added subtitle!');
  } // End of IF

  if (this.options.content) {
    let modalContent = document.createElement('p');
    !modalContent.classList.contains('modal-content') ?
      modalContent.classList.add('modal-content') :
      modalContent.classList.add('');
    modalContent.textContent = this.options.content;
    modalBody.appendChild(modalContent);
    console.log('Added contents!');
  } // End of IF

  if (this.options.closable) {
    let modalClose = document.createElement('span');
    !modalClose.classList.contains('modal-close') ?
      modalClose.classList.add('modal-close') :
      modalClose.classList.add('');
    modalClose.innerHTML = '&times;';
    modalBody.appendChild(modalClose);
    console.log('Close button added!');
  } // End of IF

  document.body.appendChild(modal);
  console.log('Modal created with ID', modal.id);

  return this;
};

/**
* Closes the current Modal object.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.close = function() {    
  let modal = document.getElementById(this.options.id);
  let modalBody = modal.children[0];

  // Delete elements from Modal Body
  for (let i = 0; i < modalBody.children.length; i++) {
    modalBody.removeChild(modalBody.children[i]);
  } // End of LOOP

  // Delete Modal Body from Modal
  modal.removeChild(modalBody);

  // Delete Modal from DOM
  modal.style.display = 'none';
  document.body.removeChild(modal);

  return this;
};

/**
* Initializes the inner functions of the modal, such as the closing capacity.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.init = function(e) {
  // let closeBtnAll = document.querySelectorAll('.modal-close');
  let closeBtn = document.querySelector('#'+this.options.id + ' .modal-close');

  // Assign close() function to all close buttons
  closeBtn.addEventListener('click', () => {
    if (this.options.closable) {
      this.close();
    }
  })

  // Press ESC to close ALL modals

  return this;
};

// Create a Modal object
let modal1 = new Modal({
  id: 'post1',
  name: 'modal',
  title: 'First Post',
  subtitle: 'I contain all the elements',
  content: 'This is awesome!',
  closable: true
});

let modal2 = new Modal({
  title: 'Second Post',
  subtitle: 'Trying new things',
  content: 'Hehehehehe',
  closable: true
});

modal1.open();
modal1.create();
modal1.init();

modal2.open();
modal2.create();
modal2.init();

Просто замените вышеуказанный код JS в коде и попробуйте.Это будет работать.

...