Динамическая генерация списка карточек
Динамически генерируем список карточек на основе массива данных 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. Для дальнейшей практики можно экспериментировать с различными вариантами модальных окон и их функциональностью.