Insertion de HTML arbitraire dans un DocumentFragment

Je sais que l' ajout de innerHTML aux fragments de documents a été discuté récemment, et nous espérons voir l'inclusion dans le standard DOM. Mais, quelle est la solution de problème que vous devriez utiliser en attendant?

C'est-à-dire prendre

 var html = '<div>x</div><span>y</span>'; var frag = document.createDocumentFragment(); 

Je veux à la fois le div et l' span intérieur de frag , avec une doublure facile.

Points bonus pour aucune boucle. JQuery est autorisé, mais j'ai déjà essayé $(html).appendTo(frag) ; frag est encore vide après.

Voici une façon dans les navigateurs modernes sans boucle:

 var temp = document.createElement('template'); temp.innerHTML = '<div>x</div><span>y</span>'; var frag = temp.content; 

Ou, comme réutilisable

 function fragmentFromString(strHTML) { var temp = document.createElement('template'); temp.innerHTML = strHTML; return temp.content; } 

MISE À JOUR: J'ai trouvé un moyen plus simple d'utiliser l'idée principale de Pete, qui ajoute IE11 au mix:

 function fragmentFromString(strHTML) { return document.createRange().createContextualFragment(strHTML); } 

La couverture est meilleure que la méthode <template> et testée ok dans IE11, Ch, FF.

Live test / demo disponible http://pagedemos.com/str2fragment/

À l'heure actuelle, la seule façon de remplir un fragment de document en utilisant uniquement une chaîne est de créer un objet temporaire et de faire passer les enfants pour les annexer au fragment.

  • Comme il n'est pas ajouté au document, rien n'est rendu, donc il n'y a pas de succès.
  • Vous voyez une boucle, mais elle ne boucle que les premiers enfants. La plupart des documents ne possèdent que quelques éléments semi-racine, ce qui n'est pas grave non plus.

Si vous souhaitez créer un document entier, utilisez plutôt DOMParser. Jetez un oeil à cette réponse .

Code:

 var frag = document.createDocumentFragment(), tmp = document.createElement('body'), child; tmp.innerHTML = '<div>x</div><span>y</span>'; while (child = tmp.firstElementChild) { frag.appendChild(child); } 

Un one-liner (deux lignes pour la lisibilité) (entrée: String html , sortie: DocumentFragment frag ):

 var frag =document.createDocumentFragment(), t=document.createElement('body'), c; t.innerHTML = html; while(c=t.firstElementChild) frag.appendChild(c); 

Utilisez Range.createContextualFragment :

 var html = '<div>x</div><span>y</span>'; var range = document.createRange(); // or whatever context the fragment is to be evaluated in. var parseContext = document.body; range.selectNodeContents(parseContext); var fragment = range.createContextualFragment(html); 

Notez que les principales différences entre cette approche et l'approche <template> sont:

  • Range.createContextualFragment est un peu plus largement pris en charge (IE11 l'a juste obtenu, Safari, Chrome et FF l'ont eu pendant un certain temps).

  • Les éléments personnalisés dans le HTML seront mis à jour immédiatement avec la gamme, mais uniquement lorsqu'ils sont clonés dans le document réel avec un modèle. L'approche du modèle est un peu plus «inerte», ce qui peut être souhaitable.

CreateDocumentFragment crée un "conteneur" DOM ​​vide. InnerHtml et d'autres méthodes ne fonctionnent que sur les nœuds DOM (pas le conteneur), donc vous devez d'abord créer vos nœuds, puis les ajouter au fragment. Vous pouvez le faire en utilisant une méthode douloureuse d'appendChild ou vous pouvez créer un noeud et le modifier dans innerHtml et l'ajouter à votre fragment.

 var frag = document.createDocumentFragment(); var html = '<div>x</div><span>y</span>'; var holder = document.createElement("div") holder.innerHTML = html frag.appendChild(holder) 

Avec jquery, il suffit de garder et de créer votre html en tant que chaîne. Si vous voulez le convertir en un objet jquery pour effectuer des opérations jquery like, il suffit de $ (html) qui crée un objet jquery en mémoire. Une fois que vous êtes prêt à l'ajouter, vous l'ajoutez simplement à un élément existant sur une page