πŸ“– Traversing the DOM with jQuery

Document Object Model (DOM)

There is an important concept in JavaScript that defines the way information is accessed in the web page. The document object contains all the information related to the display of the web page. All the elements are organized by relationship to each other in a tree-like structure. This is called the Document Object Model. It is a way of visualizing all the elements of the web page making access to those items more intuitive. There is a good explanation of the DOM at the W3 Schools. I've also included an example of using many of these methods in the Traversing the DOM Example page.

  • Elements nested inside of another element are children of that element.
  • All children of an element are siblings.
  • Elements that contain another element are the parent of that element.
Document Object Model (DOM) Explanation
CodeExplanation
<body>
  <h1>Main Title</h1>
  <div id="div1">
    <p id="p1">Some paragraph text</p>
    <p id="p2">More paragraph text</p>
    <figure>
      <img src="img1.png">
      <figcaption>My Picture</figcaption>
    </figure>
  </div>
  <div id="div2">
    <p id="p3">More paragraph text</p>
    <p id="p4">Blah blah blah</p>
  </div>
</body>

For the example code on the left, here are some of the relationships:

  • h1, div1, and div2 are children of body
  • p1, p2 and figure are children of div1
  • h1, div1 and div2 are siblings
  • p1, p2 and figure are siblings
  • div1 is the parent of p1, p2 and figure
  • figure is the parent of img and figcaption
  • #p2 and #p3 are children of #div2

Β 

DOM Traversing functions

For example purposes, the following code is used to help demonstrate how each of these functions work.

<div id="content">
	<div id="div1">
		<p>Some text</p>
		<p>More text</p>
	</div>
	<div id="div2">
		<div id="nav">
			<p><a href="index.html">Home</a> | <a href="about.html">About Us</a></p>
		</div>
		<div id="gallery">
			<p><img src="x"> <img src="y"> <img src"img3.jpg"></p>
		</div>
	</div>
</div>
jQuery Traversing Functions
SelectorExplanation
.find(selector)

Select elements within the current selection.

$('selector1').event(function() {
	$(this).find('selector2');
});
/* would find all instances of selector2 within selector1 */

/* Example (using html code above) */
$('#content').click(function() {
	$(this).find('div').css('border','red 2px solid');
}
/* puts a red border around div1, div2, nav and gallery */
.children(selector)

Selects only the immediate children of the current selection (not children of children).

$('selector1').event(function() {
	$(this).children('selector2');
});
/* would find all instances of selector2 that are children of selector1 */

/* Example */
$('#content').click(function() {
	$(this).children('div').css('border','red 2px solid');
});
/* puts a red border around div1 and div2 only */
.parent()

Locates the parent of the current element.

$('selector1').event(function() {
	$(this).parent().effect();
});

/* Example */
$('img').hover(function() {
	$(this).parent().css('border','red 2px solid');
});
/* puts a red border around the paragraph when you mouseover an image */
.closest(selector )

Locates the closest ancestor of the type selector.

$('selector1').event(function() {
	$(this).closest().effect();
});

/* Example */
$('img').hover(function() {
	$(this).closest('div').css('border','red 2px solid');
});
/* puts a red border around the gallery div when you mouseover an image */
.siblings(selector )

Selects all of the other elements at the same level of the DOM as the current element.

Selector is optional. If used, it will only select siblings of the specified type.

$('selector1').event(function() {
	$(this).siblings().effect();
});

/* Example */
$('img').hover(function() {
	$(this).siblings().css('border','none');
	$(this).css('border','red 2px solid');
});
/* removes the border from all of the other images in the same paragraph 
and places a red border around the current image */

.next(selector)

.nextAll()

Selects the next element at the same level as the current element.

Selector is optional. If used, it will only select siblings of the specified type.

$('selector1').event(function() {
	$(this).next().effect();
});

/* Example */
$('#div1').hover(function() {
	$(this).next('div').css('border','none');
	$(this).css('border','red 2px solid');
});
/* removes the border from div2 and places a red border around div1 */
/* nextAll() returns all of the next siblings for the selector */

.prev(selector)

.prevAll()

Selects the previous element at the same level as the current element.

Selector is optional. If used, it will only select siblings of the specified type.

$('selector1').event(function() {
	$(this).prev().effect();
});

/* Example */
$('#div2').hover(function() {
	$(this).prev('div').css('border','none');
	$(this).css('border','red 2px solid');
});
/* removes the border from div1 and places a red border around div2 */
/* prevAll() returns all previous siblings of the current element */
.end( )

Rewinds to the prior selection for nested selections.

$('selector1').event(function() {
	$(this).traverseFunction().effect().end();
	$(this).traverseFunction().effect();
});

/* Example */
$('#div2').hover(function() {
	$(this).find('#gallery').css('border','blue 2px dashed').end();
	$(this).find('#nav').css('border','red 2px solid');
});
/* The first line selects div2. */
/* The second line looks for #gallery and adds the border. */
/* end() returns the selection back to div2 and looks for #nav and adds the border to it. */
More HTML functions
wrap()

Wraps the contents of the selection in an html tag: $('selector').wrap('<htmlTag></htmlTag>');

Before
<p>
	<img src="x" height="100" width="80">
	<img src="x" height="100" width="80">
</p>
Example code
$('img').wrap('<figure></figure>');
After
<p>
	<figure>
		<img src="x" height="100" width="80">
	</figure>
	<figure>
		<img src="x" height="100" width="80">
	</figure>
</p>
unwrap()

Removes the parent tag from around a selection: $('selector').unwrap();

Before
<p>
	<figure>
		<img src="x" height="100" width="80">
	</figure>
    <figure>
		<img src="x" height="100" width="80">
	</figure>
</p>
Example code
$('img').unwrap();
After
<p>
	<img src="x" height="100" width="80">
	<img src="x" height="100" width="80">
</p>
wrapInner()

Wraps the contents of each element in the selection in an html tag: $('selector').wrapinner('<htmlTag></htmlTag>');

Before
<p>
	<img src="x" height="100" width="80">
	<img src="x" height="100" width="80">
</p>
Example code
$('p').wrapInner('<figure></figure>');

After
<p>
	<figure>
		<img src="x" height="100" width="80">
		<img src="x" height="100" width="80">
	</figure>
</p>
empty()

Removes all contents of the selector, but leaves the selector: $('selector').empty();

Before
<p>
	<img src="x" height="100" width="80">
	<img src="x" height="100" width="80">
</p>
Example code
$('p').empty();
After
<p></p>
Delegating Events

Delegating is used to add events to elements added to a page later. There are 2 methods.

on() (preferred method)

To delegate an event to items added after page load, add a second argument to the function which is a selector.

  • containerSelector refers to the parent of the selectors that will be bound to the event. This could be an id (#main), element (nav), or even the body element if there is no other parent element.
  • event is the type of event that will be bound to the selected nodes
  • selector is the selectors that will be bound to the event
  • objectliteral is the data to pass to the function
  • function can be an anonymous or named function.
$('containerSelector').on('event', 'selector', objectliteral, function() {
	//code to respond to event
});

/* Example */
$('body').on('mouseover', 'img', '{style: "red 2px solid"}', function(evt) {
	$(this).css('border',evt.data.style);
}
/* adds a red border around each image on the page when the user mouses over the image */
delegate()

bind() only affects existing elements. delegate() continues to apply to elements added later

$('containerSelector').delegate('selector', 'event', function() {
	//code to respond to event
});

/* Example */
$('body').delegate('img','mouseover',function() {
	$(this).css('border','red 2px solid');
}
/* adds a red border around each image when the user mouses over the image */
Useful Tips

$() is an alias for jQuery() - either can be used. A selection can be saved into a variable. This can be more efficient if the selection is called multiple times in a script and can make the code easier to read and follow.

It may help to minimize the number of times you change the DOM by placing all html into a variable and updating the page only 1 time whenever possible.

// to create the variable
var myId = $('#myId');

// to use the variable
myId.html = "<p>Some new content here</p>";

It is a good practice to optimize selectors to make scripts faster and more efficient.

  • Use ID selectors whenever possible - they are fastest, but only get one element.
  • To retrieve multiple elements, use as a descendent of an ID whenever possible. For example, all links within #nav instead of all links on the entire page.
  • Use the find() function.
  • Avoid too much specificity - too many descendents run slowly. Use only what is necessary.
jQuery Docs

jQuery Docs is found at http://docs.jquery.com and contains tutorials, help, getting started, etc. You will also find the jQuery API (Application Programming Interface) which is a great resource for detailed information of all jQuery functions, attributes, events, etc.

Examples
Adding a click event for a shopping cart.

Working from the HTML, create a click event that will select information from the item clicked and place it in a virtual shopping cart is really a process of hiding, showing and keeping track of the items in play. Here is an example of how to create this functionality.

First, you have to have the HTML coded correctly for you to acquire the information needed to track the items being moved to and from the shopping cart. We are going toΒ  create items that include an image, title, Add to Cart button and a star rating system. When an item is selected to be placed in the cart, the Add to Cart button should hide and the name of the item should appear in the cart with a new button for removing the item from the cart and placing it back "on the shelf".

<!-- Cart item -->
<figure>
   <figcaption>Image Name</figcaption>
   <img src="image1.jpg" class="flower" alt="Image Name">
   <span class="rating">
     <img src="staroff.gif"><img src="staroff.gif"><img src="staroff.gif"><img src="staroff.gif"><img src="staroff.gif">
   </span><br>
   <button class="add" id="image1" name="Image Name">Add to Cart</button>
 </figure>

<!-- Cart list -->
 <ul id="cart">
   <li id="empty">Your shopping cart is empty</li>
 </ul>

Next, we need to create a JS event to handle the changes. This event will add an item to the shopping cart and remove the "Add to Cart" button when an Add to Cart button is clicked. In order to add the related item to the cart, we need to collect the id and name of the item. We also need to check the cart to see if it is empty so we can hide the empty cart message if it is not.

/* Add to cart event */
$('.add').click(function () {
	var itemName = $(this).attr('name');
	var itemID = $(this).attr('id');
	shoppingCart++;
	if (shoppingCart > 0) {
		$('#empty').hide();
	}
	var cartLink = "<li class='cartItem' name='" + itemID + "'>" + itemName + " <span class='del'>Remove</span></li>";
	$('#cart').append(cartLink);
	$('#' + itemID).hide();
});