Skip to content

Commit 4ef39d0

Browse files
authored
Merge pull request #12 from zarram89/module12-task1
2 parents 7ff2a26 + 81e442c commit 4ef39d0

7 files changed

Lines changed: 143 additions & 23 deletions

File tree

js/api.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ const load = async (route, method = Method.GET, body = null) => {
2929
throw new Error();
3030
}
3131

32-
return method === Method.GET ? response.json() : response;
32+
return method === Method.GET ? await response.json() : await response;
3333

3434
} catch {
3535
throw new Error(ErrorText[method]);
3636
}
3737
};
3838

39-
const getData = () => load(Route.GET_DATA);
39+
const getData = async () => await load(Route.GET_DATA);
4040

41-
const sendData = (body) => load(Route.SEND_DATA, Method.POST, body);
41+
const sendData = async (body) => await load(Route.SEND_DATA, Method.POST, body);
4242

4343
export { getData, sendData };

js/main.js

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,49 @@
11
import { getData } from './api.js';
2-
import { renderGallery } from './ui/gallery.js';
2+
import { initGallery } from './ui/gallery.js';
33
import { initBigPicture } from './ui/big-picture/meta.js';
44
import { initCommentsLoader } from './ui/big-picture/comments.js';
55
import { initForm } from './ui/form/index.js';
66
import { showAlert } from './ui/messages.js';
7+
import { initFilters } from './ui/form/filter.js';
8+
import { debounce } from './utils/common.js';
79

8-
const container = document.querySelector('.pictures');
9-
const template = document.querySelector('#picture')?.content?.querySelector('.picture');
10+
const dom = {
11+
container: document.querySelector('.pictures'),
12+
template: document.querySelector('#picture')?.content?.querySelector('.picture'),
13+
filters: document.querySelector('.img-filters'),
14+
};
1015

1116
initBigPicture();
1217
initCommentsLoader();
1318
initForm();
1419

15-
const initGallery = async () => {
20+
const initApp = async () => {
21+
const { container, template, filters } = dom;
22+
1623
if (!container || !template) {
1724
return;
1825
}
1926

2027
try {
2128
const pictures = await getData();
22-
renderGallery(pictures, container, template);
29+
30+
const gallery = initGallery({ container, template });
31+
32+
const debouncedRender = debounce((filtered) => {
33+
gallery.render(filtered);
34+
}, 500);
35+
36+
initFilters({
37+
container: filters,
38+
pictures,
39+
onChange: debouncedRender,
40+
});
41+
42+
gallery.render(pictures);
43+
2344
} catch (err) {
2445
showAlert(err.message);
2546
}
2647
};
2748

28-
initGallery();
49+
initApp();

js/ui/form/filter.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const PICTURES_COUNT = 10;
2+
3+
const Filter = {
4+
DEFAULT: 'filter-default',
5+
RANDOM: 'filter-random',
6+
DISCUSSED: 'filter-discussed',
7+
};
8+
9+
const shuffle = (array) => {
10+
const result = [...array];
11+
12+
for (let i = result.length - 1; i > 0; i--) {
13+
const j = Math.floor(Math.random() * (i + 1));
14+
[result[i], result[j]] = [result[j], result[i]];
15+
}
16+
17+
return result;
18+
};
19+
20+
const filterPictures = (pictures, filterType) => {
21+
switch (filterType) {
22+
case Filter.RANDOM:
23+
return shuffle(pictures).slice(0, PICTURES_COUNT);
24+
25+
case Filter.DISCUSSED:
26+
return [...pictures].sort(
27+
(a, b) => b.comments.length - a.comments.length
28+
);
29+
30+
case Filter.DEFAULT:
31+
default:
32+
return [...pictures];
33+
}
34+
};
35+
36+
const initFilters = ({ container, pictures, onChange }) => {
37+
if (!(container instanceof HTMLElement)) {
38+
throw new Error('Filter container not found');
39+
}
40+
41+
let currentFilter = Filter.DEFAULT;
42+
43+
container.classList.remove('img-filters--inactive');
44+
45+
container.addEventListener('click', (evt) => {
46+
const button = evt.target.closest('.img-filters__button');
47+
if (!button) {
48+
return;
49+
}
50+
51+
const newFilter = button.id;
52+
53+
if (newFilter === currentFilter) {
54+
return;
55+
}
56+
57+
const activeButton = container.querySelector('.img-filters__button--active');
58+
if (activeButton) {
59+
activeButton.classList.remove('img-filters__button--active');
60+
}
61+
62+
button.classList.add('img-filters__button--active');
63+
64+
currentFilter = newFilter;
65+
66+
const filtered = filterPictures(pictures, currentFilter);
67+
onChange(filtered);
68+
});
69+
};
70+
71+
export { initFilters, filterPictures, Filter };

js/ui/gallery.js

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,39 @@
11
import { renderThumbnails } from './thumbnails.js';
22
import { showBigPicture } from './big-picture/meta.js';
33

4-
const renderGallery = (pictures, container, template) => {
5-
const picturesMap = new Map(pictures.map((item) => [item.id, item]));
4+
const initGallery = ({ container, template }) => {
5+
let currentPictures = [];
66

7-
container.addEventListener('click', (evt) => {
8-
const thumbnail = evt.target.closest('[data-thumbnail-id]');
9-
if (!thumbnail) {
10-
return;
11-
}
7+
const render = (pictures) => {
8+
currentPictures = pictures;
9+
renderThumbnails(currentPictures, container, template);
10+
};
1211

13-
evt.preventDefault();
14-
const picture = picturesMap.get(Number(thumbnail.dataset.thumbnailId));
15-
showBigPicture(picture);
16-
});
12+
const initEvents = () => {
13+
container.addEventListener('click', (evt) => {
14+
const thumbnail = evt.target.closest('[data-thumbnail-id]');
15+
if (!thumbnail) {
16+
return;
17+
}
1718

18-
renderThumbnails(pictures, container, template);
19+
evt.preventDefault();
20+
21+
const id = Number(thumbnail.dataset.thumbnailId);
22+
23+
const picture = currentPictures.find((item) => item.id === id);
24+
if (!picture) {
25+
return;
26+
}
27+
28+
showBigPicture(picture);
29+
});
30+
};
31+
32+
initEvents();
33+
34+
return {
35+
render,
36+
};
1937
};
2038

21-
export { renderGallery };
39+
export { initGallery };

js/ui/thumbnails.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const renderThumbnails = (pictures, container, template) => {
1717
throw new TypeError('Pictures must be an array');
1818
}
1919

20+
container.querySelectorAll('.picture').forEach((element) => element.remove());
21+
2022
const fragment = document.createDocumentFragment();
2123

2224
pictures.forEach((picture) => {

js/utils/common.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
const isEscapeKey = (evt) => evt.key === 'Escape';
22

3-
export { isEscapeKey };
3+
const debounce = (callback, timeoutDelay = 500) => {
4+
let timeoutId;
5+
return (...rest) => {
6+
clearTimeout(timeoutId);
7+
timeoutId = setTimeout(() => callback.apply(this, rest), timeoutDelay);
8+
};
9+
};
10+
11+
export { isEscapeKey, debounce };
File renamed without changes.

0 commit comments

Comments
 (0)