Как сделать пагинацию используя HTML и JS и не сломать фильтр?

Всем небезразличным, доброго времени суток.

Так как не знаю JS, не получается сделать пагинацию карточек товара. Где только я не смотрел и куда только не залазил, нигде не могу найти такую реализацию, чтобы за основу был взят код HTML. С фильтром вроде разобрался, а пагинацию не могу найти.

Вот сам код -

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Shop</title>
</head>

<body id="home">
	<div class="wrap">
    <div class="buttons">
		  <button class="btn" data-filter="all">Все</button>
		  <button class="btn" data-filter="gray">Серые</button>
		  <button class="btn" data-filter="red">Красные</button>
    </div>
		<div class="product-cover">
			<div class="card red">Первая</div>
			<div class="card gray">Вторая</div>
			<div class="card gray">Третья</div>
			<div class="card red">Четвертая</div>
			<div class="card red">Пятая</div>
			<div class="card gray">Шестая</div>
			<div class="card red">Седьмая</div>
			<div class="card gray">Восьмая</div>	
			<div class="card gray">Девятая</div>
			<div class="card red">Десятая</div>
		</div>
		<div class="pagination-cover">
			<ul class="pagination">
				<li class="pagination-item item-prev"><a href="#"><i class="fa fa-angle-left" aria-hidden="true"></i>prev</a></li>
				<li class="pagination-item active"><a href="#">1</a></li>
				<li class="pagination-item"><a href="#">2</a></li>
				<li class="pagination-item"><a href="#">3</a></li>
				<li class="pagination-item"><a href="#">4</a></li>
				<li class="pagination-item"><a href="#">5</a></li>
				<li class="pagination-item item-next"><a href="#"><i class="fa fa-angle-right" aria-hidden="true"></i>next</a></li>
			</ul>
		</div>
	</div>
</body>
</html>


body {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.buttons {
  margin: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
}
.wrap {
  margin-top: 10px;
  width: 1024px;
}
.product-cover {
  width: 100%;
  height: auto;
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 20px;
}

.card {
  height: 150px;
  width: calc(33.3333333% - 72px);
  border: 3px solid;
  border-color: black;
  color: white;
  text-align: center;
  line-height: 150px;
}

.gray {
  background-color: gray;
}

.red {
  background-color: red;
}

.pagination-cover {
  margin-top:94px;
}
.pagination {
  display:-webkit-box;
  display:-ms-flexbox;
  display:flex;
  -ms-flex-wrap:wrap;
  flex-wrap:wrap;
  text-decoration: none;
}
.pagination-item:not(:last-child) {
  margin-right:10px 
}
.pagination-item a {
  padding-top:1px;
  font-weight:600;
  font-size:18px;
  line-height:32px;
  width:38px;
  text-align:center;
  border:2px solid #ebedec;
  color:#535b65;
  display:block;
  border-radius:0;
  text-decoration: none;
}
.pagination-item a i {
  vertical-align:1px;
  font-weight:900;
  color:#535b65;
}
.pagination-item.active a {
  border-color:#ffd910;
  background-color:#ffd910;
}
.pagination-item.active{
  pointer-events:none;
}
.pagination-item:hover a {
  border-color:#ffd910;
}

.pagination {
  list-style-type: none;
  justify-content: center;
}

.hide-filter {
  display: none;
}


function app() {
  const buttons = document.querySelectorAll('.btn')
  const cards = document.querySelectorAll('.card')


  function filter (category, items) {
    items.forEach((item) => {
      const isItemFiltered = !item.classList.contains(category)
      const isShowAll = category === 'all'
      if (isItemFiltered && !isShowAll) {
        item.classList.add('hide-filter')
      } else {
        item.classList.remove('hide-filter')
      }
    })
  }

  buttons.forEach((button) => {
    button.addEventListener('click', () => {
      const currentCategory = button.dataset.filter
      filter(currentCategory, cards)
    })
  })
}

app()


Как мне правильно реализовать пагинацию таким образом, чтобы допустим на странице высвечивалось по 4 новые карточки, а остальные были скрыты?

Как при этом еще и не сломать фильтр, чтобы он подтягивал нужные из скрытых, пока не заполнит страницу до 4 карточек?
  • Вопрос задан
  • 2314 просмотров
Пригласить эксперта
Ответы на вопрос 2
@alexanchek
Как мне кажется, чаще всего пагинация делается на стороне сервера, делаем запрос на апи и получаем нужный массив.

Но, конечно, всякое бывает! Посмотрите вот на это решение:
https://www.code.mu/ru/javascript/video/lesson/imp...

Вроде подходит. Постоянно отображаем контейнер с записями от какой-то до какой-то
Ответ написан
Комментировать
Azurre
@Azurre
Web Developer
Как сказал alexanchek это нужно делать на стороне сервера. Но если Вы точно уверенны, что в Вашем случае нужно это делать у клиента, то должно быть как то так:

function app() {
    let currentPage = 1;
    let currentCategory;
    const itemsPerPage = 4;
    const buttons = document.querySelectorAll('.btn')
    const cards = document.querySelectorAll('.card')
    const pages = document.querySelectorAll('.pagination-item > a');

    function setPage(page, offset) {
        if (page !== undefined) {
            currentPage = page;
        } else {
            currentPage += offset;
            const pagesTotal = Math.ceil(cards.length / itemsPerPage)
            if (currentPage < 0) {
                currentPage = 0;
            } else if (currentPage > pagesTotal) {
                currentPage = pagesTotal;
            }
        }
    }

    function filter (items) {
        items.slice((currentPage - 1 * itemsPerPage) ).forEach((item) => {
            const isItemFiltered = !item.classList.contains(currentCategory)
            const isShowAll = currentCategory === 'all'
            if (isItemFiltered && !isShowAll) {
                item.classList.add('hide-filter')
            } else {
                item.classList.remove('hide-filter')
            }
        })
    }

    buttons.forEach((button) => {
        button.addEventListener('click', () => {
            currentCategory = button.dataset.filter
            // currentPage = 1; // Eсли нужно сбросить страницу при смене фильтра
            filter(cards)
        })
    })

    pages.forEach((link) => {
        link.addEventListener('click', () => {
            if (link.classList.contains('item-prev')) {
                setPage(undefined, -1);
            } else if(link.classList.contains('item-next')) {
                setPage(undefined, 1);
            } else {
                setPage(link.dataset.page);
            }
            filter(cards)
        })
    })
}


Ссылки с пагинацией должны иметь дата-аттрибут "page" с номером страницы.
Код не тестировал, могут быть опечатки, но в целом должно быть понятно.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы