我有一个表格,我想应用过滤。用户可以选择基于由逗号分隔的多个术语进行过滤。这些条款将是OR条件。我还希望用户能够在两个术语之间加上一个加号,并将其作为' AND'条件。
例如:
|---------------------|------------------|------------------|
| ID | NAME | DEPT |
|---------------------|------------------|------------------|
| 1 | BOB | Sales |
|---------------------|------------------|------------------|
| 2 | SALLY | Sales |
|---------------------|------------------|------------------|
| 3 | BOB | HouseKeeping |
|---------------------|------------------|------------------|
| 4 | SALLY | HouseKeeping |
|---------------------|------------------|------------------|
现在,如果我提出以下搜索条件:BOB,SALLY + HOUSEKEEPING
我想要以下结果
|---------------------|------------------|------------------|
| ID | NAME | DEPT |
|---------------------|------------------|------------------|
| 1 | BOB | Sales |
|---------------------|------------------|------------------|
| 3 | BOB | HouseKeeping |
|---------------------|------------------|------------------|
| 4 | SALLY | HouseKeeping |
|---------------------|------------------|------------------|
如上所述,逗号充当了“或”作为' OR'运算符和加号充当' AND'操作
我有点使用以下代码,但是我遇到了一些我不知道如何解决的问题。也许我没有正确地做到这一点,请告诉我,如果是这样,并指出我正确的方向。
以下代码将为我提供我想要的结果,前提是它们按此顺序排列。即searchterm1,searchterm2 + searchterm3
$("#myInput").on("keyup", function () {
var value = $(this).val().trim().toLowerCase();
var orConditions;
var andConditions;
if (value.indexOf(',') > -1) {
orConditions= value.split(',');
orConditions= orConditions.filter(r=>r != '');
}
$("#myTable tr").filter(function () {
$(this).hide().css('.excludeFromFilter');
});
$("#myTable tr").not('.excludeFromFilter').filter(function () {
if (value != '') {
if (orConditions) {
var length = orConditions.length;
var containsText = false;
while (length--) {
if (orConditions[length].indexOf('+') > -1) {
andConditions = orConditions[length].split('+');
andConditions = andConditions.filter(r=>r != '');
if ($(this).text().toLowerCase().indexOf(andConditions[0]) > -1 &&
$(this).text().toLowerCase().indexOf(andConditions[1]) > -1) {
containsText = true;
}
else {
containsText = false;
}
}
else {
if ($(this).text().toLowerCase().indexOf(orConditions[length]) > -1) {
containsText = true;
}
}
}
$(this).toggle(containsText);
}
else {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
}
}
else {
$(this).show().not('.excludeFromFilter')
}
});
var $table = $('.transSummary1');
$table.floatThead('reflow');
});
我面临的问题是:
对此的任何帮助将不胜感激。
答案 0 :(得分:1)
更新:我已修复逻辑以符合您的规范,如下面的评论中所述。我还在字符串中添加了修剪,以忽略每个参数上的左右间隔填充。
这里写出了jquery代码。请注意,这可以缩短和优化,但是,它是一种快速而肮脏的方式来完成您正在寻找的事情。另请注意,我已在第5行的keyup
事件处理程序中添加了一个变量,如果您希望搜索值以区分大小写,则可以将其设置为false。我这样做是为了让第一个值始终被认为是' OR'但是,如果第一个值以+
为前缀,则只会考虑AND处理程序。
请参阅下面包含HTML ID& s& amp;的代码的jsfiddle示例。分别是。请注意,我将class="avoid"
添加到<tr>
表行,以将其从行迭代中排除。
CSS
table {
width:100%;
border:1px solid rgba(0,0,0,0.15);
}
table tr td {
border:1px solid #CCC;
text-align:center;
}
#results { text-align: center; }
#filter-preview, .text-left { text-align:left; }
#caseinsensitive, .inline { display:inline-block; margin:3px; text-align:left; }
.input { display:inline-block; width:70%; }
input {
height:25px;
width:100%;
padding:5px;
vertical-align:middle;
border-radius:15px;
}
.hide td {
background-color:rgb(255,0,0);
/* Uncomment below to make rows hide. */
/* display: none; */
}
.or, .and {
display:inline-block;
vertical-align:center;
padding:3px;
text-align:center;
margin-right:3px;
border-radius:5px;
}
.or {
background-color: rgb(198, 248, 255);
border:1px solid rgb(119, 172, 178);
}
.and {
background-color: rgb(255, 240, 191);
border:1px solid rgb(234, 216, 77);
}
HTML
<table id="searchable-table">
<tr class="avoid">
<th>Search:</th>
<th colspan="2">
<input id="search-input" type="text" placeholder="Search here..."/>
</th>
</tr>
<tr class="avoid">
<td>Case Insensitive:</td>
<td colspan="2" class="text-left"><input id="caseinsensitive" type="checkbox" checked="checked"/></td>
</tr>
<tr class="avoid">
<td>Filters:</td>
<td id="filter-preview" colspan="2"></td>
</tr>
<tr class="avoid">
<th>ID</th>
<th>Name</th>
<th>Dept</th>
</tr>
<tr>
<td>1</td>
<td>BOB</td>
<td>Sales</td>
</tr>
<tr>
<td>2</td>
<td>SALLY</td>
<td>Sales</td>
</tr>
<tr>
<td>3</td>
<td>BOB</td>
<td>HouseKeeping</td>
</tr>
<tr>
<td>4</td>
<td>SALLY</td>
<td>HouseKeeping</td>
</tr>
<tr class="avoid">
<td id="results"colspan=3></td>
</tr>
</table>
Javascript / jQuery
/* NOTE: To make rows hide, adjust the CSS by uncommenting line 24. */
$(document).on('keyup', '#search-input', function() {
var rows = $('#searchable-table tr').not('.avoid'),
caseInsensitive = ($('#caseinsensitive').is(":checked")), //Set to false if you would like for the searches to respect case sensitivity.
query = parse_query((caseInsensitive === true ? $(this).val().toLowerCase():$(this).val())),
results = filter_rows(rows, query, caseInsensitive);
$('#results').empty().append(results+' record(s) found!');
});
$(document).on('change', '#caseinsensitive', function() {
$('#search-input').trigger('keyup');
});
//Filters rows based on search conditions (Highlights Red - See: CSS row 21)
function filter_rows(rows, query, caseInsensitive) {
var r = 0;
if(rows.length > 0) { //Check if there are any rows at all.
$.each(rows, function(e, k) { //Iterate rows.
var td = $(this).children('td'), //Get child cells of current row.
name = (caseInsensitive === true ? td[1].innerText.toLowerCase():td[1].innerText), //Get name in 2nd cell of current row.
dept = (caseInsensitive === true ? td[2].innerText.toLowerCase():td[2].innerText); //Get dept in 3rd cell of current row.
if(!jQuery.isEmptyObject(query.or)) { //Check if any OR values are available in the array.
if(isMatching(name, query.or) || isMatching(dept, query.or)) { //If name or dept is found matching in the 'OR' values, show row.
if($(this).hasClass('hide')) { $(this).removeClass('hide'); }
} else {
if(!jQuery.isEmptyObject(query.and)) {
if(isMatching(name, query.and) && isMatching(dept, query.and)) {
if($(this).hasClass('hide')) { $(this).removeClass('hide'); }
} else {
if(!$(this).hasClass('hide')) { $(this).addClass('hide'); }
}
} else {
if(!$(this).hasClass('hide')) { $(this).addClass('hide'); }
}
}
} else {
if(!jQuery.isEmptyObject(query.and)) {
if(isMatching(name, query.and) && isMatching(dept, query.and)) {
if($(this).hasClass('hide')) { $(this).removeClass('hide'); }
} else {
if(!$(this).hasClass('hide')) { $(this).addClass('hide'); }
}
} else {
if(!$(this).hasClass('hide')) { $(this).addClass('hide'); }
}
}
});
}
return r;
}
//Takes string and converts it to an object of arrays containing distinct AND + OR values seperately.
function parse_query(str) {
var or = str.split(","),
defaultOr = true, //If true, single value searches default as an 'OR' operator value.
params = {
'or':[],
'and':[]
};
if((or.length - 1) > 0 || (str.split("+").length - 1) > 0) { //If any 'AND' or 'OR' parameters found in string.
$.each(or, function(k,v) {
var and = v.split("+");
//If value contains any AND operators
if((and.length - 1) > 0) {
console.log('%o',and);
if(and[0].trim().length > 0) { //If the first value is not empty, add it to the 'OR' operator value list.
params.and.push(and[0].trim());
}
and.splice(0,1); //Remove 'OR' value from array
$.each(and, function(ka,va) { //Add additional 'AND' values if they exist in string.
if(va.trim().length > 0) {
params.and.push(va.trim());
}
});
} else {
if(v.trim().length > 0) {
params.or.push(v.trim());
}
}
});
} else { //If no delimeters found, default value to an operator (Default: 'OR').
if(str.trim().length > 0) { //If string is not empty.
if(defaultOr) {
params.or[0] = str.trim();
} else {
params.and[0] = str.trim();
}
}
}
populate_filter_preview(params);
console.log('%o',params);
return params;
}
//Populates Filter row with an example of the search that is filtering the rows.
function populate_filter_preview(params) {
var p = $('#filter-preview');
p.empty();
if(params.or.length > 0 || params.and.length > 0) {
if(params.or.length > 0) {
$.each(params.or, function(k,v) {
p.append('<span class="or">'+v+'</span>');
});
}
if(params.and.length > 0) {
$.each(params.and, function(k,v) {
p.append('<span class="and">'+v+'</span>');
});
}
} else {
p.empty();
}
}
//Simple short function to return boolean if string found in array.
function isMatching(s,a) {
return ($.inArray(s,a) > -1);
}
https://jsfiddle.net/Xonos/z87oqcf0/
上面的链接是上述代码的完整示例。