JQuery: adding to newly created elements

I have this code (running jQuery 1.4.2)

var elementToAdd = $('<h3>').html('header'); var p = $('<p>').html('hello world'); elementToAdd.after(p); $('div#content').append(elementToAdd); 

However output

 <div id="content"> <h3>header</h3> </div> 

The paragraph "Hello world" has not been added.

What am I doing wrong?


I tested some options:

This also does not work:

 var elementToAdd = $('<div>Header</div>'); var p = $('<p>hello world</p>'); elementToAdd.after(p); 

or that:

 var elementToAdd = $('<h3>header</h3>').after('<p>hello world</p>'); 

But this works (at least in Firefox):

 var elementToAdd = $('<div>').after('<h3>header</h3>').after('<p>hello world</p>'); 

Why?

+7
jquery
source share
7 answers

EDIT: To change the original set, you can .push() add a DOM element (not a jQuery object) to the set.

 var elementToAdd = $('<h3>').html('header'); var p = $('<p>').html('hello world'); // Push the DOM element in elementToAdd.push( p[0] ); // [0] gets the DOM element at index 0 $('div#container').append( elementToAdd );​ 

Instead of .after() use the jQuery .add() method.

 var elementToAdd = $('<h3>').html('header'); var p = $('<p>').html('hello world'); // Add the new object ----------------v $('div#container').append( elementToAdd.add(p) );​ 

This will add him as a sibling as you want.

It returns a new jQuery object with both elements as siblings. Since it does not modify the original object, you need to either call it in .append() or save the result in the added variable.


EDIT: (As pointed out in another answer, you can now use after() as add() since it returns a new set and does not change the original.)

To explain why this is due to the fact that the jQuery object is an array of DOM elements. The DOM element may be the only element with nested descendants, but not with two siblings. Therefore, when you execute .after() , you are trying to add a sibling to each individual element of the array.

To deal with siblings, jQuery stores them as additional elements in its array.

Therefore, when you create a jQuery object by passing two or more sibling elements, it breaks them into pieces and makes them separate elements in the array.

 var $obj = $("<div>div element</div> <span>span element</span>"); 

This will give you a jQuery object with an array of 2 elements.

 $obj[0] is the <div> element $obj[1] is the <span> element 

So, if you were to create them separately, you would need to use .add() to add a new element to the array.

 var $obj = $("<div>div element</div>"); $obj[0] is the <div> var $span = $("<span>span element</span>"); $obj = $obj.add( $span ); $obj[0] is the <div> $obj[1] is the <span> 
+3
source share

I don't think .after works with elements that are not yet added to the DOM ...

try it

 var elementToAdd = $('<h3>').html('header'); var p = $('<p>').html('hello world'); $('div#content').append(elementToAdd); elementToAdd.after(p); 

Edit: Yes, it works! http://jsfiddle.net/tu2GY/

Edit 2: ok, I'm not very good at this, but here goes ...

As @Extrakun noted, the jQuery documentation really notes that the element cannot be bound to the DOM ...

As in jQuery 1.4, .before() and .after() will also work with disconnected DOM nodes.

So, I took a deep breath and opened jquery-1.4.2.js (in vim: D), and I found that everything that is passed .after for an element with no parentNode is used as a string selector, which I think is fails when you pass the jQuery object. I will try to post some code of what I mean in a minute or two here ... (inside the pushStack method)

 ret.selector = this.selector + "." + name + "(" + selector + ")"; 

selector is what ends up going to .after . In fact, this is not much reflected after that.

+6
source share

Interesting. Adding temporary jobs:

 var e = $('<h3>').html('header'); var p = $('<p>').html('hello world'); var result = e.after(p); $('div#content').append(result); 

... Therefore, I assume that e.after(p) returns "p after e", but does not actually change e. This way it works in a chain and it works disconnected, but will not work the way you expect it to work.

+3
source share

'elementToAdd' is not a jQuery object pointing to an element. try the following:

 var elementToAdd = $('<h3>'); elementToAdd.html('header'); var p = $('<p>').html('hello world'); $('div#content').append(elementToAdd); elementToAdd.after(p); 
0
source share

Manipulating dom is an expensive operation, and it’s best to do it the minimum number of times, you can easily change the code above,

 $('div#content').append('<h3>header</h3><p>hello world</p>'); 
0
source share

The problem is inserting disabled DOM nodes with .before and .after only works in jQuery 1.4 (and derivatives).

 <script src="jquery-1.4.js"></script> <script> $('<div/>').after('<p>Test</p>').filter('p').appendTo('body'); </script> 
0
source share

For all recent versions of jQuery, you can also use an object that is added to insert DOM nodes:

 <script> $("<span/>", { class: "test", html: "<p><b>Click me!</b></p>" }).appendTo( "body" ); </script> 
0
source share

All Articles