diff --git a/resources/app/stylesheets/app.less b/resources/app/stylesheets/app.less index f67e74e..e55a381 100644 --- a/resources/app/stylesheets/app.less +++ b/resources/app/stylesheets/app.less @@ -249,9 +249,18 @@ table { .tbl-toolbar { display: flex; + margin-top: 2rem; - .curr-page { + .row-info { flex-grow: 99; + + .rows::before { + content: " ("; + } + + .rows::after { + content: " rows)"; + } } .prev::before { @@ -262,7 +271,7 @@ table { content: " >>"; } - button { + button, input { margin-right: @element-margin; } } diff --git a/resources/public/js/scripts.js b/resources/public/js/scripts.js index e87bb86..f1bc962 100644 --- a/resources/public/js/scripts.js +++ b/resources/public/js/scripts.js @@ -49,36 +49,52 @@ document.addEventListener('DOMContentLoaded', function () { x > y ? [] : [x, ...range(x + 1, y)]; const visibleRows = page => range(page * pageSize, (page + 1) * pageSize - 1) + const tblRows = tbl => + [...tbl.tBodies[0].rows] function toggleVisibilities(tbl, ixsToShow) { - const rows = [...tbl.tBodies[0].rows] - rows.forEach(function (row, ix) { + tblRows(tbl).forEach(function (row, ix) { row.style.display = ixsToShow.includes(ix) ? 'table-row' : 'none'; }) } function setCurrPage(tbl, currPageIx) { - const elems = document.querySelectorAll('.tbl-toolbar .curr-page') + const elems = document.querySelectorAll('.tbl-toolbar .row-info') const rows = tbl.tBodies[0].rows.length const pages = Math.ceil(rows / pageSize) elems.forEach(function(elem) { - elem.innerText = (currPageIx + 1) + ' / ' + pages + ' (' + rows + ' rows)' + elem.children[0].innerText = (currPageIx + 1) + ' / ' + pages + elem.children[1].innerText = rows + }) + + tbl.setAttribute('data-page', currPageIx) + } + + function changePage(tbl, ix) { + toggleVisibilities(tbl, visibleRows(ix)) + setCurrPage(tbl, ix) + } + + function enablePagination(on) { + document.querySelectorAll('.pg-btn').forEach(function(btn) { + btn.disabled = !on + }) + document.querySelectorAll('.row-info .page').forEach(function(elem) { + elem.style.display = on ? 'inline' : 'none' }) } function prevButton(tbl) { const btn = document.createElement('button') btn.classList.add('prev') + btn.classList.add('pg-btn') btn.innerText = 'Prev' btn.addEventListener('click', function () { const page = tbl.getAttribute('data-page') * 1 if (page > 0) { - const newPageIx = page - 1 - tbl.setAttribute('data-page', newPageIx) - toggleVisibilities(tbl, visibleRows(newPageIx)) - setCurrPage(tbl, newPageIx) + changePage(tbl, page - 1) } }) return btn; @@ -87,32 +103,76 @@ document.addEventListener('DOMContentLoaded', function () { function nextButton(tbl) { const btn = document.createElement('button') btn.classList.add('next') + btn.classList.add('pg-btn') btn.innerText = 'Next' btn.addEventListener('click', function () { const page = tbl.getAttribute('data-page') * 1 const lastRowNum = (page + 1) * pageSize - if (lastRowNum < tbl.tBodies[0].rows.length) { - const newPageIx = page + 1 - tbl.setAttribute('data-page', newPageIx) - toggleVisibilities(tbl, visibleRows(newPageIx)) - setCurrPage(tbl, newPageIx) + if (lastRowNum < tblRows(tbl).length) { + changePage(tbl, page + 1) } }) return btn } function currPage() { - const span = document.createElement('span') - span.classList.add('curr-page') - span.innerText = 1 - return span + const rowInfo = document.createElement('span') + rowInfo.classList.add('row-info') + const rows = document.createElement('span') + rows.classList.add('rows') + rows.innerText = 0 + const page = document.createElement('span') + page.classList.add('page') + page.innerText = 1 + + rowInfo.insertAdjacentElement('afterbegin', rows) + rowInfo.insertAdjacentElement('afterbegin', page) + + return rowInfo + } + + function searchBox(tbl) { + const input = document.createElement('input') + input.classList.add('search') + input.type = 'search' + input.placeholder = 'search...' + + const contents = tblRows(tbl).map(function(row) { + return Array.from(row.cells).reduce(function(carr, cell) { + return carr + cell.innerText.toLocaleLowerCase() + }, "") + }) + + input.addEventListener('input', function(evt, a) { + const term = evt.target.value.toLocaleLowerCase() + if (term.length === 0) { + changePage(tbl, 0) + enablePagination(true) + return + } + + enablePagination(false) + + const ixs = [] + contents.forEach(function(rowContent, ix) { + if (rowContent.match(term)) { + ixs.push(ix) + } + }) + document.querySelectorAll('.row-info .rows').forEach(function(elem) { + elem.innerText = ixs.length + }) + toggleVisibilities(tbl, ixs) + }) + return input } function addToolbar(tbl) { const toolbarTop = document.createElement('section') toolbarTop.classList.add('tbl-toolbar') toolbarTop.insertAdjacentElement('beforeend', currPage()) + toolbarTop.insertAdjacentElement('beforeend', searchBox(tbl)) toolbarTop.insertAdjacentElement('beforeend', prevButton(tbl)) toolbarTop.insertAdjacentElement('beforeend', nextButton(tbl)) @@ -122,8 +182,8 @@ document.addEventListener('DOMContentLoaded', function () { toolbarBottom.insertAdjacentElement('beforeend', prevButton(tbl)) toolbarBottom.insertAdjacentElement('beforeend', nextButton(tbl)) - tbl.insertAdjacentElement('afterend', toolbarTop) - tbl.insertAdjacentElement('beforebegin', toolbarBottom) + tbl.insertAdjacentElement('afterend', toolbarBottom) + tbl.insertAdjacentElement('beforebegin', toolbarTop) } document.querySelectorAll('table').forEach(function (tbl) {