CodingBison

When jQuery selector returns a list, we can use the .each() method to iterate over elements of the list. However, sometimes we would want to avoid the iteration and grab the element or a subset in just one shot. For such use-cases, jQuery provides filters that are more selective. Being able to understand filters and using the correct filter will go a long way since otherwise, we would end up iterating over the list or a subset returned using a less-precise filter.

This page discusses basic filters and index-based filter. In addition to the filters described on this page, we also have DOM-specific filters; we will revisit them when we cover DOM and jQuery.

Basic filters

Let us begin with a table that provides some of the basic jQuery filters/qualifiers.


Table: Being more selective with HTML Elements
SelectionDescription
$(:first)Selects the first element from the list (while traversing)
$(:last)Selects the last element from the list (while traversing)
.first()Selects the first element from an existing list
.last()Selects the last element from an existing list
$(:not("foo"))Selects elements that do not match the criteria "foo"
.not("foo")Selects elements from an existing list that do not match the criteria "foo"
.filter("foo")Selects elements from an existing list that match the criteria "foo"

The $(:first) and $(:last) return the first and the last element from the list respectively. These filters are applied like a pseudo-class when specifying the list before we retrieve them using jQuery. With this pseudo-class approach, the elements are selected as the list is being generated (traversed). For example, if we wanted to select the first element from a CSS class ".classFoo", then we can do so using $(".classFoo:last"). With this the jQuery would look at elements of the classFoo and return the last one.

The next two filters are methods and apply on an existing list. The .first() and .last() methods return the first and the last element. Thus, if we want to get the first element from the CSS class ".classFoo", then we can do so using $(".classFoo").first(). So, here jQuery already has an existing list returned by $(".classFoo") and then, it applies the ".first()" method to that list.

The filters $(:not("foo") and .not("foo") have a similar story. The first filter is a pseudo-filter and jQuery uses this filter to select elements that do not belong to the specified criteria as and when it generates the list. On the other hand, .not("foo") is applied to an already existing list. So, if we have a list that has already been generated, then the second approach would be the way to go.

The last method is the .filter("foo") method and it applies to existing lists as well. Note that it is easy to think that the filter method would "filter" all the elements that specify the criteria but it is the other way around. It actually returns all the elements that match the specified criteria. If we want to truly filter the elements that match the criteria, then we should go with the .not("foo") method.

Now that are done with the introduction, let us see a simple example that demonstrates the usage of these filters. The example has two parts. The first (provided below) is the HTML part. The second part is the included JavaScript file, "filter.js". The HTML part embeds the JavaScript file.

Let us look at the HTML part first. It consists of an ordered list with CSS class "classOl" that contains 4 list elements, each with different CSS IDs.

 <!doctype html>
 <html>
 <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
 </script>

 <body>
 <div class="classTitle">Nobel Laureates:</div>

 <ol class="classOl">
     <li id="idPhys" class="classFoo">Marie Curie (Physics, 1903)</li>
     <li id="idChem" class="classFoo">Marie Curie (Chemistry, 1911)</li>
     <li id="idPhys2">Albert Einstein (Physics, 1921)</li>
     <li id="idPeace">Mother Teresa (Peace, 1979)</li>
 </ol>

 <script type="text/javascript" src="filter.js"></script>

 </body>
 </html>

Next, we provide below the "filter.js" file. The jQuery logic uses both the pseudo-class when selecting the element as well using the filter methods on an existing list.

 // Filename: filter.js

 $(document).ready(function() {
     var retList =  $("li"); // Get the list first.
     var str = "" 

     // Get the first element.
     str += "[li:first] " + $("li:first").text();
     str += "<br>[li .first()] " + retList.first().text() + "<br>";

     // Get the last element.
     str += "<br>[li:last] " + $("li:last").text();
     str += "<br>[li .last()] " + retList.last().text() + "<br>";

     // Exclude elements belonging to the "classFoo" class.
     str += '<br>[li:not(".classFoo")] ' + $('li:not(".classFoo")').text();
     str += '<br>[li .not(".classFoo")] ' + retList.not(".classFoo").text() + "<br>";

     // Get elements that belong to the "classFoo" class.
     str += '<br>[li .filter(".classFoo")] ' + retList.filter(".classFoo").text();

     // Append the text to the body element. 
     $("body").append(str);
 });

Note that if we were to use "ol:first" or "ol:last", then both would return only element since there is only one "ol" element --which happens to be the list. This is opposed to "li" which actually is a list of four elements.

Also, if were to do $('ol:not(".classFoo")'), then it will return the "ol" element which is the entire list. On the other hand, if we were to do $('ol').filter(".classFoo"), then it will return empty since there is only one "ol" element and that does not belong the class "classFoo".

When we load the above example, the output shows elements returned by various jQuery filters.



Figure: Using jQuery Basic Filters

Index-based filters

This set discusses filters that work based on indexing. Like before, let us begin with a table that provides these filters/qualifiers. Similar to JavaScript, jQuery lists also use 0-based indexing -- this means that the first element of the list has an index of 0, the second element has an index of 1, and so on.


Table: Being more selective with HTML Elements
SelectionDescription
$(:even)Selects all even elements from the list (is 0-index based)
$(:odd)Selects all odd elements from the list (is 0-index based)
$(:eq(n))Selects the nth element from the list
.eq(n)Selects the nth element from the list (is a method)
$(:gt(n))Selects elements from the list that have index greater than n
$(:lt(n))Selects elements from the list that have index less than n
.slice(n1,n2)Selects all elements from index n1 and up to index n2 (excludes n2)

Pseudo-class filters, $(:even) and $(:odd), return elements that have even and odd indices respectively. If we have a list with 5 elements, then these elements would have an index starting from 0 till 4. Accordingly, the $(:even) will return elements with indices 0, 2, and 4 and the $(:odd) will return elements with indices 1 and 3.

The pseudo-class filter $(:eq(n)) returns the element with index n from the list. Since this is a pseudo-class filter, jQuery applies this filter as and when it traverses the elements and the moment it finds the element with the n-th index, it returns. This is opposed to the .eq(n) method which applies to an already existing list.

The .slice(n1,n2) method allows us to return a smaller list starting from index n1 and up to index n2 from an existing (larger) list. If we skip the second argument, then it selects all the elements starting with index n1 and till the last; jQuery assumes that n2 equals the index of the last element of the array.

Methods .eq() and .slice() can also accept negative index numbers. When negative, an index number means that it should be counted from the end. Thus, .eq(-1) means the last element and .eq(-n) means the nth element counted from the last.

The pseudo-class filter, $(:gt(n)), returns all elements that have indices greater than n, excluding n. The pseudo-class filter, $(:lt(n)), return elements that have indices less than n, excluding n.

Note that while jQuery defines .eq(n) method in addition to the ":eq(n)" pseudo-filter, it does not provide any equivalent methods for lt and gt pseudo-filters. jQuery used to provide these methods in earlier versions, but these methods have been deprecated in favor of the slice() method. Thus, .lt(n) would be same as .slice(0,n) and .gt(n) would be same as .slice(n+1).

Here is an example that provides further insight into these index-based filters.

 // Filename: filter.js

 $(document).ready(function() {
     var str = ""
     // Select even/odd elements.
     str += "[li:even] " + $("li:even").text();
     str += "<br>[li:odd] " + $("li:odd").text();
     str += "<br>";

     // Select some index-based elements.
     str += "<br>[li:eq(2)] " + $("li:eq(2)").text();
     str += "<br>[li:gt(2)] " + $("li:gt(2)").text();
     str += "<br>[li:lt(2)] " + $("li:lt(2)").text();
     str += "<br>";

     var retList =  $("li"); // Get the list first.
     // Select an element using the .eq() method.
     str += "<br>[li .eq(2)] " + retList.eq(2).text();
     // Select elements using the .slice() method.
     str += "<br>[li .slice(1,3)] " + retList.slice(1,3).text();

     // Append the text to the body element. 
     $("body").append(str);
 });

If we load the above jQuery code embedded in the "selection_filter.html" file, then we would see the following text in the browser.



Figure: Using jQuery Index Filters

In the above example, if we were to do $("ol:odd"), then this will return empty since the "ol" list has only one element (with index as 0) and so there is no odd-indexed element. On the other hand, $("ol:even") will return the first (and the only) element. Along the same lines, "ol:eq(2)" and "ol:gt(2)" would also return no elements, but "ol:lt(2)" would return the (first) "ol" element.





comments powered by Disqus