使用 jQuery/JavaScript 操作 HTML table(用于列重新排序、可见性)?
Manipulate an HTML table (for column reordering, visibility) using jQuery/JavaScript?
我有一个 ASP.NET MVC 站点,我在一个视图中有一个 HTML table。根据示例 html 代码,我有时会在单元格内嵌套 tables,但在您完成问题之前可以忽略它。
<table id="mainTable">
<thead>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>
<table class="nestedTable">
<tr><th>Col 1</th><th>Col 3</th></tr>
<tr>
<td>nested data</td><td>nested data 1</td>
</tr>
</table>
</td>
<td>data</td>
</tr>
</tbody>
</table>
我现在想使用这个 jQuery multiselect plugin 来允许用户 select 他们想要的列的排序以及显示/隐藏某些列 所以我正在创建一个 multiselect 看起来像这样:
<select id="cols" class="multiselect" multiple="multiple" name="cols[]">
<option value="Col1">Col1</option>
<option value="Col2">Col2</option>
<option value="Col3">Col3</option>
</select>
允许用户选择顺序,然后我暂时将这些数据存储在本地存储中。所以我存储的是一个字符串数组,代表 "visible order of columns" 用于设置 multiselect 选择器。这工作正常,我能够保留这个数组或 "ordered column names".
我的问题是获取此字符串数组并更新 HTML table 以反映此列排序和列可见性的最佳方法是什么?
我知道有更大的 html table 网格框架具有此功能,但在这种情况下,我需要坚持使用手动编码 html table。
更新:
@Rick Hitchcock 在下面的回答让我完成了 90% 的工作,但我意识到有一个悬而未决的问题使我的问题有点复杂。在某些情况下,我在主 table 中有一个嵌套的 table。我已经更新了问题以包含这种情况。 我不希望列选择器代码影响嵌套 table 所以我正在寻找一种方法来让代码影响主要 table.
[根据更新的问题删除了原始答案]
给定一个像这样的数组 (arr
):
['Col 2', 'Col 3', 'Col 1']
……或者这个:
['Col 1', 'Col 3']
…这将命令主 table 的列匹配,它会隐藏未使用的列:
var tr= $('#mainTable > tbody > tr, #mainTable > thead > tr');
$('> th, > td', tr).hide();
$.each(arr, function(_, val) {
var col= $('> th', tr)
.filter(function() {
return $(this).text()===val;
})
.index();
$(tr).append(function() {
return $('> td, > th', this).eq(col).show();
});
});
单击按钮重新排序 table。
工作原理
这会将后续选择器限制在 table 的主要行中:
var tr= $('#mainTable > tbody > tr, #mainTable > thead > tr');
即使排除 tbody
、it will be added for you。因此,这始终是一个空集合:$('#mainTable > tr')
。
这仅隐藏 tr
集合(来自上一行)的直接子代:
$('> th, > td', tr).hide();
作为副作用,所有后代也将被隐藏。
相当于:
$(tr).children('th, td').hide();
jQuery 的 children
和 find
方法通常是不必要的(而且代价高昂),当你可以使用 CSS 选择器完成同样的事情时——尤其是考虑到可选 context
参数的优点:
$( selector [, context ] )
这会查看数组的每个元素:
$.each(arr, function(_, val) {
...
});
这将获取 th
元素(即 tr
集合的直接子元素)的 index()
,其中它的 text()
与数组值匹配:
var col= $('> th', tr)
.filter(function() {
return $(this).text()===val;
})
.index();
这就是我们要显示的栏目。
最后,这会向 tr
集合的每个成员追加其所有具有该列号的子项,并显示它们:
$(tr).append(function() {
return $('> td, > th', this).eq(col).show();
});
jQuery 的 append()
方法(类似于 JavaScript 的 appendChild()
方法)移动一个元素 – 进入 DOM 或其他地方DOM.
知道了这一点,我们往往可以避免使用detach()
.
等方法
我有一个 ASP.NET MVC 站点,我在一个视图中有一个 HTML table。根据示例 html 代码,我有时会在单元格内嵌套 tables,但在您完成问题之前可以忽略它。
<table id="mainTable">
<thead>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>
<table class="nestedTable">
<tr><th>Col 1</th><th>Col 3</th></tr>
<tr>
<td>nested data</td><td>nested data 1</td>
</tr>
</table>
</td>
<td>data</td>
</tr>
</tbody>
</table>
我现在想使用这个 jQuery multiselect plugin 来允许用户 select 他们想要的列的排序以及显示/隐藏某些列 所以我正在创建一个 multiselect 看起来像这样:
<select id="cols" class="multiselect" multiple="multiple" name="cols[]">
<option value="Col1">Col1</option>
<option value="Col2">Col2</option>
<option value="Col3">Col3</option>
</select>
允许用户选择顺序,然后我暂时将这些数据存储在本地存储中。所以我存储的是一个字符串数组,代表 "visible order of columns" 用于设置 multiselect 选择器。这工作正常,我能够保留这个数组或 "ordered column names".
我的问题是获取此字符串数组并更新 HTML table 以反映此列排序和列可见性的最佳方法是什么?
我知道有更大的 html table 网格框架具有此功能,但在这种情况下,我需要坚持使用手动编码 html table。
更新:
@Rick Hitchcock 在下面的回答让我完成了 90% 的工作,但我意识到有一个悬而未决的问题使我的问题有点复杂。在某些情况下,我在主 table 中有一个嵌套的 table。我已经更新了问题以包含这种情况。 我不希望列选择器代码影响嵌套 table 所以我正在寻找一种方法来让代码影响主要 table.
[根据更新的问题删除了原始答案]
给定一个像这样的数组 (arr
):
['Col 2', 'Col 3', 'Col 1']
……或者这个:
['Col 1', 'Col 3']
…这将命令主 table 的列匹配,它会隐藏未使用的列:
var tr= $('#mainTable > tbody > tr, #mainTable > thead > tr');
$('> th, > td', tr).hide();
$.each(arr, function(_, val) {
var col= $('> th', tr)
.filter(function() {
return $(this).text()===val;
})
.index();
$(tr).append(function() {
return $('> td, > th', this).eq(col).show();
});
});
单击按钮重新排序 table。
工作原理
这会将后续选择器限制在 table 的主要行中:
var tr= $('#mainTable > tbody > tr, #mainTable > thead > tr');
即使排除 tbody
、it will be added for you。因此,这始终是一个空集合:$('#mainTable > tr')
。
这仅隐藏
tr
集合(来自上一行)的直接子代:
$('> th, > td', tr).hide();
作为副作用,所有后代也将被隐藏。
相当于:
$(tr).children('th, td').hide();
jQuery 的 children
和 find
方法通常是不必要的(而且代价高昂),当你可以使用 CSS 选择器完成同样的事情时——尤其是考虑到可选 context
参数的优点:
$( selector [, context ] )
这会查看数组的每个元素:
$.each(arr, function(_, val) {
...
});
这将获取
th
元素(即 tr
集合的直接子元素)的 index()
,其中它的 text()
与数组值匹配:
var col= $('> th', tr)
.filter(function() {
return $(this).text()===val;
})
.index();
这就是我们要显示的栏目。
最后,这会向 tr
集合的每个成员追加其所有具有该列号的子项,并显示它们:
$(tr).append(function() {
return $('> td, > th', this).eq(col).show();
});
jQuery 的 append()
方法(类似于 JavaScript 的 appendChild()
方法)移动一个元素 – 进入 DOM 或其他地方DOM.
知道了这一点,我们往往可以避免使用detach()
.