Skip to content

Commit 46f03a5

Browse files
authored
Merge pull request #12 from NoaVel/module12-task1
2 parents 1e41e4d + 79d9032 commit 46f03a5

5 files changed

Lines changed: 105 additions & 37 deletions

File tree

js/filters.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { renderThumbnails } from './render-thumbnails.js';
2+
import { debounce } from './util.js';
3+
4+
const RANDOM_PHOTOS_COUNT = 10;
5+
const RERENDER_DELAY = 500;
6+
const ACTIVE_BUTTON_CLASS = 'img-filters__button--active';
7+
8+
const FilterId = {
9+
DEFAULT: 'filter-default',
10+
RANDOM: 'filter-random',
11+
DISCUSSED: 'filter-discussed',
12+
};
13+
14+
const filtersSection = document.querySelector('.img-filters');
15+
const filtersForm = document.querySelector('.img-filters__form');
16+
17+
let currentFilter = FilterId.DEFAULT;
18+
let photos = [];
19+
20+
const getRandomPhotos = (photosArray) => {
21+
const shuffled = [...photosArray].sort(() => Math.random() - 0.5);
22+
return shuffled.slice(0, RANDOM_PHOTOS_COUNT);
23+
};
24+
25+
const getDiscussedPhotos = (photosArray) =>
26+
[...photosArray].sort((a, b) => b.comments.length - a.comments.length);
27+
28+
const filterPhotos = () => {
29+
switch (currentFilter) {
30+
case FilterId.RANDOM:
31+
return getRandomPhotos(photos);
32+
case FilterId.DISCUSSED:
33+
return getDiscussedPhotos(photos);
34+
default:
35+
return [...photos];
36+
}
37+
};
38+
39+
const updateActiveButton = (clickedButton) => {
40+
const activeButton = filtersForm.querySelector(`.${ACTIVE_BUTTON_CLASS}`);
41+
if (activeButton) {
42+
activeButton.classList.remove(ACTIVE_BUTTON_CLASS);
43+
}
44+
clickedButton.classList.add(ACTIVE_BUTTON_CLASS);
45+
};
46+
47+
const debouncedRenderThumbnails = debounce(
48+
() => renderThumbnails(filterPhotos()),
49+
RERENDER_DELAY
50+
);
51+
52+
const onFilterButtonClick = (evt) => {
53+
const clickedButton = evt.target.closest('.img-filters__button');
54+
55+
if (!clickedButton) {
56+
return;
57+
}
58+
59+
if (clickedButton.id === currentFilter) {
60+
return;
61+
}
62+
63+
currentFilter = clickedButton.id;
64+
updateActiveButton(clickedButton);
65+
debouncedRenderThumbnails();
66+
};
67+
68+
const showFilters = () => {
69+
filtersSection.classList.remove('img-filters--inactive');
70+
};
71+
72+
const initFilters = (loadedPhotos) => {
73+
photos = loadedPhotos;
74+
showFilters();
75+
filtersForm.addEventListener('click', onFilterButtonClick);
76+
};
77+
78+
export { initFilters };

js/main.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { initImageEditor } from './image-editor.js';
44
import { getData } from './api.js';
55
import { showDataLoadError } from './messages.js';
66
import { setPhotos } from './full-size-picture.js';
7+
import { initFilters } from './filters.js';
78

89
// Инициализация формы загрузки и редактора изображений
910
initUploadPhotoForm();
@@ -14,6 +15,7 @@ getData()
1415
.then((photos) => {
1516
setPhotos(photos);
1617
renderThumbnails(photos);
18+
initFilters(photos);
1719
})
1820
.catch((err) => {
1921
showDataLoadError(err.message);

js/messages.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,25 @@ const errorTemplate = document.querySelector('#error').content.querySelector('.e
99

1010
// Показывает сообщение об ошибке загрузки данных
1111

12-
const showDataLoadError = () => {
12+
const showDataLoadError = (message) => {
1313
const dataErrorElement = dataErrorTemplate.cloneNode(true);
14+
dataErrorElement.querySelector('.data-error__title').textContent = message;
1415
document.body.appendChild(dataErrorElement);
1516

1617
setTimeout(() => {
1718
dataErrorElement.remove();
1819
}, ALERT_SHOW_TIME);
1920
};
2021

21-
2222
// Создает и показывает модальное сообщение (успех или ошибка)
2323

24-
const showMessage = (template, buttonClass) => {
24+
const showMessage = (template, buttonClass, titleClass, message) => {
2525
const messageElement = template.cloneNode(true);
26+
27+
if (message) {
28+
messageElement.querySelector(titleClass).textContent = message;
29+
}
30+
2631
document.body.appendChild(messageElement);
2732

2833
const closeButton = messageElement.querySelector(buttonClass);
@@ -52,11 +57,11 @@ const showMessage = (template, buttonClass) => {
5257
};
5358

5459
const showSuccessMessage = () => {
55-
showMessage(successTemplate, '.success__button');
60+
showMessage(successTemplate, '.success__button', '.success__title');
5661
};
5762

58-
const showErrorMessage = () => {
59-
showMessage(errorTemplate, '.error__button');
63+
const showErrorMessage = (message) => {
64+
showMessage(errorTemplate, '.error__button', '.error__title', message);
6065
};
6166

6267
export { showDataLoadError, showSuccessMessage, showErrorMessage };

js/render-thumbnails.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// import { photos } from './create-array-photos.js';
21
import { openBigPicture } from './full-size-picture.js';
32

43
const picturesNode = document.querySelector('.pictures');
@@ -26,7 +25,14 @@ const createPicture = ({id, url, description, comments, likes }) => {
2625
return pictureNode;
2726
};
2827

28+
const clearThumbnails = () => {
29+
const pictures = picturesNode.querySelectorAll('.picture');
30+
pictures.forEach((picture) => picture.remove());
31+
};
32+
2933
const renderThumbnails = (pictures) => {
34+
clearThumbnails();
35+
3036
const picturesFragment = document.createDocumentFragment();
3137

3238
pictures.forEach((photo) => {

js/util.js

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,12 @@
1+
// Функция устранения дребезга (debounce)
12

2-
//Функция получения случайного числа
3-
const getRandomInteger = (a, b) => {
4-
const lower = Math.ceil(Math.min(a, b));
5-
const upper = Math.floor(Math.max(a, b));
6-
const result = Math.random() * (upper - lower + 1) + lower;
7-
return Math.floor(result);
8-
};
9-
10-
11-
//Функция получения случайного уникального ID
12-
const getRandomUniqueId = (min, max) => {
13-
const previousValues = [];
3+
const debounce = (callback, timeoutDelay = 500) => {
4+
let timeoutId;
145

15-
return function () {
16-
let currentValue = getRandomInteger(min, max);
17-
if (previousValues.length >= (max - min + 1)) {
18-
return null;
19-
}
20-
while (previousValues.includes(currentValue)) {
21-
currentValue = getRandomInteger(min, max);
22-
}
23-
previousValues.push(currentValue);
24-
return currentValue;
6+
return (...rest) => {
7+
clearTimeout(timeoutId);
8+
timeoutId = setTimeout(() => callback.apply(this, rest), timeoutDelay);
259
};
2610
};
2711

28-
//Функция получения случайного элемента массива
29-
const getRandomArrayElement = (elements) => elements[getRandomInteger(0, elements.length - 1)];
30-
31-
export {
32-
getRandomInteger,
33-
getRandomUniqueId,
34-
getRandomArrayElement,
35-
};
12+
export { debounce };

0 commit comments

Comments
 (0)