Skip to content

Commit 2ddca37

Browse files
authored
Merge pull request #18 from khepriKreator/master
2 parents 6e26207 + 1b2fd3c commit 2ddca37

14 files changed

Lines changed: 165 additions & 134 deletions

index.html

Lines changed: 1 addition & 1 deletion
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" method="post" action="https://31.javascript.htmlacademy.pro/kekstagram" enctype="multipart/form-data" autocomplete="off">
3434

3535
<!-- Изначальное состояние поля для загрузки изображения -->
3636
<fieldset class="img-upload__start">

js/api.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { showGetPhotosError, showPostErrorMessage } from './messages.js';
1+
import { showGetPhotosError } from './messages.js';
22

33
const BASE_URL = 'https://31.javascript.htmlacademy.pro/kekstagram';
4+
45
const getPhotos = () => fetch(`${BASE_URL}/data`, {method: 'GET'})
56
.then((response) => {
67
if (!response.ok) {
@@ -12,15 +13,11 @@ const getPhotos = () => fetch(`${BASE_URL}/data`, {method: 'GET'})
1213
showGetPhotosError();
1314
});
1415

15-
const postPhoto = (form) => fetch(BASE_URL, {method: 'POST', body: new FormData(form)})
16+
const postPhoto = (form) => fetch(`${BASE_URL}/`, {method: 'POST', body: new FormData(form)})
1617
.then((response) => {
1718
if (!response.ok) {
1819
throw new Error(`${response.status}${response.statusText}`);
1920
}
20-
return response.ok;
21-
})
22-
.catch(() => {
23-
showPostErrorMessage();
2421
});
2522

2623
export { getPhotos, postPhoto };

js/effects.js

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
const EFFECTS = {
1+
const Effects = {
22
NONE: 'none',
33
CHROME: 'chrome',
44
SEPIA: 'sepia',
55
MARVIN: 'marvin',
66
PHOBOS: 'phobos',
77
HEAT: 'heat'
88
};
9-
const DEFAULT_EFFECT = EFFECTS.NONE;
109
const EffectsSettings = {
11-
[EFFECTS.NONE]: {
10+
[Effects.NONE]: {
1211
slider: {
1312
range: {
1413
min: 0,
@@ -21,7 +20,7 @@ const EffectsSettings = {
2120
style: '',
2221
units: ''
2322
},
24-
[EFFECTS.CHROME]: {
23+
[Effects.CHROME]: {
2524
slider: {
2625
range: {
2726
min: 0,
@@ -33,7 +32,7 @@ const EffectsSettings = {
3332
style: 'grayscale',
3433
units: ''
3534
},
36-
[EFFECTS.SEPIA]: {
35+
[Effects.SEPIA]: {
3736
slider: {
3837
range: {
3938
min: 0,
@@ -45,7 +44,7 @@ const EffectsSettings = {
4544
style: 'sepia',
4645
units: ''
4746
},
48-
[EFFECTS.MARVIN]: {
47+
[Effects.MARVIN]: {
4948
slider: {
5049
range: {
5150
min: 0,
@@ -57,7 +56,7 @@ const EffectsSettings = {
5756
style: 'invert',
5857
units: '%'
5958
},
60-
[EFFECTS.PHOBOS]: {
59+
[Effects.PHOBOS]: {
6160
slider: {
6261
range: {
6362
min: 0,
@@ -69,7 +68,7 @@ const EffectsSettings = {
6968
style: 'blur',
7069
units: 'px'
7170
},
72-
[EFFECTS.HEAT]: {
71+
[Effects.HEAT]: {
7372
slider: {
7473
range: {
7574
min: 1,
@@ -82,6 +81,7 @@ const EffectsSettings = {
8281
units: ''
8382
}
8483
};
84+
const DEFAULT_EFFECT = Effects.NONE;
8585

8686
const effectsList = document.querySelector('.effects__list');
8787
const sliderFieldset = document.querySelector('.effect-level');
@@ -91,13 +91,15 @@ const imagePreviewWrapper = document.querySelector('.img-upload__preview');
9191
const imagePreview = imagePreviewWrapper.querySelector('img');
9292

9393
let currentEffect = DEFAULT_EFFECT;
94-
const isNoneEffect = () => currentEffect === EFFECTS.NONE;
94+
95+
const isNoneEffect = () => currentEffect === Effects.NONE;
9596

9697
const applyEffect = (value) => {
9798
if (isNoneEffect()) {
9899
imagePreview.style.filter = '';
99100
return;
100101
}
102+
101103
const { style, units } = EffectsSettings[currentEffect];
102104
imagePreview.style.filter = `${style}(${value}${units})`;
103105
effectsSliderInput.value = value;
@@ -107,7 +109,8 @@ noUiSlider.create(effectsSlider, EffectsSettings[currentEffect].slider);
107109

108110
effectsSlider.noUiSlider.on('update', () => {
109111
const value = effectsSlider.noUiSlider.get();
110-
applyEffect(value);
112+
const fixedValue = Number(value);
113+
applyEffect(fixedValue);
111114
});
112115

113116
const setEffect = (effect) => {
@@ -123,9 +126,7 @@ const setEffect = (effect) => {
123126
};
124127

125128
const onEffectsChange = (evt) => {
126-
if (evt.target.classList.contains('effects__radio')) {
127-
setEffect(evt.target.value);
128-
}
129+
setEffect(evt.target.value);
129130
};
130131

131132
effectsList.addEventListener('change', onEffectsChange);

js/fake-data.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {getRandomNumber} from './utils.js';
22

3-
// DATA
43
const PHOTOS_COUNT = 25;
54
const Likes = {
65
MIN: 15,
@@ -23,15 +22,13 @@ const messagesArray = [
2322
'Лица у людей на фотке перекошены, как будто их избивают. Как можно было поймать такой неудачный момент?!',
2423
];
2524

26-
//Генерирует массив комментов
2725
const generateFakeCommentsArray = () => Array.from({length: getRandomNumber(CommentsCount.MIN, CommentsCount.MAX)}, (_, id) => ({
2826
id: id + 26,
2927
avatar: `img/avatar-${getRandomNumber(1, 6)}.svg`,
3028
message: messagesArray[getRandomNumber(0, messagesArray.length - 1)],
3129
name: names[getRandomNumber(0, names.length)],
3230
}));
3331

34-
//Генерирует массив данных
3532
const generateFakeDataArray = () => Array.from({length: PHOTOS_COUNT}, (_, i) => ({
3633
id: i + 1,
3734
url: `photos/${i + 1}.jpg`,

js/filters.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
11
import { renderPics } from './render-pics.js';
2-
import { getRandomNumber } from './utils.js';
2+
import { getRandomNumber, debounce } from './utils.js';
33

44
const RANDOM_SORT_COUNT = 10;
5+
const TIMEOUT_DELAY = 500;
56

67
const filterButtons = document.querySelectorAll('.img-filters__button');
7-
88
const defaultFilter = document.querySelector('#filter-default');
9+
910
let activeFilter = defaultFilter;
1011

12+
const debouncedRenderPics = debounce(renderPics, TIMEOUT_DELAY);
13+
1114
const filters = {
1215
'filter-default': (photos) => photos,
1316
'filter-random': (photos) => {
1417
const randomIndexes = new Set();
1518
const count = Math.min(RANDOM_SORT_COUNT, photos.length);
19+
1620
while (randomIndexes.size < count) {
1721
const randomIndex = getRandomNumber(0, photos.length - 1);
1822
randomIndexes.add(randomIndex);
1923
}
24+
2025
const randomPhotos = [];
2126
randomIndexes.forEach((i) => randomPhotos.push(photos[i]));
2227
return randomPhotos;
2328
},
24-
'filter-discussed': (photos) => [...photos].sort(
25-
(a, b) => b.comments.length - a.comments.length
29+
'filter-discussed': (photos) => [...photos].sort((a, b) =>
30+
b.comments.length - a.comments.length
2631
),
2732
};
2833

@@ -32,7 +37,7 @@ const setActiveFilter = (newFilter) => {
3237
activeFilter = newFilter;
3338
};
3439

35-
const onClickSort = ({target}, photos) => {
40+
const onClickSort = ({ target }, photos) => {
3641
const initialState = photos;
3742
const { id } = target;
3843
let filteredPhotos = initialState;
@@ -45,8 +50,9 @@ const onClickSort = ({target}, photos) => {
4550
setActiveFilter(target);
4651
filteredPhotos = filters[id](initialState);
4752
}
48-
renderPics(filteredPhotos);
53+
debouncedRenderPics(filteredPhotos);
4954
};
55+
5056
const filter = (data) => filterButtons.forEach((button) =>
5157
button.addEventListener('click', (evt) => onClickSort(evt, data))
5258
);

js/functions.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,25 @@
1-
//Проверяет длину строки
21
const isStringLonger = (string, length) => string.length <= length;
32

4-
// Через преобразование в массив и обратно
5-
/* const isStringPalindrome = (string) => {
6-
const normalizedString = string.toLowerCase().replaceAll(' ', '');
7-
const reversedString = normalizedString.split('').reverse().join('');
8-
return normalizedString === reversedString;
9-
}; */
10-
11-
// Через цикл for без преобразования в массив
123
const isStringPalindrome = (string) => {
134
const normalizedString = string.toLowerCase().replaceAll(' ', '');
145
let reversedString = '';
6+
157
for (let i = normalizedString.length - 1; i >= 0; i--) {
168
reversedString += normalizedString[i];
179
}
10+
1811
return normalizedString === reversedString;
1912
};
2013

21-
// Извлекает цифры из строки и преобразует в одно число
2214
const getNumberFromString = (string) => {
2315
const normalizedString = (typeof string === 'number') ? string.toString() : string;
2416
let result = '';
17+
2518
for (let i = 0; i < normalizedString.length; i++) {
2619
const symbol = normalizedString[i];
2720
result = !isNaN(parseInt(symbol, 10)) ? result + symbol : result;
2821
}
22+
2923
return (result === '') ? NaN : parseInt(result, 10);
3024
};
3125

js/main.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import {filter} from './filters.js';
66
onModalOpen();
77
onModalClose();
88
getPhotos().then((data) => {
9+
if (!data) {
10+
return;
11+
}
12+
document.querySelector('.img-filters').style.opacity = '1';
913
renderPics(data);
1014
filter(data);
11-
document.querySelector('.img-filters').style.opacity = '1';
1215
});

js/messages.js

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,56 @@
1+
const ERROR_MESSAGE_TIMER = 5000;
2+
13
const dataErrorTemplate = document.querySelector('#data-error').content;
24
const dataError = dataErrorTemplate.querySelector('.data-error');
35
const uploadErrorTemplate = document.querySelector('#error').content;
4-
const uploadError = uploadErrorTemplate.querySelector('.error');
5-
const errorButton = uploadError.querySelector('.error__button');
6+
const uploadErrorMessage = uploadErrorTemplate.querySelector('.error');
7+
const errorButton = uploadErrorMessage.querySelector('.error__button');
68
const uploadSuccessTemplate = document.querySelector('#success').content;
7-
const uploadSuccess = uploadSuccessTemplate.querySelector('.success');
8-
const successButton = uploadSuccess.querySelector('.success__button');
9+
const uploadSuccessMessage = uploadSuccessTemplate.querySelector('.success');
10+
const successButton = uploadSuccessMessage.querySelector('.success__button');
911
const { body } = document;
1012

11-
const showGetPhotosError = () => {
12-
body.append(dataError);
13-
setTimeout(() => body.removeChild(dataError), 5000);
13+
const templates = {
14+
success: {
15+
popup: uploadSuccessMessage,
16+
button: successButton
17+
},
18+
error: {
19+
popup: uploadErrorMessage,
20+
button: errorButton
21+
},
1422
};
1523

16-
const showPostErrorMessage = () => {
17-
body.append(uploadError);
18-
errorButton.addEventListener('click', () => {
19-
body.removeChild(uploadError);
20-
}, {once: true});
24+
const showGetPhotosError = () => {
25+
body.append(dataError);
26+
setTimeout(() => body.removeChild(dataError), ERROR_MESSAGE_TIMER);
2127
};
2228

23-
const showPostSuccessMessage = () => {
29+
const showMessage = (type) => {
2430
body.classList.add('open-modal');
25-
body.append(uploadSuccess);
26-
successButton.addEventListener('click', () => {
27-
body.classList.remove('open-modal');
28-
body.removeChild(uploadSuccess);
29-
}, {once: true});
31+
const message = templates[type].popup.cloneNode(true);
32+
body.append(message);
33+
34+
const onDocumentKeydown = ({ key }) => {
35+
if (key === 'Escape') {
36+
message.remove();
37+
body.classList.remove('open-modal');
38+
document.removeEventListener('keydown', onDocumentKeydown);
39+
}
40+
};
41+
42+
message.addEventListener('click', ({ target }) => {
43+
if (target.classList.contains(type) || target.classList.contains(`${type}__button`)) {
44+
message.remove();
45+
body.classList.remove('open-modal');
46+
document.removeEventListener('keydown', onDocumentKeydown);
47+
}
48+
});
49+
50+
document.addEventListener('keydown', onDocumentKeydown);
3051
};
3152

3253
export {
3354
showGetPhotosError,
34-
showPostSuccessMessage,
35-
showPostErrorMessage
55+
showMessage
3656
};

js/render-pics.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,32 @@ const template = document.querySelector('#picture').content;
55
const renderPics = (photos) => {
66
const picturesContainer = document.querySelector('.pictures');
77
const oldPhotos = picturesContainer.querySelectorAll('.picture');
8+
89
oldPhotos.forEach((item) => item.remove());
10+
911
const renderedPhotos = document.createDocumentFragment();
12+
1013
photos.forEach((item) => {
1114
const {url, description, likes, comments} = item;
1215
const picture = template.cloneNode(true);
13-
const image = picture.querySelector('.picture__img');
16+
const imagePreview = picture.querySelector('.picture__img');
1417
const likesCount = picture.querySelector('.picture__likes');
1518
const commentsCount = picture.querySelector('.picture__comments');
16-
const link = picture.querySelector('.picture');
17-
link.addEventListener('click', (evt) => {
19+
const pictureAnchor = picture.querySelector('.picture');
20+
21+
pictureAnchor.addEventListener('click', (evt) => {
1822
evt.preventDefault();
1923
onOpenModal(item);
2024
});
21-
image.src = url;
22-
image.alt = description;
25+
26+
imagePreview.src = url;
27+
imagePreview.alt = description;
2328
likesCount.textContent = likes;
2429
commentsCount.textContent = comments.length;
30+
2531
renderedPhotos.appendChild(picture);
2632
});
33+
2734
picturesContainer.appendChild(renderedPhotos);
2835
};
2936

0 commit comments

Comments
 (0)