diff --git a/index.html b/index.html index a1aea97..88f6628 100644 --- a/index.html +++ b/index.html @@ -30,7 +30,7 @@

Фотографии других

Загрузка фотографии

-
+
@@ -233,7 +233,7 @@

Изображение успешно загруже

Не удалось загрузить данные

- + diff --git a/js/check-hashtag-validity.js b/js/check-hashtag-validity.js new file mode 100644 index 0000000..5ebbc31 --- /dev/null +++ b/js/check-hashtag-validity.js @@ -0,0 +1,30 @@ +const MAX_HASHTAG_COUNT = 5; +const MAX_HASHTAG_LENGTH = 20; +const HASHTAG_REGEXP = /^#[a-zа-яё0-9]+$/i; + +const normalizeHashtags = (value) => value + .trim() + .toLowerCase() + .split(/\s+/) + .filter((hashtag) => hashtag.length > 0); + +const hasValidHashtagCount = (value) => + normalizeHashtags(value).length <= MAX_HASHTAG_COUNT; + +const hasValidHashtagLength = (value) => + normalizeHashtags(value).every((hashtag) => hashtag.length <= MAX_HASHTAG_LENGTH); + +const hasValidHashtagFormat = (value) => + normalizeHashtags(value).every((hashtag) => HASHTAG_REGEXP.test(hashtag)); + +const hasUniqueHashtags = (value) => { + const hashtags = normalizeHashtags(value); + return hashtags.length === new Set(hashtags).size; +}; + +export { + hasValidHashtagCount, + hasValidHashtagLength, + hasValidHashtagFormat, + hasUniqueHashtags +}; diff --git a/js/full-size-picture.js b/js/full-size-picture.js index 12036b3..2a4e316 100644 --- a/js/full-size-picture.js +++ b/js/full-size-picture.js @@ -7,6 +7,16 @@ const likesCountNode = bigPictureNode.querySelector('.likes-count'); const commentsCaptionNode = bigPictureNode.querySelector('.social__caption'); const bigPictureCancelNode = bigPictureNode.querySelector('.big-picture__cancel'); +const onEscKeydown = (evt) => { + if (evt.key === 'Escape') { + evt.preventDefault(); + clearComments(); + bigPictureNode.classList.add('hidden'); + document.body.classList.remove('modal-open'); + document.removeEventListener('keydown', onEscKeydown); + } +}; + const closeBigPicture = () => { clearComments(); bigPictureNode.classList.add('hidden'); @@ -14,13 +24,6 @@ const closeBigPicture = () => { document.removeEventListener('keydown', onEscKeydown); }; -const onEscKeydown = (evt) => { - if (evt.key === 'Escape') { - evt.preventDefault(); - closeBigPicture(); - } -}; - const onBigPictureCancelClick = (evt) => { evt.preventDefault(); closeBigPicture(); diff --git a/js/main.js b/js/main.js index b9e0f5c..ce58f80 100644 --- a/js/main.js +++ b/js/main.js @@ -1,5 +1,7 @@ import { photos } from './create-array-photos.js'; import { renderThumbnails } from './render-thumbnails.js'; +import { initUploadPhotoForm } from './upload-photo-form.js'; renderThumbnails(photos); +initUploadPhotoForm(); diff --git a/js/upload-photo-form.js b/js/upload-photo-form.js new file mode 100644 index 0000000..2f97ffb --- /dev/null +++ b/js/upload-photo-form.js @@ -0,0 +1,117 @@ +import { + hasValidHashtagCount, + hasValidHashtagLength, + hasValidHashtagFormat, + hasUniqueHashtags +} from './check-hashtag-validity.js'; + +const MAX_COMMENT_LENGTH = 140; + +const bodyNode = document.body; +const uploadFormNode = document.querySelector('.img-upload__form'); +const uploadFileControl = uploadFormNode.querySelector('#upload-file'); +const uploadOverlayNode = uploadFormNode.querySelector('.img-upload__overlay'); +const uploadCancelButtonNode = uploadFormNode.querySelector('#upload-cancel'); +const hashtagsInputNode = uploadFormNode.querySelector('.text__hashtags'); +const descriptionInputNode = uploadFormNode.querySelector('.text__description'); + +const pristine = new Pristine(uploadFormNode, { + classTo: 'img-upload__field-wrapper', + errorTextParent: 'img-upload__field-wrapper', + errorTextTag: 'div', + errorTextClass: 'img-upload__field-wrapper--error' +}); + +const isEscapeKey = (evt) => evt.key === 'Escape'; + +const hasValidCommentLength = (value) => value.length <= MAX_COMMENT_LENGTH; + +const resetUploadPhotoForm = () => { + uploadFormNode.reset(); + uploadFileControl.value = ''; + pristine.reset(); +}; + +const stopEscapePropagation = (evt) => { + if (isEscapeKey(evt)) { + evt.stopPropagation(); + } +}; + +const onDocumentKeydown = (evt) => { + if (isEscapeKey(evt)) { + evt.preventDefault(); + uploadOverlayNode.classList.add('hidden'); + bodyNode.classList.remove('modal-open'); + document.removeEventListener('keydown', onDocumentKeydown); + resetUploadPhotoForm(); + } +}; + +const openUploadPhotoForm = () => { + uploadOverlayNode.classList.remove('hidden'); + bodyNode.classList.add('modal-open'); + document.addEventListener('keydown', onDocumentKeydown); +}; + +const closeUploadPhotoForm = () => { + uploadOverlayNode.classList.add('hidden'); + bodyNode.classList.remove('modal-open'); + document.removeEventListener('keydown', onDocumentKeydown); + resetUploadPhotoForm(); +}; + +const onUploadFileControlChange = () => { + openUploadPhotoForm(); +}; + +const onUploadCancelButtonClick = (evt) => { + evt.preventDefault(); + closeUploadPhotoForm(); +}; + +const onUploadFormSubmit = (evt) => { + if (!pristine.validate()) { + evt.preventDefault(); + } +}; + +pristine.addValidator( + hashtagsInputNode, + hasValidHashtagCount, + 'Нельзя указать больше пяти хэштегов' +); + +pristine.addValidator( + hashtagsInputNode, + hasValidHashtagLength, + 'Максимальная длина одного хэштега — 20 символов' +); + +pristine.addValidator( + hashtagsInputNode, + hasValidHashtagFormat, + 'Хэштег должен начинаться с # и содержать только буквы и цифры' +); + +pristine.addValidator( + hashtagsInputNode, + hasUniqueHashtags, + 'Хэштеги не должны повторяться' +); + +pristine.addValidator( + descriptionInputNode, + hasValidCommentLength, + 'Длина комментария не может составлять больше 140 символов' +); + +const initUploadPhotoForm = () => { + uploadFileControl.addEventListener('change', onUploadFileControlChange); + uploadCancelButtonNode.addEventListener('click', onUploadCancelButtonClick); + uploadFormNode.addEventListener('submit', onUploadFormSubmit); + hashtagsInputNode.addEventListener('keydown', stopEscapePropagation); + descriptionInputNode.addEventListener('keydown', stopEscapePropagation); +}; + +export { initUploadPhotoForm };