Manipulating Content and Attributes - The jQuery API - Web Development with jQuery (2015)

Web Development with jQuery (2015)

Part I. The jQuery API

Chapter 4. Manipulating Content and Attributes

jQuery is thorough; it provides everything you can imagine for working with content in the DOM. In Chapter 2, “Selecting and Filtering,” you saw how jQuery made it easy to fetch elements from the DOM via its fine-grained support for selecting and filtering selections. Then in Chapter 3, “Events,” you saw how jQuery wraps and extends the W3C event model to make it less verbose while also providing vastly more functionality. This chapter continues the discussion of jQuery's API components with an in-depth look at the methods that jQuery makes available for manipulating content and attributes. No longer do you have to worry about whether a browser supports the innerText or textContent properties, or the outerHTML property, or what the standard DOM method of removing an element from a document is. (You should know how to do those things anyway.) jQuery paves right over these verbose and sometimes fragmented methods with a rock-solid API that just works.

This chapter covers how you can shuffle DOM content around, doing things like replacing one element with another, inserting new text or HTML, appending or prepending content, cloning content, and getting rid of content.

It also covers how you manipulate attributes using jQuery, another area that jQuery makes smooth and easy by providing all the methods you'd need to use in the library. Or maybe you've had an occasion to want to save custom data with an element; jQuery provides this, too.

Setting, Retrieving, and Removing Attributes

Working with attributes is easy with jQuery. Like everything you do with jQuery, first you make a selection, and then after you've made a selection, you can do something with that selection, like setting or accessing attributes. Setting attributes on a selection sets those attributes on every element that you've selected. You can set the value of one or more attributes on one or more elements, simultaneously. Retrieving an attribute's value is also easy; after you've made a selection, accessing an attribute's value provides you with the attribute value of the first element in the selection. Finally, removing attributes is just as straightforward: When you remove an attribute, it removes that attribute from each element in the selection. If you attempt to retrieve an attribute after removing it, it returns undefined.

The following document, which appears in the source code download from www.wrox.com/go/webdevwithjquery as Example 4-1, demonstrates these concepts:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>The Marx Brothers</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-1.js'></script>

<link href='Example 4-1.css' rel='stylesheet' />

</head>

<body id='documentAttributes'>

<form action='javascript:void(0);' method='get'>

<ul>

<li>

<input type='radio'

name='documentAttributeMarx'

id='documentAttributeGrouchoMarx'

value='Groucho' />

<label for='documentAttributeGrouchoMarx'>

Groucho

</label>

</li>

<li>

<input type='radio'

name='documentAttributeMarx'

id='documentAttributeChicoMarx'

value='Chico' />

<label for='documentAttributeChicoMarx'>

Chico

</label>

</li>

<li>

<input type='radio'

name='documentAttributeMarx'

id='documentAttributeHarpoMarx'

value='Harpo' />

<label for='documentAttributeHarpoMarx'>

Harpo

</label>

</li>

<li>

<input type='radio'

name='documentAttributeMarx'

id='documentAttributeZeppoMarx'

value='Zeppo' />

<label for='documentAttributeZeppoMarx'>

Zeppo

</label>

</li>

</ul>

<p>

<button id='documentSetAttribute'>

Set Attribute

</button>

<button id='documentRetrieveAttribute'>

Retrieve Attribute

</button>

<button id='documentRemoveAttribute'>

Remove Attribute

</button>

</p>

</form>

</body>

</html>

The following style sheet is linked to the preceding document:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

body#documentAttributes ul {

list-style: none;

margin: 0;

padding: 0;

}

body#documentAttributes ul li.disabled label {

opacity: 0.5;

}

And the following JavaScript is also linked to the preceding document:

$(document).ready(

function()

{

var getCheckbox = function()

{

var input = $('input[name="documentAttributeMarx"]:checked');

if (input && input.length)

{

return input;

}

$('input[name="documentAttributeMarx"]:first')

.attr('checked', true);

return getCheckbox();

};

$('button#documentSetAttribute').click(

function(event)

{

event.preventDefault();

var input = getCheckbox();

input

.attr('disabled', true)

.parent('li')

.addClass('disabled');

}

);

$('button#documentRetrieveAttribute').click(

function(event)

{

event.preventDefault();

var input = getCheckbox();

alert('Disabled: ' + input.attr('disabled'));

}

);

$('button#documentRemoveAttribute').click(

function(event)

{

event.preventDefault();

var input = getCheckbox();

input

.removeAttr('disabled')

.parent('li')

.removeClass('disabled');

}

);

}

);

The preceding example demonstrates how you use jQuery's attr() and removeAttr() methods to set the disabled attribute on the selected radio <input> element. The preceding example produces something similar to what you see in Figure 4.1, upon clicking the Set Attribute button.

image

Figure 4.1

In the JavaScript source code, the first thing you do is set up a reusable method to retrieve the correct check box element. This method is aptly named getCheckbox().

var getCheckbox = function()

{

var input = $('input[name="documentAttributeMarx"]:checked');

if (input && input.length)

{

return input;

}

return $('input[name="documentAttributeMarx"]:first')

.attr('checked', true);

};

First, you use a selector to find the right set of check boxes, which is done with an attribute selector, input[name=”documentAttributeMarx”], and then is further narrowed down using jQuery's :checked pseudo-class. The attribute selector selects all four radio <input>elements, and then the selection is immediately narrowed to include only those with the checked=”checked” attribute, indicating a user selection. The function makes sure that an element was found with the line input && input.length; if there is an <input> element, it is returned. If there is no <input> element, the check box collection is selected again and this time is narrowed to the first item present in the selection using jQuery's :first pseudo-class. The first item is explicitly checked with attr('checked', true). You can also useattr('checked', 'checked'), if you like; both methods result in the check box being checked. The method then returns the first <input> element, ensuring that the method works whether an <input> element is checked.

The next block of code handles what happens when you click the button labeled Set Attribute:

$('button#documentSetAttribute').click(

function(event)

{

event.preventDefault();

var input = getCheckbox();

input

.attr('disabled', true)

.parent('li')

.addClass('disabled');

}

);

The Set Attribute button disables the selected radio box with the disabled=”disabled” attribute and then adds the disabled class name to its parent <li> element. Adding the disabled class name to the parent <li> element allows the opacity of the <label> to be manipulated to further provide the impression of the item being disabled.

The second button, labeled Retrieve Attribute, retrieves the current value of the disabled attribute. Because this is a boolean attribute, its possible values are either “disabled” or undefined. Figure 4.2 shows retrieval with the disabled attribute applied.

image

Figure 4.2

Retrieving the attribute is as simple as calling attr('disabled') on the selection.

$('button#documentRetrieveAttribute').click(

function(event)

{

event.preventDefault();

var input = getCheckbox();

alert('Disabled: ' + input.attr('disabled'));

}

);

The third block of code removes the disabled attribute with the removeAttr() method.

$('button#documentRemoveAttribute').click(

function(event)

{

event.preventDefault();

var input = getCheckbox();

input

.removeAttr('disabled')

.parent('li')

.removeClass('disabled');

}

);

The removeAttr('disabled') method completely removes the disabled attribute from the DOM. When working with boolean HTML attributes, jQuery also allows setting a boolean value using the attr() method, so attr('disabled', false) is functionally the same asremoveAttr('disabled'). After removing the disabled attribute, you have the result in Figure 4.3.

image

Figure 4.3

When you attempt to retrieve the value of the disabled attribute after using either removeAttr('disabled') or attr('disabled', false), you get a result of undefined, as shown in Figure 4.4.

image

Figure 4.4

Setting Multiple Attributes

Setting multiple attributes is done by providing a JavaScript Object Literal to the attr() method, which is demonstrated in the following example:

var input = $('<input/>').attr({

type : 'radio',

name : 'documentAttributeMarx',

id : 'documentAttributeGrouchoMarx',

value : 'Groucho'

});

The preceding example creates a new <input> element using jQuery identical to this one in HTML:

<input type='radio'

name='documentAttributeMarx'

id='documentAttributeGrouchoMarx'

value='Groucho' />

Passing a string such as '<input/>' tells jQuery to create a new element by parsing the snippet of HTML you've passed to it. In this example, you create a single new element, which can then be manipulated using jQuery's various API methods: You call the attr()method and pass an object containing the type, name, id, and value attributes and their corresponding values.

The resulting element assigned to the variable named input can then be further operated on with other API methods or inserted into the document using the various methods you learn about later in this chapter, such as html(), prepend(), append(), and so on.

Manipulating Class Names

In earlier chapters, you've seen examples of the addClass(), hasClass(), removeClass(), and toggleClass() methods that jQuery uses to manipulate class names.

It is considered best practice in client-side web development to avoid placing style declarations directly in your JavaScript code and instead maintain a separation of behavior and presentation by placing styles in CSS and manipulating the class names of elements for situations in which you require a dynamic change of style. This is considered best practice for a reason: It keeps things neatly organized and obvious; you don't need to search for style changes in JavaScript or HTML, only in the style sheets. Because all your presentation is neatly contained in CSS, your behaviors in JavaScript, and your structure in HTML, your documents become easier to manage because it's more predictable where to look to make a modification. If your styles are scattered inline in HTML, in the JavaScript, and in style sheets, then it becomes an order of magnitude more difficult to change the presentation of a document because now you have to track down which document contains the change. No big deal for a small web page, but when you scale up to a large website or application, those conventions come into play.

The following example demonstrates the four methods jQuery provides to manipulate and check for the existence of one or more class names. This example appears in the source code download materials from www.wrox.com/go/webdevwithjquery as Example 4-2.

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>John Lennon Albums</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-2.js'></script>

<link href='Example 4-2.css' rel='stylesheet' />

</head>

<body>

<form action='javascript:void(0);' method='get'>

<h4>John Lennon Albums</h4>

<table>

<thead>

<tr>

<th>Title</th>

<th>Year</th>

</tr>

</thead>

<tbody>

<tr>

<td>John Lennon/Plastic Ono Band</td>

<td>1970</td>

</tr>

<tr>

<td>Imagine</td>

<td>1971</td>

</tr>

<tr>

<td>Some Time in New York City</td>

<td>1972</td>

</tr>

<tr>

<td>Mind Games</td>

<td>1973</td>

</tr>

<tr>

<td>Walls and Bridges</td>

<td>1974</td>

</tr>

<tr>

<td>Rock 'n Roll</td>

<td>1975</td>

</tr>

<tr>

<td>Double Fantasy</td>

<td>1980</td>

</tr>

</tbody>

</table>

<p>

<button id='documentAddClass'>

Add Class

</button>

<button id='documentHasClass'>

Has Class

</button>

<button id='documentRemoveClass'>

Remove Class

</button>

<button id='documentToggleClass'>

Toggle Class

</button>

</p>

</form>

</body>

</html>

The preceding HTML is styled with the following style sheet:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

table.johnLennonAlbums {

table-layout: fixed;

width: 500px;

border: 1px solid black;

border-collapse: collapse;

}

table.johnLennonAlbums th,

table.johnLennonAlbums td {

padding: 3px;

border: 1px solid black;

}

table.johnLennonAlbums th {

text-align: left;

background: lightgreen;

}

table.johnLennonAlbums tbody tr:hover {

background: lightblue;

}

The various jQuery methods for working with class names are demonstrated in the following script:

$(document).ready(

function()

{

$('button#documentAddClass').click(

function(event)

{

event.preventDefault();

$('table').addClass('johnLennonAlbums');

}

);

$('button#documentHasClass').click(

function(event)

{

event.preventDefault();

if ($('table').hasClass('johnLennonAlbums'))

{

alert('The <table> has the class johnLennonAlbums');

}

else

{

alert('The <table> does not have the class johnLennonAlbums');

}

}

);

$('button#documentRemoveClass').click(

function(event)

{

event.preventDefault();

$('table').removeClass('johnLennonAlbums');

}

);

$('button#documentToggleClass').click(

function(event)

{

event.preventDefault();

$('table').toggleClass('johnLennonAlbums');

}

);

}

);

Figure 4.5 shows the preceding example in Safari on a Mac.

image

Figure 4.5

Clicking the Add Class button provides a styled table, as shown in Figure 4.6.

image

Figure 4.6

In the JavaScript created for Example 4-2, you attach four events to each of the four <button> elements present in the HTML document. The first event adds the class name johnLennonAlbums to the <table> element. jQuery adds only this class name once; if it is already present, nothing happens. The addClass() method can take one or more class names. If you want to add multiple class names, a space character should separate each class name.

$('button#documentAddClass').click(

function(event)

{

event.preventDefault();

$('table').addClass('johnLennonAlbums');

}

);

The hasClass() method, demonstrated by the event attached to the second <button> element, checks for the existence of one or more class names. If the class is present, the method returns true. If the class is missing, the method returns false. In Example 4-2, analert() message is displayed for each boolean condition. The hasClass() method is the only class method jQuery provides that does not accept multiple class names.

$('button#documentHasClass').click(

function(event)

{

event.preventDefault();

if ($('table').hasClass('johnLennonAlbums'))

{

alert('The <table> has the class johnLennonAlbums');

}

else

{

alert('The <table> does not have the class johnLennonAlbums');

}

}

);

Figure 4.7 shows the alert message displayed when the class is present.

The removeClass() method is demonstrated by pressing the third <button> element; it removes a class if it has been added. If the class does not exist, nothing happens. Like the addClass() method, the removeClass() method can accept multiple class names, and also like the addClass() method, you separate multiple class names with a space character. When the class is removed, you see the same table shown in Figure 4.5.

$('button#documentRemoveClass').click(

function(event)

{

event.preventDefault();

$('table').removeClass('johnLennonAlbums');

}

);

image

Figure 4.7

The toggleClass() method is demonstrated by pressing the fourth and final <button> element. If the class is present, it is removed. If the class is missing, then it is added. Like the addClass() and removeClass() methods, the toggleClass() method can accept one or more class names; a space character separates multiple class names.

$('button#documentToggleClass').click(

function(event)

{

event.preventDefault();

$('table').toggleClass('johnLennonAlbums');

}

);

Manipulating HTML and Text Content

jQuery provides a method for just about everything. Its unique, innovative approach to JavaScript reinvents how you program JavaScript. This reinvention is required because jQuery methods define some ground rules that can be expected to be universal among all its methods. For example, one ground rule that becomes more obvious as you learn more about how jQuery works is how wherever it is possible, its methods work on one or more elements. You never have to distinguish between whether you want to work with just one or a lot of elements, because jQuery always assumes the possibility of an array.

Because jQuery always assumes the possibility of an array, it eliminates redundant code that has historically always been required to iterate over an array or list of several elements. You can chain methods onto one another, and you can perform complex operations on just one or many elements at the same time. One thing you may ask yourself while working with jQuery is, how do I access standard or de facto standard DOM methods and properties? In many cases, you don't need to directly access DOM properties or methods because jQuery provides equivalent and, in most cases, less verbose methods that are designed to work seamlessly with jQuery's chainable model of programming. And not only are jQuery's methods less verbose, they also attempt to fix as many cross-browser stability and reliability issues as possible.

One such property that jQuery replaces is the de facto standard innerHTML property. The innerHTML property and many of Microsoft's extensions to the DOM are on their way to standardization in the HTML5 specification. The innerHTML property is one of the few Microsoft extensions to the DOM that has been ubiquitously adopted among browser makers.

Rather than relying exclusively on the implementation of Microsoft's de facto standard innerHTML property and similar properties, jQuery provides a variety of methods that assist you in manipulating HTML and text content. This section discusses the following methods offered in jQuery's API:

· The html() method sets or gets the HTML content of one or more elements.

· The text() method gets or sets the text content for one or more elements.

· The append() and prepend() methods let you append or prepend content. You will learn about how these methods are actually better than the native de facto standard alternative, innerHTML.

· The after() and before() methods let you place content beside other elements (as opposed to appending or prepending the content inside those elements).

· insertAfter() and insertBefore() methods let you modify a document by taking one selection of elements and inserting those elements beside another selection of elements.

· The wrap(), wrapAll(), and wrapInner() methods give you the ability to wrap one or more elements with other elements.

· The unwrap() method removes a parent element, leaving its descendant elements in place of the parent.

The following sections describe and demonstrate how the preceding methods work, to give you expertise in understanding how content manipulation in jQuery works.

Getting, Setting, and Removing Content

The simplest methods that jQuery provides for content manipulation are the html() and text() methods. If you make a selection and call one of these methods without any arguments, jQuery simply returns the text or HTML content of the first matched element in a jQuery selection. The following example, Example 4-3, demonstrates how this works:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>Groucho Marx Quote</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-3.js'></script>

<link href='Example 4-3.css' rel='stylesheet' />

</head>

<body>

<p>

Before I speak, I have something important to say. <i>- Groucho Marx</i>

</p>

</body>

</html>

The preceding document is linked to the following style sheet:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

The following script demonstrates how you can use the html() and text() methods and what to expect in the output that you get back:

$(document).ready(

function()

{

console.log('HTML: ' + $('p').html());

console.log('Text: ' + $('p').text());

}

);

Figure 4.8 shows that the html() method has returned the <i> element in the results, but the text() method has left that out. In this sense, you find that the html() method is similar to the innerHTML property, and the text() method is similar to the innerText ortextContent properties.

Setting Text or HTML Content

Setting content works similarly: All you have to do is provide the content that you want to set as the value for the element (or elements) in the first argument to the text() or html() method. Which method you use, of course, depends on whether you want HTML tags to be expanded as HTML. The following example, Example 4-4, demonstrates how to set text or HTML content:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>Groucho Marx Quotes</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-4.js'></script>

<link href='Example 4-4.css' rel='stylesheet' />

</head>

<body>

<p>

Before I speak, I have something important to say. <i>- Groucho Marx</i>

</p>

<p id='grouchoQuote1'></p>

<p id='grouchoQuote2'></p>

</body>

</html>

image

Figure 4.8

The following style sheet is applied to the preceding HTML document:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

The following script demonstrates setting element content via jQuery's text() and html() methods:

$(document).ready(

function()

{

$('p#grouchoQuote1').text(

'Getting older is no problem. You just have to ' +

'live long enough. <i>- Groucho Marx</i>'

);

$('p#grouchoQuote2').html(

'I have had a perfectly wonderful evening, but ' +

'this wasn’t it. <i>- Groucho Marx</i>'

);

}

);

Figure 4.9 shows how the content applied via the text() method results in the HTML tags being ignored and showing through in the rendered output of the <p> element with id name grouchoQuote1. It also shows how the HTML tags are expanded in the content of the<p> element with id name grouchoQuote2, which is applied using jQuery's html() method.

image

Figure 4.9

Setting Text or HTML Content for Multiple Items

Although you probably usually think about text or HTML content being applied only to a single element at a time, jQuery's text() and html() methods will apply that text or HTML content to one or more elements. The following example, Example 4-5, demonstrates what happens when you apply HTML content to a selection that includes multiple elements:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>Groucho Marx Quotes</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-5.js'></script>

<link href='Example 4-5.css' rel='stylesheet' />

</head>

<body>

<p>

Before I speak, I have something important to say. <i>- Groucho Marx</i>

</p>

<p id='grouchoQuote1'></p>

<p id='grouchoQuote2'></p>

</body>

</html>

The following CSS is linked to the preceding HTML document:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

The following script applies HTML content to all the <p> elements in the document:

$(document).ready(

function()

{

$('p').html(

'Quote me as saying I was mis-quoted. ' +

'<i>- Groucho Marx</i>'

);

}

);

Figure 4.10 shows a screen shot of the output. You see that the quote applied in the script has been applied to all three <p> elements, replacing whatever content was present previously, if any.

image

Figure 4.10

As you can see in Figure 4.10, jQuery applies the HTML content depending on your selection. If you've selected several elements, the content modification has been applied to several elements, and if you've selected only a single element, your content modifications have been applied to only a single element.

Removing Content

Removing content can also be done with jQuery's text() and html() elements. All you have to do to remove an element is to call either method with an empty string, that is, text(”) or html(”). That isn't the only way to remove content from a document, however, and you'll see alternative methods for doing this later in this chapter.

Appending and Prepending Content

The word prepend is a term more or less invented by the technical programming world. (It does have some use outside that world.) It means to prefix or add some content to the beginning of something else. In fact, you won't find the word prepend in many dictionaries, and if you do, you'll find that the definition offers: “(transitive) To premeditate; to weigh up mentally.” This doesn't match up with the way it's used in the technical programming community, in which this word is meant to be the opposite of append, which, of course, means “to add to the end of something.”

This term has come out of the technical programming world by virtue of the flexible nature of computing when compared to the world of print. In the print world, modifying a hard-copy body of work is difficult to do. You have to renumber pages, possibly renumber chapters, and rewrite the table of contents and the index. Without a computer, that's an enormous amount of work. So in the print world, it's easier to add to a printed body of work by appending, or tacking on new content to the end. It's not always done that way, but it's one possible explanation for why the world never actually needed a word like prepend until the existence of computers made the action a necessity. In the technical world, it's easy to glue something onto the beginning of something else, so we made a new word to describe that action.

The following example, Example 4-6, demonstrates jQuery's append() and prepend() methods:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>John Lennon Albums</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-6.js'></script>

<link href='Example 4-6.css' rel='stylesheet' />

</head>

<body>

<form action='javascript:void(0);' method='get'>

<h4>John Lennon Albums</h4>

<table class='johnLennonAlbums'>

<thead>

<tr>

<th>Title</th>

<th>Year</th>

</tr>

</thead>

<tbody>

<tr>

<td>Imagine</td>

<td>1971</td>

</tr>

<tr>

<td>Some Time in New York City</td>

<td>1972</td>

</tr>

<tr>

<td>Mind Games</td>

<td>1973</td>

</tr>

<tr>

<td>Walls and Bridges</td>

<td>1974</td>

</tr>

<tr>

<td>Rock 'n Roll</td>

<td>1975</td>

</tr>

</tbody>

</table>

<p>

<button id='documentAppend'>

Append

</button>

<button id='documentPrepend'>

Prepend

</button>

</p>

</form>

</body>

</html>

The preceding code is linked to the following style sheet:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

table.johnLennonAlbums {

table-layout: fixed;

width: 500px;

border: 1px solid black;

border-collapse: collapse;

}

table.johnLennonAlbums th,

table.johnLennonAlbums td {

padding: 3px;

border: 1px solid black;

}

table.johnLennonAlbums th {

text-align: left;

background: lightgreen;

}

table.johnLennonAlbums tbody tr:hover {

background: lightblue;

}

The following script demonstrates the prepend() and append() methods:

$(document).ready(

function()

{

$('button#documentAppend').click(

function(event)

{

event.preventDefault();

if (!$('tr#johnLennonDoubleFantasy').length)

{

$('table tbody').append(

"<tr id='johnLennonDoubleFantasy'>\n" +

"<td>Double Fantasy</td>\n" +

"<td>1980</td>\n" +

"</tr>\n"

);

}

}

);

$('button#documentPrepend').click(

function(event)

{

event.preventDefault();

if (!$('tr#johnLennonPlasticOnoBand').length)

{

$('table tbody').prepend(

"<tr id='johnLennonPlasticOnoBand'>\n" +

"<td>John Lennon/Plastic Ono Band</td>\n" +

"<td>1970</td>\n" +

"</tr>\n"

);

}

}

);

}

);

In the preceding example, to append HTML content to the <tbody> element, you use jQuery's append() method, which adds the Double Fantasy album's entry to the <tbody> element when you click the Append button. In addition, when you tap the Prepend button, the John Lennon/Plastic Ono Band entry is added to the beginning of the <tbody> element. Figure 4.11 shows the example at page load, minus the additional entries.

image

Figure 4.11

Inserting Beside Content

With the append() and prepend() methods, you're adding to content within an element. With the before() and after() methods, you are inserting content beside an element. The before() and after() methods are demonstrated in the following document (Example 4-7):

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>Groucho Marx Quote</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-7.js'></script>

<link href='Example 4-7.css' rel='stylesheet' />

</head>

<body>

<p>

Why, I'd horse-whip you, if I had a horse.

</p>

</body>

</html>

The following style sheet is applied to the preceding document:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

p.quoteAttribution {

font-style: italic;

}

The following JavaScript demonstrates how content can be inserted before and after the <p> element, via the respective before() and after() methods:

$(document).ready(

function()

{

$('p').before(

'<h4>Quote</h4>'

);

$('p').after(

"<p class='quoteAttribution'>\n" +

" - Groucho Marx\n" +

"</p>\n"

);

}

);

Figure 4.12 shows what happens when you load the preceding document in a browser.

image

Figure 4.12

The content passed to the before() method is inserted before the <p> element, and the content passed to the after() method is inserted after the <p> element.

Inserting Beside Content via a Selection

The before() and after() methods are used to insert content beside elements. The insertBefore() and insertAfter() methods do the same function, but instead of passing content directly to these methods, as you did with the before() and after() methods, you use a selector to reference another element in your document that you want inserted beside another element. In addition, the logic is reversed in how you write the script that does the insert beside action. The following document, which can be found as Example 4-8 in the source materials, demonstrates how you might use the insertBefore() and insertAfter() methods:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>John Lennon and Paul McCartney Albums</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-8.js'></script>

<link href='Example 4-8.css' rel='stylesheet' />

</head>

<body>

<!-- Template Items -->

<table id='seventiesAlbumsTemplate'>

<thead>

<tr>

<th>Title</th>

<th>Year</th>

</tr>

</thead>

<tfoot>

<tr>

<th>Title</th>

<th>Year</th>

</tr>

</tfoot>

</table>

<!-- Main Content -->

<h4>John Lennon ‘70s Albums</h4>

<table class='seventiesAlbums'>

<tbody>

<tr>

<td>John Lennon/Plastic Ono Band</td>

<td>1970</td>

</tr>

<tr>

<td>Imagine</td>

<td>1971</td>

</tr>

<tr>

<td>Some Time in New York City</td>

<td>1972</td>

</tr>

<tr>

<td>Mind Games</td>

<td>1973</td>

</tr>

<tr>

<td>Walls and Bridges</td>

<td>1974</td>

</tr>

<tr>

<td>Rock 'n Roll</td>

<td>1975</td>

</tr>

</tbody>

</table>

<h4>Paul McCartney ‘70s Albums</h4>

<table class='seventiesAlbums'>

<tbody>

<tr>

<td>McCartney</td>

<td>1970</td>

</tr>

<tr>

<td>RAM</td>

<td>1971</td>

</tr>

<tr>

<td>Wild Life</td>

<td>1971</td>

</tr>

<tr>

<td>Red Rose Speedway</td>

<td>1973</td>

</tr>

<tr>

<td>Band on the Run</td>

<td>1973</td>

</tr>

<tr>

<td>Venus and Mars</td>

<td>1975</td>

</tr>

<tr>

<td>At the Speed of Sound</td>

<td>1976</td>

</tr>

<tr>

<td>Thrillington (As Percy Thrillington)</td>

<td>1977</td>

</tr>

<tr>

<td>Londontown</td>

<td>1978</td>

</tr>

<tr>

<td>Wings Greatest</td>

<td>1978</td>

</tr>

<tr>

<td>Back To The Egg</td>

<td>1979</td>

</tr>

</tbody>

</table>

</body>

</html>

The following style sheet is applied to the preceding markup document:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

table.seventiesAlbums {

table-layout: fixed;

width: 500px;

border: 1px solid black;

border-collapse: collapse;

}

table.seventiesAlbums th,

table.seventiesAlbums td {

padding: 3px;

border: 1px solid black;

}

table.seventiesAlbums th {

text-align: left;

background: lightgreen;

}

table.seventiesAlbums tbody tr:hover {

background: lightblue;

}

table#seventiesAlbumsTemplate {

display: none;

}

The following script demonstrates how you use the insertBefore() and insertAfter() methods with selectors to duplicate content in a document:

$(document).ready(

function()

{

$('table#seventiesAlbumsTemplate thead')

.insertBefore('table.seventiesAlbums tbody');

$('table#seventiesAlbumsTemplate tfoot')

.insertAfter('table.seventiesAlbums tbody');

}

);

Figure 4.13 shows the results of the preceding document in Safari.

image

Figure 4.13

In the preceding example, you can see that the <thead> and <tfoot> elements contained within the hidden (using the display: none; CSS declaration) <table> element with id name seventiesAlbumsTemplate are duplicated to the other two <table> elements using jQuery. You start the script with the logic reversed; that is to say, you do the opposite of what you did with the before() and after() methods, where you first selected the element that you wanted to insert content beside and then provided the content to be inserted beside the selected element(s) within the before() or after() methods. This time, you begin with a selection of existing content within the document that you want to insert beside another element. In the script, you have the following:

$('table#seventiesAlbumsTemplate thead')

.insertBefore('table.seventiesAlbums tbody');

The preceding line begins with selecting the <thead> element contained in the <table> with id name seventiesAlbumsTemplate. You want to duplicate that <thead> element to the other two tables and use that content as a template. To do that, you call the insertBefore()method and then pass a selector to that method. The selector that you pass is the element before which you want the original selection, <thead>, to be inserted. The selector first references <table> elements with the class name seventiesAlbums and then selects the descendant <tbody> element. So, in plain English, the script says, “Take the <thead> element in the hidden table and duplicate and insert that <thead> element before the <tbody> elements of the other two tables containing discography information for 1970s era albums of two former Beatles.” The other line does the same thing:

$('table#seventiesAlbumsTemplate tfoot')

.insertAfter('table.seventiesAlbums tbody');

However this time, you take the <tfoot> element from the hidden table and duplicate and insert that element after the <tbody> element of the other two tables. Essentially, the insertBefore() and insertAfter() methods make it easier to do templating.

Wrapping Content

In jQuery, wrapping an element means creating a new element and placing an existing element within a document inside that new element.

jQuery provides a few methods for wrapping content, that is to say, methods that take one or more elements and place those elements within container elements to change the structural hierarchy of a document. The methods that jQuery provides that enable you to wrap content are wrap(), wrapAll(), and wrapInner(). jQuery provides a single method to do the reverse to unwrap an element, and that method is called unwrap(). The following sections demonstrate how to use these methods.

Wrapping a Selection of Elements Individually

jQuery's wrap() method wraps each element matched in a selection individually. That is, if your selection matches five different elements, jQuery's wrap() method makes five separate wrappers. To better illustrate how this works, the following code, Example 4-9, demonstrates how the wrap() method wraps three <p> elements within <div> elements:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>Mitch Hedberg Quotes</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-9.js'></script>

<link href='Example 4-9.css' rel='stylesheet' />

</head>

<body>

<h4>Mitch Hedberg Quotes</h4>

<p>

Dogs are forever in the push up position.

</p>

<p>

I haven’t slept for ten days, because that would be too long.

</p>

<p>

I once saw a forklift lift a crate of forks. And it was way

too literal for me.

</p>

</body>

</html>

The following style sheet is applied to the preceding markup document:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

div {

padding: 5px;

border: 1px dashed black;

background: orange;

margin: 5px 0;

}

div p {

margin: 5px;

}

The following script demonstrates jQuery's wrap method:

$(document).ready(

function()

{

$('p').wrap('<div/>');

}

);

In Figure 4.14, you see that each <p> element is wrapped in a <div> element, which is made obvious by the styles applied in the style sheet. Each <div> has a distinct border, margin, and background color applied to make it obvious that a <div> exists.

image

Figure 4.14

The preceding example makes it obvious that jQuery's wrap() method is used to wrap each element present in a selection individually.

Wrapping a Collection of Elements

Whereas the wrap() method wraps each item present in a selection individually, jQuery's wrapAll() method wraps all items present in a selection within a single wrapper. The following document presents the same markup and style sheet as you saw in the last section for the demonstration of the wrap() method. The only item that is changed is that the wrapAll() method is used instead of the wrap() method.

In the following script, Example 4-10, which uses the same markup and style sheet as Example 4-9, you see that the wrap() method has been swapped for the wrapAll() method:

$(document).ready(

function()

{

$('p').wrapAll('<div/>');

}

);

Figure 4.15 shows that instead of each <p> element being individually wrapped in a <div> element, you find that all three <p> elements are wrapped with a single <div> element, as made obvious again by the styles used in your style sheet.

image

Figure 4.15

As you can see in the preceding example, the wrapAll() method takes a selection of elements and collectively wraps the whole selection with a single wrapper element.

Wrapping an Element's Contents

The last wrapper method demonstrates the wrapInner() method, which wraps an element's contents. This method works similarly to the wrap() method in that a wrapper is applied to each item in a selection, but instead of the selected element being placed in a wrapper, its contents are placed in a wrapper. The following document, Example 4-11, which is the same document you saw in the last two examples, demonstrates how the wrapInner() method compares and contrasts with the wrap() and wrapAll() methods:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>Mitch Hedberg Quotes</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-11.js'></script>

<link href='Example 4-11.css' rel='stylesheet' />

</head>

<body>

<h4>Mitch Hedberg Quotes</h4>

<p>

Dogs are forever in the push up position.

</p>

<p>

I haven’t slept for ten days, because that would be too long.

</p>

<p>

I once saw a forklift lift a crate of forks. And it was way

too literal for me.

</p>

</body>

</html>

The following style sheet is applied to the preceding markup document:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

span {

background: yellow;

}

p {

margin: 5px;

}

In the following script, you see that the only change from the preceding two examples is that the wrapInner() method is used instead of the wrap() or wrapAll() methods:

$(document).ready(

function()

{

$('p').wrapInner('<span/>');

}

);

In Figure 4.16, you see that the contents of all three <p> elements are each wrapped with <span> tags, making the contents of each <p> element styled with yellow backgrounds, appearing to highlight the content of all three paragraphs.

image

Figure 4.16

As demonstrated by what you see in Figure 4.16, the wrapInner() method takes the contents of each individual element present in a selection and places that content in a wrapper.

Unwrapping Elements

Unwrapping elements using the unwrap() method means removing the parent element from one or more elements and placing those element(s) in its place. The following example, Example 4-12, demonstrates jQuery's unwrap() method in the context of the preceding wrapping examples that have been presented thus far.

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>Mitch Hedberg Quotes</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-12.js'></script>

<link href='Example 4-12.css' rel='stylesheet' />

</head>

<body>

<h4>Mitch Hedberg Quotes</h4>

<div>

<p>

Dogs are forever in the push up position.

</p>

</div>

<div>

<p>

I haven’t slept for ten days, because that would be too long.

</p>

</div>

<div>

<p>

I once saw a forklift lift a crate of forks. And it was way

too literal for me.

</p>

</div>

</body>

</html>

The HTML document is joined with the following style sheet:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

div {

padding: 5px;

border: 1px dashed black;

background: orange;

margin: 5px 0;

}

p {

margin: 5px;

}

Then, the following JavaScript unwraps each <p> element from its parent <div> element.

$(document).ready(

function()

{

$('p').unwrap();

}

);

The JavaScript removes each <div> element from the document, which results in the HTML structure shown in Figure 4.17.

image

Figure 4.17

Replacing Elements

This section discusses two methods, jQuery's replaceWith() and replaceAll(). The jQuery's replaceWith() method replaces a selection with whatever HTML content you specify. This works similarly to jQuery's html() method, but whereas the html() method sets an element's contents, jQuery's replaceWith() method replaces the element and its content. This can be thought to be similar to Microsoft's (now de facto standard) outerHTML property, for the portion of the outerHTML property that can set or replace content.

The replaceAll() method is similar to the insertBefore() and insertAfter() methods that you observed earlier in this chapter; it reverses the logic and is intended to be used with HTML content already in the document, such as HTML you might reuse as a template.

The following document, Example 4-13, demonstrates how jQuery's replaceWith() and replaceAll() methods work:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>Mitch Hedberg Quotes</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-13.js'></script>

<link href='Example 4-13.css' rel='stylesheet' />

</head>

<body>

<div id='mitchHedbergQuoteTemplate'>

<p id='mitchHedbergQuote3'>

I’m sick of following my dreams. I’m just going

to ask them where they’re goin’, and hook up with

them later.

</p>

<p id='mitchHedbergQuote4'>

My fake plants died because I did not pretend to water them.

</p>

</div>

<h4>Mitch Hedberg Quotes</h4>

<p>

<input type='submit' id='mitchHedbergQuoteReveal1' value='View Quote' />

</p>

<p>

<input type='submit' id='mitchHedbergQuoteReveal2' value='View Quote' />

</p>

<p>

<input type='submit' id='mitchHedbergQuoteReveal3' value='View Quote' />

</p>

<p>

<input type='submit' id='mitchHedbergQuoteReveal4' value='View Quote' />

</p>

</body>

</html>

The following style sheet is applied to the preceding HTML:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

div#mitchHedbergQuoteTemplate {

display: none;

}

p {

margin: 5px;

}

The following script demonstrates how jQuery's replaceWith() and replaceAll() methods are used to replace elements:

$(document).ready(

function()

{

$('input#mitchHedbergQuoteReveal1').click(

function(event)

{

event.preventDefault();

$(this).replaceWith(

"<p>\n" +

" I would imagine that if you could understand \n" +

" Morse code, a tap dancer would drive you crazy.\n" +

"</p>\n"

);

}

);

$('input#mitchHedbergQuoteReveal2').click(

function(event)

{

event.preventDefault();

$(this).replaceWith(

"<p>\n" +

" I’d like to get four people who do cart wheels \n" +

" very good, and make a cart.\n" +

"</p>\n"

);

}

);

$('input#mitchHedbergQuoteReveal3').click(

function(event)

{

$('p#mitchHedbergQuote3').replaceAll(this);

}

);

$('input#mitchHedbergQuoteReveal4').click(

function(event)

{

$('p#mitchHedbergQuote4').replaceAll(this);

}

);

}

);

Figure 4.18 shows the results of the preceding example. When you click any of the buttons, you see that the button is replaced with a quote.

image

Figure 4.18

In the preceding example, you see that a click event is attached to each button, and upon clicking any button, the button is replaced with a quote. For the first two buttons, you make a call to $(this).replaceWith(), which causes the <input> element to be replaced with the HTML content passed to the replaceWith() method.

For the second two buttons, the content you want to use for replacement is selected instead of directly provided, as p#mitchHedbergQuote3, for example, then the replaceAll() method is called, and you provide the item you want to replace as an argument to that method. In the preceding example, you pass the this keyword, but you can also use a selector. Essentially, you find that the logic is reversed from the replaceWith() method demonstrated earlier in this section.

Removing Content

Removing content can be done in a variety of ways. You can, for example, use the replaceWith() or html() methods in conjunction with an empty string. But jQuery also provides methods that are specifically designated for the removal of content, the empty() and theremove() methods. The following document, Example 4-14, demonstrates how both of these methods are used:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>John Lennon Albums</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-14.js'></script>

<link href='Example 4-14.css' rel='stylesheet' />

</head>

<body>

<form action='javascript:void(0);' method='get'>

<h4>John Lennon Albums</h4>

<table class='johnLennonAlbums'>

<thead>

<tr>

<th>Title</th>

<th>Year</th>

</tr>

</thead>

<tbody>

<tr>

<td>John Lennon/Plastic Ono Band</td>

<td>1970</td>

</tr>

<tr>

<td>Imagine</td>

<td>1971</td>

</tr>

<tr>

<td>Some Time in New York City</td>

<td>1972</td>

</tr>

<tr>

<td>Mind Games</td>

<td>1973</td>

</tr>

<tr>

<td>Walls and Bridges</td>

<td>1974</td>

</tr>

<tr>

<td>Rock 'n Roll</td>

<td>1975</td>

</tr>

<tr>

<td>Double Fantasy</td>

<td>1980</td>

</tr>

</tbody>

</table>

<p>

<button id='documentEmpty'>

Empty Data

</button>

<button id='documentRemove'>

Remove Content

</button>

</p>

</form>

</body>

</html>

The following style sheet is applied to the preceding markup document:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

table.johnLennonAlbums {

table-layout: fixed;

width: 500px;

border: 1px solid black;

border-collapse: collapse;

}

table.johnLennonAlbums th,

table.johnLennonAlbums td {

padding: 3px;

border: 1px solid black;

}

table.johnLennonAlbums th {

text-align: left;

background: lightgreen;

}

table.johnLennonAlbums tbody tr:hover {

background: lightblue;

}

The following script demonstrates both the empty() and the remove() methods:

$(document).ready(

function()

{

$('button#documentEmpty').click(

function(event)

{

event.preventDefault();

$('td').empty();

}

);

$('button#documentRemove').click(

function(event)

{

event.preventDefault();

$('h4, table').remove();

}

);

}

);

Figure 4.19 shows the result of the preceding example.

image

Figure 4.19

The preceding example shows what happens when you use jQuery's empty() method. This is essentially the same as passing an empty string to the html() method—all the element's children elements, whether HTML elements or text, are removed.

The preceding example also demonstrates jQuery's remove() method, which deletes the items specified in the selection. It should be noted, however, that those items still exist within jQuery, and you can continue to work with those items by chaining subsequent jQuery methods to the remove() method. You can also pass a selector to the remove() method, which acts as a filter. Any items specified in a selector provided to the remove() method are preserved and are not removed from the document.

Cloning Content

jQuery provides a method called clone() for cloning (copying) content. jQuery's clone() method, unlike the DOM cloneNode() method, automatically assumes that you want to copy the element and all its descendants, so you don't have to worry about specifying whether you want to clone descendant elements. Also unlike the DOM cloneNode() method, you have the option of cloning the element's event handlers (as well as those of descendant elements), which cannot be done with JavaScript's DOM manipulation methods. If you want to clone the element's event handlers, all you have to do is specify boolean true as the first argument to jQuery's clone() method. The following document, Example 4-15, demonstrates jQuery's clone() method:

<!DOCTYPE HTML>

<html lang='en'>

<head>

<meta http-equiv='X-UA-Compatible' content='IE=Edge' />

<meta charset='utf-8' />

<title>John Lennon Albums</title>

<script src='../jQuery.js'></script>

<script src='../jQueryUI.js'></script>

<script src='Example 4-15.js'></script>

<link href='Example 4-15.css' rel='stylesheet' />

</head>

<body>

<form action='javascript:void(0);' method='get'>

<h4>John Lennon Albums</h4>

<table class='johnLennonAlbums'>

<thead>

<tr>

<th>Title</th>

<th>Year</th>

</tr>

</thead>

<tbody>

<tr id='johnLennonAlbumTemplate'>

<td contenteditable='true'></td>

<td contenteditable='true'></td>

</tr>

<tr>

<td>John Lennon/Plastic Ono Band</td>

<td>1970</td>

</tr>

<tr>

<td>Imagine</td>

<td>1971</td>

</tr>

<tr>

<td>Some Time in New York City</td>

<td>1972</td>

</tr>

<tr>

<td>Mind Games</td>

<td>1973</td>

</tr>

<tr>

<td>Walls and Bridges</td>

<td>1974</td>

</tr>

</tbody>

</table>

<p>

<button id='documentAddRow'>

Add a Row

</button>

</p>

</form>

</body>

</html>

The following style sheet is linked to the preceding document:

body {

font: 12px "Lucida Grande", Arial, sans-serif;

color: rgb(50, 50, 50);

margin: 0;

padding: 15px;

}

table.johnLennonAlbums {

table-layout: fixed;

width: 500px;

border: 1px solid black;

border-collapse: collapse;

}

table.johnLennonAlbums th,

table.johnLennonAlbums td {

padding: 3px;

border: 1px solid black;

}

table.johnLennonAlbums th {

text-align: left;

background: lightgreen;

}

table.johnLennonAlbums tbody tr:hover {

background: lightblue;

}

tr#johnLennonAlbumTemplate {

display: none;

}

The following script demonstrates jQuery's clone() method:

$(document).ready(

function()

{

$('button#documentAddRow').click(

function(event)

{

event.preventDefault();

var tr = $('tr#johnLennonAlbumTemplate').clone(true);

tr.removeAttr('id');

$('table.johnLennonAlbums tbody').append(tr);

tr.children('td:first').focus();

}

);

}

);

Figure 4.20 shows the preceding example. When you click the Add a Row button, a new row is added to the table to input a new John Lennon album.

image

Figure 4.20

The following line clones the template <tr> element, with id name johnLennonAlbumTemplate.

var tr = $('tr#johnLennonAlbumTemplate').clone(true);

If any event handlers are attached to the <tr>, or the <td> elements it contains, those event handlers are carried over to the new duplicated <tr> element because the first argument provided to the clone() method is set to true.

The id attribute is removed so that the new <tr> element isn't treated like the template <tr> element, which is not displayed in the document.

tr.removeAttr('id');

The new <tr> element is appended to the <tbody> element using the append() method.

$('table.johnLennonAlbums tbody').append(tr);

Finally, the first <td> element is set to focus automatically, so you don't have to click it to enter the new album's data.

tr.children('td:first').focus();

Summary

In this chapter, you learned about a variety of jQuery's manipulative capabilities. The content discussed in this chapter is documented in detail in Appendix E, “Manipulating Content, Attributes, and Custom Data,” and Appendix F, “More Content Manipulation.” You began this chapter by learning about jQuery's attribute manipulation method attr(), which enables you to specify attributes in a variety of ways, with the attribute as the first argument, and the value as the second, or via an object literal specifying arguments in key-value pairs, and also by using callback functions. jQuery's removeAttr() method can be used to remove attributes completely.

You also learned how jQuery helps you immensely with manipulating class names. jQuery's addClass() method can add a class name to an element. Its hasClass() method can determine whether a class name is present. Its removeClass() method can remove a class name. And its toggleClass() method can toggle a class name on and off.

You learned about various jQuery methods used to manipulate text and HTML content. You can get or set text or HTML content for elements using jQuery's text() and html() methods. You can append or prepend HTML content to other elements using jQuery'sappend() or prepend() methods. jQuery's after(), before(), insertAfter(), and insertBefore() methods can all insert content beside other content. And jQuery's wrap(), wrapAll(), and wrapInner() methods can wrap elements with wrapper elements. In addition, theunwrap() method can remove a parent element.

jQuery's replaceWith() and replaceAll() methods can completely replace one or more elements with other content. Its empty() method can completely remove an element's children and descendants. Its remove() methods can remove an element and all its contents from the document. And its clone() method can duplicate content, and optionally, event handlers that exist within that content.

Exercises

1. Write sample code that might be used to set both the value and the class attributes of an <input> element.

2. If you want to set the href attribute for an <a> element to www.example.com using jQuery, what might the JavaScript look like?

3. What jQuery method is used to completely remove attributes from elements?

4. What jQuery method would you use to determine whether a class name is present for an element?

5. If an element contains HTM content and you retrieve the content of that element using jQuery's text() method, will the HTML tags be present in the returned value?

6. If you set an element's content using jQuery's text() method and that content contains HTML tags, will the HTML tags be visible in the rendered output displayed in your browser's viewport?

7. Describe one bug that jQuery's append() and prepend() methods work around in IE when compared to innerHTML.

8. Describe one bug that jQuery's append() and prepend() methods work around in Firefox when compared to innerHTML.

9. If you want to insert existing content within a document before other existing content within a document, what jQuery method might be best suited for this task?

10.What jQuery method might you use if you needed to wrap multiple items in a document in a single element?

11.jQuery's replaceWith() method is most similar to what de facto standard JavaScript property?

12.What jQuery method would you use if you want to completely remove an item and all its children from your document?

13.What jQuery function call would you make if you want to duplicate an element and its event handlers and insert the duplicate element elsewhere in the document?