11547 sujets

JavaScript, DOM et API Web HTML5

Une solution basée sur la syntaxe jQuery :

L'appel de la fonction

$(document).ready(function() 
    { 
		listNode(document.body,10);
    } 
);


Et la fonction :

function listNode(el,decal){
	$(el).children().each(
							  function(){
								  var nodeName = this.nodeName;
								  var nodeId ="";
								  var nodeClass="";
								  if(this.id != "")
								  	nodeId="#"+this.id;
								  if(this.className != "")
								  	nodeClass="."+this.className;
								  								  $('body').append("<span style='margin-left:"+decal+"px'>"+nodeName+nodeId+nodeClass+"</span><br/>");
								  if( $(this).children().length > 0)
								  	listNode(this,decal+20);
							});
}


L'arborescence de ton code apparaitra en fin de page Smiley smile
Modifié par spiral123 (05 Aug 2010 - 10:50)
Un truc du genre, ça irait pas (pas testé) ?

Array.prototype.merge=function(){
	var currentArray=this;
	
	for(var t=0, maxArguments=arguments.length; t<maxArguments; t++){
		if(arguments[t] instanceof Array){
			var arrayToMerge=arguments[t];
			for(var i=0, maxElements=arrayToMerge.length; i<maxElements; i++) currentArray.push(arrayToMerge[i]);
		}
	}
}

NodeList.prototype.toArray=function(){
	var nodeList=this;
	var array=new Array();
	
	for(var t=0, maxNode=nodeList.length; t<maxNode; t++) array.push(nodeList[t]);
	
	return array;
}

Node.prototype.getDescendantNodes=function(){
	var nodeList=this.childNodes;
	var nodeArray=new Array();
	
	if(nodeList){
		var descendantNode=new Array();
		for(var t=0, maxNode=nodeList.length; t<maxNode; t++) descendantNode.merge(nodeList[t].getDescendantNodes());
		nodeArray.merge(nodeList.toArray(), descendantNode);
	}
	
	return nodeArray;
}

window.addEventListener('load', function(){alert(document.getElementById('root').getDescendantNodes());}, false);
[/i]
Ça revient au même. C'est juste la technique de programmation qui est différente (fonctionnelle vs prototype) et le fait que j'avais jamais remarqué la méthode concat (d'où la présence de merge). Après, y a quelques petits détails qui change (ordre des nœuds, liste des nœuds de type Element uniquement, le nœud courant inclus dans la liste des descendant).
La méthode fonctionnelle à l'avantage de fonctionner sur IE6 et IE7.

Trois points concernant le code que tu as trouvé :
-dans la boucle for, tu passe la liste des enfant à ta fonction au lieu de l'enfant.
-contrairement à ma méthode merge, concat ne modifie pas la liste mais renvoi une nouvelle liste à stocker dans une variable
-englobe la boucle for dans ta condition if. Ça permettra d'y faire appel uniquement lorsque qu'un nœud est susceptible de contenir des enfants (là, il va chercher les enfants même sur les nœuds texte, attributs, commentaire,...).

Au final, en fonctionnelle, tu obtiens ça :
function dex_lister(courant_element){
	var descendants=new Array();
	
	if(courant_element.nodeType==document.ELEMENT_NODE){
		var kids=courant_element.childNodes;
		
		descendants.push(courant_element);
		for(var t=0, maxKids=kids.length; t<maxKids; t++) descendants=descendants.concat(dex_lister(kids[t]))
	}
	
	return descendants;
}

dex_lister(document.getElementById('accueil-bouton'));


En prototype, ça :
Node.prototype.getDescendantNodes=function(){
	return new Array();
}

Element.prototype.getDescendantNodes=function(){
	var nodeArray=new Array();
	var nodeList=this.childNodes;
	
	nodeArray.push(this);
	for(var t=0, maxNode=nodeList.length; t<maxNode; t++) nodeArray=nodeArray.concat(nodeList[t].getDescendantNodes());
	
	return nodeArray;
}

document.getElementById('accueil-bouton').getDescendantNodes();

Modifié par MacIntoc (05 Aug 2010 - 17:46)
Si tu ne veux pas que l'élément d'origine soit dans la liste des enfants, plutôt que de lister dans ta fonction le nœud courant et ses enfants, tu devrais lister les nœuds enfants et petits enfants (un algo plus proche de ce que j'ai mis en premier).

Je te suggères aussi d'utiliser un compteur dans ta boucle for, ça éviterait de faire des itérations inutiles sur les propriétés nommées (comme kids.length et et kids.item).

Le code ressemblerais alors à ça :
function dex_lister(aieul){
	var kids=aieul.childNodes;
	var descendants=new Array();
	
	for(var t=0, maxKids=kids.lenght; t<maxKids;t++){
		if(kids[t].nodeType==document.ELEMENT_NODE) descendants=descendants.concat(kids[t], dex_lister(kids[t]));
	}
	
	return descendants;
}


Ah si, dernier point, je crois me souvenir que IE6/7 n'intègre pas les constantes DOM. Donc ELEMENT_NODE n'est pas reconnue. Du coup, il vaudrait peut-être mieux utiliser 1 à la place si tu vise ces 2 navigateurs.