JS Модальные окна: Promise, делегирование событий и динамическая генерация карточек

Динамическая генерация списка карточек

Динамически генерируем список карточек на основе массива данных fruits. Функция render использует глобальный объект fruits (массив) и вставляет сгенерированный HTML в элемент с id fruits (используем document.querySelector(‘#fruits’)).

Шаблон карточки извлекаем из существующего HTML, оставляя повторяющуюся структуру. Функция itemToHtml принимает объект fruit и возвращает HTML-строку для одной карточки, заменяя placeholder’ы ({{fruit.img}}, {{fruit.title}}, {{fruit.price}}) данными из объекта fruit. Добавляем атрибут alt для тега <img>: alt="{{fruit.title}}".

Функция render использует метод map для массива fruits, преобразуя каждый элемент в HTML-строку с помощью itemToHtml. Полученный массив строк соединяется с помощью join(»), создавая единую HTML-строку. Эта строка устанавливается как innerHTML элемента с id fruits.

function itemToHtml(fruit) {
  return `
    <div class="fruit-card">
      <img src="${fruit.img}" alt="${fruit.title}">
      <h3>${fruit.title}</h3>
      <button data-btn="price" data-id="${fruit.id}">Посмотреть цену</button>
    </div>
  `;
}

function render() {
  const html = fruits.map(itemToHtml).join('');
  document.querySelector('#fruits').innerHTML = html;
}

После вызова render(), список карточек отображается динамически, упрощая работу с данными и изменение содержимого без изменения HTML-структуры.

Делегирование событий

Обработка кликов по кнопкам «Посмотреть цену» и «Удалить» осуществляется через делегирование событий. Добавляем один обработчик событий click для документа. В обработчике проверяем наличие атрибутов данных (dataset) у целевого элемента (event.target).

document.addEventListener('click', (event) => {
  event.preventDefault(); // Предотвращаем стандартное поведение браузера
  const btnType = event.target.dataset.btn;
  if (btnType === 'price') {
    //Обработка кнопки "Посмотреть цену"
  } else if (btnType === 'remove') {
    //Обработка кнопки "Удалить"
  }
});

Этот подход избегает добавления множества обработчиков для каждой кнопки.

Модальное окно: отображение цены и подтверждение удаления

Создаем модальные окна: priceModal для отображения цены и confirmModal для подтверждения удаления. Кнопке «Посмотреть цену» добавляем атрибуты data-btn="price" и data-id="${fruit.id}". В обработчике click получаем id фрукта из event.target.dataset.id, находим фрукт в массиве fruits и отображаем его цену в priceModal используя priceModal.setContet(). event.target.dataset.id преобразуется в число с помощью унарного плюса (+).

Кнопке «Удалить» добавляем атрибут data-btn="remove". Для обработки асинхронных операций используем Promise и плагин confirm.js, возвращающий Promise, разрешающийся при нажатии «Удалить» и отклоняющийся при нажатии «Отменить». Плагин использует метод destroy для удаления модального окна после закрытия. В обработчике события используем .then() и .catch().

// confirm.js
function confirm(options) {
  return new Promise((resolve, reject) => {
    // ... создание модального окна ...
    // ... обработчики кнопок resolve и reject ...
  });
}

// ... (в основном скрипте) ...
if (btnType === 'price') {
  const id = +event.target.dataset.id;
  const fruit = fruits.find(item => item.id === id);
  priceModal.setContet(`<p>Цена на <strong>${fruit.title}</strong>: $${fruit.price}</p>`);
  priceModal.open();
} else if (btnType === 'remove') {
  const id = +event.target.dataset.id;
  const fruit = fruits.find(item => item.id === id);
  confirm({ title: 'Вы уверены?', content: `Вы удаляете фрукт <strong>${fruit.title}</strong>` })
    .then(() => {
      fruits = fruits.filter(item => item.id !== id);
      render();
    })
    .catch(() => {}); // Обработка отмены
}

Для улучшения пользовательского опыта добавим анимацию открытия/закрытия модальных окон и удаление лишних элементов DOM после закрытия.

Рассмотрено создание динамических списков, делегирование событий, использование Promise для асинхронных операций и создание плагинов для модальных окон. Приложение демонстрирует эффективный подход к работе с модальными окнами и асинхронными действиями в JavaScript. Для дальнейшей практики можно экспериментировать с различными вариантами модальных окон и их функциональностью.

Что будем искать? Например,программа