views:

65

answers:

4

This question occurred to me after a user named patrick pointed out an error in an answer I'd given earlier today.

Given the following html:

<html>
<head>

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"&gt;&lt;/script&gt;

    <script type="text/javascript"> 
        $(function(){  
            $('#div1').add('<p>new text from add</p>');
            $('#div1').append('<p>new text from append</p>');
        });  
    </script>

</head>
<body>
    <div id="div1">
        original text</div>
</body>
</html>

and the jQuery api documentation:

.append( content ) content An element, HTML string, or jQuery object to insert at the end of each element in the set of matched elements.

.add( html ) html An HTML fragment to add to the set of matched elements.

It seems like I should see both text blocks being added to the div, however only the one added using append is actually added, so the page looks like:

original text

new text from append

Can anyone explain to me why this is?

+4  A: 

.add(html) just adds the element to the jQuery object (it's a document fragment at this point), it doesn't insert it into the DOM :)

.append() is for a different purpose, it actually adds the content to the matched elements, as their children, whereas .add() it's a sibling, and only inside that jQuery object, not in the DOM yet.

If for example you did this, .add() would have approximately the effect you're thinking of:

$('#div1').add('<p>new text from add</p>').appendTo('body');

This does the following:

  • Gets the id="div1" element via a selector
  • Adds a new document fragment to that jQuery object's set of matched elements, it's now 2 elements long
  • Appends both of them to the <body>
Nick Craver
better than my answer :)
Mark Schultheiss
So in your example I'd end up with the original div, and a copy with the new paragraph added, is that correct?
kekekela
@kekekela - Correct, if `.appendTo(selector)`'s selector matches more than one element the other elements being appended are cloned, here's an example: http://jsfiddle.net/nick_craver/AdX5A/ So the first one's the original, the 2nd is a clone of the set.
Nick Craver
Cool, I think the part that confused me is that the jQuery docs say add will add "An HTML fragment to add to the set of matched elements." when it sounds like its more accurate to say that it adds it to the jQuery object representing the document fragment. Or something.
kekekela
@kekekela - jQuery objects are a "set of matched elements", an array containing the elements matched by your query. `.add()` adds to "the set of matched elements" and returns a new set.
gnarf
@Nick Craver - hey, I want a custom subdirectory on jsfiddle -- howd you pull that one off? ;)
gnarf
@gnarf - I think user registration opens publicly soon, keep an eye out :)
Nick Craver
@gnark - Yeah, but the documentation for append uses the same verbiage, which is what makes it confusing ..."of each element in the set of matched elements." <--- append docs
kekekela
+1  A: 

The .add() does add it, but in order for it to appear, we would need to add one of the insertion methods to the chain.

Mark Schultheiss
+1  A: 

.add() adds matching elements to the set of matched elements and returns a new jQuery set.

Try this:

var $div = $("#div");

console.log($div.add('.myClass'));

You should end up with a jQuery object containing the objects matching #div and .myClass. It basically adds two jQuery objects together. It does nothing to append/insert these objects into the DOM.

If you pass HTML to .add() you will end up creating those elements and adding them to the set returned by add.

gnarf
+1  A: 

add does not add the element/html to the page, it adds it to the jQuery object set. Check out the doc: http://api.jquery.com/add/. It has a paragraph on this.

Jason McCreary
Ah so it does, guess I should've read the whole page instead of just the blurb at the top.
kekekela
Yeah, the jQuery doc tends to sneak the useful info in at the bottom. You should read the one for `bind`.
Jason McCreary