diff --git a/js/create-data-posts.js b/js/create-data-posts.js deleted file mode 100644 index 625d277..0000000 --- a/js/create-data-posts.js +++ /dev/null @@ -1,53 +0,0 @@ -import {getRandomInteger, getRandomArrayElement, createRandomValuesRangeGenerator} from './util.js'; -import {NAMES, MESSAGES, DESCRIPTIONS} from './data.js'; -const idValues = { - MIN: 1, - MAX: 25, -}; - -const adressNumbers = { - MIN: 1, - MAX: 25, -}; - -const likesNumber = { - MIN: 15, - MAX: 200, -}; - -const commentsNumber = { - MIN: 0, - MAX: 30, -}; - -const avatarValues = { - MIN: 1, - MAX: 6, -}; - -const PHOTOS_NUMBER = 25; -const createRandomId = createRandomValuesRangeGenerator(idValues.MIN, idValues.MAX); -const createRandomAdress = createRandomValuesRangeGenerator(adressNumbers.MIN, adressNumbers.MAX); -const createRandomCommentId = createRandomValuesRangeGenerator(idValues.MIN, idValues.MAX); - -const createComment = () => ({ - id: createRandomCommentId(), - avatar: `img/avatar-${getRandomInteger(avatarValues.MIN, avatarValues.MAX)}.svg`, - message: getRandomArrayElement(MESSAGES), - name: getRandomArrayElement(NAMES) -}); - - -const randomComments = () => Array.from({length: getRandomInteger(commentsNumber.MIN, commentsNumber.MAX)}, createComment); - -const createDataPost = () => ({ - id: createRandomId(), - url: `photos/${createRandomAdress()}.jpg`, - description: getRandomArrayElement(DESCRIPTIONS), - likes: getRandomInteger(likesNumber.MIN, likesNumber.MAX), - comments: randomComments() -}); - -const createDataPosts = () => Array.from({length: PHOTOS_NUMBER}, createDataPost); - -export {createDataPosts}; diff --git a/js/data.js b/js/data.js deleted file mode 100644 index ed3ca06..0000000 --- a/js/data.js +++ /dev/null @@ -1,6 +0,0 @@ -const NAMES = ['Федор', 'Камила', 'Полина', 'Сергей', 'Наталья', 'Филипп']; -const MESSAGES = ['Всё отлично!', 'В целом всё неплохо. Но не всё.', 'Когда вы делаете фотографию, хорошо бы убирать палец из кадра. В конце концов это просто непрофессионально.', 'Моя бабушка случайно чихнула с фотоаппаратом в руках и у неё получилась фотография лучше.', 'Я поскользнулся на банановой кожуре и уронил фотоаппарат на кота и у меня получилась фотография лучше.', 'Лица у людей на фотке перекошены, как будто их избивают. Как можно было поймать такой неудачный момент?!']; -const DESCRIPTIONS = ['Живописно!', 'Я фанат', 'Это мило', 'Мне нравится', 'Спасибо за фото', 'Просто магия', 'Фантастика', 'Ура! Ура! Ура!', 'Я в шоке', 'Реальные эмоции!']; - -export {NAMES, MESSAGES, DESCRIPTIONS}; - diff --git a/js/draw-fullsize-photo.js b/js/draw-fullsize-photo.js index ccc4e06..a2c098f 100644 --- a/js/draw-fullsize-photo.js +++ b/js/draw-fullsize-photo.js @@ -1,4 +1,3 @@ -import {thumbnails} from './draw-thumbnails.js'; import {isEscapeKey} from './util.js'; const modal = document.querySelector('.big-picture'); @@ -13,67 +12,64 @@ const photoDescription = document.querySelector('.social__caption'); const moreComments = document.querySelector('.comments-loader'); const commentListFragment = document.createDocumentFragment(); - const onDocumentKeydown = (evt) => { if (isEscapeKey(evt)) { evt.preventDefault(); - closeFullsizePhoto(); + closeModal(); } }; -function openFullsizePhoto() { - modal.classList.remove('hidden'); - document.addEventListener('keydown', onDocumentKeydown); -} - -function closeFullsizePhoto() { - modal.classList.add('hidden'); -} - -const showComments = (allComments) => { - for (let i = 0; i < allComments.length; i++) { +const cutsComments = (comments, minCommentIndex, step) => function() { + if (step > comments.length) { + step = comments.length; + moreComments.classList.add('hidden'); + shownComments.textContent = comments.length; + } else { + shownComments.textContent = step; + moreComments.classList.remove('hidden'); + } + for (let i = minCommentIndex; i < step; i++) { const commentItemClone = commentItem.cloneNode(true); - commentItemClone.querySelector('.social__picture').src = allComments[i].avatar; - commentItemClone.querySelector('.social__picture').alt = allComments[i].name; - commentItemClone.querySelector('.social__text').textContent = allComments[i].message; + commentItemClone.querySelector('.social__picture').src = comments[i].avatar; + commentItemClone.querySelector('.social__picture').alt = comments[i].name; + commentItemClone.querySelector('.social__text').textContent = comments[i].message; commentListFragment.appendChild(commentItemClone); } commentsContainer.appendChild(commentListFragment); + minCommentIndex += 5; + step += 5; }; - -function transferModalData(evt, photoLink) { +let showComments; +const transferModalData = (evt, thumbnails) => { modalImg.src = evt.target.src; - imgLikes.textContent = photoLink.querySelector('.picture__likes').textContent; - imgComments.textContent = photoLink.querySelector('.picture__comments').textContent; - shownComments.textContent = photoLink.querySelector('.picture__comments').textContent; - photoDescription.textContent = photoLink.querySelector('.picture__img').alt; - let minCommentIndex = 0; - let step = 5; + imgLikes.textContent = evt.target.parentElement.querySelector('.picture__likes').textContent; + imgComments.textContent = evt.target.parentElement.querySelector('.picture__comments').textContent; + shownComments.textContent = evt.target.parentElement.querySelector('.picture__comments').textContent; + photoDescription.textContent = evt.target.parentElement.querySelector('.picture__img').alt; thumbnails.forEach((thumbnail) => { if (evt.target.src.includes(thumbnail.url)) { commentsContainer.innerHTML = ''; - - showComments(thumbnail.comments.slice(minCommentIndex, step)); - shownComments.textContent = step; - moreComments.addEventListener('click', () => { - - - showComments(thumbnail.comments.slice(minCommentIndex += 5, step += 5)); - shownComments.textContent = step; - if (thumbnail.comments.length <= step) { - moreComments.classList.add('hidden'); - shownComments.textContent = thumbnail.comments.length; - } - - }); + showComments = cutsComments(thumbnail.comments, 0, 5); + showComments(); + moreComments.addEventListener('click', showComments); } }); +}; -} +const openModal = (evt, thumbnails) => { + modal.classList.remove('hidden'); + document.body.classList.add('modal-open'); + document.addEventListener('keydown', onDocumentKeydown); + transferModalData(evt, thumbnails); +}; +const closeModal = () => { + modal.classList.add('hidden'); + document.body.classList.remove('modal-open'); + document.removeEventListener('keydown', onDocumentKeydown); + moreComments.removeEventListener('click', showComments); +}; -closeButton.addEventListener('click', () => { - closeFullsizePhoto(); -}); +closeButton.addEventListener('click', closeModal); -export {transferModalData, openFullsizePhoto}; +export {openModal}; diff --git a/js/draw-thumbnails.js b/js/draw-thumbnails.js index d08c5df..76ad11d 100644 --- a/js/draw-thumbnails.js +++ b/js/draw-thumbnails.js @@ -1,7 +1,5 @@ -import {createDataPosts} from './create-data-posts.js'; const thumbnailsBlock = document.querySelector('.pictures'); const thumbnailTemplate = document.querySelector('#picture').content.querySelector('.picture'); -const thumbnails = createDataPosts(); const thumbnailsListFragment = document.createDocumentFragment(); const displaysThumbnails = (thumbnailsList) => { thumbnailsList.forEach(({url, description, likes, comments}) => { @@ -15,6 +13,6 @@ const displaysThumbnails = (thumbnailsList) => { thumbnailsBlock.appendChild(thumbnailsListFragment); }; -export {displaysThumbnails, thumbnails}; +export {displaysThumbnails}; diff --git a/js/form.js b/js/form.js index 40208ba..d1e7bc8 100644 --- a/js/form.js +++ b/js/form.js @@ -14,6 +14,13 @@ const photoForm = document.querySelector('.img-upload__preview'); const sliderElement = document.querySelector('.effect-level__slider'); const sliderEffectsList = document.querySelector('.effects__list'); const sliderElementContainer = document.querySelector('.img-upload__effect-level'); +const successMessageTemplate = document.querySelector('#success').content; +const successMessageClone = successMessageTemplate.cloneNode(true); +const successMessage = document.createDocumentFragment(); +const errorMessageTemplate = document.querySelector('#error').content; +const errorMessageClone = errorMessageTemplate.cloneNode(true); +const errorMessage = document.createDocumentFragment(); + const scallingPhoto = () => { const step = 25; @@ -53,6 +60,7 @@ const closePhotoEditForm = () => { document.body.classList.remove('modal-open'); }; + const onDocumentKeydown = (evt) => { if (isEscapeKey(evt)) { evt.preventDefault(); @@ -60,6 +68,7 @@ const onDocumentKeydown = (evt) => { } }; + buttonCloseForm.addEventListener('click', closePhotoEditForm); buttonOpenForm.addEventListener('change', () => { @@ -110,11 +119,79 @@ const findStringSpaces = (value) => { const getSpaceError = () => ('Поставьте пробел между хэштегами!'); +const clearModalData = () => { + photoForm.style.transform = `scale(${1})`; + photoForm.style.filter = 'none'; + photoScaleValue.value = `${100}%`; + sliderElement.classList.add('hidden'); + sliderElementContainer.classList.add('hidden'); + inputHashtagsText.value = ''; + commentArea.value = ''; + buttonOpenForm.value = ''; +}; -photoEditForm.addEventListener('submit', (evt) => { - evt.preventDefault(); - pristine.validate(); -}); +const setUserFormSubmit = (onSuccess) => { + photoEditForm.addEventListener('submit', (evt) => { + evt.preventDefault(); + const isValid = pristine.validate(); + if (isValid) { + const formData = new FormData(evt.target); + fetch( + 'https://32.javascript.htmlacademy.pro/kekstagram', + { + method: 'POST', + body: formData, + }, + ).then((response) => { + if (response.ok) { + onSuccess(); + clearModalData(); + successMessage.appendChild(successMessageClone); + document.body.appendChild(successMessage); + const successModal = document.querySelector('.success'); + const successButton = document.querySelector('.success__button'); + // const successInner = document.querySelector('.success__inner'); + successButton.addEventListener('click', () => { + successModal.classList.add('hidden'); + }); + document.addEventListener('keydown', (evt) => { + if (isEscapeKey(evt)) { + successModal.classList.add('hidden'); + } + }); + document.addEventListener('click', (evt) => { + if (evt.target.className !== 'success__inner') { + successModal.classList.add('hidden'); + } + }); + successModal.classList.remove('hidden'); + } + }) + .catch(() => { + errorMessage.appendChild(errorMessageClone); + document.body.appendChild(errorMessage); + const errorModal = document.querySelector('.error'); + const errorButton = document.querySelector('.error__button'); + errorButton.addEventListener('click', () => { + errorModal.classList.add('hidden'); + }); + document.addEventListener('keydown', (evt) => { + if (isEscapeKey(evt)) { + errorModal.classList.add('hidden'); + } + }); + document.addEventListener('click', (evt) => { + if (evt.target.className !== 'error__inner') { + errorModal.classList.add('hidden'); + } + }); + errorModal.classList.remove('hidden'); + }); + } + }); +}; + +buttonCloseForm.addEventListener('click', clearModalData); const compareHastags = (value) => { let flag = true; @@ -282,6 +359,4 @@ sliderEffectsList.addEventListener('click', (evt) => { } }); -export {validateForm, blockEscapeAction, scallingPhoto}; - - +export {validateForm, blockEscapeAction, scallingPhoto, closePhotoEditForm, setUserFormSubmit}; diff --git a/js/function.js b/js/function.js deleted file mode 100644 index 342db85..0000000 --- a/js/function.js +++ /dev/null @@ -1,63 +0,0 @@ -const getChecked = (string, maxLength) => string.length <= maxLength; - -getChecked('проверяемая строка', 20); -getChecked('проверяемая строка', 18); -getChecked('проверяемая строка', 10); - -const findPalidrom = (string) => { - const normString = string.replaceAll(' ', '').toLowerCase(); - let emptyString = ''; - for (let i = normString.length - 1; i >= 0; i--) { - emptyString += normString[i]; - } - return emptyString === normString; -}; - -findPalidrom('топот'); -findPalidrom('ДовОд'); -findPalidrom('Кекс'); -findPalidrom('Лёша на полке клопа нашёл '); - - -const getNumber = (string) => { - const normString = string.toString(); - let stringWithNumber = ''; - for (let i = 0; i <= normString.length - 1; i++) { - if (normString[i] === '0' || parseInt(normString[i], 10)) { - stringWithNumber += normString[i]; - } - } - - return stringWithNumber === '' ? NaN : Number(stringWithNumber); -}; - -getNumber('2023 год'); -getNumber('ECMAScript 2022'); -getNumber('1 кефир, 0.5 батона'); -getNumber('агент 007'); -getNumber('а я томат'); - -getNumber(2023); -getNumber(-1); -getNumber(1.5); - - -const getMeetingPossibility = (jobStart, jobEnd, meetingStart, meetingTime) => { - jobStart = jobStart.split(':'); - jobStart = +jobStart[0] * 60 + +jobStart[1]; - jobEnd = jobEnd.split(':'); - jobEnd = +jobEnd[0] * 60 + +jobEnd[1]; - meetingStart = meetingStart.split(':'); - meetingStart = +meetingStart[0] * 60 + +meetingStart[1]; - const meetingEnd = meetingStart + meetingTime; - if (meetingStart >= jobStart && meetingEnd <= jobEnd) { - return true; - } - return false; -}; - -getMeetingPossibility('08:00', '17:30', '14:00', 90); -getMeetingPossibility('8:0', '10:0', '8:0', 120); -getMeetingPossibility('08:00', '14:30', '14:00', 90); -getMeetingPossibility('14:00', '17:30', '08:0', 90); -getMeetingPossibility('8:00', '17:30', '08:00', 900); diff --git a/js/main.js b/js/main.js index b56f34a..a7c6395 100644 --- a/js/main.js +++ b/js/main.js @@ -1,17 +1,20 @@ -import {displaysThumbnails, thumbnails} from './draw-thumbnails.js'; -import {transferModalData, openFullsizePhoto} from './draw-fullsize-photo.js'; -import {validateForm, blockEscapeAction, scallingPhoto} from './form.js'; -displaysThumbnails(thumbnails); +import {validateForm, blockEscapeAction, scallingPhoto, closePhotoEditForm, setUserFormSubmit} from './form.js'; +import {openModal} from './draw-fullsize-photo.js'; +import {displaysThumbnails} from './draw-thumbnails.js'; +import {getData} from './api.js'; -const photosLinks = document.querySelectorAll('.picture'); -photosLinks.forEach((photoLink) => { - photoLink.addEventListener('click', (evt) => { - openFullsizePhoto(); - document.body.classList.add('modal-open'); - transferModalData(evt, photoLink); +getData() + .then((posts) => { + displaysThumbnails(posts); + const photosLinks = document.querySelectorAll('.picture'); + photosLinks.forEach((photoLink) => { + photoLink.addEventListener('click', (evt) => openModal(evt, posts)); + }); }); -}); + +setUserFormSubmit(closePhotoEditForm); + validateForm(); blockEscapeAction(); diff --git a/js/util.js b/js/util.js index 137460a..36598a3 100644 --- a/js/util.js +++ b/js/util.js @@ -1,3 +1,4 @@ +const ALERT_SHOW_TIME = 5000; const getRandomInteger = (a, b) => { const lower = Math.ceil(Math.min(a, b)); const upper = Math.floor(Math.max(a, b)); @@ -24,5 +25,25 @@ const createRandomValuesRangeGenerator = (min, max) => { }; const isEscapeKey = (evt) => evt.key === 'Escape'; +const showAlert = (message) => { + const alertContainer = document.createElement('div'); + alertContainer.style.zIndex = '100'; + alertContainer.style.position = 'absolute'; + alertContainer.style.left = '0'; + alertContainer.style.top = '0'; + alertContainer.style.right = '0'; + alertContainer.style.padding = '10px 3px'; + alertContainer.style.fontSize = '30px'; + alertContainer.style.textAlign = 'center'; + alertContainer.style.backgroundColor = 'red'; -export {getRandomInteger, getRandomArrayElement, createRandomValuesRangeGenerator, isEscapeKey}; + alertContainer.textContent = message; + + document.body.append(alertContainer); + + setTimeout(() => { + alertContainer.remove(); + }, ALERT_SHOW_TIME); +}; + +export {getRandomInteger, getRandomArrayElement, createRandomValuesRangeGenerator, isEscapeKey, showAlert};