Why filter?
Selectors are good at finding a kind of element. Often, though, you want a particular one: the first row, every other row, the items above a price. jQuery's filtering methods take a selection and return a new, smaller jQuery object. Because they return a jQuery object, you can keep chaining.
Filtering by position
<ul>
<li>Monday</li><li>Tuesday</li><li>Wednesday</li><li>Thursday</li><li>Friday</li>
</ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const $days = $("li");
console.log("first ", $days.first().text());
console.log("last ", $days.last().text());
console.log("eq(2) ", $days.eq(2).text());
console.log("eq(-2) ", $days.eq(-2).text());
console.log("even ", $days.even().text());
console.log("odd ", $days.odd().text());
console.log("slice(1,3)", $days.slice(1, 3).text());
</script>first Monday
last Friday
eq(2) Wednesday
eq(-2) Thursday
even MondayWednesdayFriday
odd TuesdayThursday
slice(1,3) TuesdayWednesday- Positions count from 0:
.eq(0)is the first element,.eq(2)the third. - Negative numbers count from the end:
.eq(-1)is the last. .even()keeps positions 0, 2, 4 (the 1st, 3rd and 5th items);.odd()keeps 1, 3. This is the opposite of what the names suggest if you count from one, so check the output above..slice(start, end)keeps a range;endis not included.
A common use is striping a table:
<table>
<tr><td>Asha</td></tr><tr><td>Ben</td></tr><tr><td>Chen</td></tr><tr><td>Dev</td></tr>
</table>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("tr").odd().css("background", "#e0f2fe");
</script>Asha
Ben
Chen
Dev(Today a CSS rule, tr:nth-child(even), is the better tool for plain striping. jQuery filtering is useful when the condition depends on data.)
Filtering by selector
.filter(selector) keeps elements that match; .not(selector) removes them:
<ul>
<li class="done">Buy milk</li>
<li>Call Ravi</li>
<li class="done">Pay rent</li>
<li>Book tickets</li>
</ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const $tasks = $("li");
console.log("done:", $tasks.filter(".done").length);
console.log("to do:", $tasks.not(".done").text());
</script>done: 2
to do: Call RaviBook ticketsThe difference from a longer selector such as $("li.done") is that you can start from a selection you already have, perhaps passed into a function, and narrow it in several ways.
Filtering with your own test
When the condition is not something a selector can express, pass a function to .filter(). It runs once per element with two arguments, the index and the plain DOM element. Return true to keep the element:
<ul>
<li data-price="40">Apple</li>
<li data-price="120">Cherries</li>
<li data-price="10">Banana</li>
<li data-price="90">Mango</li>
</ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const $expensive = $("li").filter(function (index, element) {
return Number($(element).attr("data-price")) > 50;
});
$expensive.css("font-weight", "bold");
console.log($expensive.length, "items over 50:", $expensive.text());
</script>2 items over 50: CherriesMangoInside the function, this also refers to the current element, so you will often see $(this) used instead of $(element) in older code.
Keeping elements that contain something
.has(selector) keeps elements that have a matching descendant:
<div class="post"><h3>Post one</h3><img src="" alt="photo"></div>
<div class="post"><h3>Post two</h3></div>
<div class="post"><h3>Post three</h3><img src="" alt="photo"></div>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const $withImages = $(".post").has("img");
console.log($withImages.find("h3").text());
</script>Post onePost threeAsking a yes or no question
.is() does not return a selection. It returns true if at least one element matches, otherwise false. It is ideal inside if statements:
<input type="checkbox" id="terms">
<p id="box" class="warning">Check the terms first.</p>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
console.log("checked?", $("#terms").is(":checked"));
$("#terms").prop("checked", true);
console.log("checked now?", $("#terms").is(":checked"));
console.log("is a warning?", $("#box").is(".warning"));
console.log("is visible?", $("#box").is(":visible"));
</script>checked? false
checked now? true
is a warning? true
is visible? trueGoing back with .end() and .addBack()
Each filter creates a new selection and remembers the previous one. .end() returns to it, which lets one chain style two groups:
<ul><li>One</li><li>Two</li><li>Three</li></ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("li")
.css("color", "gray")
.first().css("color", "green").end()
.last().css("color", "red");
console.log($("li").map((i, el) => el.style.color).get().join(", "));
</script>green, gray, red.addBack() does the opposite: it adds the previous selection to the current one. Use both sparingly; long chains that jump back and forth are hard to read.
Common mistakes
- Counting from 1.
.eq(1)is the second element. - Expecting
.is()to return elements. It returnstrueorfalse. - Forgetting to return a value from a
.filter()function, which drops every element. - Using deprecated selectors such as
:eq(1)or:oddinside the selector string instead of the methods.
Exercise
From a list of five li items with numbers as text (3, 8, 15, 4, 23), select those greater than 5 and give them the class big. Log how many were selected.
Show one possible answer
<ul><li>3</li><li>8</li><li>15</li><li>4</li><li>23</li></ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const $big = $("li").filter(function () {
return Number($(this).text()) > 5;
}).addClass("big");
console.log($big.length);
</script>3It logs 3 (8, 15 and 23).
Key points
- Filtering methods return a new, smaller jQuery object, so you can keep chaining.
- .first(), .last(), .eq(n), .even(), .odd() and .slice() filter by position, counting from 0.
- .filter() keeps elements that match a selector or a function; .not() removes them; .has() keeps elements containing a match.
- .is() answers a yes or no question about a selection and returns true or false.