In Adding Elements to the Page in jQuery, you explored a number of ways to add new HTML elements — such as paragraphs and images — to a page. In this tutorial you learn how to manipulate existing elements in the page, including:
- Removing elements from the page using the
empty()
,remove()
,detach()
andunwrap()
methods - Replacing elements with new elements by using the
replaceWith()
andreplaceAll()
methods, and - How to move an element from one parent element in the page to another.
Once you've read this tutorial, you'll have mastered all the jQuery techniques you need to manipulate elements in the DOM.
Removing elements from the page
Removing everything inside an element: empty()
The
empty()
method is the simplest way to remove content from the page. When you call empty()
on a jQuery object, all the content is removed from the set of matched element(s) in the jQuery object.
In other words,
empty()
removes all child elements and other child nodes (such as text nodes) from each element in the matched set, leaving the element empty.
Here's an example that empties 2
div
elements:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$( init );
function init() {
// Delete the contents of #myDiv1 and #myDiv2
$('.emptyMe').empty();
}
</script>
</head>
<body>
<div class="emptyMe" id="myDiv1">
<p>A paragraph of text</p>
</div>
<div class="emptyMe" id="myDiv2">
<p>Another paragraph of text</p>
A text node on its own
</div>
</body>
</html>
After running the above code, the page content changes to this:
<body>
<div class="emptyMe" id="myDiv1" />
<div class="emptyMe" id="myDiv2" />
</body>
Removing an element entirely: remove()
Whereas
empty()
removes everything inside an element, remove()
also removes the element itself. Here's an example:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$( init );
function init() {
// Delete #myDiv1 and #myDiv2 entirely
$('.removeMe').remove();
}
</script>
</head>
<body>
<div class="removeMe" id="myDiv1">
<p>A paragraph of text</p>
</div>
<div class="removeMe" id="myDiv2">
<p>Another paragraph of text</p>
A text node on its own
</div>
</body>
</html>
After running the above code, both
div
elements are removed entirely from the page:
<body>
</body>
You can pass an optional selector string to
remove()
. If you do this, the elements to remove are filtered by the selector. Here's an example:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$( init );
function init() {
// Delete #myDiv2 only
$('.removeMe').remove(':contains("Another paragraph")');
}
</script>
</head>
<body>
<div class="removeMe" id="myDiv1">
<p>A paragraph of text</p>
</div>
<div class="removeMe" id="myDiv2">
<p>Another paragraph of text</p>
A text node on its own
</div>
</body>
</html>
In the above example, only the
div
that has a class of removeMe
and contains the text "Another paragraph" is removed, leaving the following contents in the page:
<body>
<div class="removeMe" id="myDiv1">
<p>A paragraph of text</p>
</div>
</body>
Removing an element without destroying its data: detach()
remove()
returns a jQuery object containing the removed elements. In theory, this makes it easy to remove some elements from one place in the page, and then later reattach them elsewhere.
However, in order to save resources and avoid potential problems with memory leaks,
remove()
deletes all jQuery data and events associated with the removed elements. For example, if you've assigned a jQuery click
event to an element, and you then remove the element from the page using remove()
, the click
event is removed from the element. This can be a problem if you later want to add the element back to the page and preserve all its functionality.
This is where the
detach()
method — new in jQuery 1.4 — comes in handy. It behaves exactly like remove()
, except that it doesn't delete the jQuery data and events associated with the removed elements. This means you can later reattach the removed elements while preserving their jQuery metadata.
Here's an example. The following script assigns a jQuery
click
event to each of 2 paragraphs in the page. Both event handlers simply toggle a "red"
CSS class on the paragraph to toggle the paragraph's colour to red or black each time it's clicked.
Then the script removes the first paragraph from the page using
remove()
and stores the jQuery object containing the paragraph in a myDiv1Para
variable. It then reattaches the paragraph to its parent div
using appendTo()
.
It then does much the same thing with the second paragraph, but uses
detach()
instead of remove()
.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>p.red { color: red; }</style>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$( init );
function init() {
// Assign a click event to each div's paragraph
$("#myDiv1>p").click( function() { $(this).toggleClass("red"); } );
$("#myDiv2>p").click( function() { $(this).toggleClass("red"); } );
// Remove and reattach #myDiv1's paragraph
var myDiv1Para = $('#myDiv1>p').remove();
myDiv1Para.appendTo('#myDiv1');
// Detach and reattach #myDiv2's paragraph
var myDiv2Para = $('#myDiv2>p').detach();
myDiv2Para.appendTo('#myDiv2');
}
</script>
</head>
<body>
<div id="myDiv1">
<p>A paragraph of text</p>
</div>
<div id="myDiv2">
<p>Another paragraph of text</p>
</div>
</body>
</html>
After running this script, the first paragraph loses its
click
event handler, while the second paragraph retains it. You can try this yourself by opening the page in a browser. You'll see that you can click the second paragraph to make it red, but nothing happens when you click the first paragraph.
This is because the call to
remove()
also deleted the first paragraph's click
event, while the call to detach()
preserved the second paragraph's click
event.
You'll see more ways to move elements around at the end of this tutorial, and I'll cover jQuery events in detail in my next tutorial.
Removing an element's parent: unwrap()
The
unwrap()
function is, as you might imagine, the opposite of wrap()
. It removes the parent of an element (or the parents of a set of elements) from the DOM. The element — and its siblings, if any — then take the place of the element's parent in the DOM.
The following example unwraps a paragraph inside a
div
— in other words, it replaces the div
with its contents:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$( init );
function init() {
// Remove the #myDiv element but leave its contents
$('#myPara').unwrap();
}
</script>
</head>
<body>
<div id="myDiv">
<p id="myPara">A paragraph of text</p>
<p>Another paragraph of text</p>
</div>
</body>
</html>
After running the above code, the page's content changes to the following. Notice how both paragraphs — the target paragraph and its sibling — have been "unwrapped":
<body>
<p id="myPara">A paragraph of text</p>
<p>Another paragraph of text</p>
</body>
Replacing elements
Replacing an element with new content: replaceWith()
replaceWith()
lets you replace an element, or set of elements, with new content. Its syntax is very similar to prepend()
and similar methods. You can pass the replacement content in any of the following forms:- An element object that you've created using a JavaScript DOM function such as
document.getElementById()
ordocument.createElement()
- A string of HTML representing the replacement content
- A jQuery object containing the element(s) to use for the replacement
- A callback function that should return the replacement HTML
Here's an example that shows
replaceWith()
in action. It replaces 1 paragraph with a new string of HTML, a second paragraph with an element object, and a third paragraph with the results of a function that returns the current time:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$( init );
function init() {
// Replace the paragraph in #myDiv1 with a new paragraph
$('#myDiv1>p').replaceWith( "<p>A new paragraph of text</p>" );
// Replace the paragraph in #myDiv2 with a horizontal rule
var hr = document.createElement('hr');
$('#myDiv2>p').replaceWith( hr );
// Replace the paragraph in #myDiv3 with the current time
$('#myDiv3>p').replaceWith( currentTime );
function currentTime() {
var currentTime = new Date();
var currentHours = currentTime.getHours ( );
var currentMinutes = currentTime.getMinutes ( );
var currentSeconds = currentTime.getSeconds ( );
// Pad the minutes and seconds with leading zeros, if required
currentMinutes = ( currentMinutes < 10 ? "0" : "" ) + currentMinutes;
currentSeconds = ( currentSeconds < 10 ? "0" : "" ) + currentSeconds;
return ( "<p>The current time is: " + currentHours + ":" + currentMinutes + ":" + currentSeconds + "</p>" );
}
}
</script>
</head>
<body>
<div id="myDiv1">
<p>A paragraph of text</p>
</div>
<div id="myDiv2">
<p>A paragraph of text</p>
</div>
<div id="myDiv3">
<p>A paragraph of text</p>
</div>
</body>
</html>
After running the above code, the page's content is replaced with the following:
<body>
<div id="myDiv1">
<p>A new paragraph of text</p>
</div>
<div id="myDiv2">
<hr />
</div>
<div id="myDiv3">
<p>The current time is: 13:52:17</p>
</div>
</body>
replaceAll()
: An alternative to replaceWith()
replaceAll()
does the same job as replaceWith()
, except that rather than passing in the replacement content, you pass in the elements that you want to replace. In other words, it's the mirror image of replaceWith()
, much as prependTo()
is the mirror image of prepend()
.
For example, the following 2 lines of code both do essentially the same thing:
$('#myDiv').replaceWith( "<p>Here's some new text</p>" );
$("<p>Here's some new text</p>").replaceAll( '#myDiv' );
Moving elements around
You've now looked at adding elements to the page, as well as removing and replacing elements. There's one more piece to the puzzle: How do you move elements around the DOM tree? For example, you might have a paragraph inside one
div
element, and you want to move the paragraph so that it's inside a different div
.
While there are no specific jQuery methods for moving elements around the DOM tree, in fact it's very easy to do. All you have to do is select the element(s) you want to move, then call an "adding" method such as
append()
, appendTo()
or prepend()
to add the selected elements to another parent element. jQuery automatically realises that the element(s) to add already exist in the page, and it moves the element(s) to the new parent.
Here's an example to make this process clear. This example moves the paragraph from the first div to the second:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$( init );
function init() {
// Move the paragraph from #myDiv1 to #myDiv2
$('#myDiv2').append( $('#myDiv1>p') );
}
</script>
</head>
<body>
<div id="myDiv1">
<p>A paragraph of text</p>
</div>
<div id="myDiv2">
</div>
</body>
</html>
After running the above code, the page's content changes to this:
<div id="myDiv1">
</div>
<div id="myDiv2">
<p>A paragraph of text</p>
</div>
Here are some other ways to achieve the same thing:
// Move the paragraph from #myDiv1 to #myDiv2
$('#myDiv1>p').appendTo( $('#myDiv2') );
// Move the paragraph from #myDiv1 to #myDiv2
var para = $('#myDiv1>p');
para.prependTo( '#myDiv2' );
// Move the paragraph from #myDiv1 to #myDiv2
// by explicitly detaching it then adding it again
$('#myDiv1>p').detach().prependTo('#myDiv2');
The 3rd technique above makes use of a very handy jQuery feature called method chaining. Since most jQuery methods return a jQuery object, you can then call another method on the returned object. This in turn returns another jQuery object, and so on.
So in the above example, a jQuery object is created containing the paragraph to remove, and
So in the above example, a jQuery object is created containing the paragraph to remove, and
detach()
is called, returning another jQuery object containing the removed paragraph. Finally, prependTo()
is called on this second jQuery object to add the removed paragraph to its new parent element.
What happens if you attempt to move some content to more than 1 parent element at the same time? When you do this, jQuery first removes the content from its old parent, then clones the content as many times as necessary and adds a clone to each parent element. For example:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$( init );
function init() {
// Move the paragraph from #myDiv1 to #myDiv2 and #myDiv3
$('#myDiv2, #myDiv3').append( $('#myDiv1>p') );
}
</script>
</head>
<body>
<div id="myDiv1">
<p>A paragraph of text</p>
</div>
<div id="myDiv2">
</div>
<div id="myDiv3">
</div>
</body>
</html>
After running the above code, the page's content looks like this:
<body>
<div id="myDiv1">
</div>
<div id="myDiv2">
<p>A paragraph of text</p>
</div>
<div id="myDiv3">
<p>A paragraph of text</p>
</div>
</body>