Алгоритм пагинации
Пытаюсь сделать пагинацию, но очень плохо понимаю как сделать алгоритм пагинации. У меня сейчас так: статично выводится 2 начальные страницы и 2 конечные страницы, а посередине 2 страницы вперед и назад от текущей страницы. Я думаю как написать алгоритм, чтобы можно было управлять кол-во того что слева, справа и посередине.
Логика происходит в функции logic
const per_page_max = 100; // Максимальное кол-во страниц
let current_page = 5; // Текущая страница
const btns = document.querySelector('.btns');
function appendBtn(i, ellipsis) {
const activeBtn = current_page === i;
const button = document.createElement('button');
button.classList.add('btn');
if (ellipsis === true) {
button.innerHTML = '...';
button.disabled = true;
btns.append(button);
return false;
}
if (activeBtn) {
button.classList.add('active');
}
button.disabled = activeBtn;
button.innerHTML = i;
button.addEventListener('click', () => {
current_page = i;
btns.innerHTML = '';
logic();
});
btns.append(button);
}
logic();
function logic() {
// это лево
appendBtn(1);
appendBtn(2);
// это лево
// это середина
if (current_page < 6) {
appendBtn(3);
appendBtn(4);
appendBtn(5);
appendBtn(6);
appendBtn(7);
appendBtn(current_page, true);
} else if (current_page <= per_page_max - 5) {
appendBtn(current_page, true);
appendBtn(current_page - 2);
appendBtn(current_page - 1);
appendBtn(current_page);
appendBtn(current_page + 1);
appendBtn(current_page + 2);
appendBtn(current_page, true);
} else {
appendBtn(current_page, true);
appendBtn(per_page_max - 6);
appendBtn(per_page_max - 5);
appendBtn(per_page_max - 4);
appendBtn(per_page_max - 3);
appendBtn(per_page_max - 2);
}
// это середина
// это право
appendBtn(per_page_max - 1);
appendBtn(per_page_max);
// это право
}
.btns>* {
margin: 10px 10px 10px 0px;
display: inline-block;
}
.btn[disabled] {
pointer-events: none;
background-color: #DFDFDF !important;
-webkit-box-shadow: none;
box-shadow: none;
color: #9F9F9F !important;
cursor: default;
}
.btn {
display: inline-block;
letter-spacing: .5px;
text-align: center;
padding: 7px 14px;
background-color: #26a69a;
color: white;
border-radius: 2px;
text-transform: uppercase;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
font-size: 16px;
border: none;
outline: none;
transition: background-color .3s ease-out;
}
.btn.active {
border: 2px solid #26a69a;
padding: 6px 13px;
}
.btn:hover {
background-color: #2bbbad;
}
<div class="btns">
</div>
Ответы (2 шт):
paginator(document.getElementById("pag"),1);
function paginator(paginContID, countElem) {
if (paginContID) {
if (paginContID.children.length > countElem) {
for (let i = countElem; i < paginContID.children.length; i++) {
paginContID.children[i].style.display = 'none';
}
paginContID.style.overflow = 'hidden';
let divForPaging = document.createElement('div');
divForPaging.className = 'divPaging';
let bNext = document.createElement('button');
bNext.className = 'bNextPaging';
bNext.id = 'bNextPaging';
bNext.innerText = String.fromCharCode(8594);
let divContainerNumbers = document.createElement('div');
divContainerNumbers.className = 'divContainerNumbers';
let bPrevious = document.createElement('button');
bPrevious.className = 'bPreviousPaging';
bPrevious.id = 'bPreviousPaging';
bPrevious.innerText = String.fromCharCode(8592);
$(bPrevious).attr('disabled', 'disabled');
divForPaging.appendChild(bPrevious);
let countButtons = 3;
if (Math.ceil((paginContID.children.length) / countElem) > 7) {
for (let i = 0; i < 5; i++) {
let bNumber = document.createElement('button');
bNumber.className = 'bNumberPaging';
bNumber.name = 'bNumberPaging';
if (i == 0) {
$(bNumber).attr('disabled', 'disabled');
$(bNumber).addClass('bNumberPagingSelected');
}
bNumber.innerText = i + 1;
bNumber.value = i;
divContainerNumbers.appendChild(bNumber);
}
let bNumber = document.createElement('button');
bNumber.className = 'bNumberPaging';
bNumber.name = 'bNumberPaging';
bNumber.innerText = '...';
bNumber.value = 'points';
divContainerNumbers.appendChild(bNumber);
let bNumberMax = document.createElement('button');
bNumberMax.className = 'bNumberPaging';
bNumberMax.name = 'bNumberPaging';
bNumberMax.innerText = Math.ceil((paginContID.children.length / countElem));
bNumberMax.value = Math.ceil((paginContID.children.length / countElem) - 1);
divContainerNumbers.appendChild(bNumberMax);
} else {
for (let i = 0; i < Math.ceil((paginContID.children.length) / countElem); i++) {
let bNumber = document.createElement('button');
bNumber.className = 'bNumberPaging';
bNumber.name = 'bNumberPaging';
bNumber.innerText = i + 1;
bNumber.value = i;
if (i == 0) {
$(bNumber).attr('disabled', 'disabled');
$(bNumber).addClass('bNumberPagingSelected');
}
divContainerNumbers.appendChild(bNumber);
}
}
divForPaging.appendChild(divContainerNumbers);
divForPaging.appendChild(bNext);
paginContID.appendChild(divForPaging);
let PageNow = 0;
let trigOnce = 0;
$(bNext).click(function() {
bNextF();
});
function bNextF() {
let countHide = 0;
let countShowed = 0;
let buttonID = $(paginContID).children().last().find("div").children();
if (Math.ceil((paginContID.children.length - 1) / countElem) > 7) {
if (+PageNow >= 0 && +PageNow < 3) {
$(buttonID[PageNow]).removeAttr('disabled');
$(buttonID).removeClass('bNumberPagingSelected');
$(buttonID[+PageNow + 1]).attr('disabled', 'disabled');
$(buttonID[+PageNow + 1]).addClass('bNumberPagingSelected');
trigOnce++;
} else {
if ((+PageNow < Math.ceil((+paginContID.children.length - 1) / +countElem) - 5)) {
$(buttonID[1]).text('...');
$(buttonID[1]).val('points');
$(buttonID[2]).text(+PageNow + 1);
$(buttonID[2]).val(+PageNow);
$(buttonID[3]).text(+PageNow + 2); //;
$(buttonID[3]).val(+PageNow + 1);
$(buttonID[4]).text(+PageNow + 3);
$(buttonID[4]).val(+PageNow + 2);
$(buttonID[5]).text('...');
$(buttonID[5]).val('points');
} else {
if ((+PageNow == Math.ceil((+paginContID.children.length - 1) / +countElem) - 5)) {
$(buttonID[1]).text('...');
$(buttonID[1]).val('points');
$(buttonID[2]).text(+PageNow + 1);
$(buttonID[2]).val(+PageNow);
$(buttonID[3]).text(+PageNow + 2); //;
$(buttonID[3]).val(+PageNow + 1);
$(buttonID[4]).text(+PageNow + 3);
$(buttonID[4]).val(+PageNow + 2);
$(buttonID[5]).text(Math.ceil(((paginContID.children.length - 1) / countElem) - 1));
$(buttonID[5]).val(Math.ceil(((paginContID.children.length - 1) / countElem) - 2));
} else {
$(buttonID[trigOnce]).removeAttr('disabled');
$(buttonID).removeClass('bNumberPagingSelected');
$(buttonID[+trigOnce + 1]).attr('disabled', 'disabled');
$(buttonID[+trigOnce + 1]).addClass('bNumberPagingSelected');
trigOnce++;
}
}
}
} else {
$(buttonID[PageNow]).removeAttr('disabled');
$(buttonID).removeClass('bNumberPagingSelected');
$(buttonID[+PageNow + 1]).attr('disabled', 'disabled');
$(buttonID[+PageNow + 1]).addClass('bNumberPagingSelected');
}
PageNow++;
for (let i = 0; i < paginContID.children.length - 1; i++) {
if ($(paginContID.children[i]).is(':visible')) {
if (i == 0) {
$(bPrevious).removeAttr('disabled');
}
$(paginContID.children[i]).css({
'animation-name': 'fadeOutLeft'
});
setTimeout(function() {
$(paginContID.children[i]).css({
'display': 'none'
});
}, 600);
countHide++;
} else if (countHide == countElem) {
countShowed++
setTimeout(function() {
$(paginContID.children[i]).css({
'display': 'flex'
});
$(paginContID.children[i]).css({
'animation-name': 'fadeInRight'
});
}, 600)
if (countShowed > countElem - 1) {
if (i == paginContID.children.length - 2) {
$(bNext).attr('disabled', 'disabled');
}
break;
} else if (i == paginContID.children.length - 2) {
$(bNext).attr('disabled', 'disabled');
break;
}
}
}
}
$(bPrevious).click(function() {
bPreviousF();
});
function bPreviousF() {
let countHide = 0;
let countShowed = 0;
let trigLast = 0;
let buttonID = $(paginContID).children().last().find("div").children();
if (Math.ceil((paginContID.children.length - 1) / countElem) > 7) {
if (+PageNow >= 0 && +PageNow < 4) {
$(buttonID[PageNow]).removeAttr('disabled');
$(buttonID).removeClass('bNumberPagingSelected');
$(buttonID[PageNow - 1]).attr('disabled', 'disabled');
$(buttonID[PageNow - 1]).addClass('bNumberPagingSelected');
trigOnce--;
} else {
if ((+PageNow < Math.ceil((+paginContID.children.length - 1) / +countElem) - 4) && +PageNow > 4) {
$(buttonID[1]).text('...');
$(buttonID[1]).val('points');
$(buttonID[2]).text(+PageNow - 1);
$(buttonID[2]).val(+PageNow - 2);
$(buttonID[3]).text(+PageNow); //;
$(buttonID[3]).val(+PageNow - 1);
$(buttonID[4]).text(+PageNow + 1);
$(buttonID[4]).val(+PageNow);
$(buttonID[5]).text('...');
$(buttonID[5]).val('points');
} else if ((+PageNow >= Math.ceil((+paginContID.children.length - 1) / +countElem) - 4)) {
if ((+PageNow == Math.ceil((+paginContID.children.length - 1) / +countElem) - 4)) {
$(buttonID[1]).text('...');
$(buttonID[1]).val('points');
$(buttonID[2]).text(+PageNow - 1);
$(buttonID[2]).val(+PageNow - 2);
$(buttonID[3]).text(+PageNow); //;
$(buttonID[3]).val(+PageNow - 1);
$(buttonID[4]).text(+PageNow + 1);
$(buttonID[4]).val(+PageNow);
$(buttonID[5]).text('...');
$(buttonID[5]).val('points');
} else {;
$(buttonID[trigOnce]).removeAttr('disabled');
$(buttonID).removeClass('bNumberPagingSelected');
$(buttonID[trigOnce - 1]).attr('disabled', 'disabled');
$(buttonID[trigOnce - 1]).addClass('bNumberPagingSelected');
trigOnce--;
}
} else if (+PageNow == 4) {
$(buttonID[1]).text('2');
$(buttonID[1]).val('1');
$(buttonID[2]).text(+PageNow - 1);
$(buttonID[2]).val(+PageNow - 2);
$(buttonID[3]).text(+PageNow); //;
$(buttonID[3]).val(+PageNow - 1);
$(buttonID[4]).text(+PageNow + 1);
$(buttonID[4]).val(+PageNow);
$(buttonID[5]).text('...');
$(buttonID[5]).val('points');
}
}
} else {
$(buttonID[PageNow]).removeAttr('disabled');
$(buttonID).removeClass('bNumberPagingSelected');
$(buttonID[PageNow - 1]).attr('disabled', 'disabled');
$(buttonID[PageNow - 1]).addClass('bNumberPagingSelected');
}
PageNow--;
for (let i = paginContID.children.length - 2; i >= 0; i--) {
if ($(paginContID.children[i]).is(':visible')) {
if (i == paginContID.children.length - 2) {
$(bNext).removeAttr('disabled');
trigLast = 1
}
$(paginContID.children[i]).css({
'animation-name': 'fadeOutRight'
});
setTimeout(function() {
$(paginContID.children[i]).css({
'display': 'none'
});
}, 600);
countHide++;
} else if (countHide == countElem || (trigLast)) {
countShowed++
setTimeout(function() {
$(paginContID.children[i]).css({
'display': 'flex'
});
$(paginContID.children[i]).css({
'animation-name': 'fadeInLeft'
});
}, 600)
if (countShowed > countElem - 1) {
if (i == 0) {
$(bPrevious).attr('disabled', 'disabled');
if (buttonID[0]) {
buttonID[0].setAttribute('disabled', 'disabled');
}
}
break;
}
}
}
}
$('[name="bNumberPaging"]').click(function() {
let oneMoreTrigger = 0;
let buttonID = $(paginContID).children().last().find("div").children();
if (this.value != 'points') {
if ((Math.ceil((paginContID.children.length - 1) / countElem) > 7) && (+PageNow <= Math.ceil((+paginContID.children.length - 1) / +countElem) - 4) && +PageNow > 3 && (this.value != Math.ceil((+paginContID.children.length - 1) / +countElem) - 1) && this.value != 0) {
trigOnce = 3;
if (PageNow < this.value) {
bNextF();
} else if (PageNow >= this.value) {
bPreviousF();
}
} else {
PageNow = this.value;
$(buttonID).removeAttr('disabled');
$(buttonID).removeClass('bNumberPagingSelected');
if ((Math.ceil((paginContID.children.length - 1) / countElem) > 7)) {
if (PageNow >= this.value) {
if (this.value == Math.ceil(((+paginContID.children.length - 1) / +countElem) - 5)) {
oneMoreTrigger = 1;
$(buttonID[3]).attr('disabled', 'disabled');
$(buttonID[3]).addClass('bNumberPagingSelected');
}
}
if (PageNow <= this.value && (Math.ceil((paginContID.children.length - 1) / countElem) > 7)) {
if (this.value == 4) {
oneMoreTrigger = 1;
$(buttonID[3]).attr('disabled', 'disabled');
$(buttonID[3]).addClass('bNumberPagingSelected');
}
}
}
if (oneMoreTrigger == 0) {
$(this).attr('disabled', 'disabled');
$(this).addClass('bNumberPagingSelected');
}
for (let i = 0; i < paginContID.children.length - 1; i++) {
if ($(paginContID.children[i]).is(':visible')) {
if (i != paginContID.children.length - 2) {
$(bNext).removeAttr('disabled');
}
if (i != 0) {
$(bPrevious).removeAttr('disabled');
}
$(paginContID.children[i]).css({
'animation-name': 'fadeOut'
});
setTimeout(function() {
$(paginContID.children[i]).css({
'display': 'none'
});
}, 600);
}
}
for (let i = PageNow * countElem; i < PageNow * countElem + countElem; i++) {
setTimeout(function() {
$(paginContID.children[i]).css({
'display': 'flex'
});
$(paginContID.children[i]).css({
'animation-name': 'fadeIn'
});
}, 600)
if (i == 0) {
$(bPrevious).attr('disabled', 'disabled');
} else if (i == paginContID.children.length - 2) {
$(bNext).attr('disabled', 'disabled');
}
if ((Math.ceil((paginContID.children.length - 1) / countElem) > 7)) {
if (PageNow < 4) {
trigOnce = PageNow
}
if (PageNow <= Math.ceil((+paginContID.children.length - 1) / +countElem) && PageNow >= Math.ceil((+paginContID.children.length - 1) / +countElem) - 2) {
trigOnce = 7 - (Math.ceil((+paginContID.children.length - 1) / +countElem) - PageNow);
}
if (PageNow == 4) {
$(buttonID[1]).text('...');
$(buttonID[1]).val('points');
$(buttonID[2]).text(+PageNow);
$(buttonID[2]).val(+PageNow - 1);
$(buttonID[3]).text(+PageNow + 1); //;
$(buttonID[3]).val(+PageNow);
$(buttonID[4]).text(+PageNow + 2);
$(buttonID[4]).val(+PageNow + 1);
$(buttonID[5]).text('...');
$(buttonID[5]).val('points');
}
if (PageNow == Math.ceil(((+paginContID.children.length - 1) / +countElem) - 5)) {
$(buttonID[1]).text('...');
$(buttonID[1]).val('points');
$(buttonID[2]).text(+PageNow);
$(buttonID[2]).val(+PageNow - 1);
$(buttonID[3]).text(+PageNow + 1); //;
$(buttonID[3]).val(+PageNow);
$(buttonID[4]).text(+PageNow + 2);
$(buttonID[4]).val(+PageNow + 1);
$(buttonID[5]).text('...');
$(buttonID[5]).val('points');
trigOnce = 3;
}
if (i == 0) {
$(bPrevious).attr('disabled', 'disabled');
$(buttonID[1]).text('2');
$(buttonID[1]).val('1');
$(buttonID[2]).text(3);
$(buttonID[2]).val(2);
$(buttonID[3]).text(4); //;
$(buttonID[3]).val(3);
$(buttonID[4]).text(5);
$(buttonID[4]).val(4);
$(buttonID[5]).text('...');
$(buttonID[5]).val('points');
}
if (i == paginContID.children.length - 2) {
$(bNext).attr('disabled', 'disabled');
$(buttonID[1]).text('...');
$(buttonID[1]).val('points');
$(buttonID[2]).text(Math.ceil(((paginContID.children.length - 1) / countElem) - 4));
$(buttonID[2]).val(Math.ceil(((paginContID.children.length - 1) / countElem) - 5));
$(buttonID[3]).text(Math.ceil(((paginContID.children.length - 1) / countElem) - 3));
$(buttonID[3]).val(Math.ceil(((paginContID.children.length - 1) / countElem) - 4));
$(buttonID[4]).text(Math.ceil(((paginContID.children.length - 1) / countElem) - 2));
$(buttonID[4]).val(Math.ceil(((paginContID.children.length - 1) / countElem) - 3));
$(buttonID[5]).text(Math.ceil(((paginContID.children.length - 1) / countElem) - 1));
$(buttonID[5]).val(Math.ceil(((paginContID.children.length - 1) / countElem) - 2));
}
}
}
}
}
});
}
}
}
.divPaging {
width: calc(100% - 2vh);
height: fit-content;
display: flex;
justify-content: space-between;
background: #f4f2fb;
color: #a5d774;
border-radius: 5px;
margin: 0 1vh 1vh;
}
.divContainerNumbers{
width: fit-content;
display: flex;
height: fit-content;
}
.bPreviousPaging,.bNextPaging,.bNumberPaging{
font-size: 14px;
line-height: 16px;
padding: 1.5vh;
color: #a5d774;
background: #0F2522;
}
.bPreviousPaging,.bNextPaging,.bNumberPaging{
width: fit-content;
transition: all .3s ease-in-out;
border-radius: 5px 0 0 5px;
}
.bNumberPaging{
margin: 0 1px;
border-radius: 0;
}
.bNumberPagingSelected{
background: #a5d774;
color: #0F2522;
}
.bNextPaging{
border-radius: 0 5px 5px 0;
}
.bPreviousPaging:hover,.bNextPaging:hover,.bNumberPaging:hover{
background: #a5d774;
color: #0F2522;
cursor: pointer;
}
.bNextPaging:disabled, .bPreviousPaging:disabled{
background: #B8BBC8;
color: #0F2522;
cursor: not-allowed;
}
#pag{
display: flex;
flex-direction: column;
justify-content: center;
}
.pag{
display: flex;
width: 300px;
height: 200px;
background: green;
margin-bottom: 10px;
align-items: center;
justify-content:center;
font-size: 50px;
color: white;
}
@media screen and (max-width: 485px){
.bPreviousPaging,.bNextPaging,.bNumberPaging{
padding: 1vh;
line-height: 14px;
font-size: 12px;
flex: 1;
}
.divContainerNumbers{
flex: 1;
}
.bNumberPaging{
margin: 0;
}
}
@media screen and (max-width: 370px){
.bPreviousPaging,.bNextPaging,.bNumberPaging{
padding: 1vh 0.6vh;
line-height: 14px;
font-size: 12px;
}
}
<link href="http://vivify.mkcreative.cz/assets/css/vivify.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="pag">
<div class="vivify pag">
1
</div>
<div class="vivify pag">
2
</div>
<div class="vivify pag">
3
</div>
<div class="vivify pag">
4
</div>
<div class="vivify pag">
5
</div>
<div class="vivify pag">
6
</div>
<div class="vivify pag">
7
</div>
<div class="vivify pag">
8
</div>
<div class="vivify pag">
9
</div>
<div class="vivify pag">
10
</div>
<div class="vivify pag">
11
</div>
<div class="vivify pag">
12
</div>
</div>
Вот, недавно писал, вроде бы рабочий.
Объявляется следующим образом: 1 элемент - родитель содержащий множество элементов, 2 элемент - количество отображаемых элементов на текущей странице.
paginator(document.getElementById('notificationBlock'),2);
Для того, что бы были анимации прокрутки и прочего, требуется подключить библиотеку vivify и каждому дочернему элементу прописать дополнительный класс - "vivify"
И вот соответственно css - меняйте его как душе угодно, если будут вопросы - пишите.
Ну неособо понятно как быть с центральной частью, должна ли она всегда быть нечетного размера, чтобы соблюдалась симметрия. Но если да, то вот пример. Можно в принципе границы переопределить и рассчитывать по-другому.
Сейчас так:
logic(leftCount, centerSideCount, rightCount)
leftCount - число блоков слева
rightCount - число блоков справа
centerSideCount - число блоков по левую и правую сторону в центральной секции
const per_page_max = 40; // Максимальное кол-во страниц
let current_page = 2; // Текущая страница
const btns = document.querySelector('.btns');
function appendBtn(i, ellipsis) {
const activeBtn = current_page === i;
const button = document.createElement('button');
button.classList.add('btn');
if (ellipsis === true) {
button.innerHTML = '...';
button.disabled = true;
btns.append(button);
return false;
}
if (activeBtn) {
button.classList.add('active');
}
button.disabled = activeBtn === true ? 'disabled' : '';
button.innerHTML = i;
button.addEventListener('click', () => {
current_page = i;
btns.innerHTML = '';
logic(1, 1, 3);
});
btns.append(button);
}
logic(1, 1, 3);
function logic(leftCount, centerSideCount, rightCount) {
let centerLeft, centerRight;
range(1, leftCount).forEach(appendBtn);
centerLeft = Math.max(leftCount + 1, current_page - centerSideCount);
centerRight = Math.min(per_page_max - rightCount, centerLeft + centerSideCount * 2);
centerLeft = Math.max(leftCount + 1, centerRight - centerSideCount * 2);
if (centerLeft > leftCount + 1) {
appendBtn(current_page, true);
}
range(centerLeft, centerRight).forEach(appendBtn);
if (centerRight < per_page_max - rightCount) {
appendBtn(current_page, true);
}
range(per_page_max - rightCount + 1, per_page_max).forEach(appendBtn);
}
function range(start, stop) {
if (start === undefined || stop === undefined) return [];
const length = Math.abs(stop - start) + 1;
return Array.from({
length
}, (_, i) => i * Math.sign(stop - start) + start);
}
.btns>* {
margin: 10px 10px 10px 0px;
display: inline-block;
}
.btn[disabled] {
pointer-events: none;
background-color: #DFDFDF !important;
-webkit-box-shadow: none;
box-shadow: none;
color: #9F9F9F !important;
cursor: default;
}
.btn {
display: inline-block;
letter-spacing: .5px;
text-align: center;
padding: 7px 14px;
background-color: #26a69a;
color: white;
border-radius: 2px;
text-transform: uppercase;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
font-size: 16px;
border: none;
outline: none;
transition: background-color .3s ease-out;
}
.btn.active {
border: 2px solid #26a69a;
padding: 6px 13px;
}
.btn:hover {
background-color: #2bbbad;
}
<div class="btns"></div>