Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create an empty, non-null jQuery object ready for appending?

Tags:

jquery

dom

I want to append some html to an empty non null jQuery object only in the loop but it's not working unless I create an object and add an html tag during creation. How can I create an empty jQuery object and be able to add html to it later on?

//var $new = $().add("");  //can't use this object in the loop //var $new = $([]);        //can't use this object in the loop //var $new = $();        //can't use this object in the loop //var $new = $("#nonexistingelement"); //can't use this object in the loop var $new = $().add("<tr>");  //works but I don't want to add any html at this point.   $.each(.....)   {     $new.append("<sometag>");  });  alert($new.html());  //should display some html 

Addition: http://jsfiddle.net/vfPNT/

like image 688
Tony_Henrich Avatar asked Apr 08 '11 17:04

Tony_Henrich


2 Answers

Your problem here is that there aren't "null" jQuery objects that can't be appended to and "empty" ones that can be. You've already identified several ways to create an empty one, and while there may be more, it doesn't matter - what you're trying to do simply won't do what you expect it to, no matter how you start off, because...

...append() modifies the DOM, not the jQuery object. And an empty jQuery object has no DOM! Tomalak had the right idea, though you may not have understood it.

I'm going to make three observations about jQuery that you're probably already aware of, but which are useful in understanding the remainder of this answer and therefore may benefit future readers:

  1. A jQuery object is fundamentally a set of DOM elements.
  2. Some jQuery methods operate on the set, and some operate on the nodes in the set.
  3. Some jQuery methods operate only on (or retrieve information only from) the first node added to the set.

With these three observations in mind, let's consider your example:

// 1. create an empty set somehow (doesn't matter how) var $new = $();  // 2. iterate over something $.each( ..., function( ... ) {   // 3. construct a DOM fragment from HTML, and append it   $new.append("<sometag>");  });  // 4. try to display HTML corresponding to the jQuery object alert($new.html());   

In this example, step #3 will fail to do anything useful because the purpose of append() is to take whatever DOM elements it is given and append them as children to each DOM element in the set. Since $new is an empty set, there are no elements to append to, and... nothing happens. Step #1 is working just fine - but by creating a set without any DOM elements in it, you've set yourself up to fail when you try to use methods that exist to modify the DOM! Reference Observation #2... to modify the set, you need to call a method that actually operates on the set.

Ok, so let's say we use the set modification method add() instead:

  $new = $new.add("<sometag>"); 

Now we're good, right? Each pass through the loop will create a new jQuery object consisting of the previous set + a newly-created element. Well...

...this will just cause step #4 to do something odd. See, html() is one of those methods I mentioned in Observation #3 - it operates only on the first element in the set. So instead of a sequence ("<sometag><sometag><sometag>...") you're only gonna get a HTML representation of the element created on the first pass through the loop ("<sometag>"). Except... You're not even going to get that, because html() creates a representation of the element's children - so what you're really going to end up with is ""...

This was all just a big disappointment: you started off working with the set (Step #1), then tried to operate on the DOM (Step #3), and finished up by trying to pull data from one DOM element (that didn't exist) (and wouldn't have had any data if it did) (Step #4).

The solution you finally came up with isn't terrible - you're essentially opting to add one root element to the set starting out, and operate entirely on this DOM fragment until you're done adding new elements and are ready to operate on them. You've omitted it from your revised example, but html() would work too, since it would simply dump the contents of your root element.

But just to be complete, I'll give you a final example that works on the set, starting with an empty jQuery object:

var $new = $(); $.each( [1, 2, 3, 4], function(i, v) {   $new = $new.add("<div>"); });  alert($new.length == 4); // true  // alerts: <div></div><div></div><div></div><div></div> alert($("<div>").append($new).html());  
like image 145
Shog9 Avatar answered Oct 10 '22 19:10

Shog9


Document Fragments are perfect for this; creates an empty object ready for appending. :)

$(document.createDocumentFragment()) 
like image 39
Justin Geeslin Avatar answered Oct 10 '22 18:10

Justin Geeslin