Getting Started With jQuery - Advanced Filters
Written by Ian Elliot   
Thursday, 06 November 2014
Article Index
Getting Started With jQuery - Advanced Filters
Filter Functions and the Filter Stack

siblings, next, nextAll, nextUntil, prev, prevAll, prevUntil

Siblings are all of the elements immediately contained by the same container element. So for example in:

<div>
 <p>Zero</p>
 <p>One</p>
 <p class="title">Two</p>
 <p>Three</p>
 <p>Four</p>
</div>

all of the p elements are siblings and the div is the parent.

If you select the p element with text "Two" then the other two p elements are its siblings.

The p element containing "One" is the previous sibling of the one containing "Two" and the p element containing "Three" is the next sibling.

With these definitions it is easy to see what the sibling filters do. 

The siblings(selector) method selects all of the siblings of of each of the elements in the array. 

For example:

$(".title").siblings("p");

first returns all elements that have class set to "title". Then for each element in the array it returns all of the p elements that are its siblings. 

In this case the result would be the p elements containing the text "One" and "Three".

Notice that the original matching elements are not included in the result. 

The other filters work in the same sort of way.

The next(selector) and prev(selector) methods give you the next or previous siblings that match a selector if one is supplied. 

For example:

$(".title").next("p");

first selects the p element containing the text "Two" and then returns an array with its next sibling i.e. the p element containing the text "Three". 

In the same way:

$(".title").prev("p");

first selects the p element containing the text "Two" and then returns an array with its previous sibling i.e. the p element containing the text "One". 

The nextAll(selector) and the prevAll(selector) work in the same way as next and prev respectively but they return an array with all of the next and previous siblings i.e, not just one of the two adjacent to the selected element. 

For example:

$(".title").nextAll("p");

first selects the p element containing the text "Two" and then returns an array with its next siblings i.e. the p element containing the text "Three" and the one containing the text "Four". 

In ths same way:

$(".title").prevAll("p");

first selects the p element containing the text "Two" and then returns an array with its previous siblings i.e. the p element containing the text "One" and the one containing the text "Zero".

Finally the nextUntil(selector,filter) and prevUntil(selector,filter) work in the same general way as parentsUntil. That is nextUntil(selector,filter) extracts next siblings that match filter until it finds a selector. prevUntil works in the same way but for previous siblings.

For example if we have:

<div>
 <p>Zero</p>
 <div></div>
 <p>One</p>
 <p class="title">Two</p>
 <p>Three</p>
 <div></div>
 <p>Four</p>
</div>

then 

$(".title").nextUntil("div","p");

first selects the p element containing the text "Two" and then returns an array with its next p siblings until it reaches the first sibling that is a div i.e. it returns the p element containing the text "Three".

prevUntil works in the same way. For example:

$(".title").nextUntil("div","p");

first selects the p element containing the text "Two" and then returns an array with its previous p siblings until it reaches the first sibling that is a div i.e. it returns the p element containing the text "One".

justjquery

Filter Functions

As well as the standard filters you can easily create your own. The idea is that you pass in a function which is applied to each element in the results array. This is a very functional programming way of doing things but it suits the situation perfectly.

The filter method that we have already encountered called with a selector can also be called with a function. 

.filter(function);

the function is called for each element in the results array and only if the function returns true the element is included in the new results array. When the function is called it is passed the index of the element and the element itself in this.  You can also use an optional second parameter to get the current element.

For example the following function:

function odd(i){
 return i % 2==1;
}

tests for odd values - it is true if i is an odd number. You can use this to create a filter that removes all of the even index results:

$("p").filter(odd):

or more usually

$("p").filter(function(i){return i% 2==1;};

As this references the element at the ith position in the array you can also use this to find out more about the element and filter it accordingly. 

The only problem with this idea is that jQuery provides you with all the methods you could want to find out anything about an element without having to resort to a custom function. In practice you will usually find that there is a jQuery way of implementing any custom filter based on simple properties of the element. 

While you could use this to make changes to the element passed into the filter function this would not be a particularly obvious use of the filter method which really should attempt to be a pure filter i.e. just selecting elements. If you want to make changes then use the each(function) iterator. 

It works in the same way but it doesn't perform a filter action on the result array it simply applies the function. Although the return value isn't used to select elements if you return false the iteration is terminated. 

For example:

$("p").each(function(i){$(this).append(i.toString());});

adds a paragraph number to the end of each paragraph. Notice that the element that this is set to is a DOM object not a jQuery object. If you want to use jQuery methods then all you have to do is wrap this using $(this) as a jQuery object first. 

If you want to get access to what the function processes you can make use of local variable:

var text="";
$("p").each(function(i){ text+=$(this).text(); });

When the iteration is complete the text of all of the paragraphs will be found in the text variable. 

The map(function) filter works like a cross between filter and each. Its function is passed each index and element of the items in the results array but it returns an object to be included in a new jQuery results array. If you return an array of objects then all of them are inserted into the results array. If you return null or undefined no element is inserted. 

So for example:

$("p").map(function(i){ return this; });

returns the same jQuery result that $("p") produces. A useless operation but it does illustrate the general idea.

Another way of picking out the odd elements is:

$("p").map(function(i){
if(i% 2==1) return this;
return null;
});

In other words the element is returned if i is odd and null is returned if it is even. 

As a jQuery result array can contain plain JavaScript objects as well as DOM elements you can use map to do things that you can't do with simple filtering or with each. 

For example:

var result=$("p").map(function(i){
 return $(this).text();
});

Returns a jQuery result array with the text of each paragraph as an element. To convert the jQuery result array into a standard array you can use the get() method:

resultarray=result.get();

or you could use get(i) or [i] to work with the individual elements. 

Filter Stack

This is the final twist in the filter story.

If you have been following the description of how filters work then you will appreciate the idea that filters take one jQuery result array and convert it into another filtered result array. What hasn't been mentioned until now is that each time you create a new result array using a filter the old original unfiltered result array is kept just in case you want to use it again. You can restore the old result array in a number of ways, but the simplest is to use the .end() method. 

For example:

$("p");

produces a result array containing all of the p elements.  We can use the eq filter to reduce this to just the first p element and add some text:

$("p").eq(0).append("1");

If we now use .end we can return to the result array that had the entire set of p elements

$("p").eq(0).append("1").end();

Now we can filter again and add some text to the second p element;

$("p").eq(0).append("1").end().eq(1).append("2");

You can continue in this way using .end to return to a previous result array when ever you need to.

Usually this is about as complicated as it gets but each jQuery object maintains a stack of previous results so .end().end() returns to the result that you had before two filtering operations. 

Of course an alternative to using end() is to simply keep the intermediate results:

var result=$("p"):
result.eq(0).append("1"):
result.eq(1).append("2");

The end function and the stack simply makes it possible for you to do the same thing but using a fluent approach.

As well as end() there is also addBack(selector) method which filters the current result and then adds it to the new results. This is of course a silly operation to perform if the filter doesn't select additional elements - there is no point in eliminating some of the elements and then adding them back. This means that it really only makes sense to use it after a traversal filter. 

For example:

$("p").parent("div").addBack();

first selects all p elements, then selects all of the immediate parent div elements and then adds the original p elements back to the result array - note you get all of the p elements. 

You can also add a selector to filter the elements that are added back to the results:

$("p").parent("div").addBack(":eq(0)");

adds only the first p element back to the results.   

  

jquerycover

Chapter List 

  1. The DOM
  2. CSS Selectors
  3. Filters
  4. Advanced Filters
  5. Manipulating The DOM
  6. Promises & Deferred
  7. Promises, Deferred & WebWorkers
  8. Ajax the Basics - get
  9. Ajax the Basic -  post
  10. Ajax - Advanced Ajax To The Server 
  11. Ajax - Advanced Ajax To The Client
  12. Ajax - Advanced Ajax Transports And JSONP
  13. Ajax - Advanced Ajax The jsXHR Object
  14. Ajax - Advanced Ajax Character Coding And Encoding
  15. jQuery - Easy Plugins
  16. jQuery UI
  17. jQuery UI Custom Control - Widget Factory
  18. Getting Started With QUnit Testing
 

To be informed about new articles on I Programmer, install the I Programmer Toolbar, subscribe to the RSS feed, follow us on, Twitter, FacebookGoogle+ or Linkedin,  or sign up for our weekly newsletter.

 

Banner


JavaScript Jems - The Inheritance Tax

JavaScript should not be judged as if it was a poor version of the other popular languages - it isn't a Java or a C++ clone. It does things its own way.  In particular, it doesn't do inheritance  [ ... ]



JavaScript Jems - Objects Are Anonymous Singletons

JavaScript should not be judged as if it was a poor version of the other popular languages - it isn't a Java or a C++ clone. It does things its own way.  In particular, every object can be regard [ ... ]


Other Articles

 

 



Last Updated ( Tuesday, 25 August 2015 )