web-dev-qa-db-fra.com

JS. Comment remplacer un élément HTML par un autre élément/texte, représenté dans une chaîne?

J'ai un problème avec le remplacement des éléments HTML.

Par exemple, voici un tableau:

<table>
    <tr>
        <td id="idTABLE">0</td>
        <td>END</td>
    </tr>
</table>

(ça peut être div, span, n'importe quoi)

Et chaine en JavaScript:

var str = '<td>1</td><td>2</td>';

(Ce peut être n'importe quoi, 123 text, <span>123 element</span> 456 ou <tr><td>123</td> ou n'importe quoi)

Comment remplacer l'élément idTABLE par str?

Alors:

<table>
    <tr>
        <td id="idTABLE">0</td>
        <td>END</td>
    </tr>
</table>

Devient:

<table>
    <tr>
        <td>1</td>
        <td>2</td>
        <td>END</td>
    </tr>
</table> 
<!-- str = '<td>1</td><td>2</td>'; -->

<table>
    <tr>
        123 text
        <td>END</td>
    </tr>
</table>
<!-- str = '123 text' -->

<table>
    <tr> 
        <td>123</td> 
        <td>END</td>
    </tr>
</table>
<!-- str = '<td>123</td>' -->

J'ai essayé createElement, replaceChild, cloneNode, mais sans résultat du tout = (

18
el Dude

Comme le code Jquery replaceWith () était trop volumineux, délicat et compliqué, voici ma propre solution. =)

Le meilleur moyen est d'utiliser la propriété outerHTML, mais elle n'est pas encore croisée, alors j'ai fait quelques astuces, assez étranges mais simples.

Voici le code

var str = '<a href="http://www.com">item to replace</a>'; //it can be anything
var Obj = document.getElementById('TargetObject'); //any element to be fully replaced
if(Obj.outerHTML) { //if outerHTML is supported
    Obj.outerHTML=str; ///it's simple replacement of whole element with contents of str var
}
else { //if outerHTML is not supported, there is a weird but crossbrowsered trick
    var tmpObj=document.createElement("div");
    tmpObj.innerHTML='<!--THIS DATA SHOULD BE REPLACED-->';
    ObjParent=Obj.parentNode; //Okey, element should be parented
    ObjParent.replaceChild(tmpObj,Obj); //here we placing our temporary data instead of our target, so we can find it then and replace it into whatever we want to replace to
    ObjParent.innerHTML=ObjParent.innerHTML.replace('<div><!--THIS DATA SHOULD BE REPLACED--></div>',str);
}

C'est tout

28
el Dude

En utilisant jQuery, vous pouvez faire ceci:

var str = '<td>1</td><td>2</td>';
$('#__TABLE__').replaceWith(str);

http://jsfiddle.net/hZBeW/4/

Ou en javascript pur:

var str = '<td>1</td><td>2</td>';
var tdElement = document.getElementById('__TABLE__');
var trElement = tdElement.parentNode;
trElement.removeChild(tdElement);
trElement.innerHTML = str + trElement.innerHTML;

http://jsfiddle.net/hZBeW/1/

7
3dgoo

Parce que vous parlez de votre remplaçant soit rien, et que vous le remplacez également au milieu des enfants d'un élément, cela devient plus compliqué que d'insérer un élément singulier ou de supprimer et ajouter directement:

function replaceTargetWith( targetID, html ){
  /// find our target
  var i, tmp, Elm, last, target = document.getElementById(targetID);
  /// create a temporary div or tr (to support tds)
  tmp = document.createElement(html.indexOf('<td')!=-1?'tr':'div'));
  /// fill that div with our html, this generates our children
  tmp.innerHTML = html;
  /// step through the temporary div's children and insertBefore our target
  i = tmp.childNodes.length;
  /// the insertBefore method was more complicated than I first thought so I 
  /// have improved it. Have to be careful when dealing with child lists as  
  /// they are counted as live lists and so will update as and when you make
  /// changes. This is why it is best to work backwards when moving children 
  /// around, and why I'm assigning the elements I'm working with to `Elm` 
  /// and `last`
  last = target;
  while(i--){
    target.parentNode.insertBefore((Elm = tmp.childNodes[i]), last);
    last = Elm;
  }
  /// remove the target.
  target.parentNode.removeChild(target);
}

exemple d'utilisation:

replaceTargetWith( 'idTABLE', 'I <b>can</b> be <div>anything</div>' );

démo:

En utilisant le .innerHTML de notre div temporaire, cela générera les TextNodes et Elements que nous devons insérer sans aucun travail dur. Mais plutôt que d'insérer la div temporaire elle-même - cela nous donnerait une marge que nous ne voulons pas - nous pouvons simplement scanner et insérer ses enfants.

... soit cela, soit utilisez jQuery et sa méthode replaceWith.

jQuery('#idTABLE').replaceWith('<blink>Why this tag??</blink>');


mise à jour 2012/11/15

En réponse au commentaire de EL 2002 ci-dessus:

Ce n'est pas toujours possible. Par exemple, lorsque createElement('div') et que son code innerHTML est défini sur <td>123</td>, ce div devient <div>123</div> (js jette une balise td inappropriée). 

Le problème ci-dessus nie évidemment aussi ma solution - j'ai mis à jour mon code ci-dessus en conséquence (au moins pour le problème td). Cependant, pour certains HTML, cela se produira quoi que vous fassiez. Tous les agents utilisateurs interprètent le code HTML via leurs propres règles d'analyse, mais presque tous essaieront de corriger automatiquement le code HTML incorrect. Le seul moyen d'obtenir exactement ce dont vous parlez (dans certains de vos exemples) consiste à supprimer entièrement le code HTML du DOM et à le manipuler sous forme de chaîne. Ce sera le seul moyen d'obtenir une chaîne de balisage avec le suivant (jQuery ne résoudra pas non plus ce problème):

<table><tr>123 text<td>END</td></tr></table>

Si vous prenez ensuite cette chaîne et l'injectez dans le DOM, vous obtiendrez ce qui suit, selon le navigateur:

123 text<table><tr><td>END</td></tr></table>

<table><tr><td>END</td></tr></table>

La seule question qui reste est de savoir pourquoi vous souhaitez obtenir du HTML cassé en premier lieu? :)

7
Pebbl

Vous devez d'abord supprimer la table, puis ajouter le nouveau remplacement à l'objet parent de la table.

Recherchez removeChild et appendChild 

http://javascript.about.com/library/bldom09.htm

https://developer.mozilla.org/en-US/docs/DOM/Node.appendChild

Edit: JQuery .append permet sting-html sans enlever les tags: http://api.jquery.com/append/

3
Martin Lyne

Votre contribution dans ce cas est trop ambiguë. Votre code devra savoir s'il doit simplement insérer le texte tel quel ou analyser certaines balises HTML (ou sinon se retrouver avec du mauvais HTML). C'est une complexité inutile que vous pouvez éviter en ajustant l'entrée que vous fournissez.

Si la saisie déformée est inévitable, alors sans une analyse sophistiquée (de préférence dans une fonction séparée), vous pourriez vous retrouver avec du mauvais HTML (comme vous le faites dans votre deuxième exemple ... qui est Bad, non?).

Je suppose que vous voulez qu'une fonction insère des colonnes dans un tableau à une ligne. Dans ce cas, votre contenu doit être transmis sous forme de tableau (sans les balises table, tr, td). Chaque élément du tableau sera une colonne.

HTML

<table id="__TABLE__"><tr><td></td></tr></table>

JS

utiliser jQuery par souci de brièveté ...

function insert_columns (columns)
{
    var $row = $('<tr></tr>');

    for (var i = 0; i < columns.length; i++)
        $row.append('<td>'+columns[i]+'</td>');

    $('#__TABLE__').empty(); // remove everything inside

    $('#__TABLE__').append($row);
}

Donc alors...

insert_columns(['hello', 'there', 'world']);

Résultat

<table id="__TABLE__"><tr><td>hello</td><td>there</td><td>world</td></tr></table>
1
laughingbovine

Si vous devez réellement remplacer le td que vous sélectionnez dans le DOM, vous devez d’abord accéder au parentNode, puis remplacer le contenu remplacez le innerHTML par une nouvelle chaîne HTML représentant ce que vous voulez. L'astuce consiste à convertir la première cellule de table en une chaîne afin que vous puissiez ensuite l'utiliser dans une méthode de remplacement de chaîne.

J'ai ajouté un exemple de violon: http://jsfiddle.net/vzUF4/

<table><tr><td id="first-table-cell">0</td><td>END</td></tr></table>

<script>
  var firstTableCell = document.getElementById('first-table-cell');
  var tableRow = firstTableCell.parentNode;
  // Create a separate node used to convert node into string.
  var renderingNode = document.createElement('tr');
  renderingNode.appendChild(firstTableCell.cloneNode(true));
  // Do a simple string replace on the html
  var stringVersionOfFirstTableCell = renderingNode.innerHTML;
  tableRow.innerHTML = tableRow.innerHTML.replace(stringVersionOfFirstTableCell,
    '<td>0</td><td>1</td>');
</script>

Une grande partie de la complexité réside ici dans le fait que vous mélangez des méthodes DOM avec des méthodes de chaîne . Si les méthodes DOM fonctionnent pour votre application, il serait bien plus judicieux de les utiliser .Vous pouvez également le faire avec des méthodes DOM pures (document.createElement, removeChild, appendChild), mais cela prend plus de lignes de code et votre question indique explicitement que vous souhaitez utiliser une chaîne.

1
Jonathan Cross
idTABLE.parentElement.innerHTML =  '<span>123 element</span> 456';

bien que cela fonctionne, il est toujours recommandé d’utiliser getElementById: Les éléments d’arborescence DOM avec ID sont-ils des variables globales?

replaceChild fonctionnerait très bien si vous vouliez créer votre remplacement, élément par élément, en utilisant document.createElement et appendChild, mais je ne vois pas le but.

0
jcomeau_ictx

utiliser l'attribut "innerHTML"

en quelque sorte sélectionnez la table:

var a = document.getElementById('table, div, whatever node, id')
a.innerHTML = your_text
0
Hamed Tabatabaei