JavaScript | Пагинация силами клиента

JavaScript | Пагинация силами клиента

 

Логика работы


Смысл такой. Мы каким-то образом получили на клиенте нужный массив данных. Оперативная память хранит этот массив во вкладке по определённому адресу.

После получения массива, мы его отрисовываем на странице «частично» — как-бы постранично. На деле мы просто режем исходный массив на куски и каждый «переклик» по странице пагинации возвращает нам набор элементов из части исходного массива.

То есть на текущей странице мы создаём информационный блок, в котором будет лежать наш результат отбора, а также сами кнопки возможного клика страницы. При клике по кнопке считывается её номер положения и по этому номеру делается сдвиг выборки элементов из оригинального массива.

Решение задачи пагинации на клиенте

Предлагаю рассмотреть пример. Начнём с самого массива данных:

Есть 31 товар из интернет-магазина:

var goods = [
"Телевизор Haier LE24K6000S",
"Телевизор LG 32LM630BPLA",
"Телевизор Samsung UE32M5550AU",
"Телевизор Haier 32 Smart TV BX",
"Телевизор Haier 55 Smart TV BX",
"Телевизор LG 49NANO816NA",
"Телевизор LG 55NANO866NA",
"Телевизор Samsung UE55TU7097U",
"Телевизор LG 55UN74006LA",
"Телевизор Samsung UE55TU8570U",
"Телевизор Haier LE24K6500SA",
"Телевизор Samsung UE43J5272AU",
"Телевизор Samsung BE32R-B",
"Телевизор Samsung UE43TU7570U",
"Телевизор Samsung UE75TU7100U",
"Телевизор Samsung QE55Q87TAU",
"Телевизор LG 49NANO866NA",
"Телевизор Samsung UE50TU7170U",
"Телевизор Samsung UE43TU7097U",
"Телевизор Samsung UE50TU8570U",
"Телевизор Samsung UE43T5300AU",
"Телевизор LG 49UN73906LE",
"Телевизор LG 55UN70006LA",
"Телевизор LG 65UN73506LB",
"Телевизор Haier 58 Smart TV BX",
"Телевизор Haier 50 Smart TV BX",
"Телевизор Samsung QE50Q87TAU",
"Телевизор Samsung UE32T5300AU",
"Телевизор LG 49UK6200PLA",
"Телевизор LG 49UM7020PLF",
"Телевизор Samsung UE24N4500AU"
]

Мы хотим отобразить товары по 7 штук на странице. Это наше условие. Мы так захотели. Можно и по 5, и по 10, и по 50, и т.п.. Вы можете потренироваться на своём количестве отбираемых элементов.

 

Этап № 1 — Инициализация общего блока для всех HTML-элементов пагинации

// Главный DIV для результатов пагинации
var pagDiv = document.createElement("div");
pagDiv.setAttribute("class","pagDiv");

// Получаем элемент h1
var pagH1 = document.getElementsByTagName("h1")[0];

// Устанавливаем общий блок пагинации под заголовком h1
pagH1.after(pagDiv);

В элемент pagDiv будут сложены элементы из следующего этапа.

 

Этап № 2 — Инициализация HTML-элементов для пагинации

Мы хотим, чтобы в общем блоке под заголовком H1 были блоки, отвечающие за саму пагинацию. Создадим их:

// Линия кнопок над результатами отбора
var bl1 = document.createElement("div");
bl1.setAttribute("class","bl1");

// Линия кнопок под результатами отбора
var bl2 = document.createElement("div");
bl2.setAttribute("class","bl2");

// Блок для отрисовки результатов
var result = document.createElement("div");
result.setAttribute("class","result");

 

Всего 3 элемента для удобства и простоты. Эти элементы появятся на странице чуть позже. Выглядеть это будет таким образом.

Инициализация HTML-элементов для пагинации - JavaScript
Инициализация HTML-элементов для пагинации — JavaScript

 

 

Этап № 3 — Создание переменной с количеством элементов на странице

var quantityforselection = 7;

Мы рассматриваем простой вариант пагинации, где у пользователя нет возможности выбирать нужное количество результатов на странице.

 

Этап № 4 — Объявление функций для генерации разметки на основании массива товаров

Мы хотим написать универсальное решение, которое не будет зависеть от длины массива. Для этого нам нужны такие функции.

Мы будем оборачивать каждый элемент массива (его значение) обычным абзацем <p>. Функция будет принимать отборный массив из «нужных» элементов и возвращать строку в виде HTML-разметки.

 

4.1 — Обёртка для абзацев — HTML-разметка

function paintResult (arr){
   for(i=0, r=""; i<arr.length; i++){
      r += `<p class="result-item">${arr[i]}</p>`
   }
   return r
}

Пример её работы:

paintResult(["Телевизор LG 49UK6200PLA", "Телевизор LG 49UM7020PLF", "Телевизор Samsung UE24N4500AU"])
Функция оборачивает в параграфы - JavaScript
Функция оборачивает в параграфы — JavaScript
7 абзацев на странице - JavaScript
7 абзацев на странице — JavaScript

4.2 — Подсчёт количества кнопок(страниц) для пагинации

Считает нужное количество кнопок пагинации:

function numberofbuttons(arr, num){
   return Math.ceil(arr.length / num)
}

Получает длину массива. Делит её на 7. Дробное приводит к большему целому. Пример работы функции:

numberofbuttons([,,,,,,,,,,,,,,,,], 7)
//3 - результат округления до целого
Функция расчёта количества кнопок пагинации - JavaScript
Функция расчёта количества кнопок пагинации — JavaScript

 

4.3 — Обёртка для линий с кнопками пагинации — HTML-разметка

function paintPaginationButton(count){
   for(i=1, r=""; i <= count; i++){
      r += `<button class="pb">${i}</button>`
   }
   return r
}

 

Функция принимает целое число, которое вычисляется предыдущей функцией. Возвращает HTML-разметку в виде линии кнопок с индексами страниц пагинации, начиная с 1. Всем кнопкам пагинации присваивается класс «pb» (это сокращение от pagination button).

Пример работы функции:

paintPaginationButton(5)
// <button class="pb">1</button><button class="pb">2</button><button class="pb">3</button><button class="pb">4</button><button class="pb">5</button>
Функция оборачивает в кнопки страниц пагинации - JavaScript
Функция оборачивает в кнопки страниц пагинации — JavaScript
Линии кнопок - HTML
Линии кнопок — HTML

4.4 — Обработчик события нажатия на кнопку страницы пагинации

document.addEventListener('click', function(event){
   if([...event.target.classList].includes("pb")){
      var y = event.target.textContent;
      var start = quantityforselection*(y - 1);
      var end = quantityforselection*y;
      result.innerHTML = paintResult(goods.slice(start, end));
   }else{
      console.log(event.target)
   }
});

Мы вешаем обработчик события на весь документ. Когда происходит клик в документе, тогда обработчик проверяет условие, что на нажатом элементе установлен класс «pb» (это сокращение от pagination button).

Если это кнопка пагинации, то у неё извлекается номер и записывается в переменную «y». Номер участвует в получении нужного диапазона элементов из оригинального массива. По этой причине абсолютно не важно сколько рядов с кнопками есть на странице. Сработает любая. «Кусок» массива будет получен.

Затем массив будет обойдён функцией paintResult(), которая отрисует абзацы из значений. Нам останется присвоить строку в свойство innerHTML объекта result. Визуально документ перерисуется после клика.

 

Этап № 5 — Первичная отрисовка. Размещение элементов на страницу

bl1.innerHTML = paintPaginationButton(numberofbuttons(goods,quantityforselection));

bl2.innerHTML = paintPaginationButton(numberofbuttons(goods,quantityforselection));

// Первичная отрисовка результата
result.innerHTML = paintResult(goods.slice(0, quantityforselection))

// Помещаем линии кнопок и результат в общий блок пагинации
pagDiv.append(bl1, result, bl2)

 

Полный код. Протестируй!

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Страница отборов</title>
</head>
<body>
<h1>Товары по 7 штук на странице</h1>
<script>
// Полученный массив для отборов
var goods = [ "Телевизор Haier LE24K6000S", "Телевизор LG 32LM630BPLA", "Телевизор Samsung UE32M5550AU", "Телевизор Haier 32 Smart TV BX", "Телевизор Haier 55 Smart TV BX", "Телевизор LG 49NANO816NA", "Телевизор LG 55NANO866NA", "Телевизор Samsung UE55TU7097U", "Телевизор LG 55UN74006LA", "Телевизор Samsung UE55TU8570U", "Телевизор Haier LE24K6500SA", "Телевизор Samsung UE43J5272AU", "Телевизор Samsung BE32R-B", "Телевизор Samsung UE43TU7570U", "Телевизор Samsung UE75TU7100U", "Телевизор Samsung QE55Q87TAU", "Телевизор LG 49NANO866NA", "Телевизор Samsung UE50TU7170U", "Телевизор Samsung UE43TU7097U", "Телевизор Samsung UE50TU8570U", "Телевизор Samsung UE43T5300AU", "Телевизор LG 49UN73906LE", "Телевизор LG 55UN70006LA", "Телевизор LG 65UN73506LB", "Телевизор Haier 58 Smart TV BX", "Телевизор Haier 50 Smart TV BX", "Телевизор Samsung QE50Q87TAU", "Телевизор Samsung UE32T5300AU", "Телевизор LG 49UK6200PLA", "Телевизор LG 49UM7020PLF", "Телевизор Samsung UE24N4500AU" ]

// Количество элементов для отбора
var quantityforselection = 7;

// Главный DIV для результатов пагинации
var pagDiv = document.createElement("div");
pagDiv.setAttribute("class","pagDiv");
// Получаем элемент h1
var pagH1 = document.getElementsByTagName("h1")[0];
// Устанавливаем общий блок пагинации под заголовком h1
pagH1.after(pagDiv);


// Считает нужное количество кнопок пагинации
function numberofbuttons(arr,num){
return Math.ceil(arr.length/num)
}

// Отрисовывает кнопки пагинации
function paintPaginationButton (count){
for(i=1, r=""; i<=count; i++){
r += `<button class="pb">${i}</button>`
}
return r
}

// Отрисовывает результаты
function paintResult (arr){
for(i=0, r=""; i<arr.length; i++){
r += `<p class="result-item">${arr[i]}</p>`
}
return r
}

// Линия кнопок над результатами отбора
var bl1 = document.createElement("div");
bl1.setAttribute("class","bl1");
bl1.innerHTML = paintPaginationButton(numberofbuttons(goods,quantityforselection));

// Линия кнопок под результатами отбора
var bl2 = document.createElement("div");
bl2.setAttribute("class","bl2");
bl2.innerHTML = paintPaginationButton(numberofbuttons(goods,quantityforselection));

// Блок для отрисовки результатов
var result = document.createElement("div");
result.setAttribute("class","result");

// Первичная отрисовка
result.innerHTML = paintResult(goods.slice(0, quantityforselection))

// Помещаем линии кнопок и результат
pagDiv.append(bl1, result, bl2)

// Вешаем обработчик для всех кнопок пагинации
document.addEventListener('click', function(event){
if([...event.target.classList].includes("pb")){
var y = event.target.textContent;
var start = quantityforselection*(y - 1);
var end = quantityforselection*y;
result.innerHTML = paintResult (goods.slice(start, end));
}else{
console.log(event.target)
}
});
</script>
</body>
</html>

Информационные ссылки

JavaScript | Как получить значения из класса для HTML-элемента?

JavaScript | Как добавить класс для HTML-элемента?

JavaScript | Как создать div после h1?

JavaScript | Как округлить дробное до целого

Стандарт DOM — Раздел «Introduction to «DOM Events»» — https://dom.spec.whatwg.org/#introduction-to-dom-events

Перевод — https://efim360.ru/dom/#2-1-Introduction-to-DOM-Events