The Power of jQuery Selectors: Using Filter Selectors

Notice that the previous set of selectors all begin with a colon (:). This class of selectors is known as filters, because they filter a base selector. Just to add more to the jQuery filter mayhem, there are filters specifically for form elements, such as :button or :input, a filter for detecting if an element is in a state of animation, and other goodies. The jQuery docs classify the filter selectors into basic, visibility, content, child, and form. We talk about the :animated filter in Chapter 7.

1. Selection Using Basic Filters

Table 4-3 lists the basic filters available in jQuery. They all follow the same usage pattern as seen in the previous example.

2. Filtering Forms

As you well know, validating, parsing, and submitting form data is an everyday part of a web developer’s life. So jQuery, of course, contains filters that make it trivially easy to select form elements. When we mention form elements, we’re referring specifically to elements that belong to an HTML form used for submitting data to a server like button, input, or text area.

<!DOCTYPE html>

<html>

<head>

<script src=”http://code.jquery.com/jquery-1.7.1.js”>

</script>

<script>

$(function(){

var n = $(‘:input’).length;

console.log(n);

});

</script>

</head>

<body>

<form name=”” method=”post”>

<input type=”text” />

<input type=”hidden” />

<input type=”password” />

<input type=”radio” />

<input type=”reset” />

<input type=”submit” />

<input type=”image” />

<input type=”file” />

<input type=”checkbox” />

<input type=”reset” />

<input type=”button” value=”hit me”/>

<button>Hit me too</button>

<select>

<option>floor 1</option>

<option>floor 2</option>

</select>

<textarea></textarea>

</form>

</body>

</html>

Code snippet is from filtering-forms.txt

The :input selector gets all form controls including select, textarea, and button. There are also more specific filters for individual controls like :button, :password, and :text. As you’ve probably noticed, there’s a great amount of flexibility for how you select elements, and more than one way to get the same results. The following code snippet shows a few different ways to get all of the elements in the same form.

<!DOCTYPE html>

<html>

<head>

<script src=”http://code.jquery.com/jquery-1.7.1.js”>

</script>

<script>

$(function(){

var n1 = $(“input”).length;

var n2 = $(“:input”).length;

var n3 = $(“form > *”).length;

var n4 = $(“:text”).length;

var n5 = $(“input[type=’text’]”).length;

console.log(n1 + “,”+ n2 +”,”+ n3 + “,” + n4 + “,” + n5);

});

</script>

</head>

<body>

<form name=”” method=”post”>

<input type=”text” />

<input type=”text” />

<input type=”text” />

</form>

</body>

</html>

Code snippet is from multiple-form-filters.txt

If there had been a text area or button element, $(“form > *”) and $(“:input”) would’ve returned those elements as well. Table 4-4 summarizes all of the different form filters.

3. Filtering by Visibility

jQuery determines whether an element is visible depending on the properties offsetWidth and offsetHeight of an element. If both are zero, the element is considered hidden. If an element’s visibility is toggled directly changing its styling from display:block; to display:none; jQuery will detect those as visible/invisible, respectively. Use the :hidden and :visible filters to match each type. The next example demonstrates usage of the visible and hidden filters.

<!DOCTYPE html>

<html>

<head>

<script src=”http://code.jquery.com/jquery-1.7.1.js”>

</script>

<script>

$(function(){

var numlnv = $(“:text:hidden”).length;

var numVis = $(“:text:visible”).length;

console.log(numlnv);

console.log(numVis);

});

</script>

</head>

<body>

<form name=”” method=”post”>

<input type=”text” name=”text1″ style=”display:none;”/>

<input type=”text” name=”text2″ style=”offsetWidth:0; offsetHeight:0;”/>

<input type=”text” name=”text3″ style=”display:block;/>

</form>

</body>

</html>

Code snippet is from visibility-filters.txt

4. Filtering by Content

Sometimes you may want to select according to what an element does (or doesn’t) contain; for example, some text. Using the :contains() filter you can select an element that contains a matching text directly inside the element, inside of a descendant, or even a combination of both. The following code sample illustrates a use of contains. It selects all paragraphs that contain the text string “jenny” and stores them in a variable jennies.

<!DOCTYPE html>

<html>

<head>

<script src=”http://code.jquery.com/jquery-1.7.1.js”>

</script>

<script>

$(function(){

var jennies = $(“p:contains(‘jenny’)”).length;

console.log(jennies); // returns 2

});

</script>

</head>

<body>

<p>jenny smith</p>

<p>jennyjones</p>

<p>jim bob</p>

</body>

</html>

Code snippet is from content-filter.txt

A related selector, :has(), returns elements that contain at least one element that matches the specified selector. This allows you to select elements that have a descendent selector of a certain type amongst any of its children. You’re not limited to those with a matching direct child. The following code sample illustrates using :has() to select a div that contains a paragraph as one of its many children out of all the divs on a page.

<!DOCTYPE html>

<html>

<head>

<script src=”http://code.jquery.com/jquery-1.7.1.js”>

</script>

<script>

$(function() {

var hasDemo = $(“div:has(‘p’)”).attr(“id”);

console.log(hasDemo); // returns ‘yay’

});

</script>

</head>

<body>

<div id=”yay”>

<ul>

<li>

<p>The glorious paragraph</p>

<p>Another, glorious paragraph</p>

<p>The best paragraph yet</p>

</li>

</ul>

</div>

<div id=”nay”>

<ul>

<li> No paragraphs here. </li>

</ul>

</div>

</body>

</html>

Code snippet is from has-selector.txt

If you want to select an element that doesn’t contain anything, you can use the :empty() selector. This selector returns all elements that contain no children. This includes text.

<!DOCTYPE html>

<html>

<head>

<script src=”http://code.jquery.com/jquery-1.7.1.js”> </script>

<script>

$(function(){

var nothing = $(“p:empty”).length;

console.log(nothing) //returns 1

});

</script>

</head>

<body>

<div>

<p></p>

<p>something here</p>

</div>

</body>

</html>

Code snippet is from empty-selector.txt

The opposite of :empty() is :parent(). It selects elements that have children, The following code shows an example of using :parent() selecting a single div with children and logging the div’s ID.

<!DOCTYPE html>

<html>

<head>

<script src=”http://code.jquery.com/jquery-1.7.1.js”>

</script>

<script>

$(function(){

var parentDemo = $(“div:parent”);

console.log(parentDemo.attr(“id”)) //returns proudParent

});

</script>

</head>

<body>

<div id=”empty”></div>

<div id=”proudParent”>

<ul>

<li> Children! </li>

</ul>

</div>

</body>

</html>

Code snippet is from parent-selector.txt

It’s important to note that :parent() will select elements that contain child text nodes. This can include text nodes with just whitespace text as is illustrated in the following code sample. #empty isn’t really empty. It contains a space, so it will match as a :parent().

<!DOCTYPE html>

<html>

<head>

<script src=”http://code.jquery.com/jquery-1.7.1.js”>

</script>

<script>

$(function(){

var parents = $(“div:parent”).length;

console.log(parents) //returns 2

});

</script>

</head>

<body>

<div id=”empty”>

</div>

<div id=”proudParent”>

<ul>

<li> Children! </li>

</ul>

</div>

</body>

</html>

Code snippet is from whitespace-parent.txt

Table 4-6 lists jQuery’s available content filters.

5. Filtering by Relationships

The following code snippet demonstrates the use of filter selectors that match according to specific relationships, for example :first-child or :only-child.

<!DOCTYPE html>

<html>

<head>

<script src=”http://code.jquery.com/jquery-1.7.1.js”>

</script>

<script>

$(function(){

console.log( $(“div span:first-child”) )

//[span#turkey, span#bear, span#martian]

console.log( $(“div span:last-child”) )

//[span#hawk, span#horse, span#martian]

console.log( $(”div span:only-child”) )

//[span#martian]

console.log( $(”div span:nth-child(2)”) )

//[span#chicken, span#rabbit]

console.log( $(”div span:nth-child(2n+1)”) )

//[span#turkey, span#parrot, span#hawk, span#bear, span#fox, span#horse, span#martian] 

console.log( $(”div span:nth-child(even)”) )

//[span#chicken, span#pigeon, span#rabbit, span#monkey]

});

</script>

</head>

<body>

<div>

<span id=”turkey”>Turkey</span>
<span id=”chicken”>Chicken</span>
<span id=”parrot”>Parrot</span>
<span id=”pigeon”>Pigeon</span>
<span id=”hawk”>Hawk</span>

</div>
<div>

<span id=”bear”>bear</span>
<span id=”rabbit”>rabbit</span>
<span id=”fox”>fox</span>
<span id=”monkey”>monkey</span>
<span id=”horse”>horse</span>

</div>
<div>

<span id=”martian”>martian</span>

</div>

</body>

</html>

Code snippet is from relationship-filter.txt

Table 4-7 summarizes the position selectors of this section.

Source: Otero Cesar, Rob Larsen (2012), Professional jQuery, John Wiley & Sons, Inc

Leave a Reply

Your email address will not be published. Required fields are marked *