| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- class TableHeader {
- constructor(columns) {
- this.columns = columns;
- }
- render() {
- const tr = document.createElement('tr');
- const colgroup = document.createElement('colgroup');
- this.columns.forEach((column) => {
- const th = document.createElement('th');
- const col = document.createElement('col');
- th.setAttribute('data-column', column.column);
- col.setAttribute('data-column', column.column);
- th.innerHTML = column.label;
- tr.appendChild(th);
- colgroup.appendChild(col);
- });
- const thead = document.createElement('thead');
- thead.appendChild(tr);
- return {colgroup : colgroup, thead : thead };
- }
- }
- class ActionSet {
- arrowDown = '<i class="fa fa-arrow-down" aria-hidden="true"></i>';
- constructor(actions, element = 'button', value = null) {
- this.actions = actions;
- this.element = element;
- this.value = value;
- }
- render() {
- if (this.element == 'button') {
- return this.renderButton();
- }
- if (this.element == 'span') {
- return this.renderSpan();
- }
- }
- renderButton() {
- this.actionButton = document.createElement('a');
- this.actionButton.classList.add('btn', 'btn-outline-secondary');
- this.actionButton.innerHTML = `<i class="fa fa-${this.actions[0].icon}" aria-hidden="true"></i> ${this.actions[0].label}`;
- this.actionButton.href = this.actions[0].route.replace('{{id}}', this.value);
- if (this.actions.length == 1) {
- return { 'button': this.actionButton, 'toggle': null, 'list': null };
- }
- this.actionToggle = document.createElement('button');
- this.actionToggle.classList.add('btn', 'btn-outline-secondary', 'dropdown-toggle-split');
- this.actionToggle.innerHTML = this.arrowDown;
- this.actionToggle.setAttribute('data-bs-toggle', 'dropdown');
- this.actionList = document.createElement('ul');
- this.actionList.classList.add('dropdown-menu');
- this.actions.forEach((action) => {
- const actionHolder = document.createElement('li');
- const actionLink = document.createElement('a');
- actionLink.classList.add('dropdown-item');
- actionLink.href = action.route.replace('{{id}}', this.value);
- actionLink.innerHTML = `<i class="fa fa-${action.icon}" aria-hidden="true"></i> ${action.label}`;
- actionHolder.appendChild(actionLink);
- this.actionList.appendChild(actionHolder);
- });
- return {
- 'button': this.actionButton,
- 'toggle': this.actionToggle,
- 'list': this.actionList
- };
- }
- renderSpan() {
- this.actionButton = document.createElement('div');
- this.actionToggle = document.createElement('span');
- this.actionToggle.setAttribute('data-bs-toggle', 'dropdown');
- this.actionToggle.innerHTML = `#${this.value} ${this.arrowDown}`;
- this.actionList = document.createElement('ul');
- this.actionList.classList.add('dropdown-menu');
- this.actions.forEach((action) => {
- const actionHolder = document.createElement('li');
- if(action.type == 'divider'){
- const actionDivider = document.createElement('hr');
- actionDivider.classList.add('dropdown-divider');
- this.actionList.appendChild(actionDivider);
- return;
- }
- const actionLink = document.createElement('a');
- actionLink.classList.add('dropdown-item');
- actionLink.href = action.route.replace('{{id}}', this.value);
- actionLink.innerHTML = `<i class="fa fa-${action.icon}" aria-hidden="true"></i> ${action.label}`;
- actionHolder.appendChild(actionLink);
- this.actionList.appendChild(actionHolder);
- });
- this.actionButton.appendChild(this.actionToggle);
- this.actionButton.appendChild(this.actionList);
- return this.actionButton;
- }
- renderLabel(label, icon){
- if(icon){
- return `<i class="fa fa-${icon}" aria-hidden="true"></i> ${label}`
- }
- return label
- }
- }
- class TableBody {
- constructor(rows, columns, rowActions, options) {
- this.rows = rows;
- this.columns = columns;
- this.rowActions = rowActions;
- this.options = options;
- }
- render() {
- if(this.options.selectable){
- return this.renderSelectable();
- }
- return this.renderDefaultTable();
- }
- renderDefaultTable(){
- const tbody = document.createElement('tbody');
- this.rows.forEach((row) => {
- const tr = document.createElement('tr');
- this.columns.forEach((column) => {
- const td = document.createElement('td');
- td.setAttribute('data-name', column.column);
- td.setAttribute('data-value', row[column.column]);
- if (column.column == 'id') {
- tr.setAttribute('data-value', row[column.column]);
- const idColumn = new ActionSet(this.rowActions, 'span', row[column.column]);
- td.appendChild(idColumn.render());
- } else {
- td.innerHTML = row[column.column];
- }
- tr.appendChild(td);
- });
- tbody.appendChild(tr);
- });
- return tbody;
- }
- renderSelectable(){
- const tbody = document.createElement('tbody');
- this.rows.forEach((row) => {
- const tr = document.createElement('tr');
- this.columns.forEach((column) => {
- const td = document.createElement('td');
- td.setAttribute('data-name', column.column);
- td.setAttribute('data-value', row[column.column]);
- if (column.column == 'id') {
- tr.setAttribute('data-value', row[column.column]);
- const idColumn = document.createElement('button');
- let payload = {'element': row, ...this.options.selectable.callbackParameters};
- idColumn.addEventListener('click', this.options.selectable.select.bind(null, payload));
- idColumn.classList.add('btn', 'btn-danger', 'btn-block');
- idColumn.style = "padding: 0.1rem 0.5em;";
- idColumn.innerHTML = 'Selecionar';
- td.appendChild(idColumn);
- } else {
- td.innerHTML = row[column.column];
- }
- tr.appendChild(td);
- });
- tbody.appendChild(tr);
- });
- return tbody;
- }
- }
- class Buttons {
- constructor(currentPage, totalPages, maxButtons, onPageChange, replicateChanges) {
- this.currentPage = currentPage;
- this.totalPages = totalPages;
- this.maxButtons = maxButtons;
- this.onPageChange = onPageChange;
- this.replicateChanges = replicateChanges;
- }
- render() {
- console.log('adssaddas');
- this.buttonHolder = document.createElement('div');
- this.buttonHolder.classList.add('col-12', 'col-md-9');
- this.paginationButtons = document.createElement('ul');
- this.paginationButtons.classList.add('pagination', 'pagination-sm');
- this.prevButton = document.createElement('li');
- this.prevButton.classList.add('page-link');
- this.prevButton.textContent = 'Previous';
- this.prevButton.disabled = true;
- this.prevButton.addEventListener('click', () => {
- if (this.currentPage > 1) {
- this.onPageChange(this.currentPage - 1);
- this.updateButtons(this.currentPage - 1);
- this.replicateChanges(this.currentPage);
- }
- });
- this.paginationButtons.appendChild(this.prevButton);
- this.pageButtons = Array();
- for (let i = 1; i <= this.totalPages; i++) {
- const pageButton = document.createElement('li');
- pageButton.classList.add('page-item');
- const pageButtonLink = document.createElement('a');
- pageButtonLink.classList.add('page-link');
- pageButtonLink.textContent = i;
- if (!(this.currentPage === i ||
- i > (this.currentPage + this.maxButtons / 2) ||
- i < (this.currentPage - this.maxButtons / 2))) {
- pageButton.classList.add('hidden');
- }
- if(this.currentPage === i){
- pageButton.classList.add('active');
- }
- pageButtonLink.addEventListener('click', () => {
- this.onPageChange(i);
- this.updateButtons(i);
- this.replicateChanges(this.currentPage);
- });
- pageButton.appendChild(pageButtonLink);
- this.pageButtons.push(pageButton);
- this.paginationButtons.appendChild(pageButton);
- }
- this.nextButton = document.createElement('li');
- this.nextButton.classList.add('page-link');
- this.nextButton.textContent = 'Next';
- this.nextButton.disabled = this.totalPages === 0 || this.currentPage === this.totalPages;
- this.nextButton.addEventListener('click', () => {
- if (this.currentPage < this.totalPages) {
- this.onPageChange(this.currentPage + 1);
- this.updateButtons(this.currentPage + 1);
- this.replicateChanges(this.currentPage);
- }
- });
- this.paginationButtons.appendChild(this.nextButton);
- this.buttonHolder.appendChild(this.paginationButtons);
- return this.buttonHolder;
- }
- updateButtons(page, perPage) {
- if (page) {
- this.currentPage = parseInt(page);
- }
- if (this.prevButton) {
- this.prevButton.disabled = this.currentPage === 1;
- }
- if (this.nextButton) {
- this.nextButton.disabled = this.totalPages === 0 || this.currentPage === this.totalPages;
- }
- if (this.pageButtons) {
- this.pageButtons.forEach((button, index) => {
- button.classList.remove('active');
- if (this.currentPage === index + 1 ||
- index > (this.currentPage + this.maxButtons / 2) ||
- index < (this.currentPage - this.maxButtons / 2)) {
- button.classList.add('hidden');
- }else {
- button.classList.remove('hidden');
- }
- if (index + 1 == this.currentPage) {
- button.classList.add('active');
- button.classList.remove('hidden');
- } else {
- button.removeAttribute('value');
- }
- });
- }
- }
- }
- class Label {
- constructor(actualPage, totalPages, recordsCount, totalRecords) {
- this.actualPage = actualPage;
- this.totalPages = totalPages;
- this.recordsCount = recordsCount;
- this.totalRecords = totalRecords;
- }
- render(){
- this.paginationLabel = document.createElement('div');
- this.paginationLabel.classList.add('col-12');
- this.pageLabel = document.createElement('span');
- this.pageLabel.innerText = `Page: ${this.actualPage} of ${this.totalPages} | `;
- this.recordLabel = document.createElement('span');
- this.recordLabel.innerText = `${this.recordsCount} of ${this.totalRecords} records shown`;
- this.paginationLabel.appendChild(this.pageLabel);
- this.paginationLabel.appendChild(this.recordLabel);
- return this.paginationLabel;
- }
- rerender() {
- this.pageLabel.innerText = `Page: ${this.actualPage} of ${this.totalPages} | `;
- this.recordLabel.innerText = `${this.recordsCount} of ${this.totalRecords} records shown`;
- }
- updateLabel(page, perPage, totalPages){
- this.actualPage = page;
- this.perPage = perPage;
- this.rerender();
- }
- }
- class Search {
- constructor(currentPage, totalPages, onPageChange, replicateChanges){
- this.currentPage = currentPage;
- this.totalPages = totalPages;
- this.onPageChange = onPageChange;
- this.replicateChanges = replicateChanges;
- }
- render(){
- const paginationHolder = document.createElement('div');
- paginationHolder.classList.add('col-12', 'col-md-3');
- this.paginationSearch = document.createElement('div');
- this.paginationSearch.classList.add('search', 'input-group','col-md-3', 'col-sm-12');
- this.textualNumber = document.createElement('input');
- this.textualNumber.classList.add('form-control', 'form-control-sm');
- this.textualNumber.setAttribute('type', 'number');
- this.textualNumber.setAttribute('min', 1);
- this.textualNumber.setAttribute('max', this.totalPages);
- this.textualNumber.value = this.currentPage;
- this.textualNumber.addEventListener('blur', (event) => {
- let page = event.target.value;
- if(page > this.totalPages){
- page = this.totalPages;
- this.textualNumber.value = this.totalPages;
- }
- if(page < 1){
- page = 1;
- this.textualNumber.value = page;
- }
- this.replicateChanges(page);
- this.onPageChange(page);
- });
- this.textualNumber.addEventListener('keydown', (event) => {
- if (event.key === 'Enter') {
- console.log('reberberbrte');
- }
- });
- //this.paginationSearch.appendChild(this.textualNumber);
- this.append(this.textualNumber);
- this.selectNumber = document.createElement('select');
- this.selectNumber.classList.add('form-select', 'form-select-sm');
- for(let i = 1; i < this.totalPages; i++){
- const selectOption = document.createElement('option');
- selectOption.innerText = i;
- selectOption.setAttribute('value', i);
- this.selectNumber.appendChild(selectOption);
- }
- this.selectNumber.addEventListener('change', (event) => {
- this.replicateChanges(event.target.value);
- this.onPageChange(event.target.value);
- });
- //this.paginationSearch.appendChild(this.selectNumber);
- this.append(this.selectNumber);
- const recordsPerPage = document.createElement('select');
- recordsPerPage.classList.add('form-select', 'form-select-sm');
- for(let i = 1; i < 10; i++){
- const selectOption = document.createElement('option');
- selectOption.innerText = i * 25;
- selectOption.setAttribute('value', i * 25);
- recordsPerPage.appendChild(selectOption);
- }
- recordsPerPage.addEventListener('change', (event) => {
- //console.log(event.target.value)
- //this.replicateChanges(event.target.value);
- });
- //this.paginationSearch.appendChild(recordsPerPage);
- this.append(recordsPerPage);
- paginationHolder.appendChild(this.paginationSearch);
- return paginationHolder;
- }
- updateSearch(pageNumber, perPage) {
- this.selectNumber.value = pageNumber;
- this.textualNumber.value = pageNumber;
- }
- searchChange(){
- }
- append(element){
- let container = document.createElement('div');
- container.classList.add('col-4');
- container.appendChild(element);
- this.paginationSearch.appendChild(container);
- }
- }
- class Pagination {
- constructor(onPageChange, rowCount, perPage) {
- this.currentPage = 1;
- this.maxButtons = 10;
- this.onPageChange = onPageChange;
- this.rowCount = rowCount;
- this.perPage = perPage;
- this.totalPages = Math.ceil(rowCount / perPage);
- }
- render() {
- this.paginationContainer = document.createElement('div');
- this.paginationContainer.classList.add('pagination', 'row');
- if(this.totalPages <= 1){
- return this.paginationContainer;
- }
- this.labels = new Label(this.currentPage, this.totalPages, 10, 1000);
- this.buttons = new Buttons(this.currentPage, this.totalPages, 10, this.onPageChange, (page) => {
- this.labels.updateLabel(page, this.perPage);
- this.search.updateSearch(page, this.perPage);
- });
- this.search = new Search(this.currentPage, this.totalPages, this.onPageChange, (page, size) => {
- this.labels.updateLabel(page, this.perPage);
- this.buttons.updateButtons(page, this.perPage);
- this.search.updateSearch(page, this.perPage);
- });
- this.paginationContainer.appendChild(this.labels.render());
- this.paginationContainer.appendChild(this.buttons.render());
- this.paginationContainer.appendChild(this.search.render());
- return this.paginationContainer;
- }
- changePageSize(onPageChange, rowCount, perPage) {
- this.currentPage = 1;
- this.maxButtons = 10;
- this.onPageChange = onPageChange;
- this.rowCount = rowCount;
- this.perPage = perPage;
- this.totalPages = Math.ceil(rowCount / perPage);
- return this.paginationContainer;
- }
- }
- class ListButton{
- constructor(icon, actions){
- this.icon = icon;
- this.actions = actions;
- }
- render() {
- this.actionButton = document.createElement('button');
- this.actionButton.classList.add('btn', 'btn-outline-secondary');
- this.actionButton.innerHTML = `<i class="fa fa-${this.icon}" aria-hidden="true"></i>`;
- return this.actionButton;
- }
- }
- class SearchBar {
- constructor(onSearch) {
- this.onSearch = onSearch;
- }
- render() {
- this.searchBarContainer = document.createElement('div');
- this.searchBarContainer.classList.add('search-bar');
- this.inputElement = document.createElement('input');
- this.inputElement.classList.add('form-control');
- this.inputElement.setAttribute('type', 'text');
- this.inputElement.addEventListener('keydown', (event) => {
- if (event.key === 'Enter') {
- this.searchText = this.inputElement.value;
- this.onSearch(this.searchText);
- }
- });
- this.searchBarContainer.appendChild(this.inputElement);
- return this.searchBarContainer;
- }
- getSearch(){
- return this.inputElement.value;
- }
- }
- class ToolBar {
- constructor(onSearch, actions, options) {
- this.onSearch = onSearch;
- this.actions = actions;
- this.options = options;
- }
- render() {
- this.toolbar = document.createElement('div');
- this.toolbar.classList.add('input-group', 'mb-3');
- if (typeof this.actions !== 'undefined' && typeof this.options.selectable === 'undefined' && this.actions.length > 0) {
- this.actionSet = new ActionSet(this.actions, 'button');
- let { button, toggle, list } = this.actionSet.render();
- if (button) {
- this.toolbar.appendChild(button);
- }
- if (toggle) {
- this.toolbar.appendChild(toggle);
- }
- if (list) {
- this.toolbar.append(list);
- }
- }
- this.searchBar = new SearchBar(this.onSearch);
- this.toolbar.appendChild(this.searchBar.render());
- this.toolbar.appendChild(new ListButton('th', '').render());
- return this.toolbar;
- }
- getSearch() {
- return this.searchBar.getSearch();
- }
- }
- class DataTable {
- constructor(tableElement, options = {}) {
- if (typeof tableElement === 'string') {
- this.tableElement = document.getElementById(tableElement);
- } else {
- this.tableElement = tableElement;
- }
- this.page = 1;
- this.options = options;
- this.perPage = 25;
- this.getData();
- }
- render(data) {
- const { actions, rowActions, columns, rows, total } = data;
- this.table = document.createElement('table');
- this.table.classList.add('table', 'table-responsive');
- this.searchBar = new ToolBar((searchText) => {
- this.getData(searchText);
- }, actions, this.options);
- this.pagination = new Pagination((page, perPage) => {
- this.page = page--;
- //this.perPage = perPage;
- this.getData();
- }, total, this.perPage);
- this.headerElement = new TableHeader(columns);
- const tableHeader = this.headerElement.render();
- this.table.appendChild(tableHeader.colgroup);
- this.table.appendChild(tableHeader.thead);
- this.bodyElement = new TableBody(rows, columns, rowActions, this.options);
- this.table.appendChild(this.bodyElement.render());
- // #ToDo Convert table to div
- if (this.tableElement.tagName === 'TABLE') {
- const divContainer = document.createElement('div');
- while (this.tableElement.firstChild) {
- divContainer.appendChild(this.tableElement.firstChild);
- }
- this.tableElement.parentNode.replaceChild(divContainer, this.tableElement);
- }
- this.tableElement.appendChild(this.searchBar.render());
- this.tableElement.appendChild(this.pagination.render());
- this.tableElement.appendChild(this.table);
- }
- rerender(data) {
- const { columns, rows, rowActions, total } = data;
- if (!this.table) {
- this.render(data);
- return;
- }
- const content = new TableBody(rows, columns, rowActions, this.options).render();
- this.table.querySelector('tbody').innerHTML = content.innerHTML;
- }
- async getData() {
- let requestBody = {
- 'page': this.page - 1,
- 'pageSize': this.perPage
- };
- if(this.searchBar){
- requestBody.search = this.searchBar.getSearch();
- }
- const params = new URLSearchParams(requestBody).toString();
- const response = await fetch(this.options.url + '?' + params);
- const data = await response.json();
- this.rerender(data);
- }
- }
- export { DataTable as default };
|