Chapter 4. jQuery Web Page Manipulation: Mod the DOM

image with no caption

Just because the page is finished loading doesn’t mean it has to keep the same structure. Back in Chapter 1, we saw how the DOM gets built as the page loads to set up the page’s structure. In this chapter, we’ll look at how to move up and down through the DOM structure and work with element hierarchy and parent/ child relationships to change the page structure on the fly using jQuery.

The Webville Eatery wants an interactive menu

Alexandra, the head chef of the Webville Eatery, has a job for you. She’s been maintaining separate web pages for different versions of her menu: the regular menu and the menu with vegetarian substitutions. She wants you to make one page that will adjust the menu for the restaurant’s vegetarian customers.

image with no caption
image with no caption

Go vegetarian

Here’s what Alexandra would like you to do.

We want a Go vegetarian button that automatically substitutes the vegetarian options on our web page menu.

Here’s how our substitutions work:

  • We offer no substitutes for our fish entrées, so we need those removed.

  • We offer giant portobello mushrooms as a vegetarian substitute for our hamburgers.

  • We offer tofu as a vegetarian substitute for all of our meat and egg dishes except hamburgers.

  • We’ll need a button that restores the menu to its original state.

P.S. If you can pull it off, we’d also like a leaf icon to show up next to the substituted vegetarian entrees.

I had the web designer email you the files for the current menu so you can get started.

Note

There’s no exercise for it this time around—because you’re probably already thinking it—but be sure to write down what the requirements are in your own words so you know what you’re building here.

Before we write any jQuery, let’s look at the HTML and CSS files the web designer sent us, and see if their style and structure are up to snuff.

Brain Power

Regular web page structure (HTML) makes writing jQuery code much easier, but the ingredient elements we want to find aren’t labeled in a way that will make our jQuery code easier to write. How can we make our elements easier to select?

Class up your elements

As we’ve seen in each chapter so far, we can help jQuery find elements on web pages more effectively by setting up our HTML and CSS properly. To really make our structure sing, we should add classes and IDs to our style sheet and set our HTML elements’ attributes with the appropriate classes and IDs. This makes selecting elements easier and saves you coding time later on.

For jQuery, selectors aren’t just about controlling the look and feel of your page. Selectors allow jQuery to match (or query) elements on the page, too.

image with no caption
image with no caption

Button things up

Now that you’ve got things mostly set up, let’s go back to the napkin with the head chef’s requirements. Next up, you need to build two buttons.

— We want a Go vegetarian button that automatically substitutes the right vegetarian option on our web page menu.

— We’ll need a second button that restores the menu to its original state.

What’s next?

That was quick! You’ve got the two buttons set up. Let’s check those items off of the napkin and move on to the stuff that the Go vegetarian button needs to do.

— We want a Go vegetarian button that automatically substitutes the right vegetarian option on our web page menu.

— We’ll need a second button that restores the menu to its original state.

Here’s how our substitutions work:

  • We offer no substitutes for our fish entrées, so we need those removed.

  • We offer giant portobello mushrooms as a vegetarian substitute for our hamburgers.

  • We offer tofu as a vegetarian substitute for all of our meat and egg dishes except hamburgers.

Our next task is to tackle item 1 above: match li elements of the fish class and remove them from the menu. We matched elements with class selectors and used remove to take elements out of the DOM in Chapter 2.

jQuery also offers us the detach method. detach and remove both take elements out of the DOM. So what’s the difference between the two methods, and which one should we use?

image with no caption
image with no caption

Swinging through the DOM tree

In Chapter 1, we learned that the DOM is built like a tree. It has a root, branches, and nodes. The JavaScript interpreter in a browser can traverse (and then manipulate) the DOM, and jQuery is especially good at it. DOM traversal simply means climbing up and down and across the DOM.

We’ve been manipulating the DOM since Chapter 1. The detach method we just looked at is an example of DOM manipulation (i.e., we dynamically take elements out of the DOM).

But what is traversal really all about? Let’s take one section of the menu and visualize it as a DOM tree to see how traversal works.

image with no caption
image with no caption

Traversal methods let you select an element and grab other elements above, below, or beside it.

Let’s take a closer look at how you can grab those elements.

Traversal methods climb the DOM

To tell the DOM that we want to detach entrées whose menu lists contain fish, we have to reference elements by their relationship. jQuery’s traversal methods allow us to get at those element relationships.

image with no caption
image with no caption

Brain Power

Which of these methods can help us detach menu entrées with elements in the fish class?

Chain methods to climb farther

What if we want to climb higher, lower, or deeper? Strap on the chains, man! jQuery offers us method chaining. Method chaining lets us manipulate and traverse our pages in a more effective way. Here’s how it works:

image with no caption
image with no caption
image with no caption

Right. We can’t just detach the fish entrées and forget about them.

We’ll have to rethink our code a bit to make this work.

image with no caption

Brain Power

We need to bring back the fish entrées later. What should we do with them?

Variables can store elements, too

Variables must be pretty useful because we find ourselves needing them again. We’ve seen variables throughout the first three chapters, but we’ve only used them to store numbers and text strings. Wouldn’t it be convenient if JavaScript variables could store our elements too? As it turns out, they can.

image with no caption

The browser will hold those elements in memory temporarily. If we want to keep them to use in our program later, it’s a good idea to put them into a variable. But how do we do that?

There’s that dollar sign again...

Storing our elements is simple. We create a variable, just as we have for numbers and text strings, and set the variable (using the equals sign) to the statement that returns elements. But wouldn’t it be good to know when the variable is storing special stuff like elements (versus just numbers or text strings)? It’s common practice among jQuery coders to place a dollar sign in front of a variable that will be used to store elements returned from jQuery. That way, anyone else who looks at our code knows that we are using the variable to store stuff that we got from jQuery.

image with no caption
image with no caption

It is messy to store different elements in a variable.

That’s why jQuery uses JavaScript arrays to store elements. Let’s see what arrays are all about.

Expand your storage options with arrays

Any time we select elements from the DOM and store them in a variable, jQuery returns the data as an array. An array is simply a variable with greater storage options.

image with no caption

We can put stuff in and take things out of each storage slot. To put the value “15” into the third slot, we would write this:

image with no caption

Geek Bits

Arrays don’t have to start with a dollar sign ($). The practice of indicating a jQuery array with a dollar sign is a coding convention of jQuery developers.

Store elements in an array

When we select and detach the li elements and set a variable ($f) to the result, jQuery takes the elements the DOM returns and stores them neatly for us in a JavaScript array. When we want to put those elements back with the restore button, our job will be way less messy.

$f = $(".fish").parent().parent().detach();
image with no caption

jQuery takes the elements the DOM returns and stores them neatly for us in an array.

Relax

There’s a lot more to arrays.

But you don’t need to worry about that too much right now. We’ll get into a bunch more detail on arrays in Chapter 6.

Brain Power

We’ve seen how to take elements out of the DOM, but how do we dynamically replace DOM content with different content?

Change out elements with replaceWith

The replaceWith method allows you to replace selected element(s) with new ones. Whenever you want modify the DOM by exchanging one thing for another, you can use this handy jQuery method. Let’s say we want to dynamically change the heading level 2 element that says “Our Menu” to a heading level 1 that says “My Menu.” Here’s how you can do it using the replaceWith method:

image with no caption

How can replaceWith help?

You need to match li elements in the hamburger class and replace them with an li element of the portobello class. Let’s think about that problem before we write our code.

image with no caption

Think ahead before using replaceWith

What’s next on the checklist?

1.

Match li elements of the fish class and remove those entrées from the menu.

2.

Match li elements in the hamburger class and replace them with portobello mushrooms.

3.

Match li elements in the meat class and replace them with tofu.

You need to find entrées in the meat class and replace them with tofu.

image with no caption

Actually, we can’t use replaceWith for this one.

image with no caption

Brain Power

jQuery’s replaceWith method is straightforward and powerful, but unfortunately, it won’t help us solve this one. Why not?

replaceWith doesn’t work for every situation

The replaceWith method works well when you have a one-to-one replacement like exchanging the hamburger class for portbello class.

image with no caption

One–to–many substitution

But the scenario of trading out elements for the next item on our checklist isn’t one for one. We have to replace many different kinds of ingredients (i.e., turkey, eggs, steak, lamb chops) with one ingredient (tofu).

image with no caption

Many–to–one substitution

But when we want to select tofu and replace it later, we have a problem. When we want to put the different kinds of meat back in, the DOM has forgotten about them.

We could replace tofu with just one of the types of meat, but that’s not what we wanted at all.

So we’ll need to accomplish this menu substitution in two steps:

image with no caption
  1. Insert li elements of the tofu class into the DOM after the meat elements.

  2. Detach the elements of the meat class and hold them in a variable.

Insert HTML content into the DOM

Up to this point, we’ve either removed or replaced elements in the DOM. Fortunately for us, the creators of the jQuery library gave us many ways to insert stuff into the DOM. The ones we’ll look at are before and after.

before inserts content before the selected element.

image with no caption

after inserts content after the selected element.

image with no caption

You’ve accomplished each of the steps for the Go vegetarian button:

1.

Match li elements of the fish class and remove those entrées from the menu.

2.

Match li elements in the hamburger class and replace them with portobello mushrooms.

3.

Match li elements in the meat class and replace them with tofu.

Up next, we need to build the “Restore Menu” button. Here’s what that button needs to do.

Put the fish entrées back into the menu where we removed them (i.e., before the first menu item in the left column).

Find entrées that contain portobello mushrooms and replace them with hamburger.

Find entrées that contain tofu and replace them with the different kinds of meat (in the right order).

Let’s dig right in and look at what we need to do for the first one.

image with no caption

We know how to use before, but how do we specify the first child?

Use filter methods to narrow your selections (Part 1)

Fortunately, jQuery provides filtering methods that let us narrow our selection for problems like finding the first child. Let’s look at six of them (three on this page, three on the next).

first

eq

last

The first method will filter out everything but the first element in a selected set of elements.

The eq method will filter out everything but the element whose index number is equal to what you put in the parentheses in a selected set of elements.

The last method will filter out everything but the last element in a selected set of elements.

Let’s look at one item from our menu to see how these methods work:

image with no caption
image with no caption

Use filter methods to narrow your selections (Part 2)

Now let’s check out the slice, filter, and not methods, and how they work.

slice

filter

not

The slice method will filter out everything but elements with an index between the index numbers you put in its parentheses.

The filter method will filter out everything but elements that match the selector you put in its parentheses.

The not method will filter out everything that does not match the selector you place in the parentheses.

image with no caption

The filter and not methods let us use selectors to create a subset from the matched set using selectors as arguments of their methods.

image with no caption

Which of these methods will help you specify the first child on the menu?

Bring the burger back

So far for the “Restore Menu” requirement, we’ve got one item down, two to go:

Put the fish entrées back into the menu where we removed them (i.e., before the first menu item in the left column).

Find entrées that contain portobello mushrooms and replace them with hamburger.

Find entrées that contain tofu and replace them with the different kinds of meat (in the right order).

Our next checklist item seems a bit like déjà vu, doesn’t it? All we really need to do is reverse what we did for the original substitution. Why? Because we’re dealing with a one-to-one substitution, and we love one-to-one substitutions because they’re logically simple.

image with no caption

Where’s the beef (er...meat)?

We’re down to our last item for the “Restore Menu” button:

Put the fish entrées back into the menu where we removed them (i.e., before the first menu item in the left column).

Find entrées that contain portobello mushrooms and replace them with hamburger.

Find entrées that contain tofu and replace them with the different kinds of meat (in the right order).

What did we do with those li.meat elements again? Let’s review:

We put li.tofu elements into the DOM after the meat elements.

$(".meat").after("<li class='tofu'><em>Tofu</em></li>");

Then, we detached the li.meat elements but held on to them by saving them into $m.

$m = $(".meat").detach();

So where are those elements, and how do we bring them back?

A meaty array

Remember that whenever we store jQuery elements, we give the variable a dollar sign to signify that the variable we’re using has a special kind of storage. In this case, it’s a jQuery array, and here’s how the elements in $m are stored:

image with no caption

Brain Power

You need to put each li.meat element back in for each li.tofu element. You’ve seen many methods that put elements into the DOM. Which method would you use for this one?

The each method loops through arrays

In Chapter 3, you saw how to use the each method to loop through elements. We can use it again here to loop through all the meat elements in the $m array and put them back where they were. But to do that, we’ll need to check out a bit more about how the each method works.

The each method is like an assembly-line machine for your elements.

image with no caption
image with no caption

That’s it...right?

You did everything required for the “Restore Menu” button. Let’s update our files and call this project done.

Put the fish entrées back into the menu where we removed them (i.e., before the first menu item in the left column).

Find entrées that contain portobello mushrooms and replace them with hamburger.

Find entrées that contain tofu and replace them with the different kinds of meat (in the right order).

P.S. If you can pull it off, we’d also like a leaf icon to show up next to the substituted vegetarian entrées.

image with no caption

Oops, you’re right.

Luckily, the web designer already put the veg_leaf class in the my_style.css file. Let’s have a look at it.

image with no caption

Your jQuery Toolbox

You’ve got Chapter 4 under your belt and now you’ve added DOM manipulation and traversal, arrays, and filters to your toolbox.

DOM manipulation

You can add to, replace, and remove things from the DOM at will:

detach

remove

replaceWith

before

after

Arrays

jQuery arrays store all kinds of things, including elements, so you can access them later.

Just like with variables, put a $ in front of your array to signify that it is storing special jQuery goodies.

DOM traversal

This is all about climbing around the DOM tree so you can manipulate it.

You use element relationships with associated methods like parent and child to get where you want.

Chaining methods is an efficient way to traverse the DOM quickly.

Filters

Filter methods help you narrow down a set of selected elements:

first

equal

last

slice

filter

not

Get Head First jQuery now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.