如何使用JQuery过滤表。使用OR和AND条件

时间:2018-06-18 13:53:25

标签: javascript jquery html-table tablefilter

我有一个表格,我想应用过滤。用户可以选择基于由逗号分隔的多个术语进行过滤。这些条款将是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');
 });

我面临的问题是:

  • 如果第一个词是' AND'条件然后所有行都被隐藏(我知道这是因为只有在有条件的情况下才会考虑' +'但是不知道怎么做解决这个问题并不重要,尤其是' OR'或' AND')
  • 如果我添加另一个' OR' ' AND'之后的术语然后没有考虑这个其他术语
  • 如何修改此设置以允许两个以上的' AND'条件,即searchterm1 + searchterm2 + searchterm3

对此的任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

更新:我已修复逻辑以符合您的规范,如下面的评论中所述。我还在字符串中添加了修剪,以忽略每个参数上的左右间隔填充。

这里写出了jquery代码。请注意,这可以缩短和优化,但是,它是一种快速而肮脏的方式来完成您正在寻找的事情。另请注意,我已在第5行的keyup事件处理程序中添加了一个变量,如果您希望搜索值以区分大小写,则可以将其设置为false。我这样做是为了让第一个值始终被认为是' OR'但是,如果第一个值以+为前缀,则只会考虑AND处理程序。

请参阅下面包含HTML ID&amp; s&amp; 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/

上面的链接是上述代码的完整示例。