Skip to content

Commit c8d41b5

Browse files
authored
Merge pull request #7 from Nigina9/module9-task1
Правда или действие
2 parents bf796cb + 1a25574 commit c8d41b5

File tree

8 files changed

+310
-4
lines changed

8 files changed

+310
-4
lines changed

index.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ <h2 class="pictures__title visually-hidden">Фотографии других
3030
<section class="img-upload">
3131
<div class="img-upload__wrapper">
3232
<h2 class="img-upload__title visually-hidden">Загрузка фотографии</h2>
33-
<form class="img-upload__form" id="upload-select-image" autocomplete="off">
33+
<form class="img-upload__form" id="upload-select-image" autocomplete="off" action="https://32.javascript.htmlacademy.pro/kekstagram" method="post" enctype="multipart/form-data">
3434

3535
<!-- Изначальное состояние поля для загрузки изображения -->
3636
<fieldset class="img-upload__start">
@@ -119,7 +119,7 @@ <h2 class="img-upload__title visually-hidden">Загрузка фотограф
119119
<input class="text__hashtags" name="hashtags" placeholder="#ХэшТег">
120120
</div>
121121
<div class="img-upload__field-wrapper">
122-
<textarea class="text__description" name="description" placeholder="Ваш комментарий..."></textarea>
122+
<textarea class="text__description" name="description" placeholder="Ваш комментарий..." maxlength="140"></textarea>
123123
</div>
124124
</fieldset>
125125

@@ -235,5 +235,7 @@ <h2 class="data-error__title">Не удалось загрузить данны
235235
</template>
236236
<script src="functions.js"></script>
237237
<script type="module" src="js/main.js"></script>
238+
<script src="vendor/pristine/pristine.min.js"></script>
239+
<script src="./vendor/nouislider/nouislider.js"></script>
238240
</body>
239241
</html>

js/dataEffects.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const styleEffects = {
2+
'none': {
3+
min: 0,
4+
max: 100,
5+
step: 1
6+
},
7+
'chrome': {
8+
style: 'grayscale',
9+
unit: '',
10+
min: 0,
11+
max: 1,
12+
step: 0.1
13+
},
14+
'sepia': {
15+
style: 'sepia',
16+
unit: '',
17+
min: 0,
18+
max: 1,
19+
step: 0.1
20+
},
21+
'marvin': {
22+
style: 'invert',
23+
unit: '%',
24+
min: 0,
25+
max: 100,
26+
step: 1
27+
},
28+
'phobos': {
29+
style: 'blur',
30+
unit: 'px',
31+
min: 0,
32+
max: 3,
33+
step: 0.1
34+
},
35+
'heat': {
36+
style: 'brightness',
37+
unit: '',
38+
min: 1,
39+
max: 3,
40+
step: 0.1
41+
}
42+
};
43+
44+
export {
45+
styleEffects
46+
};

js/effectsStyle.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import {
2+
styleEffects
3+
} from './dataEffects.js';
4+
5+
let currentEffect = 'none';
6+
7+
const imgUploadPreview = document.querySelector('.img-upload__preview img');
8+
const effectLevelSlider = document.querySelector('.effect-level__slider');
9+
const effectsList = document.querySelector('.effects__list');
10+
const effectLevelValue = document.querySelector('.effect-level__value');
11+
const effectLevel = document.querySelector('.effect-level');
12+
13+
const setImageStyle = () => {
14+
if (currentEffect === 'none') {
15+
imgUploadPreview.style.filter = null;
16+
return;
17+
}
18+
19+
const value = effectLevelValue.value;
20+
const unit = styleEffects[currentEffect].unit;
21+
const style = styleEffects[currentEffect].style;
22+
imgUploadPreview.style.filter = `${style}(${value}${unit})`;
23+
};
24+
25+
const onSliderUpdate = () => {
26+
effectLevelValue.value = effectLevelSlider.noUiSlider.get();
27+
setImageStyle();
28+
};
29+
30+
const createSlider = () => {
31+
noUiSlider.create(effectLevelSlider, {
32+
range: {
33+
min: 0,
34+
max: 1
35+
},
36+
step: 0.1,
37+
start: 1,
38+
connect: 'lower',
39+
format: {
40+
to: (value) => Number(value),
41+
from: (value) => Number(value)
42+
}
43+
});
44+
45+
effectLevelValue.value = effectLevelSlider.noUiSlider.get();
46+
effectLevelSlider.noUiSlider.on('update', onSliderUpdate);
47+
};
48+
49+
const updateSlider = ({
50+
min,
51+
max,
52+
step
53+
}) => {
54+
effectLevelSlider.noUiSlider.updateOptions({
55+
range: {
56+
min,
57+
max
58+
},
59+
step,
60+
start: max
61+
});
62+
63+
effectLevelValue.value = effectLevelSlider.noUiSlider.get();
64+
};
65+
66+
const pictureEffectReset = () => {
67+
effectLevel.classList.add('hidden');
68+
imgUploadPreview.style.filter = null;
69+
effectLevelSlider.value = null;
70+
};
71+
72+
effectsList.addEventListener('change', (evt) => {
73+
currentEffect = evt.target.value;
74+
75+
if (currentEffect === 'none') {
76+
pictureEffectReset();
77+
effectLevel.classList.add('hidden');
78+
effectLevelSlider.value = null;
79+
} else {
80+
effectLevel.classList.remove('hidden');
81+
effectLevelSlider.value = currentEffect;
82+
updateSlider(styleEffects[currentEffect]);
83+
setImageStyle();
84+
}
85+
});
86+
87+
const pictureEffectInit = () => {
88+
createSlider(styleEffects[currentEffect]);
89+
};
90+
91+
export {
92+
pictureEffectInit,
93+
pictureEffectReset
94+
};

js/form.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
const MAX_HASHTAG_COUNT = 5;
2+
const MAX_HASHTAG_LENGTH = 20;
3+
const MAX_COMMENTS_LENGTH = 140;
4+
5+
const uploadFormImg = document.querySelector('.img-upload__form');
6+
const textDescription = document.querySelector('.text__description');
7+
const textHashtag = document.querySelector('.text__hashtags');
8+
9+
const options = {
10+
classTo: 'img-upload__field-wrapper',
11+
errorTextParent: 'img-upload__field-wrapper',
12+
errorTextClass: 'img-upload__field-wrapper--error'
13+
};
14+
15+
const errorMessage = {
16+
hashtag: 'Поле заполнено некорректно.',
17+
description: `длина комментария не может составлять больше ${MAX_COMMENTS_LENGTH} символов`
18+
};
19+
20+
const isErrorDescription = (value) => {
21+
let isValid = true;
22+
23+
if (value.length > MAX_COMMENTS_LENGTH) {
24+
isValid = false;
25+
}
26+
27+
return isValid;
28+
};
29+
30+
const isErrorHashtag = (value) => {
31+
value = value.replace(/\s+/g, ' ').trim().split(' ');
32+
let isValid = true;
33+
const validHachtag = /^#[А-яЁёA-z0-9]{1,19}$/i;
34+
35+
if (value.length > MAX_HASHTAG_COUNT) {
36+
errorMessage.hashtag = `Может быть не более ${MAX_HASHTAG_COUNT} хэштегов.`;
37+
isValid = false;
38+
return isValid;
39+
}
40+
41+
const setHashtag = new Set(value);
42+
if (setHashtag.size !== value.length) {
43+
errorMessage.hashtag = 'Один и тот же хэштег не может быть использован дважды.';
44+
isValid = false;
45+
return isValid;
46+
}
47+
48+
value.forEach((currentHachtag) => {
49+
if (!validHachtag.test(currentHachtag)) {
50+
errorMessage.hashtag = 'Хэштег должен начинаться с "#" и может состоять только из букв и чисел.';
51+
isValid = false;
52+
}
53+
54+
if (currentHachtag.length > MAX_HASHTAG_LENGTH) {
55+
errorMessage.hashtag = `Максимальная длина одного хэштега ${MAX_HASHTAG_LENGTH} символов, включая решётку.`;
56+
isValid = false;
57+
}
58+
});
59+
return isValid;
60+
};
61+
62+
const getHashtagErrorMessage = () => errorMessage.hashtag;
63+
64+
const pristine = new Pristine(uploadFormImg, options, true);
65+
66+
const form = () => {
67+
68+
pristine.addValidator(textDescription, isErrorDescription, errorMessage.description);
69+
pristine.addValidator(textHashtag, isErrorHashtag, getHashtagErrorMessage);
70+
};
71+
72+
const clearValidator = () => {
73+
pristine.reset();
74+
pristine.destroy();
75+
};
76+
77+
export {
78+
form,
79+
clearValidator
80+
};

js/main.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import {pictures} from './createThumbnail.js';
22
import {openPicture} from './openBigPhotoShow.js';
3+
import { uploadImageModal } from './upload.js';
34

45
pictures.addEventListener('click', (evt) => {
56
const currentPicture = evt.target.closest('.picture');
67
if (currentPicture) {
78
openPicture(currentPicture.dataset.pictureId);
89
}
910
});
11+
12+
uploadImageModal();

js/openBigPhotoShow.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ const caption = pictureBig.querySelector('.social__caption');
1616
const pictureBigcloseButton = document.querySelector('#picture-cancel');
1717
const body = document.body;
1818

19-
// Убедитесь, что модальное окно скрыто при загрузке
2019
pictureBig.classList.add('hidden');
2120

22-
// / создаю функцию где добавляю класс хидден, чтоб показать фотку
2321
const hidePictureBig = () => {
2422
// Закрываем модальное окно
2523
pictureBig.classList.add('hidden');

js/scalePictures.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const scaleControlSmaller = document.querySelector('.scale__control--smaller');
2+
const scaleControlValue = document.querySelector('.scale__control--value');
3+
const scaleControlBigger = document.querySelector('.scale__control--bigger');
4+
const bigImages = document.querySelector('.img-upload__preview img');
5+
6+
const MAX_CONTROL = 100;
7+
const MIN_CONTROL = 25;
8+
const DEFAULT_CONTROL = 100;
9+
const STEP = 25;
10+
11+
const upValue = () => Math.min(MAX_CONTROL, (parseInt(scaleControlValue.value, 10) + STEP));
12+
const endValue = () => Math.max(MIN_CONTROL, (parseInt(scaleControlValue.value, 10) - STEP));
13+
const updateScale = (value) => {
14+
scaleControlValue.value = `${value}%`;
15+
bigImages.style.transform = `scale(${value / 100})`;
16+
};
17+
18+
const pictureScale = () => {
19+
scaleControlSmaller.addEventListener('click', () => {
20+
updateScale(endValue());
21+
});
22+
23+
scaleControlBigger.addEventListener('click', () => {
24+
updateScale(upValue());
25+
});
26+
};
27+
28+
const pictureScaleDefault = () => updateScale(DEFAULT_CONTROL);
29+
30+
export {
31+
pictureScale,
32+
pictureScaleDefault
33+
};

js/upload.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { isEscapeKey } from './util.js';
2+
import { clearValidator } from './form';
3+
4+
import { form } from './form.js';
5+
import { pictureEffectInit, pictureEffectReset } from './effectsStyle.js';
6+
import { pictureScale, pictureScaleDefault } from './scalePictures.js';
7+
8+
form();
9+
pictureEffectInit();
10+
pictureScale();
11+
12+
const uploadImageModal = () => {
13+
const imgUploadInput = document.querySelector('.img-upload__input');
14+
const imgUploadOverlay = document.querySelector('.img-upload__overlay');
15+
const imgUploadCancel = document.querySelector('.img-upload__cancel');
16+
17+
const onFormKeydown = (evt) => {
18+
if (document.activeElement.name === 'hashtags' || document.activeElement.name === 'description') {
19+
return;
20+
}
21+
22+
if (isEscapeKey(evt)) {
23+
closeModal();
24+
}
25+
};
26+
27+
imgUploadInput.addEventListener('input', () => {
28+
imgUploadOverlay.classList.remove('hidden');
29+
document.body.classList.add('modal-open');
30+
pictureEffectReset();
31+
32+
document.addEventListener('keydown', onFormKeydown);
33+
imgUploadCancel.addEventListener('click', closeModal);
34+
});
35+
36+
function closeModal() {
37+
imgUploadOverlay.classList.add('hidden');
38+
document.body.classList.remove('modal-open');
39+
40+
document.removeEventListener('keydown', onFormKeydown);
41+
imgUploadCancel.removeEventListener('click', closeModal);
42+
document.querySelector('.img-upload__form').reset();
43+
clearValidator();
44+
pictureScaleDefault();
45+
}
46+
};
47+
48+
export {
49+
uploadImageModal
50+
};

0 commit comments

Comments
 (0)