diff --git a/index.html b/index.html index 4e00a66..455229f 100644 --- a/index.html +++ b/index.html @@ -35,7 +35,7 @@

Загрузка фотограф
- +
diff --git a/js/constant.js b/js/constant.js index 932942a..4e57fdd 100644 --- a/js/constant.js +++ b/js/constant.js @@ -1,3 +1,11 @@ +export const FILE_TYPES = ['jpg', 'jpeg', 'png', 'pdf']; + +export const PICTURES_COUNT = 10; + +export const TIME_OUT_DELAY = 500; + +export const SHOW_TIME = 5000; + export const MIN_POSTS_COUNT = 1; export const MAX_POSTS_COUNT = 25; export const AVATAR_MIN_COUNT = 1; diff --git a/js/filters.js b/js/filters.js index 8b13789..56a6de7 100644 --- a/js/filters.js +++ b/js/filters.js @@ -1 +1,57 @@ +import { PICTURES_COUNT } from './constant.js'; + +const Filter = { + DEFAULT: 'filter-default', + RANDOM: 'filter-random', + DISCUSSED: 'filter-discussed', +}; + +const filter = document.querySelector('.img-filters'); + +let currentFilter = Filter.DEFAULT; +let pictures = []; + +const sortRandom = () => Math.random() - 0.5; + +const sortByComments = (pictureA, pictureB) => + pictureB.comments.length - pictureA.comments.length; + +const getFilteredPictures = () => { + switch (currentFilter) { + case Filter.RANDOM: + return [...pictures].sort(sortRandom).slice(0, PICTURES_COUNT); + case Filter.DISCUSSED: + return [...pictures].sort(sortByComments); + default: + return [...pictures]; + } +}; + +const setOnFilterClick = (callback) => { + filter.addEventListener('click', (evt) => { + if (!evt.target.classList.contains('img-filters__button')) { + return; + } + + const clickedButton = evt.target; + if (clickedButton.id === currentFilter) { + return; + } + + filter + .querySelector('.img-filters__button--active') + .classList.remove('img-filters__button--active'); + clickedButton.classList.add('img-filters__button--active'); + currentFilter = clickedButton.id; + callback(getFilteredPictures()); + }); +}; + +const init = (loadedPictures, callback) => { + filter.classList.remove('img-filters--inactive'); + pictures = [...loadedPictures]; + setOnFilterClick(callback); +}; + +export { init, getFilteredPictures }; diff --git a/js/load-pictures.js b/js/load-pictures.js new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/js/load-pictures.js @@ -0,0 +1 @@ + diff --git a/js/main.js b/js/main.js index 6165fc1..deb50b7 100644 --- a/js/main.js +++ b/js/main.js @@ -1,9 +1,9 @@ import { generateThumbnails } from './thumbnail.js'; import { getData, sendData } from './api.js'; -import { showAlert } from './utils.js'; +import { showAlert, debounce } from './utils.js'; import { setOnFormSubmit, imgUploadForm } from './form-modal.js'; import { showMessageSuccess, showMessageError } from './success-error.js'; -import './filters.js'; +import { init as initFilter, getFilteredPictures } from './filters.js'; setOnFormSubmit(async (data) => { try { @@ -17,7 +17,9 @@ setOnFormSubmit(async (data) => { try { const data = await getData(); - generateThumbnails(data); + const debounceRenderGallery = debounce(generateThumbnails); + initFilter(data, debounceRenderGallery); + generateThumbnails(getFilteredPictures()); } catch { showAlert(); } diff --git a/js/scale.js b/js/scale.js index 4b97d7d..098f5bb 100644 --- a/js/scale.js +++ b/js/scale.js @@ -5,11 +5,15 @@ import { DEFAULT_SCALE } from './constant.js'; +import { loadingPicture } from './load-pictures.js'; + const scaleInput = document.querySelector('.scale__control--value'); const smallButtonElement = document.querySelector('.scale__control--smaller'); const bigButtonElement = document.querySelector('.scale__control--bigger'); const imgPreviewElement = document.querySelector('.img-upload__preview img'); +loadingPicture(); + const scaleImage = (value) => { imgPreviewElement.style.transform = `scale(${value / 100})`; scaleInput.value = `${value}%`; diff --git a/js/thumbnail.js b/js/thumbnail.js index b88e450..430f0f1 100644 --- a/js/thumbnail.js +++ b/js/thumbnail.js @@ -1,40 +1,37 @@ import { openBigPictureWindow } from './modal-pictures.js'; - -const thumbNailTemplate = document.querySelector('#picture').content.querySelector('.picture'); -const container = document.querySelector('.pictures'); - -const localPictures = []; - -const createThumbnail = ({id, url, description, likes, comments}) => { - const thumbnail = thumbNailTemplate.cloneNode(true); - thumbnail.dataset.id = id; - const pictureImage = thumbnail.querySelector('.picture__img'); - pictureImage.src = url; - pictureImage.alt = description; - thumbnail.querySelector('.picture__likes').textContent = likes; - thumbnail.querySelector('.picture__comments').textContent = comments.length; - - return thumbnail; -}; - -const generateThumbnails = (pictures) => { - localPictures.length = 0; - localPictures.push(...pictures.slice()); - const pictureFragment = document.createDocumentFragment(); - pictures.forEach((picture) => { - const thumbnail = createThumbnail(picture); - pictureFragment.append(thumbnail); +import { isEnterKey } from './utils.js'; + +const picturesContainer = document.querySelector('.pictures'); + +const pictureTemplate = document.querySelector('#picture') + .content + .querySelector('.picture'); + +const generateThumbnails = (picture) => { + picturesContainer.querySelectorAll('.picture').forEach((element) => element.remove()); + const similarListFragment = document.createDocumentFragment(); + picture.forEach(({ id, url, description, likes, comments }) => { + const pictureElement = pictureTemplate.cloneNode(true); + pictureElement.querySelector('.picture__img').dataset.id = id; + pictureElement.querySelector('.picture__img').src = url; + pictureElement.querySelector('.picture__img').alt = description; + pictureElement.querySelector('.picture__likes').textContent = likes; + pictureElement.querySelector('.picture__comments').textContent = comments.length; + similarListFragment.appendChild(pictureElement); + + pictureElement.addEventListener('click', () => { + openBigPictureWindow({ url, description, likes, comments }); + }); + + pictureElement.addEventListener('keydown', (evt) => { + if (isEnterKey(evt)) { + openBigPictureWindow({ url, description, likes, comments }); + } + }); + + picturesContainer.append(similarListFragment); + pictureElement.classList.remove('hidden'); }); - - container.append(pictureFragment); }; -container.addEventListener('click', (evt) => { - if(evt.target.closest('.picture')) { - const currentId = Number(evt.target.closest('.picture').dataset.id); - const currentPicture = localPictures.find(({id}) => id === currentId); - openBigPictureWindow(currentPicture); - } -}); - -export { generateThumbnails, container }; +export { generateThumbnails }; diff --git a/js/utils.js b/js/utils.js index 20786fa..57cdde5 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,4 +1,4 @@ -const SHOW_TIME = 5000; +import { TIME_OUT_DELAY, SHOW_TIME } from './constant.js'; const dataErrorTemplate = document .querySelector('#data-error') @@ -15,4 +15,15 @@ const showAlert = () => { const isEscapeKey = (evt) => evt.key === 'Escape'; -export { isEscapeKey, showAlert }; +const isEnterKey = (evt) => evt.key === 'Enter'; + + +const debounce = (callback, timeoutDelay = TIME_OUT_DELAY) => { + let timeoutId; + return (...rest) => { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => callback.apply(this, rest), timeoutDelay); + }; +}; + +export { isEscapeKey, isEnterKey, showAlert, debounce };