The jQuery library harnesses
the power of Cascading Style Sheets (CSS) selectors to let us quickly
and easily access elements or groups of elements in the Document Object
Model (DOM). We will explore a few of these selectors,
as well as jQuery's own custom selectors. We'll also look at jQuery's DOM traversal methods that provide even greater flexibility for getting what we want.
The Document Object Model
One of the most powerful
aspects of jQuery is its ability to make selecting elements in the DOM
easy. The Document Object Model is a family-tree structure of sorts.
HTML, like other markup languages, uses this model to describe the
relationships of things on a page. When we refer to these relationships,
we use the same terminology that we use when referring to family
relationships — parents, children, and so on. A simple example can help
us understand how the family tree metaphor applies to a document:&;
<html>
<head>
<title>the title</title>
</head>
<body>
<div>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
<p>This is yet another paragraph.</p>
</div>
</body>
</html>
Here, <html> is the ancestor of all the other elements; in other words, all the other elements are descendants of <html>. The <head> and <body> elements are not only descendants, but children of <html>, as well. Likewise, in addition to being the ancestor of <head> and <body>, <html> is also their parent. The <p> elements are children (and descendants) of <div>, descendants of <body> and <html>, and siblings of each other.
An
important point to note before we begin is that the resulting set of
elements from selectors and methods is always wrapped in a jQuery
object. These jQuery objects are very easy to work with when we want to
actually do something with the things that we find on a page. We can
easily bind events to these objects and add slick effects to them, as well as chain
multiple modifications or effects together. Nevertheless, jQuery
objects are different from regular DOM elements or node lists, and as
such do not necessarily provide the same methods and properties for some
tasks.
The $() factory function
No matter which type of selector we want to use in jQuery, we always start with the dollar sign and parentheses: $().
Just about anything that can be used in a stylesheet can also be
wrapped in quotation marks and placed inside the parentheses, allowing
us to apply jQuery methods to the matched set of elements.
Making jQuery Play Well with Other JavaScript Libraries
In jQuery, the dollar sign $ is simply an "alias" for jQuery. Conflicts could arise if more than one of these libraries were being used in a given page because a $() function is very common in JavaScript libraries. We can avoid such conflicts by replacing every instance of $ with jQuery in our custom jQuery code.
Three building blocks of these selectors are tag name, ID, and class.
They can be used either on their own or in combination with other
selectors. Here is an example of what each of these three selectors
looks like on its own:
Selector
|
CSS
|
jQuery
|
Description
|
---|
Tag name
|
p
|
$('p')
|
Selects all paragraphs in the document
|
ID
|
#some-id
|
$('#some-id')
|
Selects the single element in the document that has an ID of some-id
|
Class
|
.some-class
|
$('.some-class')
|
Selects all elements in the document that have a class of some-class
|
When we attach methods to the $()
factory function, the elements wrapped in the jQuery object are looped
through automatically and implicitly. Therefore, we can usually avoid explicit iteration, such as a for loop, that is so often required in DOM scripting.
Now that we have covered the basics, we're ready to start exploring some more powerful uses of selectors.&;
CSS selectors
The jQuery library supports nearly all of the selectors included in CSS specifications 1 through 3, as outlined on the World Wide Web Consortium's site: http://www.w3.org/Style/CSS/#specs.
This support allows developers to enhance their websites without
worrying about which browsers (particularly Internet Explorer 6) might
not understand advanced selectors, as long as the browsers have
JavaScript enabled.&;
Responsible jQuery developers should always apply the concepts of progressive enhancement and graceful degradation
to their code, ensuring that a page will render as accurately, even if
not as beautifully, with JavaScript disabled as it does with JavaScript
turned on.
To begin learning how
jQuery works with CSS selectors, we'll use a structure that appears on
many websites, often for navigation — the nested, unordered list.
<ul id="selected-plays">
<li>Comedies
<ul>
<li><a href="/asyoulikeit/">As You Like It</a></li>
<li>All's Well That Ends Well</li>
<li>A Midsummer Night's Dream</li>
<li>Twelfth Night</li>
</ul>
</li>
<li>Tragedies
<ul>
<li><a href="hamlet.pdf">Hamlet</a></li>
<li>Macbeth</li>
<li>Romeo and Juliet</li>
</ul>
</li>
<li>Histories
<ul>
<li>Henry IV (<a href="mailto:henryiv@king.co.uk">email</a>)
<ul>
<li>Part I</li>
<li>Part II</li>
</ul>
<li><a href="http://www.shakespeare.co.uk/henryv.htm">
Henry V</a></li>
<li>Richard II</li>
</ul>
</li>
</ul>
Notice that the first <ul> has an ID of selected-plays, but none of the <li> tags have a class associated with them. Without any styles applied, the list looks like this:
The nested list appears as
we would expect it to — a set of bulleted items arranged vertically and
indented according to their level.
Styling list-item levels
L&;ets suppose that we want the top-level items, and only the top-level items, to be arranged horizontally. We can start by defining a horizontal class in the stylesheet:
.horizontal {
float: left;
list-style: none;
margin: 10px;
}
The horizontal class
floats the element to the left of the one following it, removes the
bullet from it if it's a list item, and adds a 10 pixel margin on all
sides of it.
Rather than attaching the horizontal class directly in our HTML, we'll add it dynamically to the top-level list items only — Comedies, Tragedies, and Histories — to demonstrate jQuery's use of selectors:
$(document).ready(function() {
$('#selected-plays > li').addClass('horizontal');
});
We begin the jQuery code with the $(document).ready() wrapper, that runs as soon as the DOM has loaded.
The second line uses the child combinator (>) to add the horizontal class to all top-level items only. In effect, the selector inside the $() function is saying, find each list item (li) that is a child (>) of the element with an ID of
selected-plays (#selected-plays).
With the class now applied, our nested list looks like this:
Styling all of the other items — those that are not in the top level — can be done in a number of ways. Since we have already applied the horizontal class to the top-level items, one way to select all sub-level items is to use a negation pseudo-class to identify all list items that do not have a class of horizontal. Note the addition of the third line of code:
$&;&;(document).ready(function() {
CSS selectorsnegation pseudo-class used$('#selected-plays > li').addClass('horizontal');
$('#selected-plays li:not(.horizontal)').addClass('sub-level');
});
This time we are selecting every list item (li) that:
Is a descendant of the element with an ID of selected-plays (#selected-plays)
Does not have a class of horizontal (:not(.horizontal))
When we add the sub-level class to these items, they receive the shaded background defined in the stylesheet. Now the nested list looks like this: