Skip to content

Commit 02b3229

Browse files
authored
Merge pull request #11 from YouAreNotReady/module9-task2
2 parents 762d794 + abce720 commit 02b3229

7 files changed

+183
-12
lines changed

index.html

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<meta name="viewport" content="width=device-width,initial-scale=1">
66
<link rel="stylesheet" href="css/normalize.css">
77
<link rel="stylesheet" href="css/style.css">
8+
<link rel="stylesheet" href="vendor/nouislider/nouislider.css">
89
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
910
<title>Кекстаграм</title>
1011
</head>
@@ -116,10 +117,10 @@ <h2 class="img-upload__title visually-hidden">Загрузка фотограф
116117
<!-- Добавление хэштегов и комментария к изображению -->
117118
<fieldset class="img-upload__text text">
118119
<div class="img-upload__field-wrapper">
119-
<input class="text__hashtags" name="hashtags" placeholder="#ХэшТег" maxlength="100">
120+
<input class="text__hashtags" name="hashtags" placeholder="#ХэшТег">
120121
</div>
121122
<div class="img-upload__field-wrapper">
122-
<textarea class="text__description" name="description" placeholder="Ваш комментарий..." maxlength="140"></textarea>
123+
<textarea class="text__description" name="description" placeholder="Ваш комментарий..."></textarea>
123124
</div>
124125
</fieldset>
125126

@@ -239,6 +240,7 @@ <h2 class="data-error__title">Не удалось загрузить данны
239240

240241

241242
<script src="./vendor/pristine/pristine.min.js"></script>
243+
<script src="./vendor/nouislider/nouislider.js"></script>
242244
<script src="./js/main.js" type="module"></script>
243245
<script src="./js/functions.js"></script>
244246
</body>

js/comment-validation.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const validateComment = (value) => value.length <= 140;
2+
3+
export { validateComment };

js/hashtag-validation.js

+48-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const hashtag = /^#[a-zа-яё0-9]{1,19}$/i;
22

33
const validateHashtag = (value) => {
44
const hashtagArray = value.split(' ');
5-
return value === '' ? true : hashtagArray.every((el) => hashtag.test(el));
5+
return hashtagArray.every((el) => hashtag.test(el));
66
};
77

88
const checkForRepeatingHashtag = (value) => {
@@ -16,4 +16,50 @@ const checkForHashtagCount = (value) => {
1616
return hashtagArray.length <= 5;
1717
};
1818

19-
export { validateHashtag, checkForRepeatingHashtag, checkForHashtagCount };
19+
const validateAllHashtags = (value) => {
20+
if (value.trim() === '') {
21+
return true;
22+
}
23+
24+
const hashtagValidation = validateHashtag(value);
25+
if (!hashtagValidation) {
26+
return false;
27+
}
28+
29+
const repeatingValidation = checkForRepeatingHashtag(value);
30+
if (!repeatingValidation) {
31+
return false;
32+
}
33+
34+
const countValidation = checkForHashtagCount(value);
35+
if (!countValidation) {
36+
return false;
37+
}
38+
39+
return true;
40+
};
41+
42+
const validateHashtagError = (value) => {
43+
if (value.trim() === '') {
44+
return '';
45+
}
46+
47+
const hashtagValidation = validateHashtag(value);
48+
if (!hashtagValidation) {
49+
return 'Не валидный хэштег';
50+
}
51+
52+
const repeatingValidation = checkForRepeatingHashtag(value);
53+
if (!repeatingValidation) {
54+
return 'Хэштеги повторяются';
55+
}
56+
57+
const countValidation = checkForHashtagCount(value);
58+
if (!countValidation) {
59+
return 'Превышено количество хэштегов';
60+
}
61+
62+
return '';
63+
};
64+
65+
export { validateAllHashtags, validateHashtagError };

js/image-effect.js

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { imagePreview } from './image-scaling.js';
2+
3+
const sliderElementWrapper = document.querySelector('.img-upload__effect-level');
4+
const sliderElement = sliderElementWrapper.querySelector('.effect-level__slider');
5+
const valueElement = document.querySelector('.effect-level__value');
6+
const chromeValue = document.querySelector('#effect-chrome');
7+
const sepiaValue = document.querySelector('#effect-sepia');
8+
const marvinValue = document.querySelector('#effect-marvin');
9+
const phobosValue = document.querySelector('#effect-phobos');
10+
const heatValue = document.querySelector('#effect-heat');
11+
const radioInputElements = document.querySelector('.img-upload__effects');
12+
let currentSliderValue = 0;
13+
14+
sliderElementWrapper.classList.add('hidden');
15+
16+
noUiSlider.create(sliderElement, {
17+
range: {
18+
min: 0,
19+
max: 0,
20+
},
21+
start: 0,
22+
connect: 'lower',
23+
format: {
24+
to: function (value) {
25+
if (Number.isInteger(value)) {
26+
return value.toFixed(0);
27+
}
28+
return value.toFixed(1);
29+
},
30+
from: function (value) {
31+
return parseFloat(value);
32+
},
33+
},
34+
});
35+
36+
const applyFilter = () => {
37+
if (chromeValue.checked) {
38+
imagePreview.style.filter = `grayscale(${currentSliderValue})`;
39+
} else if (sepiaValue.checked) {
40+
imagePreview.style.filter = `sepia(${currentSliderValue})`;
41+
} else if (marvinValue.checked) {
42+
imagePreview.style.filter = `invert(${currentSliderValue}%)`;
43+
} else if (phobosValue.checked) {
44+
imagePreview.style.filter = `blur(${currentSliderValue}px)`;
45+
} else if (heatValue.checked) {
46+
imagePreview.style.filter = `brightness(${currentSliderValue})`;
47+
} else {
48+
imagePreview.style.filter = '';
49+
}
50+
};
51+
52+
sliderElement.noUiSlider.on('update', () => {
53+
currentSliderValue = sliderElement.noUiSlider.get();
54+
valueElement.value = currentSliderValue;
55+
applyFilter();
56+
});
57+
58+
radioInputElements.addEventListener('click', (evt) => {
59+
if (evt.target.matches('input[type="radio"]')) {
60+
let options = {};
61+
sliderElementWrapper.classList.remove('hidden');
62+
switch (evt.target) {
63+
case chromeValue:
64+
case sepiaValue:
65+
options = { range: { min: 0, max: 1 }, start: 1, step: 0.1 };
66+
break;
67+
case marvinValue:
68+
options = { range: { min: 0, max: 100 }, start: 100, step: 1 };
69+
break;
70+
case phobosValue:
71+
options = { range: { min: 0, max: 3 }, start: 3, step: 0.1 };
72+
break;
73+
case heatValue:
74+
options = { range: { min: 1, max: 3 }, start: 3, step: 0.1 };
75+
break;
76+
default:
77+
options = { range: { min: 0, max: 0 }, start: 0};
78+
applyFilter();
79+
sliderElementWrapper.classList.add('hidden');
80+
}
81+
82+
sliderElement.noUiSlider.updateOptions(options);
83+
}
84+
});
85+
86+
export { sliderElementWrapper };

js/image-scaling.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
const buttonSmaller = document.querySelector('.scale__control--smaller');
2+
const buttonBigger = document.querySelector('.scale__control--bigger');
3+
const scaleValueField = document.querySelector('.scale__control--value');
4+
const imagePreview = document.querySelector('.img-upload__preview img');
5+
6+
const MAX_SCALE_VALUE = 100;
7+
const MIN_SCALE_VALUE = 25;
8+
const STEP_SCALE_VALUE = 25;
9+
10+
buttonBigger.addEventListener('click', () => {
11+
if(parseFloat(scaleValueField.value) < MAX_SCALE_VALUE) {
12+
scaleValueField.value = `${parseFloat(scaleValueField.value) + STEP_SCALE_VALUE}%`;
13+
scaleValueField.dispatchEvent(new Event('change'));
14+
}
15+
});
16+
17+
buttonSmaller.addEventListener('click', () => {
18+
if(parseFloat(scaleValueField.value) > MIN_SCALE_VALUE) {
19+
scaleValueField.value = `${parseFloat(scaleValueField.value) - STEP_SCALE_VALUE}%`;
20+
scaleValueField.dispatchEvent(new Event('change'));
21+
}
22+
});
23+
24+
scaleValueField.addEventListener('change', () => {
25+
imagePreview.style.transform = `scale(${scaleValueField.value})`;
26+
});
27+
28+
export { imagePreview, scaleValueField };

js/image-upload.js

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { isEscapeKey } from './util.js';
2-
import { validateHashtag, checkForRepeatingHashtag, checkForHashtagCount } from './hashtag-validation.js';
2+
import { imagePreview, scaleValueField } from './image-scaling.js';
3+
import { sliderElementWrapper } from './image-effect.js';
4+
import { validateAllHashtags, validateHashtagError } from './hashtag-validation.js';
5+
import { validateComment } from './comment-validation.js';
36

47
const imageUploadForm = document.querySelector('.img-upload__form');
58
const imageUploadNode = imageUploadForm.querySelector('.img-upload__overlay');
@@ -11,14 +14,11 @@ const commentInput = imageUploadForm.querySelector('.text__description');
1114

1215
const pristine = new Pristine(imageUploadForm, {
1316
classTo: 'img-upload__field-wrapper',
14-
errorTextParent: 'img-upload__field-wrapper',
1517
errorTextClass: 'img-upload__field-wrapper--error',
18+
errorTextParent: 'img-upload__field-wrapper',
19+
errorTextTag: 'div',
1620
}, false);
1721

18-
pristine.addValidator(imageUploadForm.querySelector('.text__hashtags'), validateHashtag, 'Введён невалидный хэштег');
19-
pristine.addValidator(imageUploadForm.querySelector('.text__hashtags'), checkForRepeatingHashtag, 'Хэштеги повторяются');
20-
pristine.addValidator(imageUploadForm.querySelector('.text__hashtags'), checkForHashtagCount, 'Превышено количество хэштегов');
21-
2222
const onDocumentKeydown = (evt) => {
2323
if (isEscapeKey(evt)) {
2424
evt.preventDefault();
@@ -34,6 +34,10 @@ function uploadFormClear() {
3434
hashtagsInput.value = '';
3535
commentInput.value = '';
3636
effectOriginal.checked = true;
37+
sliderElementWrapper.classList.add('hidden');
38+
imagePreview.style.transform = '';
39+
imagePreview.style.filter = '';
40+
scaleValueField.value = '100%';
3741
}
3842

3943
function uploadFormCloseHandler() {
@@ -60,12 +64,13 @@ imageUploadInput.addEventListener('change', ()=> {
6064
document.addEventListener('keydown', onDocumentKeydown);
6165
});
6266

67+
pristine.addValidator(imageUploadForm.querySelector('.text__hashtags'), validateAllHashtags, validateHashtagError);
68+
pristine.addValidator(imageUploadForm.querySelector('.text__description'), validateComment, 'Длина комментария не может составлять больше 140 символов');
69+
6370
imageUploadForm.addEventListener('submit', (evt) => {
6471
evt.preventDefault();
6572
pristine.validate();
6673

6774
imageUploadForm.removeEventListener('keydown', uploadFormNoEscWhenInputActive);
6875
imageUploadCloseButton.removeEventListener('click', uploadFormCloseHandler);
6976
});
70-
71-

js/main.js

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { renderPictures } from './pictures-preview-loader.js';
33

44
import './show-image-fullscreen.js';
55
import './hashtag-validation.js';
6+
import './comment-validation.js';
67
import './image-upload.js';
78
import './image-scaling.js';
89
import './image-effect.js';

0 commit comments

Comments
 (0)