Selecting Elements

Contact Us or call 1-877-932-8228
Selecting Elements

Selecting Elements

The most basic concept of jQuery is to "select some elements and do something with them". jQuery supports most CSS3 selectors, as well as some non-standard selectors. For a complete selector reference, visit http://api.jquery.com/category/selectors/.

$('#myId'); // note IDs must be unique per page
$('.myClass');    // all tags with the class myClass
$('div.myClass'); // performance improves if you specify element type
$('input[name=first_name]'); // beware, this can be very slow
$('#contents ul.people li');
$('#myId').addClass('red');

Pseudo-Selectors

Pseudo-selectors are special terms prefixed with a colon ( : ) symbol, which select based on some aspect of an element that jQuery can determine. The available selectors are listed below. For any indexed selectors, the indexing is zero-based. Note that the in item within a selector operates on what was found by the selector up to that point -- if the psuedo-selector is in the middle of the selector string, than it will be applied to all the elements found by the part of the selector to the left of that point.

Some of these are defined by CSS, others are specific to jQuery.

Note: many of these operations are also available as jQuery methods that operate on a selection, e.g., $('li').not('.selected') as opposed to $('li:not(.selected)')

State-Related

Selector Description
:animated Is currently animated by jQuery
:visible Is visible (more than just the display or visibility settings, like has a size greater than 0, and is attached to the DOM, and isn't an element outside the <body> tag
:hidden Is hidden -- the opposite of the above
:focus Currently has focus

Form Elements and States

Selector Description
:button <input type="button"> or <button>
:checkbox <input type="checkbox">
:file <input type="file">
:image <input type="image">
:input Any form control (<input>, <select>, <textarea> tags)
:password <input type="password">
:radio <input type="radio">
:reset <input type="reset">
:submit <input type="submit">
:text <input type="text"> or <textarea>
:disabled Any disabled form element
:enabled Any enabled form element
:checked Any checked element (radio or checkbox)
:selected Any <option> elements that are selected

Content-Related

Selector Description
:empty Has no children
:contains(text) Contains the specified text
:not(subselector) Does not match the subselector
:has(selector) Contains one or more elements found by the subselector
:first-child Is the first child of its parent
:last-child Is the last child of its parent
:only-child Is the only child of its parent
:nth-child(index) Is the child at the nth position within its parent
:header Is one of the header types (<h1>, <h2>, etc.)

Position of Element in Collection

Selector Description
:first The first element found by the selector
:last The last element found by the selector
:even Even-index elements within the collection -- the first element is even, since its index is 0
:odd Odd-index elements within the collection
:eq(index) At the index position within the collection
:gt(index) Position within the collection is greater than index
:lt(index) Position within the collection is less than index

Code Sample:

jqy-concepts/Demos/pseudo-selectors.html
---- C O D E   O M I T T E D ----
<script>
$(document).ready(function() {

	$('tr:odd').addClass('odd');
	
	// select all input-like elements in a form
	$('#myForm :input').addClass('yellowBg');

	// select all the visible elements
	$('div:visible').addClass('italic');
	// now unhide the hidden div - it should not be italic
	$('div:hidden').removeClass('noShow');
	
	// all except the first three divs
	$('div:gt(3)').addClass('redText');
	
	// all currently animated divs (not implemented here)
	$('div:animated');
});
</script>
<style>
.odd { background-color: #eeeeff; }
.yellowBg { background-color: yellow; }
.italic { font-style:italic; }
.redText { color: red; }
.noShow { display: none; }
</style>
</head>
<body>
<div>
<table border="1" cellspacing="0" cellpadding="8">
	<thead>
		<tr>
			<th>Name</th>
			<th>Age</th>
		</tr>
	</thead>

---- C O D E   O M I T T E D ----
</table>
</div>
<div>
<form id="myForm">
<input type="text" />
<textarea>Hello</textarea>
<select>
	<option>A</option>
	<option>B</option>
</select>
</form>
</div>
<div class="noShow">Not initially visible</div>
<div>The fourth div</div>
<div>The fifth div</div>
<hr />
</body>
</html>

Choosing Selectors

Choosing good selectors will improve the performance of your JavaScript. You should always consider the browser's JavaScript tools available to jQuery to process selectors:

document.getElementById(id) - very highly optimized, so a query starting with an id is always best. A tag-qualified id (div.#myId) is actually less efficient, and should be avoided unless you want to ensure that the element is indeed the specified tag type.

element.getElementsByTagName(tagName) - optimized by browsers, even for descendants that are not direct children. Use this to reduce the set of tags to be considered for more time-consuming operations, like those based on attributes or content.

element.querySelectorAll(selector) - optimized by browsers, and used by jQuery when available and applicable. It appears that the current implementation of jQuery will only use this for an entire selector, as opposed to using it for part of a selector string, and then applying additional logic, so it might be more efficient when using a jQuery-only psuedo-selector to apply it as a separate operation (i.e., invoke the corresponding method on a collection obtained by a selector that can use querySelectorAll)

Inspecting attributes and content - generally time-consuming, and not necessarily applied in an efficient fashion, so it is best to try to reduce the number of tags considered by this part of the selection process. For example, $('input[name=q]') is more efficient than $('[name=q]'), since only input tags need to be inspected for their name.

A little specificity, for example, including an element type such as div when selecting elements by class name, can go a long way. If you know that the CSS class myClass was only applied to div tags, then $('div.myClass') is more efficient than $('.myClass'), since jQuery can use getElementsByTagName('div') before inspecting the class attribute, reducing the number of tags to consider. Generally, any time you can give jQuery a hint about where it might expect to find what you're looking for, you should.

On the other hand, too much specificity can be a bad thing. A selector such as #myTable thead tr th.special is overkill if a selector such as #myTable th.special will get you what you want. Part of efficient jQuery is designing the HTML in a way that makes optimized selection possible.

jQuery offers many attribute-based selectors, including the ability to make selections based on the content of attributes using simplified regular expressions.

Code Sample:

jqy-concepts/Demos/choose-selector.html
<html>
<head>
<script src="../../jqy-libs/jquery.js"></script> 
<script>
$(document).ready(function() {
	// find all <p>s whose class attribute
	// ends with "text"
	$("p[class$='Text']").addClass("italic");
});
</script>
<style>
.italic { font-style:italic; }
.redText { color: red; }
.blueText { color: blue; }
.greenText { color: green; }
.yellowBg { background-color: yellow; }
</style>
</head>
<body>
<p class="redText">I have red text.</p>
<p class="blueText">I have blue text.</p>
<p class="greenText">I have green text.</p>
<p class="yellowBg">I'm a p tag with some other class.</p>
<p>I'm an ordinary p tag.</p>
</body>
</html>

While these can be useful in a pinch, they can also be extremely slow. Wherever possible, make your selections using IDs, class names, and tag names.

Also, possibly the biggest drawback, at least as far as using this approach with classes, is that it tests the ending of the entire string, not the end of each individual class name. So, for example, <p class="redText special"> would not be found by [class$=Text].

Avoiding Unwanted Elements

You should be careful when choosing a selector to avoid selecting more elements than you want. In particular, with elements that can contain like elements as descendants (like lists within lists, or tables within tables), this can be a problem. The best approach is to use an id selector first, if possible, to select the container for the elements you want to select, and then the CSS child selector (>) between the container and the children you want to select.

// Bad - will select great-grandchildren if there are inner lists
$('#myList li').remove();

// Good - will only select li children
$('#myList>li').remove();

Also, you should take precautions to prevent future changes to the HTML from breaking your code, or causing unwanted effects. For example, if a form currently has only one select element, you might be tempted to use a selector like #myForm select. But, if another select is added later, it would be affected as well. It would be better to use the name attribute to ensure that only this select is chosen (as in #myForm select[name=day]). Although attribute-based selectors can be inefficient when used indiscriminately, in this case there will only be a limited number of elements (hopefully just one) actually inspected for their name.

Does My Selection Contain Any Elements?

Once you've made a selection, you'll often want to know whether you have anything to work with. You may be inclined to try something like:

if ($('div.foo')) { ... }

This won't work. When you make a selection using $(), an object is always returned, and objects always evaluate to true. Even if your selection doesn't contain any elements, the code inside the if statement will still run.

Instead, you should test the selection's length property, which tells you how many elements were selected. If the result is 0, the length property will be treated as false when used as a boolean value.

if ($('div.foo').length) { ... }

Saving Selections

Every time you make a selection, a lot of code runs, and jQuery doesn't do caching of selections for you. If you've made a selection that you might need to make again, you should save the selection in a variable rather than making the selection repeatedly.

var $divs = $('div');

Once you've stored your selection, you can call jQuery methods on the variable you stored it in just like you would have called them on the original selection.

In the above code, the variable name begins with a dollar sign. Unlike in other languages, there's nothing special about the dollar sign in JavaScript -- it's just another character. We use it here to indicate that the variable contains a jQuery object. This practice -- a sort of Hungarian notation -- is merely convention, and is not mandatory.

A selection only fetches the elements that are on the page when you make the selection. If you add elements to the page later, you'll have to repeat the selection or otherwise add them to the selection stored in the variable. Stored selections don't magically update when the DOM changes.

Next