You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
4.7 KiB
145 lines
4.7 KiB
7 years ago
|
<!doctype html>
|
||
|
<head>
|
||
|
<style>
|
||
|
body {
|
||
|
font-family: 'Helvetica', sans-serif;
|
||
|
}
|
||
|
</style>
|
||
|
</head>
|
||
|
<body>
|
||
|
<h1>People</h1>
|
||
|
<table class="js-table">
|
||
|
<tr class="js-table-header">
|
||
|
<th data-field="name">Name</th>
|
||
|
<th data-field="age">Age</th>
|
||
|
<th data-field="email">Email</th>
|
||
|
</tr>
|
||
|
<tbody class="js-table-body">
|
||
|
</tbody>
|
||
|
</table>
|
||
|
<button class="js-page-button button-prev" data-type="prev">Prev</button>
|
||
|
Page <span class="js-current-page"></span> / <span class="js-total-page"></span>
|
||
|
<button class="js-page-button button-next" data-type="next">Next</button>
|
||
|
|
||
|
<script type="text/javascript" src="data.js"></script>
|
||
|
<script>
|
||
|
(() => {
|
||
|
function init() {
|
||
|
const DOM = {
|
||
|
$pageButtons: document.querySelectorAll('.js-page-button'),
|
||
|
$prevButton: document.querySelector('.js-page-button.button-prev'),
|
||
|
$nextButton: document.querySelector('.js-page-button.button-next'),
|
||
|
$tableHeader: document.querySelector('.js-table-header'),
|
||
|
$tableBody: document.querySelector('.js-table-body'),
|
||
|
$currentPage: document.querySelector('.js-current-page'),
|
||
|
$totalPages: document.querySelector('.js-total-page'),
|
||
|
};
|
||
|
|
||
|
const PAGE_SIZE = 10;
|
||
|
function initialState() {
|
||
|
return {
|
||
|
currentPage: 0,
|
||
|
totalPages: 0,
|
||
|
sortField: 'name',
|
||
|
sortOrder: 'asc',
|
||
|
data,
|
||
|
};
|
||
|
}
|
||
|
let state = initialState();
|
||
|
state.totalPages = Math.ceil(state.data.length / PAGE_SIZE);
|
||
|
|
||
|
function navigatePages(type) {
|
||
|
let newCurrentPage = state.currentPage + (type === 'prev' ? -1 : 1);
|
||
|
newCurrentPage = Math.max(0, newCurrentPage);
|
||
|
newCurrentPage = Math.min(newCurrentPage, state.totalPages - 1);
|
||
|
state.currentPage = newCurrentPage;
|
||
|
}
|
||
|
|
||
|
function setSortField(field) {
|
||
|
state.currentPage = 0;
|
||
|
if (state.sortField !== field) {
|
||
|
state.sortField = field;
|
||
|
state.sortOrder = 'asc';
|
||
|
} else {
|
||
|
state.sortOrder = state.sortOrder === 'asc' ? 'desc' : 'asc';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function attachEventListeners() {
|
||
|
// Pagination.
|
||
|
DOM.$pageButtons.forEach(el => {
|
||
|
el.addEventListener('click', function () {
|
||
|
navigatePages(this.getAttribute('data-type'));
|
||
|
render();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Sorting.
|
||
|
DOM.$tableHeader.addEventListener('click', function (event) {
|
||
|
const el = event.target;
|
||
|
const field = el.getAttribute('data-field');
|
||
|
if (el.tagName !== 'TH' || !field) {
|
||
|
return;
|
||
|
}
|
||
|
setSortField(field);
|
||
|
render();
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function render() {
|
||
|
DOM.$tableBody.innerHTML = '';
|
||
|
|
||
|
// Sort data.
|
||
|
const sortField = state.sortField;
|
||
|
state.data.sort((a, b) => {
|
||
|
switch (sortField) {
|
||
|
case 'name':
|
||
|
case 'email':
|
||
|
return a[sortField] > b[sortField] ? 1 : -1;
|
||
|
case 'age':
|
||
|
return a[sortField] - b[sortField];
|
||
|
}
|
||
|
});
|
||
|
if (state.sortOrder === 'desc') {
|
||
|
state.data.reverse();
|
||
|
}
|
||
|
|
||
|
// Create table rows.
|
||
|
const pageData = state.data.slice(state.currentPage * PAGE_SIZE, state.currentPage * PAGE_SIZE + PAGE_SIZE);
|
||
|
const $tableRowsFragment = document.createDocumentFragment();
|
||
|
pageData.forEach(person => {
|
||
|
const $tableRow = document.createElement('tr');
|
||
|
['name', 'age', 'email'].forEach(field => {
|
||
|
const $tableCell = document.createElement('td');
|
||
|
$tableCell.textContent = person[field];
|
||
|
$tableRow.appendChild($tableCell);
|
||
|
});
|
||
|
$tableRowsFragment.appendChild($tableRow);
|
||
|
});
|
||
|
DOM.$tableBody.appendChild($tableRowsFragment);
|
||
|
|
||
|
// Pagination buttons disabled states.
|
||
|
DOM.$currentPage.textContent = state.currentPage + 1;
|
||
|
DOM.$totalPages.textContent = state.totalPages;
|
||
|
if (state.currentPage === 0) {
|
||
|
DOM.$prevButton.setAttribute('disabled', true);
|
||
|
} else {
|
||
|
DOM.$prevButton.removeAttribute('disabled');
|
||
|
}
|
||
|
if (state.currentPage === state.totalPages - 1) {
|
||
|
DOM.$nextButton.setAttribute('disabled', true);
|
||
|
} else {
|
||
|
DOM.$nextButton.removeAttribute('disabled');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
render();
|
||
|
attachEventListeners();
|
||
|
}
|
||
|
|
||
|
document.addEventListener('DOMContentLoaded', init);
|
||
|
})();
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|