6

If I do the following, then 0 and 2 are returned, respectively:

$html = $(document.createDocumentFragment());
$html.append('<a href="#">First link</a><a href="#">Second link</a>');

console.log($html.find('a').length);
console.log($html[0].querySelectorAll('a').length);

How can I make it so that the jQuery method will also work? So basically, I want to be able to search a document fragment with jQuery, rather than needing to switch back and forth with native JavaScript DOM functions.

Gary
  • 3,891
  • 8
  • 38
  • 60
  • Please explain what exactly you want to do – Apul Gupta Oct 25 '14 at 04:58
  • 1
    It's exactly as I said. I want to be able to search a document fragment for whatever I need, such as `a` elements, as in the example. jQuery's `find` works great for navigating a page's DOM, but for some reason it doesn't work on a document fragment, and I'd like to know why, and if it is possible to fix it. – Gary Oct 25 '14 at 04:59
  • The problem isn't `find`, it's `append`. In my tests, `.append()` doesn't work on a jQuery object that contains a document fragment. – Barmar Oct 25 '14 at 05:03
  • Okay, is there perhaps an alternative method of modifying a document fragment, using jQuery, that would make `find` work with it? Because it's still really nice to use `append` and `prepend` on a document fragment (the HTML that is generated still seems to be fine). And at the moment, I have a wrapper function to essentially use `querySelectorAll` on document fragments when necessary, and then wrap that back as a jQuery object, so I can continue using jQuery. A bit of a hack, but it lets me use jQuery still. – Gary Oct 25 '14 at 05:06
  • It looks like `append()` was fixed in jQuery 1.11, but `find()` still doesn't work with it. – Barmar Oct 25 '14 at 05:40
  • Thanks. I guess ultimately for now, I can just wrap my document fragments in `DIV` or `SPAN` and call it a day. There are some special cases where I'm stuck with docfrags still though. – Gary Oct 25 '14 at 05:46
  • For some reason 'find' returns an Object while querySelectorAll returns a NodeList. – HeadCode Oct 25 '14 at 05:46
  • Found this in the `Sizzle` code that jQuery uses to implement selectors: `if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { return []; }`. Document fragments are node type 11. – Barmar Oct 25 '14 at 05:46
  • Yeah, they should really get around to that someday... I found [this ticket](http://bugs.jquery.com/ticket/9522) that said they won't bother with adding `append` to docfrags, but then [this ticket](http://bugs.jquery.com/ticket/11566) where they eventually added it. – Gary Oct 25 '14 at 05:49
  • See related question http://stackoverflow.com/questions/1643349/is-there-any-way-to-find-an-element-in-a-documentfragment. – Barmar Oct 25 '14 at 05:51
  • Yeah I saw that question. That's where I got the idea of just using `querySelectorAll` instead of jQuery's `find`. – Gary Oct 25 '14 at 05:55
  • just comment, jquaey use internal `documentFragment` when you use syntax like this `$('

    ')`
    – pery mimon Aug 01 '16 at 11:26

2 Answers2

0

You need to pass the string fragment into jQuery and save a reference to it:

var $html = $(document.createDocumentFragment());
var $fragment = $('<a href="#">First link</a><a href="#">Second link</a>');
$html.append($fragment);

console.log($fragment.filter('a').length);
console.log($html[0].querySelectorAll('a').length);

Then the parsed fragment can be traversed. Note that find has been replaced with filter here, because we have a reference to a collection of a elements, and find only works on children of a containing element.

This will log 2 and 2 as expected. Demo: http://jsfiddle.net/fec9csxu/

0x8890
  • 515
  • 1
  • 4
  • 12
-1

Here, this might help:

var $html = $("html");
$html.append('<a href="#">First link</a><a href="#">Second link</a>');
console.log($html.find('a').length);
console.log($html[0].querySelectorAll('a').length);

Gives you the expected outputs 2 and 2.

user3681587
  • 566
  • 5
  • 12