The Total Newbie’s Guide to jQuery, Part II: Progressive Enhancement and the DOM

In last week’s article, we covered the most basic jQuery concepts. We’ve learned the steps to use the jQuery statement: make sure the document is ready, select elements, and change them. In this article, we’ll apply these lessons to implement some cool and useful effects—to reinforce your understanding of the jQuery basics.

This article is also taken from Chapter 2 of jQuery: Novice to Ninja by Earle Castledine and Craig Sharkie. You can download all of Chapters 1, 2, and 7 as a free PDF here. The download also includes the code archive for the whole book, so be sure to grab it if you want to follow along with the examples in this article.

Hiding and Revealing Elements

The client dislikes the disclaimer on the site—he feels it reflects badly on the product—but his lawyer insists that it’s necessary. So the client has requested that you add a button that will remove the text after the user has had a chance to read it:

Example 1. chapter_02/11_hiding/index.html (excerpt)

<input type="button" id="hideButton" value="hide" />


We’ve added an HTML button on the page with an ID of hideButton. When a user clicks on this button we want the disclaimer element, which has an ID of disclaimer, to be hidden:

Example 2. chapter_02/11_hiding/script.js (excerpt)

$('#hideButton').click(function() {  $('#disclaimer').hide();});


Run this code and make sure the disclaimer element disappears when you click the hide button.

The part in this example that makes the element actually disappear is the hide action. So, you might ask, what’s all the other code that surrounds that line? It’s what’s called an event handler—an understanding of which is crucial to becoming a jQuery ninja. There are many event handlers we can use (we’ve used the click event handler here) and we’ll be using a lot of them as we move on.

Event Handlers

Event handlers are named for their function of handling events. Events are actions and user interactions that occur on the web page. When an event happens, we say that it has fired. And when we write some code to handle the event, we say we caught the event.

There are thousands of events fired on a web page all the time: when a user moves the mouse, or clicks a button, or when a browser window is resized, or the scroll bar moved. We can catch, and act on, any of these events.

The first event that you were introduced to in this book was the document-ready event. Yes, that was an event handler: when the document said, “I’m ready” it fired an event, which our jQuery statement caught.

We used the click event handler to tell jQuery to hide the disclaimer when the button is clicked:

$('#hideButton').click(function() {  $('#disclaimer').hide();});

this

When an event fires, we will often want to refer to the element that fired it. For example, we might want to modify the button that the user has just clicked on in some way. Such a reference is available inside our event handler code via the JavaScript keyword this. To convert the JavaScript object to a jQuery object, we wrap it in the jQuery selector:

Example 3. chapter_02/12_this/script.js (excerpt)

$('#hideButton').click(function() {  $(this).hide(); // a curious disappearing button.});


$(this) provides a nicer way to talk about the element that fired the event, rather than having to re-select it.

tip: Where’s the Action?

This might be a bit confusing when you’re starting out, as the “action” component of a jQuery statement seems to have several purposes: we’ve seen it used to run animations, retrieve values and now, handle events! It’s true—it gets around! Usually the action’s name gives you a good clue to its purpose, but if you become lost, it’s best to consult the index. After a while, you’ll sort out the handlers from the animations from the utilities.

Revealing Hidden Elements

On with our task! The client has also specified that the user needs to be able to retrieve the disclaimer in case they close it by mistake. So let’s add another button to the HTML, this time with an id of showButton:

Example 4. chapter_02/13_revealing/index.html (excerpt)

<input type="button" id="showButton" value="show" />


We’ll also add another jQuery statement to our script file, to handle showing the disclaimer when the show button is clicked:

Example 5. chapter_02/13_revealing/script.js (excerpt)

$('#showButton').click(function() {  $('#disclaimer').show();});


Toggling Elements

Having separate buttons for hiding and showing the disclaimer seems like a waste of valuable screen real estate. It would be better to have one button that performed both tasks—hiding the disclaimer when it’s visible, and showing it when it’s hidden. One way we could do this is by checking if the element is visible or not, and then showing or hiding accordingly. We’ll remove the old buttons and add this nice new one:

Example 6. chapter_02/14_toggle_1/index.html (excerpt)

<input type="button" id="toggleButton" value="toggle" />


When it’s clicked, we check to find out if we should show or hide the disclaimer:

Example 7. chapter_02/14_toggle_1/script.js (excerpt)

$('#toggleButton').click(function() {  if ($('#disclaimer').is(':visible')) {    $('#disclaimer').hide();  } else {    $('#disclaimer').show();  }});


This introduces the is action. is takes any of the same selectors we normally pass to the jQuery function, and checks to see if they match the elements it was called on. In this case, we’re checking to see if our selected #disclaimer is also selected by the pseudo-selector :visible. It can also be used to check for other attributes: if a selection is a form or div, or is enabled.

important: The if Statement

If you’re entirely new to programming (that is, if you’ve only ever worked with HTML and CSS), that whole block of code is probably quite confusing! Don’t worry, it’s actually quite straightforward:

if (condition) {  // this part happens if the condition is true} else {  // this part happens if the condition is false}

The condition can be anything that JavaScript will evaluate to true or false. This sort of structure is extremely common in any type of programming, and we’ll be using it a lot for the rest of the book. If you’re uncomfortable with it, the best way to learn is to play around: try writing different if / else blocks using jQuery’s is action like the one we wrote above. You’ll get the hang of it in no time!

is will return true or false depending on whether the elements match the selector. For our purposes we’ll show the element if it’s hidden, and hide it if it’s visible. This type of logic—where we flip between two states—is called a toggle and is a very useful construct.

Toggling elements between two states is so common that many jQuery functions have a version that allows for toggling. The toggle version of show/hide is simply called toggle, and works like this:

Example 8. chapter_02/15_toggle_2/script.js (excerpt)

$('#toggleButton').click(function() {  $('#disclaimer').toggle();});


Every time you click the button, the element toggles between visible and hidden.

It would be nice, however, if the button was labeled with a more useful word than “toggle,” which might be confusing to our users. What if you want to toggle the text of the button as well? As is often the case when working with jQuery, there are a few ways we could approach this problem. Here’s one:

Example 9. chapter_02/16_toggle_text/script.js (excerpt)

$('#toggleButton').click(function() {  $('#disclaimer').toggle();  if ($('#disclaimer').is(':visible')) {    $(this).val('Hide');  } else {    $(this).val('Show');  }});


There’s a lot in this code that will be new to you. We’ll save most of the details for later, but have a look at it and see if you can figure it out yourself. (Hint: remember that the selector $(this) refers to the element that caused the event to fire—in this case, the button.)

Progressive Enhancement

Our disclaimer functionality is working perfectly—and our client will doubtlessly be impressed with it. However, there’s one subtle aspect of our solution that we should be aware of: if a user came to our site using a browser lacking support for JavaScript, they’d see a button on the page that would do nothing when they clicked it. This would lead to a very confused user, who might even abandon our site.

“No support for JavaScript?” you might snort. “What kind of browser is unable to run JavaScript?!”

There might be more people than you think browsing the Web without JavaScript: users on very old computers or limited devices (like mobile phones); people with visual impairments who require screen readers to use the Web; and those who worry that JavaScript is an unnecessary security risk and so choose to disable it.

Depending on your site’s demographic, anywhere between 5% and 10% of your users might be browsing without JavaScript capabilities, and nobody wants to alienate 10% of their customers! The solution is to provide an acceptable experience to these users—and beef it up for everyone else. This practice is known as progressive enhancement.

For our disclaimer functionality, we might settle on this compromise: we want the disclaimer to be visible to all users, so we place it in our HTML. Then, we add the ability to hide it for users with JavaScript. That said, we’d prefer to avoid displaying the show/hide button to users who’ll be unable to make use of it.

One way of accomplishing this might be to hide our button with CSS, and only show it via a jQuery css statement. The problem with this trick is that it will fail if the user’s browser also lacks support for CSS. What we’d really like to do is add the button to the page via jQuery; that way, only users with JavaScript will see the button at all. Perfect!

Adding New Elements

So far we’ve seen the jQuery function used for selecting, but it does have another function of equal importance: creating new elements. In fact, any valid HTML string you put inside the jQuery function will be created and made ready for you to stick on the page. Here’s how we might create a simple paragraph element:

$('<p>A new paragraph!</p>')

jQuery performs several useful actions when you write this code: it parses the HTML into a DOM fragment and selects it—just as an ordinary jQuery selector does. That means it’s instantly ready for further jQuery processing. For example, to add a class to our newly created element, we can simply write:

$('<p>A new paragraph!</p>').addClass('new');

The new paragraph will now be given the class new. Using this method you can create any new elements you need via jQuery itself, rather than defining them in your HTML markup. This way, we can complete our goal of progressively enhancing our page.

tip: innerHTML

Internally, the HTML string is parsed by creating a simple element (such as a div) and setting the innerHTML property of that div to the markup you provide. Some content you pass in is unable to convert quite as easily—so it’s best to keep the HTML fragments as simple as possible.

Once we’ve created our new elements, we need a way to insert in the page where we’d like them to go. There are several jQuery functions available for this purpose. The first one we’ll look at is the insertAfter function. insertAfter will take our current jQuery selection (in this case, our newly created elements) and insert it after another selected element, which we pass as a parameter to the function.

An example is the easiest way to show how this works. This is how we’d create the toggle button using jQuery:

Example 10. chapter_02/17_insert_after/script.js (excerpt)

$('<input type="button" value="toggle" id="toggleButton">')  .insertAfter('#disclaimer');$('#toggleButton').click(function() {  $('#disclaimer').toggle();});


As shown in Figure 1, “A button created and inserted with jQuery”, the button is inserted into our page after the disclaimer, just as if we’d put it there in our HTML file.

Figure 1. A button created and inserted with jQuery

A button created and inserted with jQuery


The insertAfter function adds the new element as a sibling directly after the disclaimer element. If you want the button to appear before the disclaimer element, you could either target the element before the disclaimer and use insertAfter, or, more logically, use the insertBefore method. insertBefore will also place the new element as a sibling to the existing element, but it will appear immediately before it:

Example 11. chapter_02/18_insert_before/script.js (excerpt)

$('<input type="button" value="toggle" id="toggleButton">')  .insertBefore('#disclaimer');


A quick refresher: when we talk about the DOM, siblings refer to elements on the same level in the DOM hierarchy. If you have a div that contains two span elements, the span elements are siblings.

If you want to add your new element as a child of an existing element (that is, if you want the new element to appear inside the existing element) then you can use the prependTo or appendTo functions:

Example 12. chapter_02/19_prepend_append/script.js (excerpt)

$('<strong>START!</strong>').prependTo('#disclaimer');$('<strong>END!</strong>').appendTo('#disclaimer');


As you can see in Figure 2, “prependTo and appendTo in action”, our new elements have been added to the start and the end of the actual disclaimer div, rather than before or after it. There are more actions for inserting and removing elements, but as they’re unneeded in this round of changes, we’ll address them later on.

Figure 2. prependTo and appendTo in action

prependTo and appendTo in action


important: Inserting Multiple Elements

A new item is inserted once for each element that’s matched with the selector. If your selector matches every paragraph tag, for example, the insertAfter action will add a new element after every paragraph tag. Which makes it a fairly powerful function!

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

No Reader comments

Comments on this post are closed.