1

I'm trying to create a filter feature that removes certain scores from a table based on min and max value.

My HTML:

<table id="historyTable">
    <tr>
        <th>Game #</th>
        <th>Date</th>
        <th>Location</th>
        <th>Score</th>
        <th>Strikes</th>
        <th>Spares</th>
    </tr>
    <tr>
        <td>299</td>
        <td>29 Feb 2016</td>
        <td>Hello World Bowling Alley</td>
        <td>202</td>
        <td>6</td>
        <td>1</td>
    </tr>
    <tr> ...same thing as above repeated a few times </tr>
</table>

I've got a button that takes the user's input min and max values and passes it to the following JS function onclick:

function updateFilter(min, max) {
var table = document.getElementById('historyTable');   
var rowCount = table.rows.length-1; // since I don't want to include the header row

for(var i = 1; i<=rowCount; i++) {
    var scoreCheck = table.rows[i].cells[3].innerHTML;
    if(scoreCheck < min || scoreCheck > max) {
        $(table.rows[i].innerHTML).hide();
    }
  }
}

However, it doesn't seem to be working. What am I doing wrong?

7
  • Can you use jQuery? Also consider that hiding the rows via css may be a much easier solution. Commented Apr 8, 2016 at 22:20
  • 2
    $(table.rows[i].innerHTML) is wrong – when you pass HTML code (which is what .innerHTML returns) to $(), it will create new HTML elements out of it. You want to hide the table row, so $(table.rows[i]).hide() (Although that is a rather crude mix of “vanilla” JavaScript and jQuery you have there … why not use jQuery “all the way”, if you are using it already?) Commented Apr 8, 2016 at 22:22
  • Thank you, that works! I'm pretty new to Javascript so I'm not entirely sure what I've done there. How would I go about doing it entirely in jQuery? Commented Apr 8, 2016 at 22:26
  • @CBroe – you should add that as an answer, not a comment. Claim your reputation! :) Commented Apr 8, 2016 at 22:26
  • jQuery is a crutch you should not use until you know you need. You won't know you need until you first learn JavaScript. Commented Apr 8, 2016 at 23:51

2 Answers 2

1

Example (jsFiddle)

The fiddle includes some extra functions which were created to dynamically populate the table; however, this is the crux of the fiddle:

window.updateFilter = function(min, max) {
  var table  = document.getElementById('historyTable'),
      rows   = table.tBodies[0].rows,
      fields = { score: 3 };

  // loop over rows
  for (var i = 0, n = rows.length; i < n; i++) {
    // get the numerical score; notice the unary-plus (+) for integer conversion
    var scoreCheck = +rows[i].cells[fields.score].innerText;

    if (scoreCheck < min || scoreCheck > max) {
      hidden[i] = rows[i];               // cache hidden row
      rows[i].style.display = 'none';    // hide the entire row
    } 
    // if row has a good value, make sure its shown (unhide if hidden)
    else {
      // make sure another method didn't already unhide it
      if (hidden.hasOwnProperty(i)) {
        hidden['' + i].style.display = ''; // set the styling so its visible
        delete hidden[i];                  // no longer need the value in cache
      }
    }
  }

  return false;
}

If anything, your code $(table.rows[i].innerHTML).hide() is attempting to hide a property, which probably results in an error. You probably intended to hide the entire row:

$( table.rows[i] ).hide();
Sign up to request clarification or add additional context in comments.

Comments

1

These are the issues to correct:

  1. Don't use innerHTML in this selector as it will create a new element, only in memory, and act on that:

    $(table.rows[i].innerHTML)
    

    Instead you should select the row element without innerHTML.

  2. Without any code to show rows again, the effect of a second filter will not be as intended, because the previously hidden rows will not appear again if they fit the second filter. So you should better use toggle instead of hide and pass the boolean setting as argument.

  3. When you read the cell content, don't use innerHTML, but the plain text content. Then also convert it to number so numerical comparisons work.

  4. As you use jQuery, you could shorten your code quite a bit.

You could use this code:

function updateFilter(min, max) {
    // As you use jQuery, use it to its ful potential:
    $('#historyTable > tbody > tr > td:nth-child(4)').each(function() {
        // Don't retrieve HTML but text; convert to number with `+`
        var scoreCheck = +$(this).text();
        // Toggle instead of hide, so it works both ways:
        // Don't select providing HTML, but use a TR selector.
        $(this).closest('tr').toggle(min <= scoreCheck && scoreCheck <= max);
    });
}

$('#filter').click(function () {
    var min = +$('#min').val(); // invalid input will use 0 as minimum
    // Replace invalid max input with very high value, so everything will be shown
    var max = +$('#max').val() || 1e20;
    updateFilter(min, max);
});
th, td { border-bottom: 1px solid #ddd;}
tr:hover {background-color: #f5f5f5}
table {font-size: 11px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="historyTable">
    <tr>
        <th>Game #</th>
        <th>Date</th>
        <th>Location</th>
        <th>Score</th>
        <th>Strikes</th>
        <th>Spares</th>
    </tr>
    <tr>
        <td>299</td>
        <td>29 Feb 2016</td>
        <td>Hello World Bowling Alley</td>
        <td>202</td>
        <td>6</td>
        <td>1</td>
    </tr>
    <tr>
        <td>298</td>
        <td>13 March 2016</td>
        <td>Kuwait Open</td>
        <td>158</td>
        <td>5</td>
        <td>2</td>
    </tr>
    <tr>
        <td>297</td>
        <td>13 Oct 2015</td>
        <td>11th Columbia 300 Vienna Open</td>
        <td>213</td>
        <td>7</td>
        <td>1</td>
    </tr>
    <tr>
        <td>296</td>
        <td>20 Mar 2016</td>
        <td>Brunswick Euro Challenge</td>
        <td>259</td>
        <td>3</td>
        <td>2</td>
    </tr>
</table>
Min:<input id="min" size="6" value="180"> &nbsp; 
Max:<input id="max" size="6" value="210">
<button id="filter">Apply filter</button>

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.