diff --git a/js/filters.js b/js/filters.js new file mode 100644 index 0000000..0af4b18 --- /dev/null +++ b/js/filters.js @@ -0,0 +1,58 @@ +import { debounce } from './util.js'; + +const photoFilters = document.querySelector('.img-filters'); +const filterButtons = photoFilters.querySelectorAll('.img-filters__button'); +const RANDOM_PHOTOS_COUNT = 10; + +function applyFilter(photos, filter) { + switch (filter) { + case 'filter-random': + return photos + .slice() + .sort(() => Math.random() - 0.5) + .slice(0, RANDOM_PHOTOS_COUNT); + case 'filter-discussed': + return photos + .slice() + .sort((a, b) => b.comments.length - a.comments.length); + default: + return photos; + } +} + +export function initFilters(photos, renderThumbnails) { + photoFilters.classList.remove('img-filters--inactive'); + + let selectedFilter = null; + + const applyDebouncedFilter = debounce(() => { + if (selectedFilter) { + clearThumbnails(); + const filteredPhotos = applyFilter(photos, selectedFilter); + renderThumbnails(filteredPhotos); + } + }, 500); + + filterButtons.forEach((button) => { + button.addEventListener('click', (evt) => { + // Удаляем класс активности у всех кнопок + filterButtons.forEach((btn) => btn.classList.remove('img-filters__button--active')); + + // Устанавливаем класс активности для текущей кнопки + evt.target.classList.add('img-filters__button--active'); + + // Сохраняем выбранный фильтр + selectedFilter = evt.target.id; + + // Запускаем отложенное применение фильтра + applyDebouncedFilter(); + }); + }); +} + + +function clearThumbnails() { + const pictures = document.querySelectorAll('.picture'); + pictures.forEach((picture) => picture.remove()); +} + diff --git a/js/form-api.js b/js/form-api.js new file mode 100644 index 0000000..ae43857 --- /dev/null +++ b/js/form-api.js @@ -0,0 +1,116 @@ +import { photos } from './photos.js'; +// import { renderThumbnails } from './thumbnails.js'; +import { pristine, currentEffect, resetForm } from './form.js'; + +export const uploadForm = document.querySelector('.img-upload__form'); +export const fileInput = uploadForm.querySelector('.img-upload__input'); +export const hashtagInput = uploadForm.querySelector('.text__hashtags'); +export const descriptionInput = uploadForm.querySelector('.text__description'); + + +// --------- Форма и создание поста --------- + +uploadForm.addEventListener('submit', (evt) => { + evt.preventDefault(); + const isValid = pristine.validate(); + if (isValid) { + const formData = new FormData(uploadForm); + const submitButton = uploadForm.querySelector('.img-upload__submit'); + submitButton.disabled = true; // Блокируем кнопку + + fetch('https://29.javascript.htmlacademy.pro/kekstagram', { + method: 'POST', + body: formData, + }) + .then((response) => { + if (response.ok) { + // Добавляем новую фотографию с эффектом + const newPhoto = { + id: photos.length + 1, + url: URL.createObjectURL(fileInput.files[0]), + description: descriptionInput.value || 'Новое фото', + likes: 0, + comments: [], + effect: currentEffect // Сохраняем текущий эффект + }; + photos.push(newPhoto); // Добавляем фото в массив + // renderThumbnails([newPhoto]); // Добавляем миниатюру + + showSuccessMessage(); // Показ успешного сообщения + resetForm(); + } else { + throw new Error('Ошибка отправки данных'); + } + }) + .catch(() => { + showErrorMessage(); // Показ сообщения об ошибке + }) + .finally(() => { + submitButton.disabled = false; // Разблокируем кнопку + }); + } +}); + +// --------- Обработчики успеха и ошибок --------- + +function showSuccessMessage() { + const successTemplate = document.querySelector('#success').content; + const successElement = successTemplate.cloneNode(true); + document.body.appendChild(successElement); + + const closeButton = document.querySelector('.success__button'); + const successOverlay = document.querySelector('.success'); + + function closeSuccess() { + successOverlay.remove(); + document.removeEventListener('keydown', onKeydownSuccess); + document.removeEventListener('click', onClickOutsideSuccess); + } + + function onKeydownSuccess(evt) { + if (evt.key === 'Escape') { + closeSuccess(); + } + } + + function onClickOutsideSuccess(evt) { + if (evt.target === successOverlay) { + closeSuccess(); + } + } + + closeButton.addEventListener('click', closeSuccess); + document.addEventListener('keydown', onKeydownSuccess); + document.addEventListener('click', onClickOutsideSuccess); +} + +function showErrorMessage() { + const errorTemplate = document.querySelector('#error').content; + const errorElement = errorTemplate.cloneNode(true); + document.body.appendChild(errorElement); + + const closeButton = document.querySelector('.error__button'); + const errorOverlay = document.querySelector('.error'); + + function closeError() { + errorOverlay.remove(); + document.removeEventListener('keydown', onKeydownError); + document.removeEventListener('click', onClickOutsideError); + } + + function onKeydownError(evt) { + if (evt.key === 'Escape') { + closeError(); + } + } + + function onClickOutsideError(evt) { + if (evt.target === errorOverlay) { + closeError(); + } + } + + closeButton.addEventListener('click', closeError); + document.addEventListener('keydown', onKeydownError); + document.addEventListener('click', onClickOutsideError); +} diff --git a/js/photos.js b/js/photos.js new file mode 100644 index 0000000..84884aa --- /dev/null +++ b/js/photos.js @@ -0,0 +1,3 @@ +import { generatePhotos } from './data.js'; + +export const photos = generatePhotos(); diff --git a/js/thumbnails.js b/js/thumbnails.js new file mode 100644 index 0000000..8a49cea --- /dev/null +++ b/js/thumbnails.js @@ -0,0 +1,42 @@ +import { openBigPicture } from './big-picture.js'; + +const thumbnailTemplate = document.querySelector('#picture').content.querySelector('.picture'); + +function createThumbnail(photoData) { + const thumbnail = thumbnailTemplate.cloneNode(true); + const img = thumbnail.querySelector('.picture__img'); + img.src = photoData.url; + img.alt = photoData.description; + + thumbnail.querySelector('.picture__likes').textContent = photoData.likes; + thumbnail.querySelector('.picture__comments').textContent = photoData.comments.length; + + thumbnail.addEventListener('click', () => { + openBigPicture(photoData); // Открываем большое изображение + }); + + return thumbnail; +} + +function renderThumbnails(photoArray) { + const thumbnailContainer = document.querySelector('.pictures'); + + photoArray.forEach((photo) => { + const thumbnailElement = createThumbnail(photo); + thumbnailElement.querySelector('.picture__img').src = photo.url; + thumbnailElement.querySelector('.picture__likes').textContent = photo.likes; + thumbnailElement.querySelector('.picture__comments').textContent = photo.comments.length; + + // Применяем эффект к миниатюре + if (photo.effect && photo.effect !== 'none') { + thumbnailElement.querySelector('.picture__img').classList.add(`effects__preview--${photo.effect}`); + } + + thumbnailContainer.appendChild(thumbnailElement); + }); +} + + +export { renderThumbnails }; + +