The next level of complication is that type selectors can have additional conditions attached to them. The general form of a selector is a type selector followed by a condition. The problem is what to call these conditions. The CSS documentation calls them selectors which is confusing. Some of these conditions are also called pseudo classes. jQuery calls them selectors or filters. However, a filter has a very specific meaning in jQuery.
So we have no choice but to call them selectors, even though they are auxiliary conditions that apply to selectors.
Let's start by looking at one of the most easy to understand and easy to apply - the attribute selectors.
Elements can also be selected on the basis of their attributes. Recall that attributes are name value pairs that occur within tags. For example,
uses the HTML5 data-* attribute to record the number of items sold. If you haven't discovered data-* it is worth knowing about because it enables you to embed custom data in any HTML tag.
jQuery has lots of selector types that allow you to select elements based on attributes both their names and their values.
To pick out all of the elements of type T that have a particular attribute you would use T[name] where name is the full name of the attribute.
The square brackets generally indicate a selector that works with attributes.
For example, to select all of the elements with a data-sales attribute you would use:
Notice that the result would be an array of <div> elements that had a data-sales attribute not an array of attributes.
There are jQuery methods that allow you to retrieve and change attributes. For example:
retrieves the specified attributes from the first element in the array i.e 10.
You can also use the universal type selector to select any elements with a particular attribute.
selects any elements that have a data-sales attribute. Following the rule that you can drop the asterisk you can also write this as:
Which makes it look as if [name] is a selector all on its own - it isn't as there is an implied universal type selector. This is the reason that these extra conditions are often called selectors in their own right.
You can also select attributes based on their values. All of the following select elements with an attribute "name" with a condition on the value that it is set to:
[name="value"] set to "value
[name!="value"] set to something not equal to "value" or doesn't have the specified attribute.
[name^="value"] set to a something that begins with "value"
[name$="value"] set to something that ends with "value"
[name*="value"] set to something that contains "value"
[name~="value"] set to something that contains the word "value" i.e. delimited by spaces.
[name|="value] set to something that is value or starts with "value-" i.e. prefixed with value.
selects all elements with an attribute "data-sales" set equal to a value that starts with "2" - not generally useful!
Notice that the not-equal selector isn't quite as useful as it first appears. For example
doesn't select all the elements with data-sales attributes that are non-zero. It also selects all of the elements which don't have data-sales attributes.
The solution to this sort of problem is the multiple attribute selector.
If you write:
[attribute selector 1[[attribute selector 2]...
then all of the selectors are applied i.e. the selected elements have to satisfy the "and" of the attribute selectors.
For example to select all elements with data-sales attributes that are non-zero you would use:
Notice that attribute values are regarded as strings and so a data-sales attribute set to "00" is not equal to "0".
It is also worth knowing that the != attribute selector isn't a CSS selector which means that jQuery has to implement it from scratch and this makes it a more time consuming process.
There is a lot more to say about jQuery's extensions to the basic selectors.
Class And ID Revisited
The selectors that we have been using right from the start i.e. the class and id selectors are just special cases of the general ideas that we have been looking at. CSS defines two additional selectors T.name which selects all <T> elements with the attribute class=name and T#name which selects the <T> element with the attribute id=name.
You can see that using the default universal type selector this means you can write selectors without specifying a type so that .name selects all elements with the attribute class=name and #name selects all elements with the attribute id=name.
However, you can now also see that you can select elements according to class and id using:
There are some other shortcuts defined in CSS and jQuery for commonly used selectors.
The CSS Pseudo Classes
If we are restricting our attention to CSS selectors, there are only a few left - referred to as pseudo classes for reasons that aren't particularly important. Also, all they really have in common is that they start with a colon.
The one CSS pseudo class that jQuery supports is:
which selects all <T> that are the first child of their parent, i.e. that come immediately after their container's definition.
selects any <p> elements that are the first child of any other element.
This one example of a CSS pseudo class giving rise to lots of others that jQuery adds to the selectors you can use.
jQuery lets you combine complete selectors using the rules given for the type selectors listed earlier. That is, you can write things like
selects all <p> elements that are contained within a <div> element with a data-sales attribute.
You can see that this has the potential to become very complicated very quickly. Especially when you add all of the extra selector types that jQuery adds to the mix.
If you find that you are writing very complicated selectors you need to ask if it is really necessary. If it is, consider using the filter approach - build up an array of element that is bigger than you desire and then use the filter method to remove the ones you don't need. More about filters in a later article.
One of the interesting things about jQuery's approach to Ajax is that it can be extended in many ways. In the previous chapter we discovered that you can use converters to create your own data types, [ ... ]