first commit
This commit is contained in:
parent
ca0aedfe2b
commit
bed65410de
|
|
@ -0,0 +1,552 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Bootstrap Example</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/remixicon@4.0.1/fonts/remixicon.min.css" />
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container mt-3">
|
||||||
|
<h2>Striped Rows</h2>
|
||||||
|
<p>The .table-striped class adds zebra-stripes to a table:</p>
|
||||||
|
|
||||||
|
<!-- Filter -->
|
||||||
|
<div class="card mb-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Filter</h5>
|
||||||
|
<form id="filterForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email:</label>
|
||||||
|
<input type="text" class="form-control" id="email" name="email">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="code">Code:</label>
|
||||||
|
<input type="text" class="form-control" id="code" name="code">
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-primary mt-2" onclick="getFormValues()">Filter</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Filter -->
|
||||||
|
|
||||||
|
<!-- Search -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="search_input">Search:</label>
|
||||||
|
<input id="search_input" type="text" class="form-control">
|
||||||
|
</div>
|
||||||
|
<!-- Search -->
|
||||||
|
|
||||||
|
<!-- Table -->
|
||||||
|
<table class="table table-striped table-bordered table-hover" id="bookTabe">
|
||||||
|
</table>
|
||||||
|
<!-- Table -->
|
||||||
|
|
||||||
|
<!-- Pagination -->
|
||||||
|
<div id="pagination"></div>
|
||||||
|
<!-- Pagination -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
class TableData {
|
||||||
|
config = {
|
||||||
|
order: null, // example order = { column : "name", orderBy : "ASC" }
|
||||||
|
filter: null, // example filter = { name : "huynh" }
|
||||||
|
heads: [], // config headers of table
|
||||||
|
page: 1,
|
||||||
|
per_page: 15,
|
||||||
|
data: {}, // la data ben laravel tra ve
|
||||||
|
rowRender: (colName, colValue, row) => {
|
||||||
|
return colValue;
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
pagination: false,
|
||||||
|
detail: false
|
||||||
|
},
|
||||||
|
sort: {
|
||||||
|
enable: false,
|
||||||
|
listColumn: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(tableId, config) {
|
||||||
|
this.config = {
|
||||||
|
...this.config,
|
||||||
|
...config
|
||||||
|
};
|
||||||
|
this.tableId = tableId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update configuration, display data after sorting, listen again for appropriate icon
|
||||||
|
sorted(column) {
|
||||||
|
if (
|
||||||
|
this.config.order !== null &&
|
||||||
|
Object.values(this.config.order)[0] === "asc"
|
||||||
|
) {
|
||||||
|
this.config.order = null;
|
||||||
|
this.updateConfig(this.config);
|
||||||
|
} else {
|
||||||
|
if (this.config.order === null) {
|
||||||
|
this.config.order = {
|
||||||
|
[`order_by_${column}`]: "desc"
|
||||||
|
};
|
||||||
|
this.updateConfig(this.config);
|
||||||
|
this.attachSortEventListeners(".ri-arrow-down-s-fill");
|
||||||
|
} else {
|
||||||
|
this.config.order = {
|
||||||
|
[`order_by_${column}`]: "asc"
|
||||||
|
};
|
||||||
|
this.updateConfig(this.config);
|
||||||
|
this.attachSortEventListeners(".ri-arrow-up-s-fill");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen events of sort buttons
|
||||||
|
attachSortEventListeners(className) {
|
||||||
|
const icons = document.querySelectorAll(className);
|
||||||
|
icons.forEach((icon) => {
|
||||||
|
icon.addEventListener("click", (event) => {
|
||||||
|
const columnName = event.target.dataset.columnName;
|
||||||
|
this.sorted(columnName, icon);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the sort icon again when the sort button is clicked
|
||||||
|
renderIconSort(column) {
|
||||||
|
if (this.config.order === null) {
|
||||||
|
return `<i class="ri-expand-up-down-fill" style="cursor: pointer;" data-column-name="${column}"></i>`;
|
||||||
|
} else {
|
||||||
|
var orderKey = Object.keys(this.config.order)[0];
|
||||||
|
var orderValue = Object.values(this.config.order)[0];
|
||||||
|
if (orderKey === `order_by_${column}`) {
|
||||||
|
if (orderValue === "asc") {
|
||||||
|
return `<i class="ri-arrow-up-s-fill" style="cursor: pointer;" data-column-name="${column}"></i>`;
|
||||||
|
} else {
|
||||||
|
return `<i class="ri-arrow-down-s-fill" style="cursor: pointer;" data-column-name="${column}"></i>`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen events of per page
|
||||||
|
attachPerPageEventListeners() {
|
||||||
|
const elements = document.querySelectorAll(`${this.tableId} #perpage div #perPageSelect`);
|
||||||
|
elements[0].addEventListener("change", (event) => {
|
||||||
|
const value = event.target.value;
|
||||||
|
this.config.per_page = value
|
||||||
|
this.render()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen events of pagination buttons
|
||||||
|
attachPaginationEventListeners() {
|
||||||
|
const pages = document.querySelectorAll(".page_number");
|
||||||
|
pages.forEach((page) => {
|
||||||
|
page.addEventListener("click", (event) => {
|
||||||
|
const pageNumber = event.target.dataset.columnName;
|
||||||
|
if (pageNumber !== "null" && pageNumber !== this.config.page) {
|
||||||
|
this.config.page = pageNumber;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen events of action buttons
|
||||||
|
attachActionEventListeners(className) {
|
||||||
|
const buttons = document.querySelectorAll(className);
|
||||||
|
buttons.forEach((btn) => {
|
||||||
|
btn.addEventListener("click", (event) => {
|
||||||
|
const rowId = event.target.dataset.rowId;
|
||||||
|
if (rowId) {
|
||||||
|
if (className === ".btn_edit") {
|
||||||
|
this.rowEdit(rowId);
|
||||||
|
}
|
||||||
|
if (className === ".btn_done") {
|
||||||
|
this.rowEditDone(rowId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render headers in table
|
||||||
|
renderHeads() {
|
||||||
|
var ths = "";
|
||||||
|
this.config.heads.map((head) => {
|
||||||
|
if (head.name === "__actions") {
|
||||||
|
ths += `<th scope="col">
|
||||||
|
<div class="d-flex justify-content-center align-items-center">
|
||||||
|
${head.value}
|
||||||
|
</div>
|
||||||
|
</th>`;
|
||||||
|
} else {
|
||||||
|
if (head.hasOwnProperty("render")) {
|
||||||
|
ths += `<th scope="col">
|
||||||
|
<div class="d-flex justify-content-center align-items-center">
|
||||||
|
${head.render(head)}
|
||||||
|
${this.config.sort.enable &&
|
||||||
|
this.config.sort.listColumn &&
|
||||||
|
this.config.sort.listColumn.includes(head.name) ?
|
||||||
|
this.renderIconSort(head.name) : ''}
|
||||||
|
</div>
|
||||||
|
</th>`;
|
||||||
|
} else {
|
||||||
|
ths += `<th scope="col">
|
||||||
|
<div class="d-flex justify-content-center align-items-center">
|
||||||
|
${head.value}
|
||||||
|
${this.config.sort.enable &&
|
||||||
|
this.config.sort.listColumn &&
|
||||||
|
this.config.sort.listColumn.includes(head.name) ?
|
||||||
|
this.renderIconSort(head.name) : ''}
|
||||||
|
</div>
|
||||||
|
</th>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var html = `<thead class="table-light text-center align-middle">
|
||||||
|
<tr>
|
||||||
|
${ths}
|
||||||
|
<tr>
|
||||||
|
</thead>`;
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render rows in table
|
||||||
|
renderRows(data) {
|
||||||
|
let html = "<tbody>";
|
||||||
|
data.data.map((row, index) => {
|
||||||
|
html += `<tr id='row_${row.id}'>`;
|
||||||
|
this.config.heads.map((col) => {
|
||||||
|
html += `<td ${col.name!=="__actions"?`title="${row[col.name]}"`:""}>${this.config.rowRender(
|
||||||
|
col.name,
|
||||||
|
row[col.name],
|
||||||
|
row
|
||||||
|
)}</td>`;
|
||||||
|
});
|
||||||
|
html += "</tr>";
|
||||||
|
});
|
||||||
|
html += "</tbody>";
|
||||||
|
// Initial pagination use 'data.links'
|
||||||
|
let htmlPagination = `<ul class="pagination">`;
|
||||||
|
data.links.map((link) => {
|
||||||
|
htmlPagination += `
|
||||||
|
<li class="page-item ${link.active ? "active" : ""}">
|
||||||
|
<span class="page_number page-link" data-column-name="${
|
||||||
|
link.url !== null ? link.url.split("=")[1] : null
|
||||||
|
}" style="cursor: pointer;">${link.label
|
||||||
|
.replace(" Previous", "")
|
||||||
|
.replace("Next ", "")}</span>
|
||||||
|
</li>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
htmlPagination += "</ul>";
|
||||||
|
html += `<caption>
|
||||||
|
<div class="d-flex align-items-center" style="justify-content: space-between;">`
|
||||||
|
html += `<div id="perpage">
|
||||||
|
<!-- Per page -->
|
||||||
|
<div class="d-flex align-items-center form-inline">
|
||||||
|
<label class="mr-2">Show</label>
|
||||||
|
<select id="perPageSelect" class="form-select form-select-sm me-2" style="font-size: 0.8rem; margin: 0 5px; cursor: pointer;">
|
||||||
|
<option value="15" ${this.config.per_page.toString() === "15" ? 'selected' : ''}>15</option>
|
||||||
|
<option value="30" ${this.config.per_page.toString() === "30" ? 'selected' : ''}>30</option>
|
||||||
|
<option value="50" ${this.config.per_page.toString() === "50" ? 'selected' : ''}>50</option>
|
||||||
|
<option value="80" ${this.config.per_page.toString() === "80" ? 'selected' : ''}>80</option>
|
||||||
|
<option value="100" ${this.config.per_page.toString() === "100" ? 'selected' : ''}>100</option>
|
||||||
|
</select>
|
||||||
|
<label style="width: auto;">entries</label>
|
||||||
|
</div>
|
||||||
|
<!-- Per page -->
|
||||||
|
</div>`
|
||||||
|
if (this.config.footer.detail) {
|
||||||
|
html += `<div id="footer_detail">Show ${data.from} to ${data.to} of ${data.total} entries</div>`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.config.footer.pagination) {
|
||||||
|
html += `<div id="footer_pagination">${htmlPagination}</div>`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
html += `</div></caption>`
|
||||||
|
$(this.tableId).append(html);
|
||||||
|
this.attachPaginationEventListeners();
|
||||||
|
this.attachPerPageEventListeners()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render table
|
||||||
|
async render() {
|
||||||
|
let data;
|
||||||
|
let params = {
|
||||||
|
per_page: this.config.per_page,
|
||||||
|
page: this.config.page,
|
||||||
|
};
|
||||||
|
// Clear html
|
||||||
|
$(this.tableId).html("");
|
||||||
|
// Initial headers
|
||||||
|
$(this.tableId).append(this.renderHeads());
|
||||||
|
this.attachSortEventListeners(".ri-expand-up-down-fill");
|
||||||
|
|
||||||
|
// Append 'order' and 'filter' into params if exist
|
||||||
|
if (this.config.hasOwnProperty("ajax")) {
|
||||||
|
if (this.config.order !== null) {
|
||||||
|
Object.assign(params, this.config.order);
|
||||||
|
}
|
||||||
|
if (this.config.filter !== null) {
|
||||||
|
Object.assign(params, this.config.filter);
|
||||||
|
}
|
||||||
|
// Call ajax and render data
|
||||||
|
data = await this.config.ajax(params);
|
||||||
|
this.renderRows(data);
|
||||||
|
} else {
|
||||||
|
// Use data transmitted directly
|
||||||
|
data = this.config.data;
|
||||||
|
this.renderRows(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start listening to events of already initialized buttons
|
||||||
|
this.attachActionEventListeners(".btn_edit");
|
||||||
|
this.attachActionEventListeners(".btn_done");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current configuration of the table
|
||||||
|
getConfig() {
|
||||||
|
return this.config;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically merger new config and re-render
|
||||||
|
updateConfig(newConfig) {
|
||||||
|
this.config = {
|
||||||
|
...this.config,
|
||||||
|
...newConfig
|
||||||
|
};
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define and automatically create edit buttons
|
||||||
|
// Used in rowRender configuration
|
||||||
|
actionEdit(row) {
|
||||||
|
return `
|
||||||
|
<div class="d-flex" style="justify-content: space-evenly;">
|
||||||
|
<i class="ri-edit-2-fill btn_edit btn btn-primary" style="--bs-btn-padding-y: .15rem; --bs-btn-padding-x: .3rem; --bs-btn-font-size: .75rem;" data-row-id="${row.id}"></i>
|
||||||
|
<i class="ri-check-line btn_done btn btn-success" style="--bs-btn-padding-y: .15rem; --bs-btn-padding-x: .3rem; --bs-btn-font-size: .75rem; display: none;" data-row-id="${row.id}"></i>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define and automatically create editable cells
|
||||||
|
// Used in rowRender configuration
|
||||||
|
cellEdit(colName, colValue) {
|
||||||
|
return `
|
||||||
|
<div class="cell_show"><span class="${colName}">${colValue}</span></div>
|
||||||
|
<div class="cell_edit"><input class="${colName}" style="display: none;" type='text' value='${colValue}'/></div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Works when the edit button is clicked
|
||||||
|
rowEdit(rowId) {
|
||||||
|
this.config.heads.map((col) => {
|
||||||
|
var cellShow = $(`#row_${rowId} .cell_show .${col.name}`);
|
||||||
|
var cellEdit = $(`#row_${rowId} .cell_edit .${col.name}`);
|
||||||
|
|
||||||
|
if (cellShow) {
|
||||||
|
cellShow.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellEdit) {
|
||||||
|
cellEdit.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$(`#row_${rowId} div .btn_done`).show();
|
||||||
|
$(`#row_${rowId} div .btn_edit`).hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
rowEditDone(rowId) {
|
||||||
|
// Initial params with row id
|
||||||
|
let params = {
|
||||||
|
id: parseInt(rowId)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get api update info
|
||||||
|
let apiUpdateInfo = this.config.apiUpdate;
|
||||||
|
|
||||||
|
// Add edited values to params
|
||||||
|
this.config.heads.map((col) => {
|
||||||
|
var cellEdit = $(`#row_${rowId} .cell_edit .${col.name}`);
|
||||||
|
|
||||||
|
if (cellEdit.val()) {
|
||||||
|
Object.assign(params, {
|
||||||
|
[col.name]: cellEdit.val()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Call API update data row
|
||||||
|
if (this.config.hasOwnProperty("apiUpdate")) {
|
||||||
|
$.ajax({
|
||||||
|
url: apiUpdateInfo.url,
|
||||||
|
type: apiUpdateInfo.type,
|
||||||
|
data: params,
|
||||||
|
headers: apiUpdateInfo.headers,
|
||||||
|
success: (response) => {
|
||||||
|
// alert("Edit success");
|
||||||
|
this.render();
|
||||||
|
},
|
||||||
|
error: function(error) {
|
||||||
|
console.log(error);
|
||||||
|
alert("Edit Fail");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
alert("Missing updated API information");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
$(`#row_${rowId} div .btn_done`).hide();
|
||||||
|
$(`#row_${rowId} div .btn_edit`).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update config and render when change per page
|
||||||
|
changePerPage() {
|
||||||
|
this.config.per_page = $(`${this.tableId} #perPageSelect`).val();
|
||||||
|
this.render();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
// Declare configuration for table headers
|
||||||
|
// 'render' function is used to customize the header
|
||||||
|
heads: [{
|
||||||
|
name: "id",
|
||||||
|
value: "ID",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "email",
|
||||||
|
value: "Email",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "code",
|
||||||
|
value: "Code",
|
||||||
|
render: (heads) => {
|
||||||
|
var html = `
|
||||||
|
<h1>${heads.value}</h1>
|
||||||
|
`;
|
||||||
|
return html;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "created_at",
|
||||||
|
value: "Created at",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "__actions",
|
||||||
|
value: "Action",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
/* data: data, */ //Use data if config.ajax not exist
|
||||||
|
|
||||||
|
// Used to customize rows according to column names
|
||||||
|
rowRender: (colName, colValue, row) => {
|
||||||
|
switch (colName) {
|
||||||
|
case "id":
|
||||||
|
return `
|
||||||
|
<div class="text-center">
|
||||||
|
${row.id}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
case "email":
|
||||||
|
return tableData.cellEdit(colName, colValue);
|
||||||
|
case "code":
|
||||||
|
return tableData.cellEdit(colName, colValue);
|
||||||
|
case "__actions":
|
||||||
|
return tableData.actionEdit(row);
|
||||||
|
default:
|
||||||
|
return colValue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Ajax function to automatically get initial data and re-render times
|
||||||
|
// If this parameter is not present, the library will use the default parameter "data" passed directly
|
||||||
|
ajax: (params) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
$.ajax({
|
||||||
|
url: "https://payment.nswteam.net/api/v1/admin/discount/get",
|
||||||
|
type: "GET",
|
||||||
|
data: params,
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3BheW1lbnQubnN3dGVhbS5uZXQvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzA4NDgxMDUwLCJleHAiOjE3MDg1Njc0NTAsIm5iZiI6MTcwODQ4MTA1MCwianRpIjoid0k3alN1OWxlZHJxM3IwSiIsInN1YiI6IjUiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.8aWr2DlfNvQZqBiXIFaDRS8_VsARAl1TEynsuYpZcqY", // Include the token in the request header
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
resolve(response);
|
||||||
|
},
|
||||||
|
error: function(error) {
|
||||||
|
console.log(error);
|
||||||
|
reject(error);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// Information used to call the API for the row and cell update function
|
||||||
|
apiUpdate: {
|
||||||
|
url: "https://payment.nswteam.net/api/v1/admin/discount/update",
|
||||||
|
type: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3BheW1lbnQubnN3dGVhbS5uZXQvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzA4NDgxMDUwLCJleHAiOjE3MDg1Njc0NTAsIm5iZiI6MTcwODQ4MTA1MCwianRpIjoid0k3alN1OWxlZHJxM3IwSiIsInN1YiI6IjUiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.8aWr2DlfNvQZqBiXIFaDRS8_VsARAl1TEynsuYpZcqY", // Include the token in the request header
|
||||||
|
},
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
pagination: true,
|
||||||
|
detail: true
|
||||||
|
},
|
||||||
|
sort: {
|
||||||
|
enable: true,
|
||||||
|
listColumn: ["id", "email", "code", "created_at"]
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
order_by_id: 'desc'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initial table
|
||||||
|
var tableData = new TableData("#bookTabe", config);
|
||||||
|
tableData.render();
|
||||||
|
|
||||||
|
// Get values from form html and append to config -> re-render with new data
|
||||||
|
const getFormValues = () => {
|
||||||
|
const formData = {};
|
||||||
|
const form = document.getElementById("filterForm");
|
||||||
|
|
||||||
|
for (let i = 0; i < form.elements.length; i++) {
|
||||||
|
const element = form.elements[i];
|
||||||
|
|
||||||
|
if (!element.name || element.tagName === "BUTTON") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
formData[element.name] = element.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
config.filter = formData;
|
||||||
|
tableData.updateConfig(config);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Search for keywords by line (tr tag)
|
||||||
|
$("#search_input").on("keyup", function() {
|
||||||
|
var value = $(this).val().toLowerCase();
|
||||||
|
$("#bookTabe tbody tr").filter(function() {
|
||||||
|
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
Loading…
Reference in New Issue