Search code examples
javascriptjquerylivesearch

Make Regex only filter table based on a single column


I made a phonebook where I work for internal use. All results are shown in a table. I used to just have this as my function to filter on that table:

function LiveSearch() {
    $('input#srch-field').on('keyup', function () {
        var rex = new RegExp($(this).val(), 'i');
        $('.srch-table tr').hide();
        $('.srch-table tr').filter(function () {
            return rex.test($(this).text());
        }).show();
    });
}

But my users are apparently unhappy with this requested function, so they want a filter instead. So I have made a dropdown that supposed to act like a filter. I was then looking at my function and was thinking "How can I modify this, to make it work generally the same?", so I came up with this:

function LiveSearch() {
    $('input#srch-field').on('keyup', function () {
        var rex = new RegExp($(this).val(), 'i');
        var e = document.getElementById("srchFilter");
        var filter = e.options[e.selectedIndex].value;
        if (filter === 'all') {
            $('.srch-table tr').hide();
            $('.srch-table tr').filter(function () {
                return rex.test($(this).text());
            }).show();
        } else {
            $('.srch-table tr[id=' + filter + ']').hide();
            $('.srch-table tr[id=' + filter + ']').filter(function () {
                return rex.test($(this).text());
            }).show();
        }
    });
}

The idea is that every value in my select:

<div class="form-group">
    <select id="srchFilter" class="form-control">
        <option value="all" selected="selected">No Filter</option>
        <option value="name">Name</option>
        <option value="title">Title</option>
        <option value="department">Department</option>
        <option value="private-phone">Private Phone</option>
        <option value="work-email">Work Email</option>
        <option value="work-phone-land">Work Phone Landline</option>
        <option value="work-phone-mobile">Work Phone Mobile</option>
    </select>
</div>

Corresponds to a Column ID in my table. But if my filter is anything but all it simply doesn't do any filtering whatsoever. I might just be misunderstanding how the regex works. Could anyone shed some light on it?

EDIT

The code for my Table as request:

<div class="col-lg-6" id="customtable">
    <table class="table table-striped" id="tablesorter">
        <thead>
            <tr>
                <th class="col-xs-4" id="name">
                    Name<span class="glyphicon glyphicon-filter"></span>
                </th>
                <th class="col-xs-4" id="title">
                    Title<span class="glyphicon glyphicon-filter"></span>
                </th>
                <th class="col-xs-4" id="department">
                    Department<span class="glyphicon glyphicon-filter"></span>
                </th>
                <th style="display: none;" id="private-phone">
                    Private Phone
                </th>
                <th style="display: none;" id="work-email">
                    Work Email
                </th>
                <th style="display: none;" id="work-phone-land">
                    Work Phone Landline
                </th>
                <th style="display: none;" id="work-phone-mobile">
                    Work Phone Mobile
                </th>
            </tr>
        </thead>
        <tbody class="srch-table" id="srch-table">
            <tr>
                <td class="col-xs-12"><b>Please Wait...</b></td>
            </tr>
        </tbody>
    </table>
    <div class="fl-separator"></div>
</div>

Solution

  • Please note that you are assigning duplicate IDs to the table elements (as I sniff from your JavaScript code). IDs should be unique across an HTML page, and that's why your filter won't work as expected.

    You can try to assign a class instead (or and HTML data attribute is recommended). So, for example, the td related to name will have a class name instead of id name.

    And then, your JavaScript code can be changed like this, so that it can leverage classes instead of ids:

    // ... code truncated for brevity
    
    if (filter === 'all') {
      $('.srch-table tr').hide();
      $('.srch-table tr').filter(function () {
        return rex.test($(this).text());
      }).show();
    } else {
      $('.srch-table tr').hide();
      $('.srch-table tr').filter(function () {
        return rex.test($(this).find('td.' + filter).text());
      }).show();
    }
    
    // ... code truncated for brevity
    

    Note the use of dot selector which matches the trs which only have tds with specified class.

    Bonus: Since you're using jQuery, these lines:

    var e = document.getElementById("srchFilter");
    var filter = e.options[e.selectedIndex].value;
    

    can simply be replaced by this line:

    var filter = $("#srchFilter").val();
    

    Update:

    This is a forked version of your fiddle which works.