Insérer des éléments HTML avec JavaScript

105

Au lieu de rechercher fastidieusement des solutions de contournement pour chaque type d'attribut et d'événement lorsque vous utilisez la syntaxe suivante:

elem = document.createElement("div");
elem.id = 'myID';
elem.innerHTML = ' my Text '
document.body.insertBefore(elem,document.body.childNodes[0]);

Existe-t-il un moyen de déclarer simplement l'élément HTML entier sous forme de chaîne? comme:

elem = document.createElement("<div id='myID'> my Text </div>");
document.body.insertBefore(elem,document.body.childNodes[0]);
Le flash
la source

Réponses:

124

Au lieu de innerHTMLjouer directement avec, il peut être préférable de créer un fragment, puis d'insérer cela:

function create(htmlStr) {
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}

var fragment = create('<div>Hello!</div><p>...</p>');
// You can use native DOM methods to insert the fragment:
document.body.insertBefore(fragment, document.body.childNodes[0]);

Avantages:

  1. Vous pouvez utiliser des méthodes DOM natives pour l'insertion telles que insertBefore, appendChild, etc.
  2. Vous avez accès aux nœuds DOM réels avant leur insertion; vous pouvez accéder à l'objet childNodes du fragment.
  3. L'utilisation de fragments de document est très rapide; plus rapide que de créer des éléments en dehors du DOM et dans certaines situations plus rapide que innerHTML.

Même s'il innerHTMLest utilisé dans la fonction, tout se passe en dehors du DOM, donc c'est beaucoup plus rapide que vous ne le pensez ...

James
la source
3
Je parie que ce createDocumentFragment () ne serait pas aussi bon que le "legacy" innerHTML.
TheFlash
2
Cette méthode fonctionne dans tous les navigateurs modernes. Pour IE 5.5 et les versions antérieures, vous pouvez effectuer une vérification comme :: if (document.createDocumentFragment) {create ('...'); } else {/ * Utilisez peut-être innerHTML * /}
James
32
crescentfresh, j'aide sur SO parce que j'aime aider les gens; Je suis désolé si une solution n'est pas exploitable à 100% dans toutes les situations. Si vous êtes si inquiet, pourquoi ne pas proposer votre propre solution au lieu de critiquer inutilement les réponses déjà proposées? Quelle que soit l'abstraction, il y aura toujours des bordures! C'est un environnement d'apprentissage - nous ne sommes pas ici pour donner aux gens une solution sur une assiette - nous sommes là pour nous entraider dans ce que nous faisons! Et désolé, mais où est-ce que quelqu'un a mentionné "AJAX"?
James
1
C'est suffisant. Mes excuses. Je pense juste qu'il y a tellement d'abstractions ici sans aucune mise en garde.
Crescent Fresh
1
c'est beaucoup plus complexe que nécessaire - la réponse de sime vidas est bien meilleure
JonnyRaa
83

Tu veux ça

document.body.insertAdjacentHTML( 'afterbegin', '<div id="myID">...</div>' );
Šime Vidas
la source
13
Je ne sais pas pourquoi ce n'est pas la réponse acceptée. C'est beaucoup plus simple et plus évidemment correct
JonnyRaa
@JonnyLeeds cela ne semble pas fonctionner sur l' bodyélément mais fonctionne bien sur n'importe quel autre élément.
Phill
1
@Phill Bien sûr, cela fonctionne <body>. En fait, l'exécuter <body>est ma méthode standard pour injecter des éléments tels que des feuilles de style dans des pages Web via la console. Quel problème rencontrez-vous?
Šime Vidas
@ ŠimeVidas probablement parce que l'élément body n'a pas été défini au moment de l'exécution ... j'ai associé votre ligne avec window.onload = function () {…} pour éviter ce problème
GDY
@Grandy Phill a écrit que cela fonctionne sur d'autres éléments. Si elles <body>n'étaient pas définies, tous les autres éléments le seraient aussi, donc ce n'est probablement pas le problème de Phill.
Šime Vidas
32

Jetez un œil à insertAdjacentHTML

var element = document.getElementById("one");
var newElement = '<div id="two">two</div>'
element.insertAdjacentHTML( 'afterend', newElement )
// new DOM structure: <div id="one">one</div><div id="two">two</div>

position est la position par rapport à l'élément que vous insérez à côté de:

'beforebegin' Avant l'élément lui-même

'afterbegin' Juste à l'intérieur de l'élément, avant son premier enfant

'beforeend' Juste à l'intérieur de l'élément, après son dernier enfant

'afterend' Après l'élément lui-même

svnm
la source
17

Dans le JavaScript old school, vous pouvez faire ceci:

document.body.innerHTML = '<p id="foo">Some HTML</p>' + document.body.innerHTML;

En réponse à votre commentaire:

[...] J'étais intéressé à déclarer la source des attributs et des événements d'un nouvel élément, pas celle innerHTMLd'un élément.

Vous devez cependant injecter le nouveau HTML dans le DOM; c'est pourquoi innerHTMLest utilisé dans l'exemple JavaScript de la vieille école. Le innerHTMLde l' BODYélément est précédé du nouveau HTML. Nous ne touchons pas vraiment au HTML existant dans le BODY.

Je vais réécrire l'exemple ci-dessus pour clarifier ceci:

var newElement = '<p id="foo">This is some dynamically added HTML. Yay!</p>';
var bodyElement = document.body;
bodyElement.innerHTML = newElement + bodyElement.innerHTML;
// note that += cannot be used here; this would result in 'NaN'

L'utilisation d'un framework JavaScript rendrait ce code beaucoup moins verbeux et améliorerait la lisibilité. Par exemple, jQuery vous permet d'effectuer les opérations suivantes:

$('body').prepend('<p id="foo">Some HTML</p>');
Mathias Bynens
la source
Assez bien. Mais j'étais intéressé à déclarer la source des attributs et événements d'un nouvel élément, pas le innerHTML d'un élément.
TheFlash
1
document.getElementsByTagName('body')[0]peut en effet être remplacé par document.body, bon point. Cependant, si vous souhaitez ajouter ou ajouter le nouveau HTML à un autre élément existant au lieu du BODY, vous devrez utiliser document.getElementById()et / ou document.getElementsByTagName(); c'est pourquoi je l'ai utilisé dans l'exemple.
Mathias Bynens
1
De plus, votre code peut devenir très désordonné très rapidement si vous ajoutez / insérez directement "innerHTML"
James
1
@JimmyP: Quelles ordures! Le but même de cette question est de pouvoir insérer directement du HTML sous forme de chaînes au lieu de jouer avec des fonctions pour le construire, attrib par attrib, nœud par nœud, élément par élément.
TheFlash
1
cela détache tous les gestionnaires d'événements et peut provoquer d'importantes fuites de mémoire.
adardesign
1

À ma connaissance, ce qui, pour être honnête, est assez récent et limité, le seul problème potentiel avec cette technique est le fait que vous ne pouvez pas créer dynamiquement certains éléments de tableau.

J'utilise un formulaire pour créer des modèles en ajoutant des éléments "template" à un DIV caché puis en utilisant cloneNode (true) pour créer un clone et en l'ajoutant si nécessaire. Gardez à l'esprit que vous devez vous assurer de réattribuer les identifiants au besoin pour éviter la duplication.

Rpc
la source
-1

Comme d'autres l'ont dit, la fonctionnalité pratique de préfixe de jQuery peut être émulée:

var html = '<div>Hello prepended</div>';
document.body.innerHTML = html + document.body.innerHTML;

Alors que certains disent qu'il vaut mieux ne pas "gâcher" avec innerHTML , c'est fiable dans de nombreux cas d'utilisation, si vous savez ceci:

Si un <div>, <span>ou <noembed>nœud a un nœud de texte enfant qui comprend les caractères ( &), ( <), ou ( >), innerHTML retourne ces caractères comme &amp, &ltet &gtrespectivement. Utilisez Node.textContentpour obtenir une copie correcte du contenu de ces nœuds de texte.

https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML

Ou:

var html = '<div>Hello prepended</div>';
document.body.insertAdjacentHTML('afterbegin', html)

insertAdjacentHTMLest probablement une bonne alternative: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML

taseenb
la source
-2

Si vous souhaitez insérer du code HTML dans la balise de la page existante, utilisez Jnerator . Cet outil a été créé spécialement pour cet objectif.

Au lieu d'écrire le code suivant

    var htmlCode = '<ul class=\'menu-countries\'><li
        class=\'item\'><img src=\'au.png\'></img><span>Australia </span></li><li
        class=\'item\'><img src=\'br.png\'> </img><span>Brazil</span></li><li
        class=\'item\'> <img src=\'ca.png\'></img><span>Canada</span></li></ul>';
    var element = document.getElementById('myTag');
    element.innerHTML = htmlCode;

Vous pouvez écrire une structure plus compréhensible

    var jtag = $j.ul({
        class: 'menu-countries',
        child: [
            $j.li({ class: 'item', child: [
                $j.img({ src: 'au.png' }),
                $j.span({ child: 'Australia' })
            ]}),
            $j.li({ class: 'item', child: [
                $j.img({ src: 'br.png' }),
                $j.span({ child: 'Brazil' })
            ]}),
            $j.li({ class: 'item', child: [
                $j.img({ src: 'ca.png' }),
                $j.span({ child: 'Canada' })
            ]})
        ]
    });
    var htmlCode = jtag.html();
    var element = document.getElementById('myTag');
    element.innerHTML = htmlCode;
Berezh
la source