Javascript - Ajouter du HTML à un élément de conteneur sans innerHTML

167

J'ai besoin d'un moyen d'ajouter du HTML à un élément de conteneur sans utiliser innerHTML. La raison pour laquelle je ne veux pas utiliser innerHTML est que quand il est utilisé comme ceci:

element.innerHTML += htmldata

Cela fonctionne en remplaçant tout le html avant d'ajouter l'ancien html plus le nouveau html. Ce n'est pas bon car cela réinitialise les médias dynamiques tels que les vidéos flash intégrées ...

Je pourrais le faire de cette façon qui fonctionne:

var e = document.createElement('span');
e.innerHTML = htmldata;
element.appendChild(e);

Cependant, le problème avec cette façon est qu'il y a cette balise span supplémentaire dans le document maintenant que je ne veux pas.

Comment cela peut-il être fait alors? Merci!

Bob
la source
1
Pourquoi ne pas utiliser Jquery? Vérifiez ma réponse détaillée ci-dessous. stackoverflow.com/a/50482776/5320562
Loukan ElKadi

Réponses:

102

Pour donner une alternative (car l'utilisation DocumentFragmentne semble pas fonctionner): Vous pouvez la simuler en itérant sur les enfants du nœud nouvellement généré et en les ajouter uniquement.

var e = document.createElement('div');
e.innerHTML = htmldata;

while(e.firstChild) {
    element.appendChild(e.firstChild);
}
Félix Kling
la source
2
Je pensais que nous recherchions une solution qui n'utilise pas "innerHTML"
kennydelacruz
1
@kennydelacruz: L'OP ne voulait pas ajouter de nouveau HTML à un HTML existant car il détruit et recrée les éléments existants. L'OP a trouvé une solution en créant un nouvel élément et en l'ajoutant, mais ils ne voulaient pas ajouter d'élément supplémentaire. Je viens d'étendre cette solution pour montrer qu'ils peuvent déplacer / ajouter les éléments nouvellement créés, ce qui n'a aucun impact sur les éléments existants.
Felix Kling
Je sais que c'est vieux, mais quelqu'un peut-il m'expliquer pourquoi on peut itérer sur e.firstChild?
Toastgeraet
1
@Toastgeraet: Ceci est par exemple n'est pas itérer plus e.firstChild . Au contraire, il vérifie s'il ea un enfant et si oui, déplace cet enfant vers l'élément.
Felix Kling
570

Je suis surpris qu'aucune des réponses ne mentionne la insertAdjacentHTML()méthode. Découvrez-le ici . Le premier paramètre est l'endroit où vous voulez que la chaîne soit ajoutée et prend ("beforebegin", "afterbegin", "beforeend", "afterend"). Dans la situation du PO, vous utiliseriez "beforeend". Le deuxième paramètre est juste la chaîne html.

Utilisation de base:

var d1 = document.getElementById('one');
d1.insertAdjacentHTML('beforeend', '<div id="two">two</div>');
alnafie
la source
53
Je viens d'essayer votre solution ainsi que celle acceptée. Les deux fonctionnent, mais le vôtre n'est que de 2 lignes et pas de boucles. Cela me semble un gagnant.
Corwin01
3
Pour référence à toute personne qui pourrait choisir cette route: Cette méthode ne joue pas bien avec les tables dans IE9.
Corwin01
2
Dans Chrome, ça me dit Uncaught TypeError: undefined is not a function!
J86
19
Ce joyau caché a besoin de plus d'exposition.
Seth
Vous obtiendrez une erreur si vous essayez d'utiliser cette méthode sur quelque chose qui n'est pas un nœud, juste FYI.
Alex W
15

alnafie a une excellente réponse à cette question. Je voulais donner un exemple de son code pour référence:

var childNumber = 3;

function addChild() {
  var parent = document.getElementById('i-want-more-children');
  var newChild = '<p>Child ' + childNumber + '</p>';
  parent.insertAdjacentHTML('beforeend', newChild);
  childNumber++;
}
body {
  text-align: center;
}
button {
  background: rgba(7, 99, 53, .1);
  border: 3px solid rgba(7, 99, 53, 1);
  border-radius: 5px;
  color: rgba(7, 99, 53, 1);
  cursor: pointer;
  line-height: 40px;
  font-size: 30px;
  outline: none;
  padding: 0 20px;
  transition: all .3s;
}
button:hover {
  background: rgba(7, 99, 53, 1);
  color: rgba(255,255,255,1);
}
p {
  font-size: 20px;
  font-weight: bold;
}
<button type="button" onclick="addChild()">Append Child</button>
<div id="i-want-more-children">
  <p>Child 1</p>
  <p>Child 2</p>
</div>

J'espère que cela sera utile aux autres.

Trevor Nestman
la source
2
Je déteste être un maniaque des règles, mais je pense qu'il aurait été préférable de créer une démo (jsfiddle, codepen, etc.) et de l'ajouter ensuite à la réponse d'Alnafie en utilisant la fonction d'édition ou en soumettant un commentaire. Créer une réponse uniquement pour démontrer la réponse d'un autre utilisateur n'est pas la façon dont fonctionne SO, quelle que soit l'utilité des informations que vous avez fournies. Imaginez si chaque utilisateur décidait de démontrer une autre réponse en créant une réponse - cela deviendrait compliqué.
Martin James
2
<div id="Result">
</div>

<script>
for(var i=0; i<=10; i++){
var data = "<b>vijay</b>";
 document.getElementById('Result').innerHTML += data;
}
</script>

assignez les données pour div avec le symbole "+ =" vous pouvez ajouter des données, y compris les données HTML précédentes

vijay
la source
11
La question nécessite spécifiquement de ne pas utiliser element.innerHTML += data.
musicnothing
1

C'est ce à quoi cela DocumentFragmentétait destiné.

var frag = document.createDocumentFragment();
var span = document.createElement("span");
span.innerHTML = htmldata;
for (var i = 0, ii = span.childNodes.length; i < ii; i++) {
    frag.appendChild(span.childNodes[i]);
}
element.appendChild(frag);

document.createDocumentFragment, .childNodes

Raynos
la source
Je viens de tester cela et cela ne fonctionne pas. Est-ce ainsi qu'il devrait être utilisé?
Bob
D'où venez-vous (a)? Est-ce une faute de frappe.
Ash Burlaczenko
1
Oui, c'est une faute de frappe, ça devrait être e. Je ne pense pas que vous puissiez utiliser innerHTML pour un fragment. Cela ne fonctionne pas
Bob
@Bob Je suis parti pour l'utilisation de la dérobade jQuery.
Raynos
jQuery non non! Je ne vais pas inclure jQuery juste pour une petite fonction: \ C'est juste exagéré
Bob
-1

Comment pêcher et en utilisant un code strict. Il y a deux fonctions préalables nécessaires au bas de cet article.

xml_add('before', id_('element_after'), '<span xmlns="http://www.w3.org/1999/xhtml">Some text.</span>');

xml_add('after', id_('element_before'), '<input type="text" xmlns="http://www.w3.org/1999/xhtml" />');

xml_add('inside', id_('element_parent'), '<input type="text" xmlns="http://www.w3.org/1999/xhtml" />');

Ajoutez plusieurs éléments (l'espace de noms doit uniquement être sur l'élément parent):

xml_add('inside', id_('element_parent'), '<div xmlns="http://www.w3.org/1999/xhtml"><input type="text" /><input type="button" /></div>');

Code réutilisable dynamique:

function id_(id) {return (document.getElementById(id)) ? document.getElementById(id) : false;}

function xml_add(pos, e, xml)
{
 e = (typeof e == 'string' && id_(e)) ? id_(e) : e;

 if (e.nodeName)
 {
  if (pos=='after') {e.parentNode.insertBefore(document.importNode(new DOMParser().parseFromString(xml,'application/xml').childNodes[0],true),e.nextSibling);}
  else if (pos=='before') {e.parentNode.insertBefore(document.importNode(new DOMParser().parseFromString(xml,'application/xml').childNodes[0],true),e);}
  else if (pos=='inside') {e.appendChild(document.importNode(new DOMParser().parseFromString(xml,'application/xml').childNodes[0],true));}
  else if (pos=='replace') {e.parentNode.replaceChild(document.importNode(new DOMParser().parseFromString(xml,'application/xml').childNodes[0],true),e);}
  //Add fragment and have it returned.
 }
}
John
la source