Вы можете создать список терминов на основе их положения в столбце и сохранить тип ввода и значение.
Затем можно выполнить цикл по каждой строке и определить, хотите ли вы отобразить его, на основетекстовое содержимое каждой ячейки и соответствующий ей термин.
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');
});
}
Demo
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 для генерации таблиц в этой демонстрации основан на плагине для сортируемых таблиц Я ранее реализовал.