/**
* @summary pfPagination for DataTables
* @description A collection of API methods providing functionality to paginate DataTables data. This ensures
* DataTables meets the Patternfly design pattern while maintaining accessibility.
*
* The pagination layout is expected to contain the classes as shown in the example below.
*
* Example:
*
*
*
*
*
*/
(function (factory) {
"use strict";
if (typeof define === "function" && define.amd ) {
// AMD
define (["jquery", "datatables.net"], function ($) {
return factory ($, window, document);
});
} else if (typeof exports === "object") {
// CommonJS
module.exports = function (root, $) {
if (!root) {
root = window;
}
if (!$ || !$.fn.dataTable) {
$ = require("datatables.net")(root, $).$;
}
return factory($, root, root.document);
};
} else {
// Browser
factory(jQuery, window, document);
}
}(function ($, window, document, undefined) {
"use strict";
var DataTable = $.fn.dataTable;
var BACK_ACTIONS_SELECTOR = ".pagination-pf-back"; // Back navigation actions
var CURRENT_ITEMS_SELECTOR = ".pagination-pf-items-current"; // Current items text (e.g., 1-15)
var CURRENT_PAGE_SELECTOR = ".pagination-pf-page"; // Current page input
var FIRST_PAGE_SELECTOR = ".pagination-pf-back .fa-angle-double-left"; // First page button
var FORWARD_ACTIONS_SELECTOR = ".pagination-pf-forward"; // Forward navigation actions
var LAST_PAGE_SELECTOR = ".pagination-pf-forward .fa-angle-double-right"; // Last page button
var PAGE_SIZE_SELECTOR = "select.pagination-pf-pagesize"; // Page size selection
var TOTAL_ITEMS_SELECTOR = ".pagination-pf-items-total"; // Total items
var TOTAL_PAGES_SELECTOR = ".pagination-pf-pages"; // Total pages text
var PREVIOUS_PAGE_SELECTOR = ".pagination-pf-back .fa-angle-left"; // Previous page button
var NEXT_PAGE_SELECTOR = ".pagination-pf-forward .fa-angle-right"; // Next page button
DataTable.pfPagination = {};
/**
* Initialize
*
* @param {DataTable.Api} dt DataTable
* @private
*/
DataTable.pfPagination.init = function (dt) {
var ctx = dt.settings()[0];
var opts = (ctx.oInit.pfConfig) ? ctx.oInit.pfConfig : {};
ctx._pfPagination = {};
ctx._pfPagination.backActions = $(BACK_ACTIONS_SELECTOR, opts.paginationSelector); // Back navigation actions
ctx._pfPagination.currentItems = $(CURRENT_ITEMS_SELECTOR, opts.paginationSelector); // Current items
ctx._pfPagination.currentPage = $(CURRENT_PAGE_SELECTOR, opts.paginationSelector); // Current page
ctx._pfPagination.firstPage = $(FIRST_PAGE_SELECTOR, opts.paginationSelector); // First page button
ctx._pfPagination.forwardActions = $(FORWARD_ACTIONS_SELECTOR, opts.paginationSelector); // Forward navigation actions
ctx._pfPagination.lastPage = $(LAST_PAGE_SELECTOR, opts.paginationSelector); // Last page button
ctx._pfPagination.nextPage = $(NEXT_PAGE_SELECTOR, opts.paginationSelector); // Next page button
ctx._pfPagination.pageSize = $(PAGE_SIZE_SELECTOR, opts.paginationSelector); // Page size selection
ctx._pfPagination.previousPage = $(PREVIOUS_PAGE_SELECTOR, opts.paginationSelector); // Next page button
ctx._pfPagination.totalItems = $(TOTAL_ITEMS_SELECTOR, opts.paginationSelector); // Total items
ctx._pfPagination.totalPages = $(TOTAL_PAGES_SELECTOR, opts.paginationSelector); // Total pages
// Set initial page size
ctx._pfPagination.currentPageSize = (opts.pageSize !== undefined) ? opts.pageSize : 15;
// Handle page navigation
handleCurrentPage(dt);
handleFirstPage(dt);
handleLastPage(dt);
handlePageSize(dt);
handleNextPage(dt);
handlePreviousPage(dt);
// Update table on DataTables draw event
dt.on("draw.page", function () {
updateCurrentPage(dt);
updateCurrentItems(dt);
updateTotalItems(dt);
updateTotalPages(dt);
updateBackActions(dt);
updateForwardActions(dt);
});
// Initialize page info
dt.table().page.len(ctx._pfPagination.currentPageSize);
dt.table().draw('page');
};
// Local functions
/**
* Handle page navigation when enter is pressed
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function handleCurrentPage (dt) {
var ctx = dt.settings()[0];
if (ctx._pfPagination.currentPage === undefined || ctx._pfPagination.currentPage.length === 0) {
return;
}
ctx._pfPagination.currentPage.on("keypress", function (e) {
var page, pageInfo = dt.table().page.info();
var keycode = (e.keyCode ? e.keyCode : e.which);
if (keycode === 13) {
e.preventDefault();
page = parseInt(this.value) - 1;
if (page >= 0 && page < pageInfo.pages) {
dt.table().page(page).draw('page');
} else {
updateCurrentPage(dt); // Always update to replace bad values
}
return false;
}
return true;
});
}
/**
* Handle page navigation when first button is selected
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function handleFirstPage (dt) {
var ctx = dt.settings()[0];
if (ctx._pfPagination.firstPage === undefined || ctx._pfPagination.firstPage.length === 0) {
return;
}
$(ctx._pfPagination.firstPage).closest('li').on("click", function (e) {
dt.table().page('first').draw('page');
});
}
/**
* Handle page navigation when last button is selected
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function handleLastPage (dt) {
var ctx = dt.settings()[0];
if (ctx._pfPagination.lastPage === undefined || ctx._pfPagination.lastPage.length === 0) {
return;
}
$(ctx._pfPagination.lastPage).closest('li').on("click", function (e) {
dt.table().page('last').draw('page');
});
}
/**
* Handle page navigation when next button is selected
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function handleNextPage (dt) {
var ctx = dt.settings()[0];
if (ctx._pfPagination.nextPage === undefined || ctx._pfPagination.nextPage.length === 0) {
return;
}
$(ctx._pfPagination.nextPage).closest('a').on("click", function (e) {
dt.table().page('next').draw('page');
});
}
/**
* Handle page size when selected
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function handlePageSize (dt) {
var ctx = dt.settings()[0];
if (ctx._pfPagination.pageSize === undefined || ctx._pfPagination.pageSize.length === 0) {
return;
}
ctx._pfPagination.pageSize.on("change", function (e) {
ctx._pfPagination.currentPageSize = parseInt(this.value);
dt.table().page.len(ctx._pfPagination.currentPageSize).draw('page');
});
}
/**
* Handle page navigation when previous button is selected
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function handlePreviousPage (dt) {
var ctx = dt.settings()[0];
if (ctx._pfPagination.previousPage === undefined || ctx._pfPagination.previousPage.length === 0) {
return;
}
$(ctx._pfPagination.previousPage).closest('a').on("click", function (e) {
dt.table().page('previous').draw('page');
});
}
/**
* Update current page
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function updateCurrentPage (dt) {
var ctx = dt.settings()[0];
var pageInfo = dt.table().page.info();
var page = (pageInfo.recordsDisplay === 0) ? 0 : pageInfo.page + 1;
if (ctx._pfPagination.currentPage === undefined || ctx._pfPagination.currentPage.length === 0) {
return;
}
// Disable if pagination is not available due to filtering
if (pageInfo.recordsDisplay > pageInfo.length) {
$(ctx._pfPagination.currentPage).prop("disabled", false);
} else {
$(ctx._pfPagination.currentPage).prop("disabled", true);
}
// Set current page value
$(ctx._pfPagination.currentPage).val(page);
}
/**
* Update back navigation actions
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function updateBackActions (dt) {
var ctx = dt.settings()[0];
var pageInfo = dt.table().page.info();
if (pageInfo.page === 0) {
$("li", ctx._pfPagination.backActions).each(function () {
$(this).addClass("disabled");
});
} else {
$("li", ctx._pfPagination.backActions).each(function () {
$(this).removeClass("disabled");
});
}
}
/**
* Update current items
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function updateCurrentItems (dt) {
var ctx = dt.settings()[0];
var pageInfo = dt.table().page.info();
var start = (pageInfo.recordsDisplay === 0) ? 0 : pageInfo.start + 1;
ctx._pfPagination.currentItems.html(start + "-" + pageInfo.end);
}
/**
* Update forward navigation actions
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function updateForwardActions (dt) {
var ctx = dt.settings()[0];
var pageInfo = dt.table().page.info();
if (pageInfo.recordsDisplay === 0 || pageInfo.page === pageInfo.pages - 1) {
$("li", ctx._pfPagination.forwardActions).each(function () {
$(this).addClass("disabled");
});
} else {
$("li", ctx._pfPagination.forwardActions).each(function () {
$(this).removeClass("disabled");
});
}
}
/**
* Update total items
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function updateTotalItems (dt) {
var ctx = dt.settings()[0];
var pageInfo = dt.table().page.info();
ctx._pfPagination.totalItems.html(pageInfo.recordsDisplay);
}
/**
* Update total pages
*
* @param {DataTable.Api} dt DataTable
* @private
*/
function updateTotalPages (dt) {
var ctx = dt.settings()[0];
var pageInfo = dt.table().page.info();
ctx._pfPagination.totalPages.html(pageInfo.pages);
}
// DataTables API
/**
* Navigate to next page
*
* Example: dt.table().pfPagination.next();
*/
DataTable.Api.register("pfPagination.next()", function () {
return this.iterator("table", function (ctx) {
handleNextPage(new DataTable.Api(ctx));
});
});
/**
* Navigate to previous page
*
* Example: dt.table().pfPagination.previous();
*/
DataTable.Api.register("pfPagination.previous()", function () {
return this.iterator("table", function (ctx) {
handlePreviousPage(new DataTable.Api(ctx));
});
});
// DataTables creation
$(document).on("init.dt", function (e, ctx, json) {
if (e.namespace !== "dt") {
return;
}
DataTable.pfPagination.init(new DataTable.Api(ctx));
});
return DataTable.pfPagination;
}));