Skip to content

Commit 349f280

Browse files
committed
Добавляет сортировку
1 parent e9840f4 commit 349f280

11 files changed

+197
-36
lines changed

index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ <h2 class="img-upload__title visually-hidden">Загрузка фотограф
3636

3737
<!-- Изначальное состояние поля для загрузки изображения -->
3838
<fieldset class="img-upload__start">
39-
<input type="file" id="upload-file" class="img-upload__input visually-hidden" name="filename" required>
39+
<input type="file" id="upload-file" class="img-upload__input visually-hidden" name="filename" accept="image/*" required>
4040
<label for="upload-file" class="img-upload__label img-upload__control">Загрузить</label>
4141
</fieldset>
4242

js/main.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import { renderBigPicture } from './pictures/big-pictures.js';
2-
import { renderThumbnails } from './pictures/thumbnails.js';
2+
import { renderFilters } from './pictures/sort-pictures.js';
33
import { showErrorMessage } from './modal-form/validation.js';
44
import { getData } from './api.js';
5+
import './modal-form/upload-picture.js';
56
import './modal-form/slider-effects.js';
67
import './modal-form/upload-form.js';
78
import './modal-form/scale-control.js';
89
import './modal-form/validation.js';
910

11+
1012
// Полчение изображений с сервера
1113

1214
const loadDataFromServer = () => {
1315
getData()
1416
.then((photos) => {
15-
renderThumbnails(photos);
17+
renderFilters(photos);
1618
renderBigPicture(photos);
1719
})
1820
.catch((error) => {

js/modal-form/scale-control.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const resetScale = () => {
3535

3636
// Кнопка Увеличить
3737

38-
const increaseScale = () => {
38+
const onIncreaseButtonClick = () => {
3939
if (currentValue < MAX_SCALE) {
4040
currentValue += SCALE_STEP;
4141
changeScale();
@@ -44,7 +44,7 @@ const increaseScale = () => {
4444

4545
// Кнопка Уменьшить
4646

47-
const decreaseScale = () => {
47+
const onDecreaseButtonClick = () => {
4848
if (currentValue > MIN_SCALE) {
4949
currentValue -= SCALE_STEP;
5050
changeScale();
@@ -53,7 +53,7 @@ const decreaseScale = () => {
5353

5454
// Добавляем обработчики для кнопок
5555

56-
increaseButton.addEventListener('click', increaseScale);
57-
decreaseButton.addEventListener('click', decreaseScale);
56+
increaseButton.addEventListener('click', onIncreaseButtonClick);
57+
decreaseButton.addEventListener('click', onDecreaseButtonClick);
5858

5959
export { resetScale };

js/modal-form/upload-picture.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const imageUpload = document.querySelector('.img-upload');
2+
const uploadFile = imageUpload.querySelector('#upload-file');
3+
const imagePreview = imageUpload.querySelector('.img-upload__preview img');
4+
const effectsPreview = imageUpload.querySelectorAll('.effects__preview');
5+
6+
const FILE_TYPES = ['gif', 'jpg', 'jpeg', 'png', 'webp'];
7+
8+
uploadFile.addEventListener('change', () => {
9+
const file = uploadFile.files[0];
10+
const fileName = file.name.toLowerCase();
11+
12+
const matches = FILE_TYPES.some((it) => fileName.endsWith(it));
13+
14+
if (matches) {
15+
imagePreview.src = URL.createObjectURL(file);
16+
effectsPreview.forEach((preview) => {
17+
preview.style.backgroundImage = `url('${imagePreview.src}')`;
18+
});
19+
}
20+
});

js/modal-form/validation.js

+17-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { numDecline, getTemplate } from '../utils/dom';
1+
import { numDecline, getTemplate, isEscapeKey } from '../utils/dom';
22
import { sendData } from '../api';
33
import { closeUploadForm } from './upload-form.js';
4-
import { isEscapeKey } from '../utils/dom';
54

65
const uploadForm = document.querySelector('.img-upload__form');
76
const submitButton = uploadForm.querySelector('.img-upload__submit');
@@ -19,13 +18,9 @@ const errorTemplate = getTemplate('#data-error');
1918
// Константы для валидации
2019

2120
const HASHTAG_VALID_SYMBOLS = /^#[a-zа-яё0-9]{1,19}$/i;
22-
2321
const HASHTAG_MAX_NUMBER = 5;
24-
2522
const HASHTAG_MAX_SYMBOLS = 20;
26-
2723
const COMMENT_MAX_LENGTH = 140;
28-
2924
const REMOVE_MESSAGE_TIMEOUT = 5000;
3025

3126
let errorText = '';
@@ -74,7 +69,7 @@ const showErrorMessage = (errorMessageText) => {
7469
const errorModal = errorTemplate.cloneNode(true);
7570

7671
const errorMessage = errorModal.querySelector('.data-error__title');
77-
if (!errorMessage) {
72+
if (errorMessage) {
7873
errorMessage.textContent = errorMessageText;
7974
}
8075

@@ -102,6 +97,12 @@ const unblockSubmitButton = () => {
10297
submitButton.textContent = SubmitButtonText.IDLE;
10398
};
10499

100+
// const uodateText = debounce(() => {
101+
// const filteredImages = applyFilter(pictures, currentFilter);
102+
// renderThumbnails(filteredImages);
103+
// }, RERENDER_DELAY);
104+
105+
105106
// Проверка хэштега на валидность
106107

107108
const isHashtagsValid = (value) => {
@@ -133,7 +134,7 @@ const isHashtagsValid = (value) => {
133134
error: `Хештег не может быть больше ${HASHTAG_MAX_SYMBOLS} символов, включая символ решётки`,
134135
},
135136
{
136-
check: inputArray.length > COMMENT_MAX_LENGTH,
137+
check: inputArray.length > HASHTAG_MAX_NUMBER,
137138
error: `Нельзя указать больше ${HASHTAG_MAX_NUMBER} ${numDecline(
138139
HASHTAG_MAX_NUMBER, 'хештега', 'хештегов', 'хештегов'
139140
)}, `
@@ -191,4 +192,12 @@ pristine.addValidator(hashtagInput, isHashtagsValid, error, false);
191192

192193
uploadForm.addEventListener('submit', onFormSubmit);
193194

195+
hashtagInput.addEventListener('input', (evt) => {
196+
validateHashtags(evt.target.value);
197+
});
198+
199+
commentInput.addEventListener('input', (evt) => {
200+
validateComments(evt.target.value);
201+
});
202+
194203
export { showErrorMessage };

js/pictures/big-pictures.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { isEscapeKey } from '../utils/dom.js';
2-
import { picturesList } from './thumbnails.js';
32
import { showComments, clearComments } from './render-comments.js';
43

54
const bigPicture = document.querySelector('.big-picture');
65
const bigPictureCancel = bigPicture.querySelector('.big-picture__cancel');
76
const bigPictureImg = bigPicture.querySelector('.big-picture__img img');
87
const bigPictureLikes = bigPicture.querySelector('.likes-count');
98
const socialCaption = bigPicture.querySelector('.social__caption');
9+
const picturesList = document.querySelector('.pictures');
10+
11+
// Обработчики
1012

1113
const onDocumentKeydown = (evt) => {
1214
if (isEscapeKey(evt)) {
@@ -19,6 +21,8 @@ const onBigPictureClick = () => {
1921
closeBigPicture();
2022
};
2123

24+
// Открытия окна полноразмерной картинки
25+
2226
const openBigPicture = () => {
2327
bigPicture.classList.remove('hidden');
2428
document.body.classList.add('modal-open');
@@ -27,6 +31,8 @@ const openBigPicture = () => {
2731
bigPictureCancel.addEventListener('click', onBigPictureClick, {once: true});
2832
};
2933

34+
// Ищем картинку среди миниатюр
35+
3036
const renderBigPicture = (photos) => {
3137
picturesList.addEventListener('click', (evt) => {
3238
const currentThumbnail = evt.target.closest('[data-photo-id]');
@@ -50,6 +56,8 @@ const renderBigPicture = (photos) => {
5056
});
5157
};
5258

59+
// Функция закрытия окна
60+
5361
function closeBigPicture () {
5462
clearComments();
5563
bigPicture.classList.add('hidden');

js/pictures/render-comments.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
const bigPicture = document.querySelector('.big-picture');
2-
const socialCommentsList = bigPicture.querySelector('.social__comments');
3-
const socialCommentsItem = bigPicture.querySelector('.social__comment');
4-
const socialCommentsCount = bigPicture.querySelector('.social__comment-count');
5-
const socialCommentsLoader = bigPicture.querySelector('.comments-loader');
6-
71
//Колличество комментарией добавляемое по кнопке
82

93
const COMMENTS_COUNT = 5;
@@ -13,6 +7,15 @@ const COMMENTS_COUNT = 5;
137
let commentsShown = 0;
148
let commentsData = [];
159

10+
// Элементы комментариев и картинки
11+
12+
const bigPicture = document.querySelector('.big-picture');
13+
const socialCommentsList = bigPicture.querySelector('.social__comments');
14+
const socialCommentsItem = bigPicture.querySelector('.social__comment');
15+
const socialCommentsCount = bigPicture.querySelector('.social__comment-count');
16+
const socialCommentsLoader = bigPicture.querySelector('.comments-loader');
17+
18+
1619
//Наполнение для полноэкранных изображений
1720

1821
const renderComments = () => {

js/pictures/sort-pictures.js

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { debounce } from '../utils/dom';
2+
import { renderThumbnails } from './thumbnails';
3+
4+
const imageFilters = document.querySelector('.img-filters');
5+
const filterButtons = imageFilters.querySelectorAll('.img-filters__button');
6+
7+
const RERENDER_DELAY = 500;
8+
const RANDOM_IMAGES_NUMBER = 10;
9+
10+
const Filter = {
11+
DEFAULT: 'filter-default',
12+
RANDOM: 'filter-random',
13+
DISCUSSED: 'filter-discussed'
14+
};
15+
16+
let pictures = [];
17+
let currentFilter = Filter.DEFAULT;
18+
19+
// Функция сортировки по умолчанию
20+
21+
const sortDefault = (images) => images.slice();
22+
23+
// Функция сортировки случайных изображений
24+
25+
const sortRandom = (images) => {
26+
const shuffledImages = images.slice().sort(() => Math.random() - 0.5);
27+
return shuffledImages.slice(0, RANDOM_IMAGES_NUMBER);
28+
};
29+
30+
// Функция сортировки по кол-ву комменатриев
31+
32+
const sortDiscussed = (images) => images.slice().sort((a, b) => b.comments.length - a.comments.length);
33+
34+
// Функция для изменения сортировки
35+
36+
const applyFilter = (images, filter) => {
37+
switch (filter) {
38+
case Filter.RANDOM:
39+
return sortRandom(images);
40+
case Filter.DISCUSSED:
41+
return sortDiscussed(images);
42+
default:
43+
return sortDefault(images);
44+
}
45+
};
46+
47+
// Функция для обновления отображения изображений
48+
49+
const updateImages = debounce(() => {
50+
const filteredImages = applyFilter(pictures, currentFilter);
51+
renderThumbnails(filteredImages);
52+
}, RERENDER_DELAY);
53+
54+
// Обработчик изменения фильтра
55+
56+
const onFilterChange = (evt) => {
57+
const selectedButton = evt.target;
58+
filterButtons.forEach((button) => button.classList.remove('img-filters__button--active'));
59+
selectedButton.classList.add('img-filters__button--active');
60+
currentFilter = selectedButton.id;
61+
updateImages();
62+
};
63+
64+
// Инициализация фильтров
65+
66+
const renderFilters = (picturesData) => {
67+
pictures = picturesData;
68+
imageFilters.classList.remove('img-filters--inactive');
69+
70+
filterButtons.forEach((button) => {
71+
button.addEventListener('click', onFilterChange);
72+
});
73+
updateImages();
74+
};
75+
76+
export { renderFilters };
77+

js/pictures/thumbnails.js

+21-11
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,37 @@
1-
//import { getPhotos } from '../data.js';
21
import { getTemplate } from '../utils/dom.js';
32

3+
// Элементы миниатюр
44

55
const picturesList = document.querySelector('.pictures');
66
const picturesListTemplate = getTemplate('#picture');
77

8+
// Создаем миниатюры
9+
10+
const createThumbnails = ({id, url, description, likes, comments}) => {
11+
const newPicture = picturesListTemplate.cloneNode(true);
12+
13+
newPicture.querySelector('.picture__img').src = url;
14+
newPicture.querySelector('.picture__img').alt = description;
15+
newPicture.setAttribute('data-photo-id', id);
16+
newPicture.querySelector('.picture__comments').textContent = comments.length;
17+
newPicture.querySelector('.picture__likes').textContent = likes;
18+
return newPicture;
19+
};
20+
821
// Рендер миниатюр
922

1023
const renderThumbnails = (photos) => {
24+
const currentThumbnails = picturesList.querySelectorAll('.picture');
1125

12-
const picturesListFragment = document.createDocumentFragment();
26+
currentThumbnails.forEach((thumbnail) => thumbnail.remove());
1327

14-
photos.forEach(({id, url, description, likes, comments}) => {
15-
const newPicture = picturesListTemplate.cloneNode(true);
28+
const picturesListFragment = document.createDocumentFragment();
1629

17-
newPicture.querySelector('.picture__img').src = url;
18-
newPicture.querySelector('.picture__img').alt = description;
19-
newPicture.setAttribute('data-photo-id', id);
20-
newPicture.querySelector('.picture__comments').textContent = comments.length;
21-
newPicture.querySelector('.picture__likes').textContent = likes;
22-
picturesListFragment.appendChild(newPicture);
30+
photos.forEach((thumbnail) => {
31+
picturesListFragment.appendChild(createThumbnails(thumbnail));
2332
});
33+
2434
picturesList.appendChild(picturesListFragment);
2535
};
2636

27-
export { picturesList, renderThumbnails };
37+
export { renderThumbnails };

js/utils/dom.js

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Функция для проверки и вывода шаблона
2+
13
const getTemplate = (id) => {
24
const template = document.querySelector(id);
35

@@ -12,6 +14,8 @@ const getTemplate = (id) => {
1214
return template.content.firstElementChild;
1315
};
1416

17+
// Функция склонения слов после чисел
18+
1519
const numDecline = (num, nominative, genitiveSingular, genitivePlural) => {
1620
if (num % 10 === 0 || num % 100 > 4 && num % 100 < 21) {
1721
return genitivePlural;
@@ -21,6 +25,34 @@ const numDecline = (num, nominative, genitiveSingular, genitivePlural) => {
2125
: genitiveSingular;
2226
};
2327

28+
// Устранение "дребезга"
29+
30+
function debounce (callback, timeoutDelay = 500) {
31+
let timeoutId;
32+
33+
return (...rest) => {
34+
clearTimeout(timeoutId);
35+
timeoutId = setTimeout(() => callback.apply(this, rest), timeoutDelay);
36+
};
37+
}
38+
39+
// Устранение задержки между кадрами
40+
41+
function throttle (callback, delayBetweenFrames) {
42+
let lastTime = 0;
43+
44+
return (...rest) => {
45+
const now = new Date();
46+
47+
if (now - lastTime >= delayBetweenFrames) {
48+
callback.apply(this, rest);
49+
lastTime = now;
50+
}
51+
};
52+
}
53+
54+
// Кнопка esc
55+
2456
const isEscapeKey = (evt) => evt.key === 'Escape';
2557

26-
export { getTemplate, isEscapeKey, numDecline };
58+
export { getTemplate, isEscapeKey, numDecline, debounce, throttle };

0 commit comments

Comments
 (0)