0

I have a table that contains alot of data. i want my users to be able to search for any of the given fields and if a match is found the complete table row will be visible.

I started out by doing something like this:

    $('.table_column').each(function(){
    var content = $(this).html();
    if(!content.toUpperCase().contains(value.toUpperCase())){
        $(this).hide()
    }
});

However i quickly realised that this would just hide all the columns that doesnt match so this didnt work.

my table struckture looks like this:

<?php if (isset($vars['excel'])): ?>
<table class="table table-striped table-bordered table-hover" id="<?php echo $vars['list_id']?>">
    <thead>
        <tr>
            <th class="table-header">
                <input type="checkbox" id="select_all"/>
            </th>
            <th class="table-header">
                <img src="/site/resources/images/outlook.png">
            </th>
            <th class="table-header">
                <i class="fa fa-phone"></i>
            </th>
            <th id="phone_sort" class="table-header"> Telefon  <i class="fa fa-angle-down" style="float: right;"></i>
                <span class="hidden">sort_asc</span>
            </th>
            <th id="company_sort" class="table-header">
                Selvskab <i class="fa fa-angle-down" style="float: right;"></i>
                <span class="hidden">sort_asc</span>
            </th >
            <th id="zip_sort" class="table-header">
                Postnr  <i class="fa fa-angle-down" style="float: right;"></i>
                <span class="hidden">sort_asc</span>
            </th>
            <th id="name_sort" class="table-header">
                Fulde navn  <i class="fa fa-angle-down" style="float: right;"></i>
                <span class="hidden">sort_asc</span>
            </th>
            <th id="email_sort" class="table-header">
                Email  <i class="fa fa-angle-down" style="float: right;"></i>
                <span class="hidden">sort_asc</span>
            </th>
            <th class="table-header">
                <i class="fa fa-ban " style="color:#ff4330"></i>
            </th>
        </tr>
    </thead>
    <tbody id="body">
        <?php
        $excel = $vars['excel'];
        for ($i = 1; $i <= count($excel); $i++): ?>
            <tr class="table_elements" style="cursor: pointer">
                <td>
                    <input type="checkbox" class="" id="<?php echo $excel[$i]['row'] ?>" />
                </td>
                <td>
                    <img src="/site/resources/images/outlook.png">
                </td>
                <td>
                    <i class="fa fa-phone"></i>
                </td>
                <td class="table_column">
                    <?php echo $excel[$i]['telephone'] ?>
                </td>
                <td class="table_column">
                    <?php echo $excel[$i]['provider'] ?>
                </td>
                <td class="table_column">
                    <?php echo $excel[$i]['zip_code'] ?>
                </td>
                <td class="table_column">
                    <?php echo $excel[$i]['first_name'] . ' ' . $excel[$i]['last_name'] ?>
                </td>
                <td class="table_column">
                    <?php echo $excel[$i]['email'] ?>
                </td>
                <td>
                    <i class="fa fa-ban " style="color:#ff4330"></i>
                </td>
            </tr>
        <?php endfor; ?>
    </tbody>
</table>

Has anyone tried something like this and know a work around / hack to solve the problem?

Marc Rasmussen
  • 19,771
  • 79
  • 203
  • 364

2 Answers2

2

Firstly, do NOT get the html

Secondly Hide all and show what you want

Live Demo

$("#body tr").hide(); // hide the TRs in the TBODY only
$("#body tr:contains('"+value+"')").show();

To make case insensitive, you need to hack the contains:

https://stackoverflow.com/a/4936066/295783

$.extend($.expr[':'], {
  'containsi': function(elem, i, match, array)
  {
    return (elem.textContent || elem.innerText || '').toLowerCase()
    .indexOf((match[3] || "").toLowerCase()) >= 0;
  }
});

note that that will be used as :containsi instead of :contains

If you have a search box called id="search":

$(function() {
  $("#search").on("keyup",function() {
    $("#body tr").hide();
    $("#body tr:containsi('"+this.value+"')").show();
  });
});    

For a large table, try

$(function() {
  $("#search").on("keyup",function() {
    $("#body tr").each(function() {
      var $row = $(this);
      $row.toggle($row.containsi('"+this.value+"')"));
    });
  });
});    
Community
  • 1
  • 1
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • This seems like a good solution. I'm sure there are more efficient methods, but hard to beat the readability of two lines of code. My only major qualm is that this iterates all rows twice (once to hide, then again to check if they match filter to show). That could be subverted with the use of `.each` – crush Feb 05 '14 at 14:21
  • I will have to test, but I added an each – mplungjan Feb 07 '14 at 05:18
0

Here is an example of how this can be done, this is a bit more verbose than the other example, but it might be easier to add more of your own logic to it.

In my example a row will be shown if any of the written words match to some part of a td in a row.

Here is the fiddle: Fiddler

As a side not, if there is alot of data I would suggest server side searching instead, with a large enough dataset it will be faster.

First the HTML:

What are you looking for: <input type="text" id="searchbox"> <br />
<table id="searchMe">
    <tr>
        <td>one</td>
        <td>two</td>
    </tr>
    <tr>
        <td>three</td>
        <td>four</td>
    </tr>
    <tr>
        <td>five</td>
        <td>six</td>
    </tr>
</table>

Then the javascript:

$("#searchbox").keyup(function () { // listen to every key press
    var searchterms = $("#searchbox").val().toLowerCase().split(' '); // break apart your search terms to an array
    $('#searchMe tr').each(function (i, row) { // go through all table rows
        $(row).hide(1); // hide the row initially
        $("td", row).each(function (y, td) {
            var tdValue = $(td).text().toLowerCase(); // go through each td value
            searchterms.forEach(function (entry) {
                if (tdValue.indexOf(entry) != -1) {
                    $(row).show(1); // and show the entire row if we get a match on any of our search terms
                }
            });
        });
    });
});
JensB
  • 6,663
  • 2
  • 55
  • 94