Page 1 of 2
When you first encounter filters they seem easy enough - just extract the results you want from the results you have. The trouble is that filters are fun and jQuery pushes the idea beyond the obvious. In this chapter we look at traversal filters and more.
Now Available as a Print Book:
You can buy it from:
USA and World Amazon.com
I The Core UI
- Understanding jQuery (Book Only)
- The DOM And Selectors
- CSS Selectors
- The jQuery Object (Book Only)
- Advanced Filters - Traversing The DOM
- Modifying DOM Objects
- Creating And Modifying The DOM
- jQuery Data
- Function Queues
- jQuery UI
- jQuery UI Custom Control - Widget Factory
- jQuery - Easy Plugins
- Getting Started With QUnit Testing
The companion volume will be available as a book very soon:
Just jQuery: Events, Async & Ajax
- Reinventing Events
- Working With Events (coming soon)
- Asynchronous Code (coming soon)
- Consuming Promises
- Using Promises (coming soon)
- Ajax the Basics - get
- Ajax the Basics - post
- Ajax - Advanced Ajax To The Server
- Ajax - Advanced Ajax To The Client
- Ajax - Advanced Ajax Transports And JSONP
- Ajax - Advanced Ajax The jsXHR Object
- Ajax - Advanced Ajax Character Coding And Encoding
jQuery has a tendency to classify anything that isn't a straightforward CSS standard selector as a filter. An additional confusion is that it is often said that there are two forms of filter - selector filters and results filters.
- A selector filter is added to a standard selector to reduce or refine the selection as it is being made.
- A result filter is applied to the jQuery result array to produce a new array with just the results that match the filter.
You might think that these were the only possible types of filter, but there is another - the traversal filters. These are strange in that they filter the results array and they also process the DOM to return elements that were not in the original results array.
In other words, traversal filters return new elements that are related to the elements in the results filter using information about how elements are nested within one another.
Let's see how this works.
The traversal filters are perhaps the most complicated because while they process the jQuery result to give you a new jQuery result array the way that they do it isn't just based on the immediate properties of the element. What is more, its results array isn't just a slimmed down version of the original results array, it can contain a completely new set of elements.
If you find any of the following difficult to understand skip forward to the first example of a traversal filter, has, and then come back and re-read this introduction.
The traversal filters allow you to make selections based on the position of the element in the entire DOM.
This is the first time it has been important to realize that each of the elements in the result object is a full DOM element and still located in the same place in the DOM tree as it always was.
That is, an element in the results array is not just an isolated DOM element - it is an element with a position in the current DOM tree.
For example, if there is a div element in the result it is in a particular position in the DOM tree and it has descendants - that is, the elements that it contains and elements that contain it. It is not just a general DOM element/ it is a particular DOM element within the web page at a particular location in the DOM tree.
The tree traversal filters process each element in the result and return a new jQuery result consisting of DOM objects that have a given relationship to the original elements in the DOM tree.
Perhaps the simplest to understand is the has method.
The has filter returns all of the elements in a result that have a descendant of the specified type, i.e. they contain an element of the specified type.
returns an array of div elements that contain a p element. Any divs selected by the initial selector that don't contain a p element are removed by the selector.
This is very much like the filters we have met before except that the condition for keeping an element now depends not on the element but on the DOM tree it is part of.
So for example, if the page is:
first extracts both divs and returns a result array with two elements, then has("p") filters the results to return a new array that consists only of the elements that contain a p - i.e. only the first div in this case. Notice that the single element that is returned is a div, i.e. the div that contains the p.
Now that you have seen the has filter selecting elements based on what they contain, you should be able to guess that there are filters that work with what the element is contained in - the parent filters.
Perhaps the next easy set of traversal filters to understand is the set that deals with parents of the elements in the result object.
An immediate parent is the DOM object that immediately contains the object. That is, if a paragraph is contained in a div
then the div is the paragraph's parent or more accurately its immediate parent.
The parent(selector) method filters the result object testing to see if the immediate parent of each one is selected by the selector. If it is then the parent that is selected is returned.
first selects all the p objects and then filters them to those that have a div as their immediate parents - and returns an array of the parent divs.
Notice that you do not get the p objects in the result as you would if this was a simple filter. You get the div elements which are the immediate parents of the p elements, i.e. you get elements that were not in the original array.
Of course the p elements are now the children of each of the divs in the result array.
You can now probably guess what parents(selector) does.
It filters the results array only now selecting elements that have at least one parent of the specified type and it returns an array containing all of the parents. That is, it is the same as parent, but not restricted to just the immediate parent.
first selects all of the p objects and then creates a result object that has each of the divs that contain the p object.
That is, if a paragraph is contained by three divs then there are three separate divs returned in the result. Notice that if the same element is selected more than once it still only occurs once in the result.
The big problem with parents is that it tends to return far too many elements - after all parents() with no selector returns everything that an element is contained in all the way up to the html object.
Often what you are looking for is the first parent of a particular type. For example, you want to find the closest div that encloses the element.
This is what the closest(selector) filter does. It searches up the DOM tree looking for the first parent that matches the selector.
first selects all of the p elements and then creates a result object that has the closest div element that contain each p element. Note the results array consists of div elements.
Notice that closest starts its search with the current element, i.e. the element in the array may be of the correct type to qualify as being the closest to itself.
The parentsUntil method provides another way to limit the results of a parent filter.
The parentsUntil(selector) method works exactly like parents, but it stops when the parent matches the selector. The results contain all the parents up to, but not including, the one that matched.
first selects all of the p objects and then creates a result object that has all of the parents of each p object up to but not including the first div. So if you had:
then the result set would include just the span. Again if the same elements are selected more than once they occur only once in the results.
To make parentsUntil slightly more complicated and slightly more useful you can also add a filter to specify the type of parent you are looking for. That is
returns only parents that match filter up to but not including the parent matched by selector.
will return only spans that are parents of the paragraph up to the first div.
The final member of the parent family is offsetParent.
This simply returns the closest parent, i.e. the first found going up the set of containers, that is positioned - i.e. has a relative, absolute or fixed position attribute. It is mostly used in animation because the closest positioned container determines where its children are positioned.
children, find, contents
Just as there are filters for parents there are some filters for children. Children are the elements that are contained by the selected element.
The children(selector) method gets the immediate children of each element in the array and filters them according to the selector.
If you have:
first returns an array of all p elements i.e. the only p element in this case. Next it finds the elements that are immediately contained by each p element and selects just the span elements. That is, it returns an array of all span elements that are immediate children of a p element. Which in this case is only the second span element because the first isn't an immediate child.
The find(selector) method extends the children method to return all of the children that match the selector not just the immediate children.
first returns an array of all p elements. Next if finds all of the elements contained within each paragraph element irrespective of how deeply nested and selects all of the span elements. In the case of the example above it returns both spans because they are both contained by the p.
There is one very special child filter that you really need to know about - the contents method returns all children including text nodes, comments and even the contents of iframes. It really does return the content of every element in the jQuery array.
returns an array with the complete content of every "p" element.