我正在尝试根据用户从下拉列表中选择的排序选项对表进行排序。我遇到了this主题和that一个主题,但是它们都基于jQuery,但是它们似乎都不适合我,因为我需要纯Javascript解决方案。
我的HTML:
<label>Sort order:</label>
<select>
<option>Item asc</option>
<option>Item desc</option>
<option>Price asc</option>
<option>Price desc</option>
<option>Year asc</option>
<option>Year desc</option>
</select>
<table>
<thead>
<tr>
<th>item</th>
<th>price</th>
<th>year</th>
</tr>
</thead>
<tbody>
<tr>
<td>Skoda Octavia</td>
<td>7000</td>
<td>2012</td>
</tr>
<tr>
<td>Toyota Yaris</td>
<td>3000</td>
<td>2011</td>
</tr>
<tr>
<td>Ford Focus</td>
<td>5000</td>
<td>2009</td>
</tr>
</tbody>
</table>
自从我是新来的人,我非常感谢您提供有关如何解决问题的帮助。
答案 0 :(得分:0)
基本上,您的问题可以分为三个较小的问题:
将HTML表数据放入包含对象数组的javascript对象中,每个对象都具有对应于列标题和单元格值的属性,以便您可以根据属性值对该数组进行排序:
const jsonFromHtml = (tbody, thead) => {
let tableJson = {rows:[]};
[...tbody.children].forEach(tableRow => {
let rowEntry = {};
[...tableRow.children].forEach((cell, column) => rowEntry[thead.children[0].children[column].textContent] = cell.textContent);
tableJson.rows.push(rowEntry);
});
return tableJson;
};
以任意顺序对行项目进行排序:
const customSort = (arr, key, order) => {
let sortCompare = order == 'Desc' ? -1 : 1;
return arr.sort((first, second) => first[key]>second[key] ? sortCompare : first[key]<second[key] ? -sortCompare : 0);
};
根据行的排序数组组成表主体内部HTML:
const arrayToTable = (arr, tbody, thead) => {
let rows = [];
arr.forEach((row, rowNum) => {
row = [...thead.children[0].children].map(th => row[th.textContent] ? row[th.textContent] : '');
row = row.map(td => `<td>${td}</td>`);
row = `<tr>${row.join('')}</tr>`;
rows.push(row);
});
tbody.innerHTML = rows.join('');
};
const myTableTbody = document.querySelector('#myTable tbody');
const myTableThead = document.querySelector('#myTable thead');
const jsonFromHtml = (tbody, thead) => {
let tableJson = {rows:[]};
[...tbody.children].forEach(tableRow => {
let rowEntry = {};
[...tableRow.children].forEach((cell, column) => rowEntry[thead.children[0].children[column].textContent] = cell.textContent);
tableJson.rows.push(rowEntry);
});
return tableJson;
};
const customSort = (arr, key, order) => {
let sortCompare = order == 'Desc' ? -1 : 1;
return arr.sort((first, second) => first[key]>second[key] ? sortCompare : first[key]<second[key] ? -sortCompare : 0);
};
const arrayToTable = (arr, tbody, thead) => {
let rows = [];
arr.forEach((row, rowNum) => {
row = [...thead.children[0].children].map(th => row[th.textContent] ? row[th.textContent] : '');
row = row.map(td => `<td>${td}</td>`);
row = `<tr>${row.join('')}</tr>`;
rows.push(row);
});
tbody.innerHTML = rows.join('');
};
document.querySelector('#selectionOrder').addEventListener('change', function(){
let sortKey = this.value.match(/[a-z]+/)[0];
let sortOrder = this.value.match(/(A|De)sc/) ? this.value.match(/(A|De)sc/)[0] : 'Asc';
let myTableJson = jsonFromHtml(myTableTbody, myTableThead);
myTableJson.rows = customSort(myTableJson.rows, sortKey, sortOrder);
arrayToTable(myTableJson.rows, myTableTbody, myTableThead);
});
<label>Sort order:</label>
<select id="selectionOrder">
<option value="itemAsc">Item asc</option>
<option value="itemDesc">Item desc</option>
<option value="priceAsc">Price asc</option>
<option value="priceDesc">Price desc</option>
<option value="yearAsc">Year asc</option>
<option value="yearDesc">Year desc</option>
</select>
<table id="myTable">
<thead>
<tr>
<th>item</th>
<th>price</th>
<th>year</th>
</tr>
</thead>
<tbody>
<tr>
<td>Skoda Octavia</td>
<td>7000</td>
<td>2012</td>
</tr>
<tr>
<td>Toyota Yaris</td>
<td>3000</td>
<td>2011</td>
</tr>
<tr>
<td>Ford Focus</td>
<td>5000</td>
<td>2009</td>
</tr>
</tbody>
</table>
答案 1 :(得分:0)
这是一种解决方案,它可以在变量中定义数据,然后从中构建HTML。
// Define data in variables, not in HTML:
const columns = ["item", "price", "year"];
const data = [
{ "item": "Skoda Octavia", "price": 7000, "year": 2012 },
{ "item": "Toyota Yaris", "price": 3000, "year": 2011 },
{ "item": "Ford Focus", "price": 5000, "year": 2009 },
]
// Elements in the DOM
const orderSelect = document.getElementById("orderSelect");
const dataTable = document.getElementById("dataTable");
// Populate select list based on the columns of the data
for (const column of columns) {
for (const dir of [" asc", " desc"]) {
const opt = document.createElement("option");
opt.value = opt.text = column + dir;
orderSelect.add(opt);
}
}
function refreshTable() {
const [sortBy, order] = orderSelect.value.split(" ");
const sign = order === "asc" ? -1 : 1;
data.sort((a, b) => a[sortBy] < b[sortBy] ? sign : a[sortBy] > b[sortBy] ? -sign : 0);
// Clear table
dataTable.innerHTML = "";
// Create header row
const row = dataTable.insertRow(-1);
for (const column of columns) {
const th = document.createElement("th");
th.textContent = column;
row.appendChild(th);
}
// Create data rows
for (const record of data) {
const row = dataTable.insertRow(-1);
for (const column of columns) {
const td = row.insertCell(-1);
td.textContent = record[column];
}
}
}
// Populate data table
refreshTable();
// handler
orderSelect.addEventListener("change", refreshTable);
<label for="orderSelect">Sort order:</label>
<select id="orderSelect"></select>
<table id="dataTable"></table>