2

If I have fragment = document.createDocumentFragment()
with some random Dom inside and I want to get the entire HTML ( excaly like innerHTML in regular element or document.documentElement.innerHTML in document object.

And after some text manipulation (by regex) return the HTML to the fragment how can I do that ?

pery mimon
  • 7,713
  • 6
  • 52
  • 57
  • have you tryed something? – rick Jul 07 '16 at 12:59
  • Add the fragment to a random node you create, get that nodes innerHTML. Alas the fragment object itsself doesnt support innerHTML, querySelector, etc. To re-add the updated html string, do the opposite. Add the string as innerHTML to a random node, then copy all childnodes to a new fragment. – Shilly Jul 07 '16 at 13:02
  • I post my end up solution – pery mimon Jul 08 '16 at 15:16
  • Possible duplicate of [JavaScript: Copy Node to DocumentFragment](http://stackoverflow.com/questions/41774889/javascript-copy-node-to-documentfragment) – MTroy Apr 20 '17 at 13:47

4 Answers4

2

I end up with that ugly solution :

        var helperDiv = document.createElement('div');
        helperDiv.appendChild(fragment)
        var innerHTML = helperDiv.innerHTML.replace(someRegExp,()=>values())
        helperDiv.innerHTML = innerHTML;
        var len = helperDiv.children.length;
        while(len--){
            fragment.appendChild( helperDiv.firstChild );
        }

So I appreciated a better way

2017 some update

I come with better solution with Range.

function fragmentInnerHTML(fragment, callback){
  var range = new Range();
  var helperDiv = document.createElement('div');
  helperDiv.appendChild(fragment);
  helperDiv.innerHTML = callback( helperDiv.innerHTML) 
  range.selectNodeContents(helperDiv);
  fragment.append( range.extractContents() );
  range.detach();
}

fragmentInnerHTML( fr, html => html.replace(/test(\d)/g,'test-$1') );

can be edited to be even fewer lines if needed

demo: https://jsfiddle.net/vtssq8jz/26/

pery mimon
  • 7,713
  • 6
  • 52
  • 57
2

If f is a documentFragment, its innerHTML can be retrieved using:

console.log([].map.call(f.children, e => e.outerHTML).join('\n'));

Note that map is not a method of f.children. As a result, the following code doesn't work:

console.log(f.children.map(e => e.outerHTML).join('\n'));
Simon Hi
  • 2,838
  • 1
  • 17
  • 17
  • `console.log([...f.children].map(e => e.outerHTML).join('\n'));` does work however. – Nate Symer May 17 '21 at 15:07
  • 1
    And, one doesn't necessarily need to join on newlines, it's possible to just do `.join('')`. It also makes much more sense since outerHTML is usually generated as a compact, unspaced string of HTML from the browser - i.e. it's not the original HTML the developer wrote that DID have spaces.. – Nate Symer May 17 '21 at 15:11
1

I stumbled upon similar problem and see if this can help you:

var $frag = new DocumentFragment();
var html = '' ; 
[].forEach.call($frag.children, function(el) { 
  html += el.outerHTML;
});

Basically iterate through the children property of document fragment and concatenate the outerHTMLs of its elements. :)

y.c
  • 4,845
  • 2
  • 19
  • 11
0

I have come across this sort of problem previously, and I came to the conclusion that a document fragment is easier to work with when it has a single, top-level node. With that in mind, I would probably use a known 'container' element inside the document fragment, and then set and retrieve the innerHTML of that.

Something like this:

var fragment = document.createDocumentFragment(); //Initialise the fragment
fragment.appendChild(document.createElement('div')); //Create a top-level container element.
fragment.firstChild.innerHTML = 'Your chunk of DOM'; // Set the contents of your fragment, either with innerHTML, or by appending the child node.

console.log(fragment.firstChild.innerHTML); //Use any normal DOM node method to access the contents.

Basically you always use fragment.firstChild to access the contents of your fragment, so you have access to all of a DOM node's usual methods.

Ben Hull
  • 7,524
  • 3
  • 36
  • 56
  • nice, but if you use the first `div` what the benefit you get from using `documentFragment`. I use it for the ability to contain sibling at the root . and add the entire siblings elements with simple `div.appendChild( fragment )` – pery mimon Jul 08 '16 at 14:55