7

So I've read that jQuery uses document fragments internally to make rendering faster. But I am wondering if anyone knows if jQuery would use createDocumentFragment in this situation where I'm appending img elements to the DOM using the each loop?

var displayArray = []; // Lots of img elements

$.each(displayArray, function()
{
    $('#imgSection').append(this);
});

Or would I need to use this code in order to reduce the number of browser reflows?

var displayArray = []; // Lots of img elements
var imgHolder = $('<div/>');

$.each(displayArray, function()
{
    imgHolder.append(this);
});

$('#imgSection').append(imgHolder);

Also, the displayArray is populated by other code, not shown here, that creates img elements based off of paths in a JSON file.

Thank you for any advice.

Matt Whitehead
  • 1,743
  • 3
  • 19
  • 34
  • 1
    `.append` will directly add the element to the other element. I don't see how a document fragment could even work here. – Felix Kling Jan 30 '13 at 23:02
  • @FelixKling The idea here is to reduce the number of times the browser has to reflow the screen. I was just wondering if jQuery does that internally or not. – Matt Whitehead Jan 30 '13 at 23:11
  • Yes, I understand that, but in this case you are iterating over an array of DOM elements lets say and in each iteration your are adding an element to an existing element in the tree. There cannot be a middle step where jQuery is using a document fragment. You have to take of avoiding reflows yourself. – Felix Kling Jan 30 '13 at 23:15
  • @FelixKling Ahh... that makes more sense now. Thank you. – Matt Whitehead Jan 30 '13 at 23:21
  • 1
    If you have "*lots of img elements*", the browser will rather be troubled with image loading than with reflowing. – Bergi Jan 30 '13 at 23:24
  • @Bergi Already thought of that. The images preload and are not put in the DOM until they have a width > 0. – Matt Whitehead Jan 30 '13 at 23:31
  • @Freethinker Just wondering why preloading images then put them in the DOM is better than user watch them loading in queue (at least user can see the loading progress)? – kakacii Sep 06 '13 at 06:30
  • @kakacii The application I was doing this for is an interactive virtual tour and I needed to download at least 6 of the images before allowing the user to interact with it. Otherwise, they might get confused if they we're trying to use it before the images were downloaded. While this was happening, I did use a loading progress screen. – Matt Whitehead Sep 06 '13 at 19:20

3 Answers3

8

Why all the looping to add elements?

$('#imgSection').append("<div>" + displayArray .join("") + "</div>");

Okay so it is elements.

The quickest way is going to be using append with the array itself.

$("#out").append(elems);

other option using one div to append is

var div = $("<div/>").append(elems);
$("#out").append(div);

BUT appending a lot of images at once is going to be bad unless they are preloaded. That will be a bunch of http requests being queued up.

jsPerf test cases

epascarello
  • 204,599
  • 20
  • 195
  • 236
  • `displayArray` might contain DOM elements or jQuery objects. – Blender Jan 30 '13 at 23:03
  • Blender is right, my displayArray is populated by some other code, not shown here, that takes image paths from a JSON file and creates img elements. – Matt Whitehead Jan 30 '13 at 23:09
  • you can't call `.append()` with an array like that. – Alnitak Jan 30 '13 at 23:29
  • @Alnitak Really? Would you like to make a bet on that? http://jsfiddle.net/A3TM7/ – epascarello Jan 30 '13 at 23:31
  • @epascarello Thanks for the test cases, that really helps. And yes the images are preloaded and preloaded one at a time, they're big images for a slide show. – Matt Whitehead Jan 30 '13 at 23:35
  • according to this blog article - http://www.bennadel.com/blog/2281-jQuery-Appends-Multiple-Elements-Using-Efficient-Document-Fragments.htm - jQuery will use a doc fragment if you pass an array of elements to `.append()` – Alnitak Jan 30 '13 at 23:36
  • @Alnitak Thank you! That's the kind of article I was looking for. Good to know. – Matt Whitehead Jan 30 '13 at 23:44
  • Hi @epascarello , One thing that I don't understand about preloading. When you preload lots of images, doesn't that needs the same bunch of http requests? When do you do preloading, right after the page loading? – kakacii Sep 06 '13 at 06:42
  • @kakacii Yes it still needs the requests, but it you want it to all appear at once, than you would need to preload. If you don't you would have the empty spaces. – epascarello Sep 06 '13 at 14:29
8
  1. No, if you use $.each() then jQuery won't use a DocumentFragment - jQuery has no way of knowing what you're going to do inside the loop and each iteration is independent.

  2. The point of the document fragment is that you don't have to wrap all your new elements up in a wrapper element as you've done in your second example to limit the reflows.

  3. jQuery apparently will use a document fragment if you pass an array of elements directly to .append() instead of iterating over them yourself.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • I think "if your elements need a common parent[...]" is an important point. Thanks for pointing that out. Confirmed my thinking. – Wolfone Nov 12 '18 at 08:22
  • "the fragment can contain multiple elements all of which will be inserted at the required point."... Are you saying that those multiple elements can be attached at _different_ parents in one go? How do you do that? – Robert Siemer Mar 25 '20 at 02:27
  • @RobertSiemer no, I'm not saying that at all. A document fragment is just a way of inserting a whole set of elements to the DOM _in one place_ and in a single operation. – Alnitak Mar 25 '20 at 10:29
  • Then the sentence “If your elements need a common parent then you don't need document fragments.” does not make much sense.—This is the only thing a document fragment is good at: attaching to a common parent. And if your elements _don’t_ need a common parent (i.e. should go to different parents), you are out of luck with atomic operations with document fragments or any other method I know of. – Robert Siemer Mar 25 '20 at 23:09
  • @RobertSiemer I can maybe rephrase that, but bear in mind I wrote it 7 years ago. I think I was trying to say that you don't need a fragment to perfom an atomic insert if the elements are the _whole set_ of elements that are going to share a newly inserted parent. – Alnitak Mar 26 '20 at 00:21
  • Thanks for clearing that up. My knowledge would not be on the level it is now without this q/a and the dialogue we just had. – Robert Siemer Mar 26 '20 at 00:50
  • @Wolfone ...some time passed, but your comment indicates a thinking which might had taken a different turn with the other comments on this answer now. – Robert Siemer Mar 26 '20 at 00:53
  • @RobertSiemer Valid! Thanks for leading me back to the topic! – Wolfone Mar 31 '20 at 08:42
0

If you really care about reflows (and have noticed the displaying to be slow), you can hide and show the image-holding element:

var displayArray = […]; // Lots of img elements
var holder = $('#imgSection').hide();
for (var i=0; i<displayArray.length; i++)
    holder.append(displayArray[i]);
holder.show();
Bergi
  • 630,263
  • 148
  • 957
  • 1,375