Javascript 如何使用js/html对表进行排序

Javascript 如何使用js/html对表进行排序,javascript,html,Javascript,Html,我有一张桌子: Name | Department | status 我在单击时按字母顺序对姓名进行了排序,但现在我在状态单元格中创建了一个下拉列表,其中显示了诸如“内部/外部”之类的值,我希望在单击其中一个过滤器时对表格进行排序,我只希望看到进入/退出的人员。我当前的JS功能: function sortStatusDesc() { var table, rows, switching, i, x, y, shouldSwitch; table = document.getEl

我有一张桌子:

Name | Department | status 
我在单击时按字母顺序对姓名进行了排序,但现在我在状态单元格中创建了一个下拉列表,其中显示了诸如“内部/外部”之类的值,我希望在单击其中一个过滤器时对表格进行排序,我只希望看到进入/退出的人员。我当前的JS功能:

function sortStatusDesc() {
   var table, rows, switching, i, x, y, shouldSwitch;
   table = document.getElementById("myTable");
   switching = true;

   while (switching) {
      switching = false;
      rows = table.rows;

      for (i = 1; i < (rows.length - 1); i++) {
         shouldSwitch = false;
         x = rows[i].getElementsByTagName("th")[2];
         y = rows[i + 1].getElementsByTagName("th")[2];

         if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
            shouldSwitch = true;
            break;
         }
      }
      if (shouldSwitch) {
         rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
         switching = true;
      }
   }
}
函数sortStatusDesc(){
var表,行,切换,i,x,y,shouldSwitch;
table=document.getElementById(“myTable”);
切换=真;
while(切换){
切换=错误;
行=表。行;
对于(i=1;i<(rows.length-1);i++){
shouldSwitch=false;
x=行[i].getElementsByTagName(“th”)[2];
y=行[i+1].getElementsByTagName(“th”)[2];
if(x.innerHTML.toLowerCase()

它按字母顺序排序。

下面的代码片段显示了对任何属性的排序。 单击其中一个属性标题可更改排序

同样,您可以创建过滤。与使用
data.sort()
对特定属性上的源数据进行排序不同,您需要对所有具有正确值的条目进行
data.filter()

//我们正在渲染的数据的名称。
常量源名称='位置';
//要从中创建表的源数据。
常量源数据=[
{“id”:1,“名称”:“生产大厅”,“部门”:“生产”,“状态”:“内部”},
{“id”:2,“名称”:“备件室”,“部门”:“生产”,“状态”:“内部”},
{“id”:3,“名称”:“仓库”,“部门”:“生产”,“状态”:“内部”},
{“id”:4,“名称”:“装货区”,“部门”:“生产”,“状态”:“外部”},
{“id”:5,“姓名”:“人力资源办公室”,“部门”:“行政”,“状态”:“内部”},
{“id”:6,“名称”:“办公室质量保证”,“部门”:“管理”,“状态”:“内部”},
{“id”:7,“姓名”:“安全休息室”,“部门”:“行政”,“状态”:“外部”}
];
//创建表。
//对于本例,我们将使用字符串操纵来创建HTML。
//对于复杂的布局,模板系统更好。
常量呈现=(名称、数据)=>{
//始终为名称包含标题。
//当有0行时,我们仍然知道表中显示的内容。
常量标签=data.length
?“”+Object.keys(数据[0]).map(名称=>`${name}`).连接(“”)+”
: '';
//数据属性的实际标头。
常量头=`${name}${labels}`;
//数据中的每个条目对应一行。
const rows=data.map(entry=>(``+Object.values(entry.map)(value=>`${value}')).join('''+'').join(''');
//把它全部合并在一起。
常量表=`${header}${rows}`;
//渲染到页面中。
document.querySelector('#output').innerHTML=table;
};
//这是一种财产。
常量排序=(数据、属性)=>{
//按字母顺序对属性上的数据进行排序。
返回数据。排序((第一,第二)=>{
if(第一[属性]<第二[属性])返回-1;
else if(第一个[属性]>第二个[属性])返回1;
否则返回0;
});
};
//将单击事件添加到标题,以便单击标题将对行进行排序。
常量添加_排序=函数(表){
大堆
.from(table.querySelectorAll('th'))
.forEach(header=>header.addEventListener('click',create_table));
};
//主要功能
const create_table=事件=>{
//我们将手动和通过单击重复使用此功能
const property=event&&event.target
?event.target.getAttribute('data attr')
:事件;
常量集合=排序(源数据、属性);
渲染(源名称、集合);
添加排序(document.querySelector('table');
};
创建_表(“名称”)
th,td{
边框:1px纯灰;
}

可以使用任何算法,根据比较器函数(例如,“该单元格是否应该出现在该单元格之前?”,
Math.min
)轻松地对表格部分进行排序,这里演示的实际表格排序代码不到10行:

class InsertionSort {
    static sort_children(parent, comparator) {
        for(let i = 0; i != parent.children.length; i++) {
            const current = parent.children[i];
            let element;
            for(element = current.previousElementSibling; element && comparator(current, element); element = element.previousElementSibling);
            parent.insertBefore(current, element ? element.nextElementSibling : parent.firstElementChild);
        }
    }
}
如果有一个表节(或一个表)(上面的
sort_children
parent
参数)包含大量行作为子行,则可以使用上面定义的
sort_children
方法对其进行排序,只要您自己正确定义了行的比较方式:

InsertionSort.sort_children(your_table, (row_A, row_B) => row_A.cells[0].textContent < row_B.cells[0].textContent);
然后使用一个不太详细、可读性更高的表达式调用表排序:

InsertionSort.sort_children(your_table, table_cell_comparator(1, Number)); 
上面对行进行排序,使第二列数值较低的单元格显示在数值较高的单元格之前。

通过类切换等操作,可以轻松地对现有行进行表的“筛选”:

function filter_table(section, predicate) {
    for(const row of section.rows) row.classList.toggle("filtered", predicate(row));
}
上面发生的事情是,
谓词
函数认为“已过滤”的整个表或表节(
以上)的行通过在这些行上切换“已过滤”类进行标记

谓词
函数是您自己设计和选择的函数,它接受一个表行并返回
true
(如果该行应该被过滤)或
false
(否则)

以员工行为例,假设每行的第三个表格单元格包含一个
select
(下拉)控件,其中一个选项用于“In”,另一个选项用于“Out”:

如何设置过滤行的样式取决于您,您可能只想隐藏它们,当然:

tr.filtered {
    display: none;
}
由于每个员工的状态都会随着下拉选择中的更改而有效地更改,因此每次此类更改都会调用
filter\u table
,这样会再次遍历所有行,从而浪费资源。因此,听“改变”是一个更好的主意
<tr><!-- ... --><td><select><option value="in">In</option><option value="out">Out</option></select></tr>
const predicate = row => row.cells[2].firstElementChild.value == "in";
tr.filtered {
    display: none;
}
table.addEventListener("change", event => {
    if(event.target instanceof HTMLSelectElement) {
        const row = event.target.parentElement.parentElement;
        row.classList.toggle("filtered", predicate(row));
    }
})