diff --git a/conf/default.php b/conf/default.php
index e3899d0..16bcb21 100644
--- a/conf/default.php
+++ b/conf/default.php
@@ -16,3 +16,7 @@
$conf['sort'] = 0;
$conf['rsort'] = 0;
$conf['sortby'] = '';
+$conf['pagination'] = 0;
+$conf['rowsperpage'] = 10;
+$conf['buttonsposition'] = 'bottom';
+$conf['buttonswindow'] = 3;
\ No newline at end of file
diff --git a/conf/metadata.php b/conf/metadata.php
index 6203011..f9eb705 100644
--- a/conf/metadata.php
+++ b/conf/metadata.php
@@ -21,3 +21,7 @@
$meta['sort'] = array('onoff');
$meta['rsort'] = array('onoff');
$meta['sortby'] = array('string', '_pattern' => '/^([^&=]*)$/');
+$meta['pagination'] = array('onoff');
+$meta['rowsperpage'] = array('string', '_pattern' => '/^\d+$/');
+$meta['buttonsposition'] = array('multichoice', '_choices' => array('top', 'bottom'));
+$meta['buttonswindow'] = array('string', '_pattern' => '/^-?\d+$/');
\ No newline at end of file
diff --git a/helper.php b/helper.php
index d7105cd..4e19c7f 100644
--- a/helper.php
+++ b/helper.php
@@ -110,6 +110,11 @@ public function __construct()
if($this->sortKey) {
$this->sort = true;
}
+ //Pagination flags
+ $this->pagination = $this->getConf('pagination'); //on-off
+ $this->rowsPerPage = $this->getConf('rowsperpage'); //string
+ $this->buttonsPosition = $this->getConf('buttonsposition'); //string (top, bottom)
+ $this->buttonsWindow = $this->getConf('buttonswindow'); //string
$this->plugins = [
'discussion' => ['comments'],
@@ -291,6 +296,8 @@ public function setFlags($flags)
case 'showdiff':
$flag = 'diff';
break;
+ case 'pagination':
+ $this->pagination = true;
}
// it is not required to set the sort flag, rsort flag will reverse.
@@ -315,6 +322,27 @@ public function setFlags($flags)
$value = true;
}
+ /**Pagination params. Rows per page */
+ if (substr($flag, 0, 12) == 'rowsperpage=') {
+ $this->rowsPerPage = (int) substr($flag, 12);
+ $this->pagination = true;
+ }
+
+ /**Pagination params. Navigation buttons position (top/bottom) */
+ if (substr($flag, 0, 16) == 'buttonsposition=') {
+ $this->buttonsPosition = substr($flag, 16);
+ if ($this->buttonsPosition != 'top' && $this->buttonsPosition != 'bottom') {
+ $this->buttonsPosition = 'bottom';
+ }
+ $this->pagination = true;
+ }
+
+ //**Pagination params. Regulate the max number of navigation show at the same time. Min possible value 2. Use -1 to disable*/
+ if (substr($flag, 0, 14) == 'buttonswindow=') {
+ $this->buttonsWindow = (int) substr($flag, 14);
+ $this->pagination = true;
+ }
+
if (isset($this->column[$flag]) && $flag !== 'page') {
$this->column[$flag] = $value;
}
@@ -354,7 +382,12 @@ public function startList($callerClass = null)
if ($callerClass) {
$class .= ' ' . $callerClass;
}
- $this->doc = '
';
+ $this->doc = '';
} else {
// Simplelist is enabled; Skip header and firsthl
$this->showheader = false;
@@ -549,6 +582,11 @@ protected function renderPageRow($page)
$class .= $this->page['class'];
}
+ //If pagination is in use, all the rows start hidden (for fix 'flickering' onload)
+ if ($this->pagination) {
+ $class .= 'hidden ';
+ }
+
if (!empty($class)) {
$class = ' class="' . $class . '"';
}
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..5da1ed9
--- /dev/null
+++ b/script.js
@@ -0,0 +1,122 @@
+document.addEventListener('DOMContentLoaded', function () {
+ //Get all tables with pagination class included
+ const tables = document.querySelectorAll('.table-with-pagination');
+
+ //Foreach table found in the wiki page
+ tables.forEach(table => {
+ const tableState = {
+ tableRef: table,
+ rowsRef: Array.from(table.getElementsByTagName('tr')).slice(1),
+ currentPage: 0,
+ rowsPerPage: Number(table.getAttribute('data-rowsperpage')) || 10, //Number of rows per page
+ buttonsPosition: table.getAttribute('data-buttonsposition') || 'bottom', //Position of buttons navigator
+ buttonsWindow: Number(table.getAttribute('data-buttonwindow')) || 3, //Number of max buttons in screen = buttonsWindow * 2 + 1 //Use -1 to disable
+ };
+ tableState.totalPages = Math.ceil(tableState.rowsRef.length / tableState.rowsPerPage);
+
+ createPageButtons(tableState); // Create the navigation buttons initially
+ showPage(tableState); // Set initial page state
+ });
+
+ function createPageButtons(tableState) {
+ const { totalPages, buttonsPosition, tableRef } = tableState;
+ const paginationTdContainer = document.createElement('td');
+
+ //Create buttons nodes
+ const buttonsRef = [];
+ for (let i = 0; i < totalPages; i++) {
+ buttonsRef.push(document.createElement('button'));
+ }
+
+ //Set style and evento for each button
+ for (let i = 0; i < totalPages; i++) {
+ buttonsRef[i].textContent = i + 1;
+ buttonsRef[i].classList.add('pagination-button');
+ //Event on click button
+ buttonsRef[i].addEventListener('click', () => {
+ tableState.currentPage = i;
+ showPage(tableState); //Set page content
+ setButtons(buttonsRef, tableState); //Set buttons state
+ });
+ paginationTdContainer.appendChild(buttonsRef[i]);
+ }
+
+ setButtons(buttonsRef, tableState); //Set buttons state
+
+ paginationTdContainer.classList.add('pagination-buttons-container');
+ paginationTdContainer.setAttribute('colspan', '99'); //to use all the width of the table
+ const paginationTrContainer = document.createElement('tr');
+ paginationTrContainer.appendChild(paginationTdContainer);
+
+ // Append the navigation buttons in the table
+ if (buttonsPosition == 'top') {
+ tableRef.insertBefore(paginationTrContainer, tableRef.firstChild);
+ } else {
+ tableRef.appendChild(paginationTrContainer);
+ }
+ }
+
+ //Set de buttons style and others elements of the navigation buttons
+ function setButtons(buttonsRef, tableState) {
+ const { currentPage, totalPages, buttonsWindow } = tableState;
+
+ for (let i = 0; i < totalPages; i++) {
+
+ //Set active class to the current page button
+ buttonsRef[i].classList.toggle('active', i == currentPage);
+
+ //Hidden extra buttons if buttonsWindow if set. Min value for buttonsWindow is 2.
+ if (buttonsWindow >= 2 && i >= 1 && i < totalPages - 1) {
+ const leftMargin = currentPage - buttonsWindow;
+ const rightMargin = currentPage + buttonsWindow;
+ const leftCompensation = leftMargin < 0 ? leftMargin : 0;
+ const rightCompensation = rightMargin - totalPages >= 0 ? rightMargin - totalPages + 1 : 0;
+
+ //Hide or reveal buttons base in current page
+ if ( leftMargin - rightCompensation < i && rightMargin - leftCompensation > i) {
+ buttonsRef[i].classList.toggle('hidden', false);
+ } else {
+ buttonsRef[i].classList.toggle('hidden', true);
+ }
+
+ //Hide or reveal space dots to limit the total number of buttons in screen
+ if ((currentPage - rightCompensation == i + buttonsWindow - 1) && i >= buttonsWindow - 1) {
+ deleteSpaceDots('left');
+ drawSpaceDots(buttonsRef, i, 'left')
+ } else if (currentPage - 1 < buttonsWindow) {
+ deleteSpaceDots('left');
+ }
+ if ((currentPage - leftCompensation + buttonsWindow - 1 == i) && i <= totalPages - buttonsWindow) {
+ deleteSpaceDots('right');
+ drawSpaceDots(buttonsRef, i, 'right')
+ } else if (currentPage + 1 >= totalPages - buttonsWindow) {
+ deleteSpaceDots('right');
+ }
+ }
+ }
+ }
+
+ //Draw space dots after or before a certain button
+ function drawSpaceDots(buttonsRef, i, side) {
+ const dotsRef = document.createElement('a');
+ dotsRef.textContent = " ..... ";
+ dotsRef.id = side == 'right' ? 'pagination_right_dots' : 'pagination_left_dots';
+ buttonsRef[i].insertAdjacentElement(side == 'right' ? 'afterend' : 'beforebegin', dotsRef);
+ }
+
+ //Delete left or right space dots
+ function deleteSpaceDots(side) {
+ const spaceDotsRef = document.getElementById( side == 'right' ? 'pagination_right_dots' : 'pagination_left_dots');
+ if (spaceDotsRef) spaceDotsRef.parentNode.removeChild(spaceDotsRef);
+ }
+
+ //Show and hide elements (rows) of a page
+ function showPage(tableState) {
+ const { currentPage, rowsPerPage, rowsRef } = tableState;
+ const startIndex = currentPage * rowsPerPage;
+ const endIndex = startIndex + rowsPerPage;
+ rowsRef.forEach((rowRef, index) => {
+ rowRef.classList.toggle('hidden', index < startIndex || index >= endIndex);
+ });
+ }
+});
\ No newline at end of file
diff --git a/style.css b/style.css
index 7cb7679..1e821bd 100644
--- a/style.css
+++ b/style.css
@@ -55,3 +55,12 @@ div.dokuwiki table.pagelist td.page,
div.dokuwiki table.ul td.page {
font-size: 100%;
}
+
+div.dokuwiki button.pagination-button.active {
+ font-weight: bold;
+}
+
+td.pagination-buttons-container {
+ text-align: center;
+ background: none !important;
+}
\ No newline at end of file