Skip to content

Commit c60daa8

Browse files
authored
Merge pull request #9 from natalya87324/module9-task1
Правда или действие
2 parents e41a2b9 + 50f1ee4 commit c60daa8

File tree

3 files changed

+214
-25
lines changed

3 files changed

+214
-25
lines changed

index.html

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<!DOCTYPE html>
22
<html lang="ru">
3+
34
<head>
45
<meta charset="utf-8">
56
<meta name="viewport" content="width=device-width,initial-scale=1">
@@ -16,7 +17,8 @@
1617
<section class="img-filters img-filters--inactive container">
1718
<h2 class="img-filters__title visually-hidden">Фильтр фотографий</h2>
1819
<form class="img-filters__form" action="index.html" method="get" autocomplete="off">
19-
<button type=button class="img-filters__button img-filters__button--active" id="filter-default">По умолчанию</button>
20+
<button type=button class="img-filters__button img-filters__button--active" id="filter-default">По
21+
умолчанию</button>
2022
<button type=button class="img-filters__button" id="filter-random">Случайные</button>
2123
<button type=button class="img-filters__button" id="filter-discussed">Обсуждаемые</button>
2224
</form>
@@ -30,7 +32,8 @@ <h2 class="pictures__title visually-hidden">Фотографии других
3032
<section class="img-upload">
3133
<div class="img-upload__wrapper">
3234
<h2 class="img-upload__title visually-hidden">Загрузка фотографии</h2>
33-
<form class="img-upload__form" id="upload-select-image" autocomplete="off">
35+
<form class="img-upload__form" id="upload-select-image" method="post"
36+
action="https://31.javascript.htmlacademy.pro/kekstagram" enctype="multipart/form-data" autocomplete="off">
3437

3538
<!-- Изначальное состояние поля для загрузки изображения -->
3639
<fieldset class="img-upload__start">
@@ -46,7 +49,8 @@ <h2 class="img-upload__title visually-hidden">Загрузка фотограф
4649
<!-- Изменение размера изображения -->
4750
<fieldset class="img-upload__scale scale">
4851
<button type="button" class="scale__control scale__control--smaller">Уменьшить</button>
49-
<input type="text" class="scale__control scale__control--value" value="100%" title="Image Scale" name="scale" readonly>
52+
<input type="text" class="scale__control scale__control--value" value="100%" title="Image Scale"
53+
name="scale" readonly>
5054
<button type="button" class="scale__control scale__control--bigger">Увеличить</button>
5155
</fieldset>
5256

@@ -69,42 +73,48 @@ <h2 class="img-upload__title visually-hidden">Загрузка фотограф
6973
<fieldset class="img-upload__effects effects">
7074
<ul class="effects__list">
7175
<li class="effects__item">
72-
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-none" value="none" checked>
76+
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-none"
77+
value="none" checked>
7378
<label for="effect-none" class="effects__label">
7479
<span class="effects__preview effects__preview--none">Превью фото без эффекта</span>
7580
Оригинал
7681
</label>
7782
</li>
7883
<li class="effects__item">
79-
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-chrome" value="chrome">
84+
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-chrome"
85+
value="chrome">
8086
<label for="effect-chrome" class="effects__label">
8187
<span class="effects__preview effects__preview--chrome">Превью эффекта Хром</span>
8288
Хром
8389
</label>
8490
</li>
8591
<li class="effects__item">
86-
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-sepia" value="sepia">
92+
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-sepia"
93+
value="sepia">
8794
<label for="effect-sepia" class="effects__label">
8895
<span class="effects__preview effects__preview--sepia">Превью эффекта Сепия</span>
8996
Сепия
9097
</label>
9198
</li>
9299
<li class="effects__item">
93-
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-marvin" value="marvin">
100+
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-marvin"
101+
value="marvin">
94102
<label for="effect-marvin" class="effects__label">
95103
<span class="effects__preview effects__preview--marvin">Превью эффекта Марвин</span>
96104
Марвин
97105
</label>
98106
</li>
99107
<li class="effects__item">
100-
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-phobos" value="phobos">
108+
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-phobos"
109+
value="phobos">
101110
<label for="effect-phobos" class="effects__label">
102111
<span class="effects__preview effects__preview--phobos">Превью эффекта Фобос</span>
103112
Фобос
104113
</label>
105114
</li>
106115
<li class="effects__item">
107-
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-heat" value="heat">
116+
<input type="radio" class="effects__radio visually-hidden" name="effect" id="effect-heat"
117+
value="heat">
108118
<label for="effect-heat" class="effects__label">
109119
<span class="effects__preview effects__preview--heat">Превью эффекта Зной</span>
110120
Зной
@@ -154,15 +164,18 @@ <h2 class="big-picture__title visually-hidden">Просмотр фотогра
154164
</div>
155165

156166
<!-- Комментарии к изображению -->
157-
<div class="social__comment-count"><span class="social__comment-shown-count">5</span> из <span class="social__comment-total-count">125</span> комментариев</div>
167+
<div class="social__comment-count"><span class="social__comment-shown-count">5</span> из <span
168+
class="social__comment-total-count">125</span> комментариев</div>
158169
<ul class="social__comments">
159170
<li class="social__comment">
160-
<img class="social__picture" src="img/avatar-4.svg" alt="Аватар комментатора фотографии" width="35" height="35">
171+
<img class="social__picture" src="img/avatar-4.svg" alt="Аватар комментатора фотографии" width="35"
172+
height="35">
161173
<p class="social__text">Мега фото! Просто обалдеть. Как вам так удалось?</p>
162174
</li>
163175
<li class="social__comment">
164-
<img class="social__picture" src="img/avatar-3.svg" alt="Аватар комментатора фотографии" width="35" height="35">
165-
<p class="social__text">Да это фоташоп!!!!!!!!</p>
176+
<img class="social__picture" src="img/avatar-3.svg" alt="Аватар комментатора фотографии" width="35"
177+
height="35">
178+
<p class="social__text">Да это фоташоп!!!!!!!!</p>
166179
</li>
167180
</ul>
168181

@@ -171,7 +184,8 @@ <h2 class="big-picture__title visually-hidden">Просмотр фотогра
171184

172185
<!-- Форма для отправки комментария -->
173186
<div class="social__footer">
174-
<img class="social__picture" src="img/avatar-6.svg" alt="Аватар комментатора фотографии" width="35" height="35">
187+
<img class="social__picture" src="img/avatar-6.svg" alt="Аватар комментатора фотографии" width="35"
188+
height="35">
175189
<input type="text" class="social__footer-text" placeholder="Ваш комментарий...">
176190
<button type="button" class="social__footer-btn" name="button">Отправить</button>
177191
</div>
@@ -186,11 +200,14 @@ <h2 class="big-picture__title visually-hidden">Просмотр фотогра
186200
<footer class="page-footer container">
187201
<div class="page-footer__wrapper">
188202
<div class="page-footer__copyright copyright">
189-
<a class="copyright__link copyright__link--image" href="https://htmlacademy.ru/intensive/javascript"><img src="img/htmla-logo.svg" width="130" height="45" alt="HTML Academy"></a>
190-
<p>Сделано в <a class="copyright__link copyright__link--text" href="https://htmlacademy.ru/intensive/javascript">HTML Academy</a></p>
203+
<a class="copyright__link copyright__link--image" href="https://htmlacademy.ru/intensive/javascript"><img
204+
src="img/htmla-logo.svg" width="130" height="45" alt="HTML Academy"></a>
205+
<p>Сделано в <a class="copyright__link copyright__link--text"
206+
href="https://htmlacademy.ru/intensive/javascript">HTML Academy</a></p>
191207
</div>
192208
<ul class="page-footer__contacts contacts">
193-
<li><a href="https://twitter.com/htmlacademy_ru" class="contacts__link contacts__link--twitter">Twitter</a></li>
209+
<li><a href="https://twitter.com/htmlacademy_ru" class="contacts__link contacts__link--twitter">Twitter</a>
210+
</li>
194211
<li><a href="https://vk.com/htmlacademy" class="contacts__link contacts__link--vk">VK</a></li>
195212
</ul>
196213
</div>
@@ -227,13 +244,15 @@ <h2 class="success__title">Изображение успешно загруже
227244
</section>
228245
</template>
229246

230-
<!-- Сообщение с ошибкой загрузки изображений от других пользователей -->
231-
<template id="data-error">
232-
<section class="data-error">
233-
<h2 class="data-error__title">Не удалось загрузить данные</h2>
234-
</section>
235-
</template>
247+
<!-- Сообщение с ошибкой загрузки изображений от других пользователей -->
248+
<template id="data-error">
249+
<section class="data-error">
250+
<h2 class="data-error__title">Не удалось загрузить данные</h2>
251+
</section>
252+
</template>
236253

237-
<script src="./js/main.js" type="module"></script>
254+
<script src="./vendor/pristine/pristine.min.js"></script>
255+
<script src="./js/main.js" type="module"></script>
238256
</body>
239-
</html>
257+
258+
</html>

js/main.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { addPhotos } from './data.js';
22
import { renderPhotos } from './photos.js';
3+
import { initPhotoUploadForm } from './upload-photo.js';
34

45
renderPhotos(addPhotos());
6+
7+
initPhotoUploadForm();

js/upload-photo.js

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import { toggleClass, isEscapeKey } from './util.js';
2+
3+
const HASHTAG_MAX_COUNT = 5;
4+
5+
const DESCRIPTION_MAX_LENGTH = 140;
6+
7+
const HashtagLength = {
8+
MIN: 2,
9+
MAX: 20
10+
};
11+
12+
const photoUploadForm = document.querySelector('.img-upload__form');
13+
const photoUploadInput = photoUploadForm.querySelector('.img-upload__input');
14+
const photoUploadOverlay = photoUploadForm.querySelector('.img-upload__overlay');
15+
const hashtagInput = photoUploadForm.querySelector('.text__hashtags');
16+
const photoDescriptionField = photoUploadForm.querySelector('.text__description');
17+
const cancelPhotoUploadBtn = photoUploadForm.querySelector('#upload-cancel');
18+
const photoSubmitBtn = photoUploadForm.querySelector('#upload-submit');
19+
20+
let errorMessage = '';
21+
22+
const getHashtagErrorMessage = () => errorMessage;
23+
24+
const getDescriptionErrorMessage = () => `Длина комментария не может составлять больше ${DESCRIPTION_MAX_LENGTH} символов`;
25+
26+
const pristine = new Pristine(photoUploadForm, {
27+
classTo: 'img-upload__field-wrapper',
28+
errorTextParent: 'img-upload__field-wrapper',
29+
errorTextClass: 'img-upload__field-wrapper--error',
30+
});
31+
32+
33+
const validatePhotoDescription = (description) => description.length < DESCRIPTION_MAX_LENGTH;
34+
35+
const validateHashtags = (value) => {
36+
errorMessage = '';
37+
38+
const hashtagRegex = /^#[a-zа-яё0-9]{1,19}$/i;
39+
40+
const inputText = value.toLowerCase().trim();
41+
42+
if (!inputText) {
43+
return true;
44+
}
45+
46+
const inputArray = inputText.split(/\s+/);
47+
48+
const rules = [
49+
{
50+
check: inputArray.some((item) => item.indexOf('#', 1) >= 1),
51+
error: 'Хэштеги разделяются пробелами'
52+
},
53+
{
54+
check: inputArray.some((item) => item[0] !== '#'),
55+
error: 'Хэштег должен начинаться с символа #'
56+
},
57+
{
58+
check: inputArray.some((item, index, array) => array.includes(item, index + 1)),
59+
error: 'Хэштеги не должны повторяться'
60+
},
61+
{
62+
check: inputArray.some((item) => item.length > HashtagLength.MAX),
63+
error: `Максимальная длина одного хэштега ${HashtagLength.MAX} символов, включая решётку`
64+
},
65+
{
66+
check: inputArray.some((item) => item.length < HashtagLength.MIN),
67+
error: 'Хештег не может состоять только из одной решётки'
68+
},
69+
{
70+
check: inputArray.length > HASHTAG_MAX_COUNT,
71+
error: `Нельзя указать больше ${HASHTAG_MAX_COUNT} хэштегов`
72+
},
73+
{
74+
check: inputArray.some((item) => !hashtagRegex.test(item)),
75+
error: 'Хештег содержит недопустимые символы'
76+
}
77+
];
78+
79+
return rules.every((rule) => {
80+
const isInvalid = rule.check;
81+
if (isInvalid) {
82+
errorMessage = rule.error;
83+
}
84+
return !isInvalid;
85+
});
86+
87+
};
88+
89+
pristine.addValidator(photoDescriptionField, validatePhotoDescription, getDescriptionErrorMessage);
90+
pristine.addValidator(hashtagInput, validateHashtags, getHashtagErrorMessage);
91+
92+
const toggleSubmitBtn = () => {
93+
if (pristine.validate()) {
94+
photoSubmitBtn.disabled = false;
95+
} else {
96+
photoSubmitBtn.disabled = true;
97+
}
98+
};
99+
100+
const onHashtagInput = () => toggleSubmitBtn();
101+
const onDescriptionInput = () => toggleSubmitBtn();
102+
103+
const toggleModal = () => {
104+
toggleClass(photoUploadOverlay, 'hidden');
105+
toggleClass(document.body, 'modal-open');
106+
};
107+
108+
const resetForm = () => {
109+
const errorArray = document.querySelectorAll('.img-upload__field-wrapper--error');
110+
if (errorArray.length !== 0) {
111+
errorArray.forEach((error) => {
112+
error.textContent = '';
113+
});
114+
}
115+
photoUploadForm.reset();
116+
};
117+
118+
const onCancelPhotoUpload = (evt) => {
119+
evt.preventDefault();
120+
resetForm();
121+
closePhotoUploadForm();
122+
};
123+
124+
const onPhotoUploadEscKey = (evt) => {
125+
if (isEscapeKey(evt) && document.activeElement !== hashtagInput && document.activeElement !== photoDescriptionField) {
126+
evt.preventDefault();
127+
resetForm();
128+
closePhotoUploadForm();
129+
}
130+
};
131+
132+
const onOpenPhotoUploadForm = (evt) => {
133+
if (evt.target.value) {
134+
openPhotoUploadForm();
135+
}
136+
};
137+
138+
function openPhotoUploadForm() {
139+
document.addEventListener('keydown', onPhotoUploadEscKey);
140+
toggleModal();
141+
toggleSubmitBtn();
142+
}
143+
144+
function closePhotoUploadForm() {
145+
document.removeEventListener('keydown', onPhotoUploadEscKey);
146+
photoUploadInput.value = '';
147+
toggleModal();
148+
}
149+
150+
const onPristineValidate = (evt) => {
151+
evt.preventDefault();
152+
153+
if (pristine.validate()) {
154+
photoUploadForm.submit();
155+
}
156+
};
157+
158+
const initPhotoUploadForm = () => {
159+
photoUploadForm.addEventListener('submit', onPristineValidate);
160+
photoUploadInput.addEventListener('change', onOpenPhotoUploadForm);
161+
cancelPhotoUploadBtn.addEventListener('click', onCancelPhotoUpload);
162+
hashtagInput.addEventListener('input', onHashtagInput);
163+
photoDescriptionField.addEventListener('input', onDescriptionInput);
164+
};
165+
166+
167+
export { initPhotoUploadForm };

0 commit comments

Comments
 (0)