11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous,
j'essaie de détruire en DOM les balises p qui se trouvent dans une div.
Pour cela j'ai fais une petite boucle mais je n'arrive à détruire qu'une seule balise p, je ne comprends pas ce que je fais d'incorrect.
J'ai fais une petite page de test qui reproduit le "problème".
Voici le code:

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
	<title>Test</title>
	<meta http-equiv="content-type" content="text/html;charset=utf-8" />

	<script language="JavaScript" type="text/javascript">

		function test() 
			{
				var baliseEnv = document.getElementById("enveloppe");
				var baliseEnvP = baliseEnv.getElementsByTagName("p");
				var nbBalisesPdansEnv = baliseEnvP.length;
			
				for(var a=0; a< nbBalisesPdansEnv; a++)
					{
						baliseEnv.removeChild(baliseEnvP[a]);
					}
			}

	</script>

</head>

<body>
	<div id="enveloppe">
		<p>test1</p>
		<p>test2</p>
		<input type="button" id="bouton" name="bouton" value="test" onclick="test();" />
	</div>

</body>

</html>


Seul test1 est détruit quand on clique sur le bouton qui appelle la fonction.
Ce comportement est-il normal? Comment faire pour détruire les 2 balises p?

Merci d'avance
Modifié par moreall (13 Aug 2011 - 12:04)
Bonjour,

Ce fonctionnement est normal. Quand tu supprimes un de tes éléments p, ton getElementsByTagName("p") est également impacté ce qui cause le plantage de ton script.

L'idée est alors de passer par un tableau intermédiaire où tu stockeras chaque DOMNode p trouvé. Ainsi, tu pourras supprimer en combinant la propriété parentNode et la méthode removeChild.
Bonjour yodaswii et merci pour ta réponse,

Je me doutais bien que ce comportement était normal.
Est ce que tu pourrais me préciser la méthodologie dont tu me parles stp?
Je viens d'essayer de créer un nouveau tableau dans lequel j'ai stocké les DOMNode p trouvés.
J'applique ensuite removeChild sur ce tableau mais j'obtiens le même comportement.

Je te montre le code:

function test() 
			{
				var baliseEnv = document.getElementById("enveloppe");
				var baliseEnvP = baliseEnv.getElementsByTagName("p");
				var nbBalisesPdansEnv = baliseEnvP.length;
			
				for(var a=0; a< nbBalisesPdansEnv; a++)
					{
                                          var tableau = new Array;
                                          tableau[a] = baliseEnvP[a];
						
                                         baliseEnv.removeChild(tableau[a]);
					}
			}


Je dois oublier quelque chose....
Modifié par moreall (13 Aug 2011 - 13:45)
Ci-dessous fonction corrigée :


function test()  { 
	var enveloppe = document.getElementById("enveloppe"); 
	var enveloppePs = enveloppe.getElementsByTagName("p");
	var temp = [];
	for (var p = 0; p < enveloppePs.length; p++) {
		temp.push(enveloppePs[p]);
	}
	enveloppePs = temp;
	for (var p = 0; p < enveloppePs.length; p++) 
	{ 
		enveloppePs[p].parentNode.removeChild(enveloppePs[p]);
	} 
}


vincentD83 a écrit :
Pourquoi ne pas utiliser JQuery ?


Hum, juste pour supprimer 2 paragraphes ... bon chacun ces choix (mais qu'est-ce qu'on ferait pas pour éviter le moindre codage parce que Javascript c'est compliqué toussa).
a écrit :
Hum, juste pour supprimer 2 paragraphes ... bon chacun ces choix (mais qu'est-ce qu'on ferait pas pour éviter le moindre codage parce que Javascript c'est compliqué toussa).


J'espère que son site / projet est plus que la suppression de 2 paragraphes ...
Après plutôt que d'écrire des fonctions longues et perdre 2 heures sur un forum, on gagne en ligne de code, rapidité de codage etc ...

Mais chacun ses choix, je prime la productivité pour ma part.
@vincentD83 : cela n'a rien à voir avec la productivité ou non : c'est une histoire de compétence. Savoir que la longueur d'une NodeList varie c'est la base de la base, jQuery est un bon outil, mais il ne doit pas être utilisé pour palier à un manque de savoir-faire.
Etre contraint d'utiliser un framework car on ne sais pas itérer une NodeList c'est un niveau d'incompétence innaceptable. C'est à cause de ce genre de raisonnement qu'on a aujourd'hui des agences qui livrent des sites avec une douzaine de librairies et modules liées (et souvent redondants du genre : 1 prototype, 2 jQuery, 3 carroussels différents, un MooTools, etc) car elles ne savent rien faire d'elle mêmes !

Sinon pour en revenir à la question, tu as une solution plus optimale que de transformer ta NodeList en tableau, tu peux tout simplement itérer à l'envers ou maintenir ton lenght à jour !

Le plus simple en itérant à l'envers :

function test()  
    { 
        var parent = document.getElementById("enveloppe"),
             childs = parent.getElementsByTagName("p"); 
     
        while(childs.length) parent.removeChild(childs[childs.length-1]);
    }


ou à l'endroit (attention petite subtilité avec l'opérateur virgule Smiley cligne ) :

function test()  
    { 
        var parent = document.getElementById("enveloppe"),
             childs = parent.getElementsByTagName("p"),
             a, n = childs.length; 
     
        for(a=0; a<n; a++) parent.removeChild(childs[--n,a]);
    }

Modifié par Ywg (16 Aug 2011 - 16:05)
@Ywg: ta première méthode marche impeccable et est d'une simplicité désarmante! Cela clôt le débat jQuery qui parait effectivement disproportionné par rapport à ces 3 petites lignes de code!

Par contre la 2ème méthode ne fonctionne pas correctement, le dernier élément de la NodeList n'est pas détruit.
J'ai d'ailleurs du mal à comprendre comment fonctionne
 childs[--n,a]

Je ne comprend pas à quoi servent les 2 tirets...
Effectivement, j'ai écrit les fonctions de tête sans tester et je me suis planté sur la seconde. Il faut en fait faire :

function test()     
    {    
        var parent = document.getElementById("enveloppe"),   
             childs = parent.getElementsByTagName("p"),   
             n = childs.length;    
  
        for(;--n;) parent.removeChild(childs[0]);   
    }  
  
test();


Pour le -- (double tiret comme tu dit) il s'agit de l'opérateur de (pré/post)-décrémentation

Sans rentrer dans les détails, que tu trouvera mieux expliqués en cherchant un peu sur google, c'est l'équivalent de

n = n-1;

Modifié par Ywg (17 Aug 2011 - 18:43)
La fonction ne marche toujours pas. J'ai essayé de la débugger mais pas de résultat...

Merci pour l'explication du --. En fait c'est le contraire du ++!
Oh mon dieu quel boulet, je n'ai pas posté la bonne version :

function test()    
    {   
        var parent = document.getElementById("enveloppe"),  
             childs = parent.getElementsByTagName("p"),  
             n = childs.length;   
 
        for(;n--;) parent.removeChild(childs[0]);  
    } 
 
test();


Oui sinon tu as raison la décrémentation est l'inverse de l'incrémentation.
Et pour l'erreur que j'ai fait elle vient justement de la subtilité de l'opérateur qui peut être soit pré "--n" (je donne la valeur de n et ensuite je fais n-1) ou post "n--" (je fais n-1 et ensuite je renvois la valeur de n).