Alternative pour innerHTML?
Je me demande s'il existe un moyen de changer le texte de N'importe quoi en HTML sans utiliser innerHTML.
La raison pour laquelle je demande est parce que c'est un peu mal vu par le W3C. Je sais que c'est chiant, mais je veux juste savoir, y a-t-il un moyen?
EDIT: les gens semblent mal comprendre ce que je demande ici: je veux trouver un moyen de changer efficacement le texte affiché.
Si j'ai:
<div id="one">One</a>
InnerHTML me permet de faire ceci:
var text = document.getElementsById("one");
text.innerHTML = "Two";
Et le texte sur mon écran aura changé.
Je ne souhaite pas ajouter plus de texte, je souhaite changer deja texte existant.
11 réponses
La méthode recommandée est la manipulation DOM, mais elle peut être assez verbeuse. Par exemple:
// <p>Hello, <b>World</b>!</p>
var para = document.createElement('p');
para.appendChild(document.createTextNode('Hello, '));
// <b>
var b = document.createElement('b');
b.appendChild(document.createTextNode('World');
para.appendChild(b);
para.appendChild(document.createTextNode('!'));
// Do something with the para element, add it to the document, etc.
modifier
En réponse à votre modification, afin de remplacer le contenu actuel, vous supprimez simplement le contenu existant, puis utilisez le code ci-dessus pour remplir le nouveau contenu. Par exemple:
var someDiv = document.getElementById('someID');
var children = someDiv.childNodes;
for(var i = 0; i < children.length; i++)
someDiv.removeChild(children[i]);
Mais comme quelqu'un d'autre l'a dit, je recommande d'utiliser quelque chose comme jQuery à la place, car tous les navigateurs ne supportent pas entièrement DOM, et ceux qui ont des bizarreries qui sont traitées en interne par les bibliothèques JavaScript. Par exemple, jQuery ressemble à ceci:
$('#someID').html("<p>Hello, <b>World</b>!</p>");
La meilleure façon de le faire est d'utiliser document.createTextNode
. L'une des principales raisons d'utiliser cette fonction au lieu de innerHTML
est que tous les échappements de caractères HTML seront pris en charge pour vous alors que vous devrez échapper vous-même votre chaîne si vous définissez simplement innerHTML
.
Vous pouvez obtenir le même effet en manipulant le DOM. Le moyen le plus sûr pour changer le texte est de supprimer tous les nœuds enfants de l'élément et de les remplacer par un nouveau nœud de texte.
var node = document.getElementById("one");
while( node.firstChild )
node.removeChild( node.firstChild );
node.appendChild( document.createTextNode("Two") );
La suppression des nœuds enfants élimine le contenu du texte de votre élément avant de le remplacer par le nouveau texte.
La raison pour laquelle la plupart des développeurs évitent d'utiliser innerHTML est que l'accès aux éléments via le DOM est conforme aux normes.
Si vous voulez seulement changer le texte brut, alors il y a une solution plus rapide qui repose sur des normes:
document.getElementById("one").firstChild.data = "two";
Quoi qu'il en soit, veuillez noter que innerHTML fera partie de la prochaine norme HTML 5.
Simple.
Remplacer text.innerHTML = 'two'
avec text.firstChild.nodeValue = 'two'
.
var who=document.getElementById('one'), txt='new text';
if(who.innerText) who.innerText=txt;
else if(who.textContent) who.textContent= txt;
Cela peut être aussi répréhensible que innerHTML pour vous, mais il a l'avantage de fonctionner dans certains cas (IE) où innerHTML ou appendChild ne font pas, comme certains nœuds de table, le texte des éléments de style et de script et la valeur des champs de formulaire
Vous pouvez utiliser DOM comme suit:
<html>
<body>
<div>before</div>
<script type="text/javascript">
var element = document.getElementsByTagName("div")[0];
alert(element.firstChild.nodeValue);
element.removeChild(element.firstChild);
element.appendChild(document.createTextNode('after'));
alert(element.firstChild.nodeValue);
</script>
</body>
Mais je pense que quelqu'un le fait rarement mais utilise un framework comme jQuery ou Prototype ou tout autre framework javascript là à la place. C'est un exemple jquery:
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
</head>
<body>
<div>before</div>
<script type="text/javascript">
var element = $("div");
alert(element.text());
element.text("after");
alert(element.text());
</script>
</body>
Il me semble que la combinaison CSS+HTML + JS devrait obtenir les effets souhaités:
.myelement:before {
content: attr(alt);
}
...
<span class='myelement' alt='initial value'></span>
...
element.setAttribute('alt', 'new value');
Est-ce que quelqu'un sait si cela fonctionne dans la pratique?
Eh bien, si je comprends bien votre question, cela devrait être une réponse.
var text = document.getElementById("one");
//text.innerHTML = "Two";
text.childNodes[0].nodeValue="two";
Aussi à la recherche d'une bonne alternative pour contourner element.innerHTML
j'ai finalement trouvé cette solution:
HTMLElement.prototype.htmlContent = function(html)
{
var dom = new DOMParser().parseFromString('<template>'+html+'</template>', 'text/html').head;
this.appendChild(dom.firstElementChild.content);
}
//-- document.getElementById('my-id').innerHTML = string_of_html;
document.getElementById('my-id').htmlContent(string_of_html);
Une autre alternative sans balises , mais boucle à la place:
HTMLElement.prototype.htmlContent = function(html)
{
var dom = new DOMParser().parseFromString(html, 'text/html').body;
while (dom.hasChildNodes()) this.appendChild(dom.firstChild);
}
Gardez à l'esprit que cette méthode "ajoute" du contenu lorsque innerHTML "remplace" le contenu...
Cela peut aider:
HTMLElement.prototype.clearContent = function()
{
while (this.hasChildNodes()) this.removeChild(this.lastChild);
}
//-- document.getElementById('my-id').innerHTML = '';
document.getElementById('my-id').clearContent();
Doc: https://github.com/swannty/escaping-innerHTML
perf: https://jsperf.com/escaping-innerhtml
Je trouve parfois utile de stocker une référence directe au nœud de texte si je vais le mettre à jour régulièrement. Je fais quelque chose comme ceci:
var dynamicText = myDiv.appendChild(document.createTextNode("the initial text"));
Et puis chaque fois que j'ai besoin de le mettre à jour, je fais juste ceci:
dynamicText.nodeValue = "the updated text";
Cela évite d'avoir à marcher sur le DOM ou d'ajouter ou de supprimer des enfants.