Как реализовать пагинацию на JavaScript для нескольких независимых секций на одной странице?

Как организовать независимую пагинацию для каждой секции на одной странице с помощью JavaScript, если имею опыт работы с пагинацией для одного массива? Каждая секция имеет одинаковые CSS-классы, и в разметке представлено несколько секций. Необходимо ли использовать массив массивов для реализации этой задачи, и если да, то как правильно его построить?
  • 16 ноября 2024 г. 14:53
Ответы на вопрос 2
Для реализации независимой пагинации для нескольких секций на одной странице вам потребуется создать систему, которая будет отслеживать состояние каждой секции отдельно. Предполагая, что каждая секция содержит одинаковые CSS-классы и вам нужны кнопки для навигации (например, "следующая" и "предыдущая"), мы можем использовать JavaScript для управления этой функциональностью.

### Общая структура разметки

Предположим, у вас есть несколько секций, каждая из которых содержит элементы для пагинации:

```html
<div class="section" data-section-id="1">
    <div class="item">Элемент 1.1</div>
    <div class="item">Элемент 1.2</div>
    <div class="item">Элемент 1.3</div>
    <div class="item">Элемент 1.4</div>
    <div class="item">Элемент 1.5</div>
    <button class="prev">Назад</button>
    <button class="next">Вперед</button>
</div>

<div class="section" data-section-id="2">
    <div class="item">Элемент 2.1</div>
    <div class="item">Элемент 2.2</div>
    <div class="item">Элемент 2.3</div>
    <div class="item">Элемент 2.4</div>
    <div class="item">Элемент 2.5</div>
    <button class="prev">Назад</button>
    <button class="next">Вперед</button>
</div>
```

### JavaScript для пагинации

1. **Соберите все секции** и настройте начальные состояния для каждой из них.
2. **Отслеживайте текущую страницу** для каждой секции.
3. **Показывайте и скрывайте элементы** в зависимости от текущей страницы.

Вот пример реализация на JavaScript:

```javascript
document.addEventListener('DOMContentLoaded', () => {
    const sections = document.querySelectorAll('.section');
    const itemsPerPage = 2;

    sections.forEach(section => {
        const items = section.querySelectorAll('.item');
        const prevButton = section.querySelector('.prev');
        const nextButton = section.querySelector('.next');
        let currentPage = 0;

        const numberOfPages = Math.ceil(items.length / itemsPerPage);

        function showPage(page) {
            items.forEach((item, index) => {
                item.style.display = (index >= page * itemsPerPage && index < (page + 1) * itemsPerPage) ? 'block' : 'none';
            });
        }

        function updateButtons() {
            prevButton.disabled = currentPage === 0;
            nextButton.disabled = currentPage === numberOfPages - 1;
        }

        prevButton.addEventListener('click', () => {
            if (currentPage > 0) {
                currentPage--;
                showPage(currentPage);
                updateButtons();
            }
        });

        nextButton.addEventListener('click', () => {
            if (currentPage < numberOfPages - 1) {
                currentPage++;
                showPage(currentPage);
                updateButtons();
            }
        });

        // Показать первую страницу при загрузке
        showPage(currentPage);
        updateButtons();
    });
});
```

### Объяснение кода

- **Селекторы**: Мы выбираем все `.section` и элементы внутри них.
- **Параметры**: `itemsPerPage` определяет, сколько элементов отображать на странице.
- **Функция `showPage`**: Скрывает или показывает элементы в зависимости от текущей страницы.
- **Функция `updateButtons`**: Обновляет состояние кнопок "Следующая" и "Предыдущая" в зависимости от текущей страницы.
- **Слушатели событий**: Добавляются кнопкам, чтобы позволить пользователю навигировать по страницам.

### Заключение

Такой подход позволяет легко реализовать независимую пагинацию для нескольких секций на одной странице. Вам не нужно использовать массив массивов, так как каждая секция обрабатывается отдельно в рамках своего контекста.
Здравствуйте. Здесь нужно бы обрабатывать каждую секцию отдельно, используя отдельный массив элементов для каждой, а потом генерировать независимые контролы пагинации для каждой секции. 

<div class="wrap_item" data-section="1">
  <h3 class="title_heading">Секция №1</h3>
  <div class="wrap_elements">
    <div class="class_element">Элемент 1</div>
    <div class="class_element">Элемент 2</div>
    <div class="class_element">Элемент 3</div>
    <div class="class_element">Элемент 4</div>
    <div class="class_element">Элемент 5</div>
  </div>
  <div class="pagination"></div>
</div>

<div class="wrap_item" data-section="2">
  <h3 class="title_heading">Секция №2</h3>
  <div class="wrap_elements">
    <div class="class_element">Элемент A</div>
    <div class="class_element">Элемент B</div>
    <div class="class_element">Элемент C</div>
    <div class="class_element">Элемент D</div>
    <div class="class_element">Элемент E</div>
  </div>
  <div class="pagination"></div>
</div>

<div class="wrap_item" data-section="3">
  <h3 class="title_heading">Секция №3</h3>
  <div class="wrap_elements">
    <div class="class_element">Элемент α</div>
    <div class="class_element">Элемент β</div>
    <div class="class_element">Элемент γ</div>
    <div class="class_element">Элемент δ</div>
    <div class="class_element">Элемент ε</div>
  </div>
  <div class="pagination"></div>
</div>


document.addEventListener('DOMContentLoaded', () => {

    const itemsPerPage = 2;

    document.querySelectorAll('.wrap_item').forEach((section) => {
      const wrapElements = section.querySelector('.wrap_elements');
      const elements = Array.from(wrapElements.children);
      const paginationContainer = section.querySelector('.pagination');
      const totalPages = Math.ceil(elements.length / itemsPerPage);

      function showPage(page) {
        elements.forEach((el, index) => {
          el.style.display =
            index >= (page - 1) * itemsPerPage && index < page * itemsPerPage
              ? ''
              : 'none';
        });
      }

      function createPagination() {
        paginationContainer.innerHTML = ''; // очистили контейнер пагинации
        for (let i = 1; i <= totalPages; i++) {
          const button = document.createElement('button');
          button.textContent = i;
          button.addEventListener('click', () => {
            showPage(i);
            updateActiveButton(i);
          });
          paginationContainer.appendChild(button);
        }
        updateActiveButton(1); 
      }

      function updateActiveButton(activePage) {
        paginationContainer.querySelectorAll('button').forEach((btn, index) => {
          btn.classList.toggle('active', index + 1 === activePage);
        });
      }

      showPage(1);
      createPagination();
    });
  });


.wrap_elements {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
  }

  .class_element {
    padding: 10px;
    border: 1px solid #ccc;
    background: #f5f5f5;
  }

  .pagination button {
    margin: 0 5px;
    padding: 5px 10px;
    border: none;
    background: #ddd;
    cursor: pointer;
  }

  .pagination button.active {
    background: #ff6f61;
    color: #fff;
  }


Теперь имеем что? Каждый .wrap_item обрабатывается отдельно, кайф. Все дочерние элементы .class_element собираются в массив, ну красота. Style.display для скрытия/показа элементов в зависимости от текущей страницы.
Количество кнопок определяется totalPages.
При клике на кнопку отображаются элементы, соответствующие выбранной странице. Вроде ничего не упустил.
Похожие вопросы