Demo: https://adriancs.com/html-css-js/1372/demo-of-using-javascript-to-build-html-pagination/
Source Code: https://adriancs.com/wp-content/uploads/2023/11/demo-pagination-javascript-2.zip
Assume that we have the following HTML element:
<div id="pagination1" class="pager1"></div>
The following javascript function is generated by ChatGPT 4.0. By following some of my requirements, this javascript function will help to generate a HTML pagination block with the following parameters:
totalRecords
andtotalRecordsPerPage
will be used for calculating the page numbers.totalPagerSlots
will define the total pagination buttons.pageFileldName
and container used for fillling in the page numbers.hrefURL
andonclickScript
will be used as a basic string format for generating the links.
Here’s the finalized working code:
function generatePagination(totalRecords, totalRecordsPerPage,
currentPage, totalPagerSlots, pageFieldName,
hrefURL, onclickScript) {
// Calculate the total number of pages
let totalPages = Math.ceil(totalRecords / totalRecordsPerPage);
let pagerHTML = "";
// Determine how many page links to show on either side of the current page
let halfPagerSlots = Math.floor(totalPagerSlots / 2);
// Calculate the first page number to display in the pager
let pagerStart = Math.max(currentPage - halfPagerSlots, 1);
// Calculate the last page number to display in the pager
let pagerEnd = Math.min(pagerStart + totalPagerSlots - 1, totalPages);
// Adjust the pager start if we're at the end of the page range
if (pagerEnd - pagerStart < totalPagerSlots - 1) {
pagerStart = Math.max(pagerEnd - totalPagerSlots + 1, 1);
}
// If not on the first pager slot, add a link to the first page
if (pagerStart > 1) {
let hrefFirstPage = hrefURL.replace(pageFieldName, '1');
let firstPageOnClick = onclickScript ? onclickScript.replace(pageFieldName, '1') : '';
pagerHTML += `<a href="${hrefFirstPage}"${firstPageOnClick ? ` onclick="${firstPageOnClick}"` : ''}>First</a>\n`;
// Add ellipsis to indicate skipped pages
pagerHTML += "<span class='ellipsis'>...</span>\n";
}
// Loop through page numbers from the start to end of the pager
for (let i = pagerStart; i <= pagerEnd; i++) {
// Replace the pageFieldName placeholder with the actual page number
let hrefValue = hrefURL.replace(pageFieldName, i);
// Begin anchor tag for the page link
let linkHTML = `<a href="${hrefValue}"`;
// If an onclick script is provided, add it to the anchor tag
if (onclickScript) {
let onClickValue = onclickScript.replace(pageFieldName, i);
linkHTML += ` onclick="${onClickValue}"`;
}
// Finish the anchor tag and add the page number as the link text
linkHTML += `>${i}</a>\n`;
// If this is the current page, wrap it in a <strong> tag to highlight it
if (i === currentPage) {
pagerHTML += `<strong>${linkHTML}</strong>\n`;
} else {
// Otherwise, add the link to the pager HTML as is
pagerHTML += linkHTML;
}
}
// If not on the last pager slot, add a link to the last page
if (pagerEnd < totalPages) {
// Add ellipsis to indicate skipped pages
pagerHTML += "<span class='ellipsis'>...</span>\n";
let hrefLastPage = hrefURL.replace(pageFieldName, totalPages);
let lastPageOnClick = onclickScript ? onclickScript.replace(pageFieldName, totalPages) : '';
pagerHTML += `<a href="${hrefLastPage}"${lastPageOnClick ? ` onclick="${lastPageOnClick}"` : ''}>Last</a>`;
}
// Return the complete HTML for the pager
return pagerHTML;
}
This function requires two dynamic values.
- Total records (or toal rows in database perpective)
- Current page number
To get number of total records, in SQL database perspective, one would normally do this:
SELECT COUNT(*) FROM tablename where ...<conditions>....
For the number of current page, if you are doing non-javascript direct link page navigation, it can be obtained from the URL’s query string or route parameter (route data).
A javascript to get the page number from URL’s query string:
// Assuming the URL is something like: https://www.example.com/?page=2
let queryString = window.location.search;
let urlParams = new URLSearchParams(queryString);
let page = urlParams.get("page");
Example of Usage
Example of usage 1: Direct link only, no javascript onclick event
let htmlPagination = generatePagination(10000, 10, 9, 7, '[page]',
'SearchItems?page=[page]', '');
document.getElementById("pagination1").innerHTML = htmlPagination;
Result:
<a href="SearchItems?page=1">First</a>
<span class='ellipsis'>...</span>
<a href="SearchItems?page=6">6</a>
<a href="SearchItems?page=7">7</a>
<a href="SearchItems?page=8">8</a>
<strong><a href="SearchItems?page=9">9</a>
</strong>
<a href="SearchItems?page=10">10</a>
<a href="SearchItems?page=11">11</a>
<a href="SearchItems?page=12">12</a>
<span class='ellipsis'>...</span>
<a href="SearchItems?page=1000">Last</a>
Example of usage 2: No redirect link, only javascript onclick events
let htmlPagination = generatePagination(10000, 10, 9, 7, '[page]', '',
'return loadTable([page], event);');
document.getElementById("pagination1").innerHTML = htmlPagination;
Result:
<a href="" onclick="return loadTable(1, event);">First</a>
<span class='ellipsis'>...</span>
<a href="" onclick="return loadTable(6, event);">6</a>
<a href="" onclick="return loadTable(7, event);">7</a>
<a href="" onclick="return loadTable(8, event);">8</a>
<strong><a href="" onclick="return loadTable(9, event);">9</a>
</strong>
<a href="" onclick="return loadTable(10, event);">10</a>
<a href="" onclick="return loadTable(11, event);">11</a>
<a href="" onclick="return loadTable(12, event);">12</a>
<span class='ellipsis'>...</span>
<a href="" onclick="return loadTable(1000, event);">Last</a>
Example of usage 3: Combo, Direct Link + Javascript onclick event
let htmlPagination = generatePagination(10000, 10, 9, 7, '[page]',
'SearchItems?page=[page]', 'return loadTable([page], event);');
document.getElementById("pagination1").innerHTML = htmlPagination;
Result:
<a href="SearchItems?page=1" onclick="return loadTable(1, event);">First</a>
<span class='ellipsis'>...</span>
<a href="SearchItems?page=6" onclick="return loadTable(6, event);">6</a>
<a href="SearchItems?page=7" onclick="return loadTable(7, event);">7</a>
<a href="SearchItems?page=8" onclick="return loadTable(8, event);">8</a>
<strong><a href="SearchItems?page=9" onclick="return loadTable(9, event);">9</a>
</strong>
<a href="SearchItems?page=10" onclick="return loadTable(10, event);">10</a>
<a href="SearchItems?page=11" onclick="return loadTable(11, event);">11</a>
<a href="SearchItems?page=12" onclick="return loadTable(12, event);">12</a>
<span class='ellipsis'>...</span>
<a href="SearchItems?page=1000" onclick="return loadTable(1000, event);">Last</a>
The onclick
javascript event provides an override mechanism which makes the pagination system serve a dual purpose. They contain an href
attribute for standard navigation, ensuring that the links remain functional and accessible without JavaScript. However, they also include an onclick
event handler that overrides the default behavior when a user performs a left-click. On a left-click, rather than navigating to a new page, the loadTable
function is invoked, which leverages FetchAPI to update the table content dynamically on the same page. This approach provides a seamless user experience by avoiding full page reloads, thereby enhancing the responsiveness and interactivity of the web application.
The following code demonstrates the idea of overriding the default direct-link behaviour that will use FetchAPI
to load the table:
function loadTable(pageNumber, event) {
// Check if the click is a standard left-click
if (!event || event.button === 0) {
// Prevent default link behavior on left click
event.preventDefault();
// ... additional code to load the table ...
// ... using FetchApi, etc...
return false;
}
// For non-left clicks, allow the default behavior (href navigation)
return true;
}
Example with FetchAPI
:
function loadTable(pageNumber, event) {
// Check if the click is a standard left-click
if (!event || event.button === 0) {
// Prevent default link behavior on left click
event.preventDefault();
// Fetch data from server
fetch('https://your-api-endpoint.com/data?page=' + pageNumber)
.then(response => {
// Check if the response is ok (status code 200-299)
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json(); // Parse JSON response
})
.then(data => {
// Build HTML table
let table = '<table>';
table += '<tr>';
// Add headers to table, assuming 'headers' is an array of header names
data.headers.forEach(header => {
table += '<th>' + header + '</th>';
});
table += '</tr>';
// Add rows to table, assuming 'rows' is an array of row objects
data.rows.forEach(row => {
table += '<tr>';
Object.values(row).forEach(value => {
table += '<td>' + value + '</td>';
});
table += '</tr>';
});
table += '</table>';
// Add the table to the page, assuming you have a div with id 'tableContainer'
document.getElementById('tableContainer').innerHTML = table;
})
.catch(error => {
console.error('There has been a problem with your fetch operation:', error);
});
return false;
}
// For non-left clicks, allow the default behavior (href navigation)
return true;
}
Example of usage 4: Use pure javascript in HREF
let htmlPagination = generatePagination(10000, 10, 9, 7, '[page]',
'javascript:loadTable([page])', '');
Result:
<a href="javascript:loadTable(1)">First</a>
<span class='ellipsis'>...</span>
<a href="javascript:loadTable(6)">6</a>
<a href="javascript:loadTable(7)">7</a>
<a href="javascript:loadTable(8)">8</a>
<strong><a href="javascript:loadTable(9)">9</a>
</strong>
<a href="javascript:loadTable(10)">10</a>
<a href="javascript:loadTable(11)">11</a>
<a href="javascript:loadTable(12)">12</a>
<span class='ellipsis'>...</span>
<a href="javascript:loadTable(1000)">Last</a>
CSS Styling for The Pagination
Here’s the basic style adopted by the following examples.
body {
font-family: Arial;
font-size: 12pt;
}
CSS Example 1:
.pager1 a {
border-radius: 7px;
background-color: lightblue;
text-decoration: none;
padding: 7px 10px;
color: black;
font-style: normal;
}
.pager1 a:hover, .pager1 strong a {
background-color: darkblue;
color: white;
}
CSS Example 2:
.pager1 a {
border-radius: 7px;
background-color: lightblue;
text-decoration: none;
padding: 7px 10px;
color: black;
font-style: normal;
}
.pager1 a:hover, .pager1 strong a {
background-color: darkblue;
color: white;
}
.pager1 {
color: white;
}
.pager1 {
padding: 10px;
background-color: #333;
border-radius: 5px;
}
.pager1 a {
text-decoration: none;
margin: 0 5px;
padding: 5px 10px;
border-radius: 5px;
background-color: #555;
color: #ddd;
transition: background-color 0.3s, color 0.3s;
}
.pager1 a:hover,
.pager1 a:focus {
background-color: #777;
color: #fff;
outline: none;
}
.pager1 strong a {
background-color: #0088cc;
color: #fff;
pointer-events: none;
cursor: default;
}
.pager1 .ellipsis {
color: #aaa;
pointer-events: none;
}
CSS Example 3:
.pager1 {
text-align: center;
padding: 10px;
background-color: #2f2f2f;
border-radius: 5px;
color: #b9e986;
}
.pager1 a {
text-decoration: none;
margin: 0 5px;
padding: 5px 10px;
border-radius: 5px;
background-color: #3e3e3e;
color: #b9e986;
transition: background-color 0.3s, color 0.3s;
}
.pager1 a:hover,
.pager1 a:focus {
background-color: #4e4e4e;
color: #d4fcb8;
outline: none;
}
.pager1 strong a {
background-color: #8dc641;
color: #2f2f2f;
pointer-events: none;
cursor: default;
}
.pager1 .ellipsis {
color: #6f6f6f;
pointer-events: none;
}
CSS Example 4:
.pager1 {
text-align: center;
padding: 10px;
background-color: #fff0f0;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.pager1 a {
text-decoration: none;
margin: 0 5px;
padding: 5px 10px;
border-radius: 5px;
background-color: #ffe5e5;
color: #333;
transition: background-color 0.3s, color 0.3s;
}
.pager1 a:hover,
.pager1 a:focus {
background-color: #ffc3c3;
color: #d60000;
outline: none;
}
.pager1 strong a {
background-color: #ff9999;
color: #fff;
pointer-events: none;
cursor: default;
}
.pager1 .ellipsis {
color: #bfbfbf;
pointer-events: none;
}
CSS Example 5:
.pager1 {
text-align: center;
padding: 10px;
background-color: #f0faff;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.pager1 a {
text-decoration: none;
margin: 0 5px;
padding: 5px 10px;
border-radius: 5px;
background-color: #e1efff;
color: #007bff;
transition: background-color 0.3s, color 0.3s;
}
.pager1 a:hover,
.pager1 a:focus {
background-color: #d0e7ff;
color: #0056b3;
outline: none;
}
.pager1 strong a {
background-color: #007bff;
color: #ffffff;
pointer-events: none;
cursor: default;
}
.pager1 .ellipsis {
color: #bfbfbf;
pointer-events: none;
}