我正在使用data-table中的Framework7,该column filter input是使用JSON数据动态构建的,并且我正在尝试使起作用。使用Stack Overflow上显示的其他示例,我已经能够成功地进行第一列过滤:
HTML
<input type="text" id="brandFilter" onkeyup="filterTable()" placeholder="Filter">
JS
function filterTable() {
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("brandFilter");
filter = input.value.toUpperCase();
table = document.getElementById("productList");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
http://feedserver.com/jsonfeed.php?output=json
我不知道如何改进此脚本,以便可以使用第2列和第3列中的输入进一步过滤表?
<input type="text" id="modelFilter" onkeyup="filterTable()" placeholder="Filter">
<input type="text" id="energyFilter" onkeyup="filterTable()" placeholder="Filter">
任何简单的解决方案,因为我还是新手?
答案 0 :(得分:1)
您可以根据术语的列位置构建一个术语列表,并存储输入的类型和值。
然后,您可以遍历每一行,并根据每个单元格的文本内容及其相应的术语来确定是否要显示它。
function onFilterChange(e) {
let table = findParentBySelector(e.target, 'table');
var terms = [].slice.call(table.querySelectorAll('.input')).map(el => {
let item = el.querySelector('input, select');
return { type : item.tagName, value : item.value };
});
table.querySelectorAll('tbody tr').forEach(tr => {
let visible = [].slice.call(tr.querySelectorAll('td')).every((td, i) => {
if (terms[i].type === 'SELECT' && terms[i].value === 'All') return true;
let text = td.innerHTML.trim();
return text != '' ? text.indexOf(terms[i].value) > -1 : true;
});
tr.classList[visible ? 'remove' : 'add']('hidden-row');
});
}
var data = `2,Jane Doe,jane.doe@com,Female
3,Vladimir Kharlampidi,vladimir@google.com,Male
4,Jennifer Doe,jennifer@doe.com,Female`.split('\n');
let tbody = document.querySelector('.data-table table tbody')
data.forEach(r => {
let tr = document.createElement('TR');
r.split(/,\s*?/g).forEach(c => {
let td = document.createElement('TD');
td.innerHTML = c;
tr.appendChild(td);
});
tbody.appendChild(tr);
});
document.querySelectorAll('.input').forEach(el => {
el.querySelectorAll('input').forEach(x => x.addEventListener('keyup', onFilterChange));
el.querySelectorAll('*').forEach(x => x.addEventListener('change', onFilterChange));
});
function onFilterChange(e) {
let table = findParentBySelector(e.target, 'table'),
caseInsensitive = table.getAttribute('data-ignore-case') === 'true',
terms = [].slice.call(table.querySelectorAll('.input')).map(el => {
let item = el.querySelector('input, select');
return {
type : item.tagName,
value : (v => caseInsensitive ? v.toLowerCase() : v)(item.value)
};
});
table.querySelectorAll('tbody tr').forEach(tr => {
let visible = [].slice.call(tr.querySelectorAll('td')).every((td, i) => {
let text = (t => caseInsensitive ? t.toLowerCase() : t)(td.textContent.trim());
if (terms[i].type === 'SELECT') {
if (terms[i].value.toUpperCase() === 'ALL') return true;
return terms[i].value === text;
}
return text != '' ? text.indexOf(terms[i].value) > -1 : true;
});
tr.classList.toggle('hidden-row', !visible);
});
}
// https://stackoverflow.com/a/14234618/1762224
// Note: Modified as a recursive routine
function findParentBySelector(el, target) {
return el != null ? el && ![].slice.call(typeof target === 'string' ? (target = document.querySelectorAll(target)) : target).some(c => c == el) ? findParentBySelector(el.parentNode, target) : el : null;
}
body {
background: #444 !important;
}
.data-table {
width: 96% !important;
margin: 1em auto !important;
padding: 0.5em;
}
/** Toggled */
.hidden-row {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/framework7/4.5.0/css/framework7.bundle.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/framework7/4.5.0/js/framework7.bundle.min.js"></script>
<div class="card data-table">
<table data-ignore-case="true">
<thead>
<tr>
<th class="input-cell">
<span class="table-head-label">ID</span>
<div class="input" style="width: 50px">
<input type="number" placeholder="Filter">
</div>
</th>
<th class="input-cell">
<span class="table-head-label">Name</span>
<div class="input">
<input type="text" placeholder="Filter">
</div>
</th>
<th class="input-cell">
<span class="table-head-label">Email</span>
<div class="input">
<input type="text" placeholder="Filter">
</div>
</th>
<th class="input-cell">
<span class="table-head-label">Gender</span>
<div class="input input-dropdown">
<select>
<option value="All">All</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>John Doe</td>
<td>john@doe.com</td>
<td>Male</td>
</tr>
</tbody>
</table>
</div>
使用数据属性将一个类添加到您的搜索字段中:
$('<input>').addClass('search-field').data('field', field))
向表单元格中添加一个字段名称。
$('<td>').text(rec[field]).data('field-name', field)
在搜索图中添加这些术语,并在所有条件都满足每个单元格的文本内容的情况下过滤每一行。如果该列的术语为空白,则假设true
。
var $table = $.tableFromJson(data).addClass('stylized').appendTo('body');
$table.on('keyup', '.search-field', function(e) {
// Map fields to pairs and then reduce into a map.
let terms = $('.search-field').map(function(i, field) {
return { field : $(field).data('field'), value : $(field).val().trim() };
}).toArray().reduce(function(terms, pair) {
return Object.assign(terms, { [pair.field] : pair.value });
}, {});
let len = Object.keys(terms).length; // Store the length of the keys
// Find the parent (table) of the search field that you modified and locate the rows
$(e.target).closest('table').find('tbody tr').each(function(i, tr) {
// Toggle the row visibility
$(tr).toggle($(tr).find('td').filter(function(j, td) {
let term = terms[$(td).data('field-name')];
// If not empty, locate the term within the text of the cell
return term != '' ? $(td).text().trim().indexOf(term) > -1 : true;
}).length === len);
});
});
(function($) {
$.reduce = function(arr, fnReduce, valueInitial) {
if (Array.prototype.reduce) {
return Array.prototype.reduce.call(arr, fnReduce, valueInitial);
}
$.each(arr, function(i, value) {
valueInitial = fnReduce.call(null, valueInitial, value, i, arr);
});
return valueInitial;
};
$.fn.reduce = function(fnReduce, valueInitial) {
return $.reduce(this, fnReduce, valueInitial);
};
$.fn.renderTable = function(data, options) {
options = options || {};
let ignoreCase = options.ignoreCase, fields = Object.keys(data[0]);
return this.renderHeaders(fields).renderRows(fields, data)
.on('keyup', '.search-field', function(e) {
let terms = $('.search-field').reduce(function(m, field) {
return Object.assign(m, {
[$(field).data('field')]: (function(val) {
return ignoreCase && val ? val.toLowerCase() : val;
})($(field).val().trim())
});
}, {}), len = Object.keys(terms).length;
$(e.target).closest('table').find('tbody tr').each(function(i, tr) {
$(tr).toggle($(tr).find('td').filter(function(j, td) {
let term = terms[$(td).data('field-name')];
return term != '' ? (function(text) {
return ignoreCase && text ? text.toLowerCase() : text;
})($(td).text().trim()).indexOf(term) > -1 : true;
}).length === len);
});
});
};
$.fn.renderHeaders = function(fields) {
return this.append($.renderHeaders(fields));
}
$.fn.renderRows = function(fields, data) {
return this.append($.renderRows(fields, data));
};
$.tableFromJson = function(data, options) {
return $('<table>').renderTable(data, options)
.toggleClass('stylized', (options || {}).stylized);
};
$.renderHeaders = function(fields) {
return $('<thead>').append($('<tr>').append(fields
.map(field => $('<th>')
.append($('<div>').text(field))
.append($('<input>').addClass('search-field').data('field', field)))));
};
$.renderRows = function(fields, data) {
return $('<tbody>').append(data
.map((rec, row) => $('<tr>').append(fields
.map((field, col) => $('<td>').text(rec[field]).data('field-name', field)))));
};
})(jQuery);
var data = [
{ "brand" : "Bosch", "model" : 333, "energyUse" : "A" },
{ "brand" : "Bosch", "model" : 456, "energyUse" : "A++" }
];
$.tableFromJson(data, { ignoreCase: true, stylized: true }).appendTo('body');
body {
padding: 0.25em;
}
h1 {
font-weight: bold;
margin-top: 0.75em;
margin-bottom: 0.33em;
}
table.stylized {
font-family: "Lucida Sans Unicode", "Lucida Grande", Sans-Serif;
font-size: 12px;
text-align: left;
border-collapse: collapse;
margin: 4px;
width: 600px;
}
table.stylized thead th {
text-transform: capitalize;
font-size: 13px;
color: #039;
background: #b9c9fe;
padding: 6px;
cursor: pointer;
}
table.stylized thead th input {
background: #f2f5ff;
color: #039;
font-size: smaller;
}
table.stylized tbody tr:nth-child(odd) {
background: #f2f5ff;
}
table.stylized tbody tr:nth-child(even) {
background: #e8edff;
}
table.stylized tbody td {
border-top: 1px solid #fff;
color: #669;
padding: 6px;
}
table.stylized tbody tr:hover td {
background: #d0dafd;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
注意:本演示中的表生成jQuery插件基于我先前实现的sortable table plugin。
答案 1 :(得分:0)
如果要将过滤器更改为每一列,只需更改以下内容即可:
function filterTable(column) { // add a parameter
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("brandFilter");
filter = input.value.toUpperCase();
table = document.getElementById("productList");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];// change this
td = tr[i].getElementsByTagName("td")[column];// to this
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
这样,您将列索引作为值传递给每个列进行过滤
希望有帮助