2

In JQuery hiding a table row based on a predefined columns td value is easy using the following code.

function filterRows(word){
$('.application>tbody>tr')
.show()
.find('td:nth-child(2)').not(':contains("'+word+'")')
.parent()
.hide()
}

However how would I go about showing rows that match td values in more than one column.

Something like the following (which does not work)

function filterRows(word){
$('.application>tbody>tr')
.show()
.find('td:nth-child(2)').not(':contains("'+word+'")')
.find('td:nth-child(3)').not(':contains(30)')
.parent()
.hide()
}

Basically I want to be able to show only rows where my word is passed in "word" is in the second column td and the third column contains "30".

Thanks for any heads up.

4 Answers 4

5

You can use .end() to hop back in the chain, like this:

function filterRows(word){
  $('.application>tbody>tr').show()
    .find('td:nth-child(2)').not(':contains("'+word+'")').parent().hide()
    .end().end().end() //back 3 spots for parent, not and find
    .find('td:nth-child(3)').not(':contains(30)').parent().hide();
}

Though, in this case chaining is a bit verbose, just keep a reference in a variable, like this:

function filterRows(word){
  var rows = $('.application>tbody>tr').show();
  rows.find('td:nth-child(2):not(:contains("'+word+'"))').parent().hide();
  rows.find('td:nth-child(3):not(:contains(30))').parent().hide();
}

Or a bit more complex selector:

function filterRows(word){
  $('.application>tbody>tr').show()
    .find('td:nth-child(2):not(:contains("'+word+'")), td:nth-child(3):not(:contains(30))').parent().hide();
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the solution to my issue.I used the selector in the 3rd code block. Next stop is getting a book on JQuery and learning it in more depth to understand where selectors can be nested etc.
0

How about putting .parent() after the first find.

.find('td:nth-child(2)').not(':contains("'+word+'")').parent()

2 Comments

This would make the second find only look in the first find's results.
I think he is wanting to select rows which satisfies both conditions (conjunction), so hoping back in the previos set is not useful. Some experiments herE: jsfiddle.net/N25pM
0
function filterrows(word) {
  var row = $(".application>tbody>tr");
  row.each(function () {
    $this = $(this);
    var secondColumn = $('td:nth-child(2):not(contains("'+word+'"))', $this)
    var thirdColumn= $('td:nth-child(2):not(:contains("30")', $this)
    if (secondColumn.length && thridcolumn.length) {  //if you find both a second and third column that matches
      $this.hide();
    } else { //if the second and third column dont match
      $this.show();
    }
  });
}

1 Comment

This would fire up the selector engine 2n+1 times, n being the number of rows...plus create about 2n more jQuery objects...the performance would be very, very bad especially with larger tables. Also it's not correct, your if check would always be true since you're checking if(jQueryObject && jQueryObject).
0

Here's a more efficient way to do it:

function filterRows(word){
    $('.application>tbody>tr').show()
        .filter(function() {
            return this.cells[ 1 ].innerHTML.indexOf( word ) < 0 ||
                   this.cells[ 2 ].innerHTML.indexOf( "30" ) < 0;
        }).hide()
}

If there are nested tags, a slightly different approach should be taken in the filter. In that case, you would replace this.cells[ 1 ].innerHTML with:

(this.cells[ 1 ].innerText || this.cells[ 1 ].textContent)

(Same for cells[ 2 ] of course.)


EDIT: I had && instead of ||. Sounds like the requirement is to .show() if both matches are found. Fixed. Now it will hide if either match is not found.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.