What does this script do?
This script enables paginated browsing through a list of content elements (.demo-content
), showing one at a time with navigation controls that adaptively show surrounding page numbers, ellipses, and first/last pages.
HTML
<div class="demo-wrap">
<div id="demo-content-container">
<div class="demo-content"><h1>I</h1><h2>prīmus</h2></div>
<div class="demo-content"><h1>II</h1><h2>secundus</h2></div>
<div class="demo-content"><h1>III</h1><h2>tertius</h2></div>
<div class="demo-content"><h1>IV</h1><h2>quārtus</h2></div>
<div class="demo-content"><h1>V</h1><h2>quīntus</h2></div>
<div class="demo-content"><h1>VI</h1><h2>sextus</h2></div>
<div class="demo-content"><h1>VII</h1><h2>septimus</h2></div>
<div class="demo-content"><h1>VIII</h1><h2>octāvus</h2></div>
<div class="demo-content"><h1>IX</h1><h2>nōnus</h2></div>
<div class="demo-content"><h1>X</h1><h2>decimus</h2></div>
<div class="demo-content"><h1>XI</h1><h2>ūndecimus</h2></div>
<div class="demo-content"><h1>XII</h1><h2>duodecimus</h2></div>
<div class="demo-content"><h1>XIII</h1><h2>tertius decimus</h2></div>
<div class="demo-content"><h1>XIV</h1><h2>quārtus decimus</h2></div>
<div class="demo-content"><h1>XV</h1><h2>quīntus decimus</h2></div>
<div class="demo-content"><h1>XVI</h1><h2>sextus decimus</h2></div>
<div class="demo-content"><h1>XVII</h1><h2>septimus decimus</h2></div>
<div class="demo-content"><h1>XVIII</h1><h2>duodēvīcēsimus</h2></div>
<div class="demo-content"><h1>XIX</h1><h2>ūndēvīcēsimus</h2></div>
<div class="demo-content"><h1>XX</h1><h2>vīcēsimus</h2></div>
<div class="demo-content"><h1>XXI</h1><h2>vīcēsimus prīmus</h2></div>
<div class="demo-content"><h1>XXII</h1><h2>vīcēsimus secundus</h2></div>
</div>
<div class="demo-pagination-container">
<div class="container pagination justify-content-center flex-wrap"></div>
</div>
</div>
JS
<script type="text/javascript">
function getPagesList(pagesTotal, currentPage, maxLength, leftWidth = 2, rightWidth = 2) {
if (maxLength < 5) throw "maxLength must be at least 5";
function range(start, end) {
return Array.from({ length: end - start + 1 }, (_, i) => i + start);
}
const sideWidth = maxLength < 9 ? 1 : 2;
const middleCount = maxLength - sideWidth * 2 - 2;
if (pagesTotal <= maxLength) {
return range(1, pagesTotal);
}
const leftEnd = sideWidth + leftWidth;
const rightStart = pagesTotal - sideWidth - rightWidth + 1;
if (currentPage <= leftEnd + 1) {
return [
...range(1, leftEnd + rightWidth), 0,
...range(pagesTotal - sideWidth + 1, pagesTotal)
];
}
if (currentPage >= rightStart - 1) {
return [
...range(1, sideWidth), 0,
...range(pagesTotal - leftWidth - rightWidth - sideWidth + 1, pagesTotal)
];
}
return [
...range(1, sideWidth), 0,
...range(currentPage - leftWidth, currentPage + rightWidth), 0,
...range(pagesTotal - sideWidth + 1, pagesTotal)
];
}
$(function () {
const contentContainer = $("#demo-content-container");
const items = contentContainer.find(".demo-content");
const itemsPerPage = 1;
const paginationLength = 6;
let currentPage = 1;
const leftEllipsisCount = 2;
const rightEllipsisCount = 2;
const totalPages = Math.ceil(items.length / itemsPerPage);
function showPage(pageNum) {
if (pageNum < 1 || pageNum > totalPages) return;
currentPage = pageNum;
// Preload or load content here if needed ...
items.hide().slice((pageNum - 1) * itemsPerPage, pageNum * itemsPerPage).show();
$(".pagination li").slice(1, -1).remove(); // remove old items
const pages = getPagesList(totalPages, currentPage, paginationLength, leftEllipsisCount, rightEllipsisCount);
pages.forEach(p => {
$("<li>").addClass("page-item")
.addClass(p ? "current-item" : "disabled")
.toggleClass("active", p === currentPage)
.append(
// $("<a>").addClass("page-link ellipses").attr({ href: "javascript:void(0);" }).text(p || "...")
$("<a>")
.addClass("page-link")
.addClass(p ? "" : "pagination-ellipsis") // Custom class for ellipses
.attr({ href: "javascript:void(0);" })
.html(p || '<span class="pagination-ellipsis-icon">…</span>')
).insertBefore("#next-page");
});
$("#previous-page").toggleClass("disabled", currentPage === 1);
$("#next-page").toggleClass("disabled", currentPage === totalPages);
}
// Initialize pagination controls
$(".pagination").append(
$("<li>").addClass("page-item").attr("id", "previous-page").append(
$("<a>").addClass("page-link").attr("href", "javascript:void(0);").text("«")
),
$("<li>").addClass("page-item").attr("id", "next-page").append(
$("<a>").addClass("page-link").attr("href", "javascript:void(0);").text("»")
)
);
contentContainer.show();
showPage(1);
// Event bindings
$(document).on("click", ".pagination li.current-item:not(.active)", function () {
showPage(+$(this).text());
});
$("#next-page").on("click", () => showPage(currentPage + 1));
$("#previous-page").on("click", () => showPage(currentPage - 1));
// Keyboard navigation
$(document).keydown(e => {
if (e.which === 39) return showPage(currentPage + 1); // right arrow
if (e.which === 37) return showPage(currentPage - 1); // left arrow
});
});
</script>
CSS
@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400..900&display=swap');
.mwd-content-banner {
background-image: url("bg.jpg");
background-repeat: no-repeat;
background-size: cover;
background-position: center center;
text-align: center;
}
.mwd-content-banner-overlay {
min-height: 240px;
background: linear-gradient(to top, rgba(9, 32, 63, 0.6) 0%, rgba(83, 120, 149, 0.1) 100%);
padding: 2em 0;
}
.demo-container {
margin: 0 auto;
max-width: 1200px;
padding: 1rem;
text-align: center;
}
.demo-content {
font-size: 2.4em;
padding: 20px;
text-align: center;
border: 1px solid rgba(255, 255, 255, 0.6);
background-color: rgba(255, 255, 255, 0.4);
border-radius: 10px;
}
.demo-content h1, .demo-content h2 {
margin: 0 !important;
padding: 0;
font-weight: 600;
line-height: 1em;
}
.demo-content h1 {
font-family: "Cinzel", serif;
font-size: 2.6em;
color: rgba(0, 0, 0, 0.6);
}
.demo-content h2 {
font-size: 1em;
color: rgba(0, 0, 0, 0.4);
}
.demo-pagination-container {
margin-top: 2em;
}
.demo-pagination-container .pagination a,
.demo-pagination-container .pagination a:focus {
outline: none;
box-shadow: none;
}
.demo-pagination-container .pagination-outer {
text-align: center;
}
.demo-pagination-container .pagination {
display: inline-flex;
position: relative;
}
.demo-pagination-container .pagination li a.page-link {
color: #555;
background: rgba(255, 255, 255, 0.6);
border: 1px solid #ffffff;
font-weight: 500;
line-height: 40px;
height: 40px;
width: 40px;
padding: 0;
margin: 0 4px 10px 4px;
border-radius: 0;
position: relative;
z-index: 1;
text-align: center;
}
.demo-pagination-container .pagination-ellipsis {
border: none !important;
background: transparent !important;
}
.demo-pagination-container .pagination-ellipsis-icon {
font-size: 1.4rem;
color: #ffffff !important;
}
.demo-pagination-container .pagination li a.page-link:hover,
.demo-pagination-container .pagination li a.page-link:focus,
.demo-pagination-container .pagination li.active a.page-link:hover,
.demo-pagination-container .pagination li.active a.page-link {
color: #222222;
background: rgba(255, 255, 255, 0.9);
}
.demo-pagination-container .pagination li a.page-link:before,
.demo-pagination-container .pagination li a.page-link:after {
content: '';
background-color: #256596;
height: 100%;
width: 100%;
border-radius: 50%;
transform: scale(0);
position: absolute;
left: 0;
top: 0;
z-index: -1;
}
Basic Page
Button alignment
Button styles
Button with an icon
Button with text and icon on the left
Button with text and icon on the right
Content pagination
Include CSS and JS Files
Modal window
Popover
Popover with HTML content
Progress bars
Progress bars with tooltip
Popover with HTML content and a close button
Responsive cards
Responsive cards styled like business cards
Responsive cards styled like post-it notes
Responsive columns
Table
Table pagination with keyboard keys
Tabs
Tooltip
Tooltip with HTML content