From bea80c71f8fc6024daf81c4c20bb0ff428ced072 Mon Sep 17 00:00:00 2001 From: Keks Date: Wed, 18 Dec 2024 07:01:25 +0300 Subject: [PATCH] =?UTF-8?q?:heavy=5Fcheck=5Fmark:=20=D0=A1=D0=B1=D0=BE?= =?UTF-8?q?=D1=80=D0=BA=D0=B0=20#11?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 11/js/comment-creator.js | 13 ++++ 11/js/comments-loader.js | 39 +++++++++++ 11/js/data.js | 87 +++++++++++------------- 11/js/functions.js | 22 +++---- 11/js/main.js | 4 +- 11/js/photo-modal.js | 139 +++++++++++++-------------------------- 11/js/thumbnails.js | 33 ++++------ 7 files changed, 161 insertions(+), 176 deletions(-) create mode 100644 11/js/comment-creator.js create mode 100644 11/js/comments-loader.js diff --git a/11/js/comment-creator.js b/11/js/comment-creator.js new file mode 100644 index 0000000..229504e --- /dev/null +++ b/11/js/comment-creator.js @@ -0,0 +1,13 @@ +const commentTemplateElement = document.querySelector('.social__comment'); + +const createCommentTemplateElement = ({ avatar, message, name }) => { + const newCommentTemplateElement = commentTemplateElement.cloneNode(true); + const socialPictureElement = newCommentTemplateElement.querySelector('.social__picture'); + const socialTextElement = newCommentTemplateElement.querySelector('.social__text'); + socialPictureElement.src = avatar; + socialPictureElement.alt = name; + socialTextElement.textContent = message; + return newCommentTemplateElement; +}; + +export { createCommentTemplateElement }; diff --git a/11/js/comments-loader.js b/11/js/comments-loader.js new file mode 100644 index 0000000..f78ec3a --- /dev/null +++ b/11/js/comments-loader.js @@ -0,0 +1,39 @@ +import { createCommentTemplateElement } from './comment-creator.js'; +const COMMENTS_LOAD_STEP = 5; // Количество комментариев, которые показываются за один раз + +const bigPictureSocialElement = document.querySelector('.big-picture__social'); + +const socialCommentCountElement = bigPictureSocialElement.querySelector('.social__comment-shown-count'); +const socialCommentTotalCountElement = bigPictureSocialElement.querySelector('.social__comment-total-count'); +const commentsContainerElement = bigPictureSocialElement.querySelector('.social__comments'); +const commentsLoaderElement = bigPictureSocialElement.querySelector('.comments-loader'); + + +// Переменные для хранения текущих комментариев +let currentComments = []; +let displayedCommentsCount = 0; + +// Функция рендера комментариев порциями +const renderComments = () => { + const remainingComments = currentComments.slice(displayedCommentsCount, displayedCommentsCount + COMMENTS_LOAD_STEP); // Выделяем из массива комментариев группу из COMMENTS_LOAD_STEP комментов для подгрузки + const commentsFragment = document.createDocumentFragment(); // Создаем фрагмент для подгрузки + remainingComments.forEach((comment) => { // Добавляем новую порцию комментариев + commentsFragment.append(createCommentTemplateElement(comment)); // Прогоняем каждый элемент через функцию создания комментария и добавляем во фрагмент + }); + commentsContainerElement.append(commentsFragment); // Добавляем фрагмент в конец контейнера + displayedCommentsCount += remainingComments.length; // Обновляем счетчик показанных комментариев + commentsLoaderElement.classList.toggle('hidden', displayedCommentsCount >= currentComments.length); + socialCommentCountElement.textContent = displayedCommentsCount; + socialCommentTotalCountElement.textContent = currentComments.length; +}; + +// Функция инициализации загрузки комментариев +const initComments = (comments) => { + currentComments = comments; // Сохраняем все комментарии + displayedCommentsCount = 0; // Сбрасываем счетчик показанных комментариев + commentsContainerElement.innerHTML = ''; // Очищаем контейнер комментариев + renderComments(); // Первичная загрузка комментариев + commentsLoaderElement.addEventListener('click', renderComments); +}; + +export { initComments }; diff --git a/11/js/data.js b/11/js/data.js index c4dc7d6..db8995d 100644 --- a/11/js/data.js +++ b/11/js/data.js @@ -1,8 +1,4 @@ -import { - getRandomInt, - getRandomUniqueInt, - getRandomArrElement -} from './util.js'; +import { getRandomInt, getRandomUniqueInt, getRandomArrElement } from './util.js'; const OBJECT_QTY = 25; @@ -42,47 +38,47 @@ const AvatarRange = { }; const DESCRIPTION = [ - "Закат на берегу моря", - "Старинная улочка европейского города", - "Котенок спит на кровати", - "Заснеженные склоны Хибин", - "Букет цветов на столе", - "Велосипед пристегнутый на велопарковке", - "Чашка горячего кофе", - "Осенний парк с опавшей листвой", - "Маяк на скалистом берегу", - "Шмель на цветке", - "Деревенский домик в глухом лесу", - "Отражение звезд на поверхности Ладоги", - "Птенцы в гнезде", - "Радуга над зеленым полем после дождя", - "Следы на песчаном пляже", + 'Закат на берегу моря', + 'Старинная улочка европейского города', + 'Котенок спит на кровати', + 'Заснеженные склоны Хибин', + 'Букет цветов на столе', + 'Велосипед пристегнутый на велопарковке', + 'Чашка горячего кофе', + 'Осенний парк с опавшей листвой', + 'Маяк на скалистом берегу', + 'Шмель на цветке', + 'Деревенский домик в глухом лесу', + 'Отражение звезд на поверхности Ладоги', + 'Птенцы в гнезде', + 'Радуга над зеленым полем после дождя', + 'Следы на песчаном пляже', ]; const MESSAGE = [ - "Всё отлично!", - "В целом всё неплохо. Но не всё.", - "Когда вы делаете фотографию, хорошо бы убирать палец из кадра. В конце концов это просто непрофессионально.", - "Моя бабушка случайно чихнула с фотоаппаратом в руках и у неё получилась фотография лучше.", - "Я поскользнулся на банановой кожуре и уронил фотоаппарат на кота и у меня получилась фотография лучше.", - "Лица у людей на фотке перекошены, как будто их избивают. Как можно было поймать такой неудачный момент?!", + 'Всё отлично!', + 'В целом всё неплохо. Но не всё.', + 'Когда вы делаете фотографию, хорошо бы убирать палец из кадра. В конце концов это просто непрофессионально.', + 'Моя бабушка случайно чихнула с фотоаппаратом в руках и у неё получилась фотография лучше.', + 'Я поскользнулся на банановой кожуре и уронил фотоаппарат на кота и у меня получилась фотография лучше.', + 'Лица у людей на фотке перекошены, как будто их избивают. Как можно было поймать такой неудачный момент?!', ]; const AUTHOR_NAME = [ - "Довакин", - "Алдуин", - "Шеппард", - "Геральт", - "Супер Марио", - "Соник", - "Кратос", - "Солид Снейк", - "Клод Страйф", - "Лара Крофт", - "Наруто", - "Элли", - "Джоель", - "Сэм Фишер", + 'Довакин', + 'Алдуин', + 'Шеппард', + 'Геральт', + 'Супер Марио', + 'Соник', + 'Кратос', + 'Солид Снейк', + 'Клод Страйф', + 'Лара Крофт', + 'Наруто', + 'Элли', + 'Джоель', + 'Сэм Фишер', ]; const getPhotoId = getRandomUniqueInt(IdPhotoRange.MIN, IdPhotoRange.MAX); @@ -101,16 +97,13 @@ const createComment = () => { return { id: getMessageId(), avatar: `img/avatar-${getRandomInt(AvatarRange.MIN, AvatarRange.MAX)}.svg`, - message: messagesQty.join(" "), + message: messagesQty.join(' '), name: getRandomArrElement(AUTHOR_NAME), }; }; const generateObj = () => { - const comments = Array.from( - { length: getRandomInt(CommentsRange.MIN, CommentsRange.MAX) }, - createComment - ); + const comments = Array.from({ length: getRandomInt(CommentsRange.MIN, CommentsRange.MAX) }, createComment); return { id: getPhotoId(), url: `photos/${getRandomUrl()}.jpg`, @@ -122,6 +115,4 @@ const generateObj = () => { const generateArrObj = () => Array.from({ length: OBJECT_QTY }, generateObj); -export { - generateArrObj -}; +export { generateArrObj }; diff --git a/11/js/functions.js b/11/js/functions.js index b3e64db..d61e753 100644 --- a/11/js/functions.js +++ b/11/js/functions.js @@ -1,14 +1,14 @@ -const isWithinWorkingHours = (workdayStart, workdayEnd, meetingStart, meetingLength) => { - const convertToMinutes = (timeString) => { - const [hours, minutes] = timeString.split(':'); - return (Number(hours) * 60) + Number(minutes) - }; - const workdayStartMinutes = convertToMinutes(workdayStart); - const workdayEndMinutes = convertToMinutes(workdayEnd); - const meetingStartMinutes = convertToMinutes(meetingStart); - const meetingEndMinutes = meetingStartMinutes + meetingLength; - return meetingStartMinutes >= workdayStartMinutes && meetingEndMinutes <= workdayEndMinutes -}; +// const isWithinWorkingHours = (workdayStart, workdayEnd, meetingStart, meetingLength) => { +// const convertToMinutes = (timeString) => { +// const [hours, minutes] = timeString.split(':'); +// return (Number(hours) * 60) + Number(minutes) +// }; +// const workdayStartMinutes = convertToMinutes(workdayStart); +// const workdayEndMinutes = convertToMinutes(workdayEnd); +// const meetingStartMinutes = convertToMinutes(meetingStart); +// const meetingEndMinutes = meetingStartMinutes + meetingLength; +// return meetingStartMinutes >= workdayStartMinutes && meetingEndMinutes <= workdayEndMinutes +// }; // console.log(isWithinWorkingHours('08:00', '17:30', '14:00', 90)); // console.log(isWithinWorkingHours('8:0', '10:0', '8:0', 120)); diff --git a/11/js/main.js b/11/js/main.js index d1148dc..79c4280 100644 --- a/11/js/main.js +++ b/11/js/main.js @@ -4,6 +4,4 @@ import { setupPictureEventListeners } from './photo-modal.js'; const photoCollection = generateArrObj(); renderGallery(photoCollection); -setupPictureEventListeners (photoCollection); - - +setupPictureEventListeners(photoCollection); diff --git a/11/js/photo-modal.js b/11/js/photo-modal.js index 3c7db5e..9ab7206 100644 --- a/11/js/photo-modal.js +++ b/11/js/photo-modal.js @@ -1,122 +1,71 @@ import { isEscapeKey } from './util.js'; +import { initComments } from './comments-loader.js'; -const picturesContainerElement = document.querySelector('.pictures'); -const socialCommentCountElement = document.querySelector('.social__comment-shown-count'); -const socialCommentTotalCountElement = document.querySelector('.social__comment-total-count'); -const commentsLoaderElement = document.querySelector('.comments-loader'); +// Общий контейнер const bodyContainerElement = document.body; -const bigPictureContainerElement = document.querySelector('.big-picture'); -const bigPictureCloseButtonElement = bigPictureContainerElement.querySelector('.big-picture__cancel'); -const bigPictureImageElement = bigPictureContainerElement.querySelector('img'); -const bigPictureLikesElement = bigPictureContainerElement.querySelector('.likes-count'); -const bigPictureDescriptionElement = bigPictureContainerElement.querySelector('.social__caption'); -const commentsQuantityElement = bigPictureContainerElement.querySelector('.social__comment-total-count'); -const commentsContainerElement = bigPictureContainerElement.querySelector('.social__comments'); -const commentTemplateElement = document.querySelector('.social__comment'); -const COMMENTS_STEP = 5; // Количество комментариев, которые показываются за один раз +// Контейнер с картинками +const picturesContainerElement = document.querySelector('.pictures'); -// Функция добавления обработчика событий на контейнер с картинками и вычисление ID картинки, по которой был клик -const setupPictureEventListeners = (photoCollection) => { - picturesContainerElement.addEventListener('click', (evt) => { - const currentEventPictureId = evt.target.closest('.picture').dataset.pictureId; - if (currentEventPictureId) { - const foundedPhoto = photoCollection.find((picture) => picture.id === Number(currentEventPictureId)); - renderBigPicture(foundedPhoto); - } - }); -}; +// Элементы большой картинки +const bigPictureContainerElement = document.querySelector('.big-picture'); +const bigPictureOverlayElement = document.querySelector('.overlay'); +const bigPictureCloseButtonElement = bigPictureContainerElement.querySelector('.big-picture__cancel'); +const bigPictureImageElement = bigPictureContainerElement.querySelector('.big-picture__img img'); +const bigPictureSocialElement = bigPictureContainerElement.querySelector('.big-picture__social'); +const bigPictureLikesElement = bigPictureSocialElement.querySelector('.likes-count'); +const bigPictureDescriptionElement = bigPictureSocialElement.querySelector('.social__caption'); // Рендер большой картинки const renderBigPicture = ({ url, likes, comments, description }) => { bigPictureImageElement.src = url; bigPictureLikesElement.textContent = likes; - commentsQuantityElement.textContent = comments.length; bigPictureDescriptionElement.textContent = description; - attachBigPictureListeners(); // Вешаем обработчик событий - initComments(comments); // Инициализируем комментарии - toggleVisibility(true); // Переключатель видимости -}; - -// добавление обработчиков события на кнопку закрытия и эскейп -const attachBigPictureListeners = () => { bigPictureCloseButtonElement.addEventListener('click', onClickCloseButton); + bigPictureOverlayElement.addEventListener('click', onOverlayClick); document.addEventListener('keydown', onKeydownDocument); + initComments(comments); // Инициализируем комментарии + bigPictureContainerElement.classList.remove('hidden'); // включаем видимость контейнера большой картинки + bodyContainerElement.classList.add('modal-open'); // блокируем прокрутку body }; -// Переменные для хранения текущих комментариев -let currentComments = []; -let displayedCommentsCount = 0; - -// Функция инициализации загрузки комментариев -const initComments = (comments) => { - currentComments = comments; // Сохраняем все комментарии - displayedCommentsCount = 0; // Сбрасываем счетчик показанных комментариев - commentsContainerElement.innerHTML = ''; // Очищаем контейнер комментариев - commentsLoaderElement.addEventListener('click', renderComments); // Добавляем обработчик кнопки "Загрузить еще" - renderComments(); // Первичная загрузка комментариев -}; - -// Функция рендера комментариев порциями -const renderComments = () => { - const remainingComments = currentComments.slice(displayedCommentsCount, displayedCommentsCount + COMMENTS_STEP); // Выделяем из массива комментариев группу из COMMENTS_STEP комментов для подгрузки - const commentsFragment = document.createDocumentFragment(); // Создаем фрагмент для подгрузки - remainingComments.forEach(comment => { // Добавляем новую порцию комментариев - commentsFragment.append(createCommentTemplateElement(comment)); // Прогоняем каждый элемент через функцию создания комментария и добавляем во фрагмент - }); - commentsContainerElement.append(commentsFragment); // Добавляем фрагмент в конец контейнера - displayedCommentsCount += remainingComments.length; // Обновляем счетчик показанных комментариев - updateCommentsLoaderElementVisibility(); // Обновляем видимость кнопки "Загрузить еще" - updateCommentCounter(); // Обновляем счетчик комментариев -}; - -// Функция создания элемента комментария -const createCommentTemplateElement = ({ avatar, message, name }) => { - const newCommentTemplateElement = commentTemplateElement.cloneNode(true); - const socialPictureElement = newCommentTemplateElement.querySelector('.social__picture'); - const socialTextElement = newCommentTemplateElement.querySelector('.social__text'); - socialPictureElement.src = avatar; - socialPictureElement.alt = name; - socialTextElement.textContent = message; - return newCommentTemplateElement; -}; - -// Функция обновления счетчика комментариев -const updateCommentCounter = () => { - socialCommentCountElement.textContent = displayedCommentsCount; - socialCommentTotalCountElement.textContent = currentComments.length; -}; - -// Функция обновления видимости кнопки "Загрузить еще" -const updateCommentsLoaderElementVisibility = () => { - commentsLoaderElement.classList.toggle('hidden', displayedCommentsCount >= currentComments.length); -}; +// Вызов закрытия картинки нажатием на закрывающий элемент +function onClickCloseButton () { + closeBigPicture(); +} -// Функция переключения видимости контейнера с картинкой и прокрутки -const toggleVisibility = (isOpen) => { - bigPictureContainerElement.classList.toggle('hidden', !isOpen); - bodyContainerElement.classList.toggle('modal-open', isOpen); -}; +// Вызов закрытия картинки нажатием мимо модального окна +function onOverlayClick(evt) { + if (evt.target === bigPictureOverlayElement) { + closeBigPicture(); + } +} -// Вызов закрытия картинки нажатием на эскейп -const onKeydownDocument = (evt) => { +// Вызов закрытия картинки нажатием на escape +function onKeydownDocument (evt) { if (isEscapeKey(evt)) { evt.preventDefault(); closeBigPicture(); } -}; +} -// Вызов закрытия картинки нажатием на закрывающий элемент -const onClickCloseButton = () => { - closeBigPicture(); -}; - -// Функция закрытия большой картинки, переключение видимостей, снятие обработчиков событий -const closeBigPicture = () => { - commentsLoaderElement.removeEventListener('click', renderComments); +function closeBigPicture () { bigPictureCloseButtonElement.removeEventListener('click', onClickCloseButton); + bigPictureContainerElement.removeEventListener('click', onOverlayClick); document.removeEventListener('keydown', onKeydownDocument); - toggleVisibility(false); + bigPictureContainerElement.classList.add('hidden'); + bodyContainerElement.classList.remove('modal-open'); +} + +// Функция добавления обработчика событий на контейнер с картинками и вычисление ID картинки, по которой был клик +const setupPictureEventListeners = (photoCollection) => { + picturesContainerElement.addEventListener('click', (evt) => { + const id = evt.target.closest('.picture').dataset.pictureId; // поиск по установленному атрибуту data-set-id + if (id) { + const foundedPhoto = photoCollection.find((picture) => picture.id === Number(id)); + renderBigPicture(foundedPhoto); + } + }); }; export { setupPictureEventListeners }; diff --git a/11/js/thumbnails.js b/11/js/thumbnails.js index 2820fb9..349930b 100644 --- a/11/js/thumbnails.js +++ b/11/js/thumbnails.js @@ -1,24 +1,19 @@ const renderGallery = (userPictures) => { -const picturesContainer = document.querySelector('.pictures'); -const pictureTemplate = document.querySelector('#picture') - .content - .querySelector('a'); + const picturesContainer = document.querySelector('.pictures'); + const pictureTemplate = document.querySelector('#picture').content.querySelector('a'); -const pictureFragment = document.createDocumentFragment(); + const pictureFragment = document.createDocumentFragment(); -userPictures.forEach(({id, url, description, likes, comments}) => { - const pictureElement = pictureTemplate.cloneNode(true); - pictureElement.dataset.pictureId = id; - pictureElement.querySelector('.picture__img').src = url; - pictureElement.querySelector('.picture__img').alt = description; - pictureElement.querySelector('.picture__likes').textContent = likes; - pictureElement.querySelector('.picture__comments').textContent = comments.length; - pictureFragment.append(pictureElement); -}); - -picturesContainer.append(pictureFragment); + userPictures.forEach(({id, url, description, likes, comments}) => { + const pictureElement = pictureTemplate.cloneNode(true); + pictureElement.dataset.pictureId = id; // Устанавливает атрибут data-set-id + pictureElement.querySelector('.picture__img').src = url; + pictureElement.querySelector('.picture__img').alt = description; + pictureElement.querySelector('.picture__likes').textContent = likes; + pictureElement.querySelector('.picture__comments').textContent = comments.length; + pictureFragment.append(pictureElement); + }); + picturesContainer.append(pictureFragment); }; -export { - renderGallery -}; +export { renderGallery };