11524 sujets

JavaScript, DOM et API Web HTML5

Pages :
(reprise du message précédent)

Bon j'crois sincerement que j'vais laissez tomber, j'en ai vraiment marre.
pfff c'est du foutage de gueule, pas un seul cours sur le DOM, et le gars il nous balance ça comme ça...

c'était mon petit coup de gueule desolé Smiley confused

sinon chmel, j'te remercie encore, mais j'arrive a rien afficher, même en reprenant ton code, en le changeant etc... Smiley decu
chmel a écrit :
et la tu vois ?


euh ... oui, j'vois bien même lol.
Mais stp dis moi que t'as pas afficher ça avec le code que t'as posté ? Smiley bawling
j'arrêtes pas d'avoir des "XXX has no properties" dans la console JavaScript de Firefox...
JRM a écrit :


euh ... oui, j'vois bien même lol.
Mais stp dis moi que t'as pas afficher ça avec le code que t'as posté ? Smiley bawling .


Je pense que ça ne marchait pas parce que tu faisais un simple copié / collé du code HTML de la page. Il vaut mieux d'abord cliquer sur "citer", puis récupérer le code dans le textarea sinon il te manque des caractères à cause des BBCODEs.
Il faudrait que Raphaël précise ça dans sa FAQ si ça n'est pas déjà fait Smiley ohwell

Dans la page en ligne, j'ai seulement modifié :
    // on clone le noeud texte du titre
    tampon=ex.childNodes[a].firstChild.cloneNode(true);		
    //pour le coller dans le nouvel item
    newLI.appendChild(tampon)    

car appendChild effectue un couper/coller, et les textes de titre étaient déplacés au lieu d'être copiés.
Je n'ai pas d'erreurs dans Firefox 1.04

Pour ce qui est de l'ordre non respecté des titre 2-1 et titre 2-2, ça se corse, il faut tenir compte aussi des h1, h2, h3.
Tu crois que tu pourras gérer ? Smiley lol
Modifié par chmel (04 Nov 2005 - 17:41)
chmel a écrit :
Tu crois que tu pourras gérer ? Smiley lol


Sincerement non, mais j'commence à comprendre ce que tu as fais et c'est déjà beaucoup pour moi Smiley lol
Administrateur
Bonjour,

JRM a écrit :


euh ... oui, j'vois bien même lol.
Mais stp dis moi que t'as pas afficher ça avec le code que t'as posté ? Smiley bawling
j'arrêtes pas d'avoir des "XXX has no properties" dans la console JavaScript de Firefox...

le signe que le code affiché n'est pas le bon, c'est l'italique qui commence à la moitié du code et se poursuit jusqu'à la fin d'un message ... Smiley ohwell
La faute aux indices de tableau tableau[ i] ... Il doit y avoir d'autres problèmes de balises interprétées à tort.

chmel a écrit :
Il vaut mieux d'abord cliquer sur "citer", puis récupérer le code dans le textarea sinon il te manque des caractères à cause des BBCODEs.
Il faudrait que Raphaël précise ça dans sa FAQ si ça n'est pas déjà fait Smiley ohwell

Smiley jap pour la méthode "citer" (plutôt "éditer" en fait)
L'idéal serait que dew modifie le comportement de la balise [ code], c'est je crois sur la to-dew mais il a d'autres priorités pour l'instant.

function generateToc()
{
	document.body.insertBefore( nextLevel( "toc" , 1, document.body.firstChild ), document.body.firstChild );
}


function nextLevel( curid, curlevel, curelement )
{
	var i = 1;
	var list = document.createElement( "ul" );
	var listitem = null;

	var nextelement = curelement;
	var doneSubLevel = true;
	do {
		
		if( nextelement.nodeType == 1 && nextelement.tagName.substr(0,1) == "H" )
		{
			nextlevel = nextelement.tagName.substr(1,1);
			if( nextlevel == curlevel )
			{
				nextelement.id = nextid = curid + "_" + i++;
				
				var anchor = document.createElement( "a" );
				anchor.href = "#" + nextid;
				
				for( j = 0; j < nextelement.childNodes.length; j ++ ) 
				{ anchor.appendChild( nextelement.childNodes[j].cloneNode(true)); }

				listitem = document.createElement( "li");		
				listitem.appendChild( anchor );
				list.appendChild( listitem );
				doneSubLevel = false ;
			} 
			else if( nextlevel > curlevel && !doneSubLevel ) 
			{
				listitem.appendChild( nextLevel( nextid, nextlevel, nextelement ) );
				doneSubLevel = true;

			}
			else if( nextlevel < curlevel )
			{
				return list;
			}
		}
		
		nextelement = nextelement.nextSibling;
		
	} while( nextelement != null )

	return list;	
}

window.onload = generateToc;


Moi aussi j'aime bien m'amuser Smiley cligne

ça marche si on passe directement d'un h1 à un h4. Par contre si arprès le h4 on trouve un h2 ou un h3, ces derniers sont ignorés, mais de toutes façons, c'est impossible si on respecte l'énoncé de l'exercice, qui précise bien que si on saute des niveaux (du h1 au h4 par exemple), on fait comme si on passait au niveau suivant (du h1 au h2).

Je n'ai pas fait la vérification de la présence du DOM2, ni le <div class="toc"> (qui au passage ne sert à rien, on pourrait tout aussi bien mettre le class="toc" sur le <ul> directement).
Sinon je crois que j'ai bon Smiley lol

Je commenterai plus en détails et je mettrai mes fichiers en ligne demain, si j'ai le temps.

Testé sous Firefox et Konqueror.
Modifié par Lanza (04 Nov 2005 - 23:49)
Smiley biggol Bonjour,
Bravo Lanza, tu as répondu aux trois niveaux de difficulté, et moi seulement au premier.
D'ailleurs, c'est plutôt tordu comme problème, mais ça permets de se familiariser avec le DOM
que peut de monde utilise.

Felippe, je persiste pour le bouton "citer", car c'est le code des autres qu'on veut éditer,
On connait le sien Smiley cligne

C'est les crochets, communs aux 2 langages qui posent problèmes entre les balises code du BBCODE.
Je ne sait avec quel langage de script c'est écrit, mais il doit y avoir moyen de lui faire ignorer les crochets
entre les balises code. Smiley biggol
Merci beaucoup Lanza, en effet j'aimerai bien que tu commentes ce que tu as fais, parce que j't'avou que j'ai un peu de mal. Smiley lol
chmel a écrit :

Felippe, je persiste pour le bouton "citer", car c'est le code des autres qu'on veut éditer,
On connait le sien Smiley cligne

hé hé ! Felipe a oublié que ce n'est pas tout le monde qui a le privilège d'avoir un bouton « éditer » pour chacun des membres Smiley lol
Bon et bien comme à mon habitude je n'arrive pas afficher la table des matière avec le code de Lanza, mais là en plus la console JavaScript ne me sors aucun erreur... cool.

Ensuite, j'voulais savoir, pour detecter si le DOM level 2 était disponible, si il y'avais une fonction spécifique qui servait a cela ?
Administrateur
Stephan a écrit :

hé hé ! Felipe a oublié que ce n'est pas tout le monde qui a le privilège d'avoir un bouton « éditer » pour chacun des membres Smiley lol

autant pour moi: j'ai trop l'habitude d'autres forums comme HFr où tout le monde peut voir le bouton citer de tous les messages (mais ne peut pas valider la modification à moins d'être modo bien sûr)
JRM a écrit :
Bon et bien comme à mon habitude je n'arrive pas afficher la table des matière avec le code de Lanza, mais là en plus la console JavaScript ne me sors aucun erreur... cool.


Je suppose que c'est parce que tu as gardé le <div class="exemple">. Mon code suppose que les titres sont à la racine du body. A mon sens le div dans l'énoncé de l'exercice n'est là que pour séparer l'exemple de l'énoncé proprement dit, donc j'ai fait comme s'il n'était pas là.

JRM a écrit :

Ensuite, j'voulais savoir, pour detecter si le DOM level 2 était disponible, si il y'avais une fonction spécifique qui servait a cela ?


document.implementation.hasFeature( "HTML", "2.0" ); pour le DOM HTML niveau 2.

Je ne sais pas jusqu'à quel point c'est supporté par les différents navigateurs, cependant.

JRM a écrit :
Merci beaucoup Lanza, en effet j'aimerai bien que tu commentes ce que tu as fais, parce que j't'avou que j'ai un peu de mal. Smiley lol


Bon je vais faire un topo, je reviens tout de suite après
Smiley cligne
Bon ça m'a pris plus longtemps que prévu, dû à un problème de connexion ...

Pour commencer la fonction citée ci-dessus (document.implementation.hasFeature( "HTML", "2.0" ); ) ne fonctionne pas sous IE.

Alors comment fonctionne ce bout de code.

Le principe est le suivant :
On part du premier enfant du body en définissant le niveau de titre recherché à 1, et le préfixe de nos id à "toc". C'est ce que fait la fonction generateToc() avec ce bout de code :


nextLevel( "toc" , 1, document.body.firstChild )


Dans la fonction nextLevel(), on commence par créer une liste <ul> et au passage on initialise quelques variables :

var i = 1;
var list = document.createElement( "ul" );
var listitem = null;

var nextelement = curelement;
var doneSubLevel = true;


"i" nous servira à construire les ID.
nextelement est une copie de l'élément de départ, mais au fur et à mesure que l'on parcourra le document, il s'agira de l'élément en cours.

je reviendrai sur "listitem" et doneSubLevel plus loin.

On parcourt les noeuds jusqu'à trouver un élément (noeud dont le "nodeType" est 1) dont le "tagName" commence par H :


do
{
if( nextelement.nodeType == 1 && nextelement.tagName.substr(0,1) == "H" )
{


(Attention pour un document servi en tant que "text/html" le tagName est toujours en majuscule, même si c'est du xhtml.)

Si cet élément a le bon niveau de titre (on compare le niveau passé en paramètre au second caractère du tagName) :

On lui crée un ID avec le préfixe passé en paramètre et en y ajoutant un "_" et un numéro d'occurence. (ici c'est notre compteur "i" ). Au passage on se garde ce nouvel id sous le coude dans la variable nextid.


nextlevel = nextelement.tagName.substr(1,1); //récupération du second caractère du tagName
if( nextlevel == curlevel ) // comparaison avec le niveau de titre passé en paramètre
{
nextelement.id = nextid = curid + "_" + i++;


On crée un lien vers notre titre avec son id tout neuf :


var anchor = document.createElement( "a" );
anchor.href = "#" + nextid;


On recopie tous les noeuds enfants de notre titre dans ce lien.


for( j = 0; j < nextelement.childNodes.length; j ++ )
{ anchor.appendChild( nextelement.childNodes[j].cloneNode(true)); }


Ensuite on crée un <li> dans (le "listitem" déclaré plus haut), on y ajoute notre lien et on rattache le tout à la liste crée au début de la fonction :

				listitem = document.createElement( "li");		
				listitem.appendChild( anchor );
				list.appendChild( listitem );


Ensuite on défini doneSubLevel à false, pour signifier que l'on n'a pas encore traité les titres de niveau inférieurs (donc avec un numéro <hx> supérieur) qui suivent notre titre courant.


doneSubLevel = false ;
} 


Si notre élément a un niveau de titre inférieur (donc avec un numéro <hx> supérieur) et que l'on n'a pas encore traité les niveaux de titre inférieur (doneSubLevel est faux), on n'a donc pas fait ce qui précède pour l'élément courant.

Comme le niveau ne correspond pas à celui qu'on cherche, on rappelle la fonction nextlevel() (celle là même qui est en cours d'execution et que je suis en train de décrire, et qui est donc une fonction récursive), avec le dernier ID qu'on a créé et qui servira de préfixe, et avec le niveau de titre que l'on vient de trouver, et on part de l'élément courant.

La fonction retournera un <ul> que l'on ajoute au listitem courant, juste derrière le titre que l'on y a mis précédement. Notez que si on n'a pas trouvé de titre du bon niveau, ici ça plante, puisque listitem est défini à null par défaut.

On n'oublie pas de positionner doneSubLevel à true pour indiquer qu'on a déjà traité les sous niveaux pour le titre courant.


else if( nextlevel > curlevel && !doneSubLevel )
{
listitem.appendChild( nextLevel( nextid, nextlevel, nextelement ) );
doneSubLevel = true;

}


Si on trouve un niveau de titre superieur à ce qu'on cherche, il nous faut donc remonter d'un cran, et on laisse en plan ce qu'on était en train de faire, on renvoie notre liste <ul> dans l'état où elle est.

La fonction appelante se chargera alors de l'ajouter là où il faut, soit après un titre dans un <li> si nextlevel() a été appelé par nextlevel() soit avant le premier enfant du body si nextlevel() a été appelé par generateToc().



}
else if( nextlevel < curlevel )
{
return list;
}


Si on est pas sorti de la fonction à l'étape suivante, on cherche le prochain noeud, s'il est "null" on a fini le document et on sort de la boucle, puis on renvoie la liste.


nextelement = nextelement.nextSibling;

} while( nextelement != null )

return list;
}


Fin de la fonction nextlevel().

Ce qui est difficile à appréhender et à décrire c'est qu'elle est récursive et qu'elle fait la même chose pour tous les niveaux de titre.

en gros ça fait le parcours suivant :

premier enfant du body : appel de nextlevel( niveau1 ) -> H1 -> H1 -> H2 ah, on appelle nextlevel( niveau2 ) -> H2 -> H2 -> H1 : ah, on retourne la liste des H2 -> H1 -> h3 : on appelle nextlevel( niveau3 ) -> h3 -> h1 ; on retourne la liste des h3 -> etc... jusqu'à la fin du document.

Les autres tags sont ignorés.

J'espère que l'explication est utile et assez claire...
Je suis pas sûr de me comprendre. Smiley biggol

J'oubliais, mes fichiers sont en ligne à ces adresses :
http://lanza.online.fr/toc.html
http://lanza.online.fr/toc.js
Modifié par Lanza (06 Nov 2005 - 21:21)
Salut,

voilà quelque chose qui va bien t'aider je pense. C'est pas moi mais je ne sais plus où j'avais récupéré ça Smiley biggol

toc.js

function H_getText(el) {
  var text = "";
  for (var i = el.firstChild; i != null; i = i.nextSibling) {
    if (i.nodeType == 3 /* Node.TEXT_NODE, IE doesn't speak constants */)
      text += i.data;
    else if (i.firstChild != null)
      text += H_getText(i);
  }
  return text;
}
function TOC_EL(el, text, level) {
  this.element = el;
  this.text = text;
  this.level = level;
}
function getHeadlines(el) {
  var l = new Array;
  var rx = /[hH]([1-6])/;
  // internal recursive function that scans the DOM tree
  var rec = function (el) {
    for (var i = el.firstChild; i != null; i = i.nextSibling) {
      if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
        if (rx.exec(i.tagName))
          l[l.length] = new TOC_EL(i, H_getText(i), parseInt(RegExp.$1));
        rec(i);
      }
    }
  }
  rec(el);
  return l;
}
function generate_TOC(parent_id) {
  var parent = document.getElementById(parent_id);
  var hs = getHeadlines(document.getElementsByTagName("body")[0]);
  for (var i = 0; i < hs.length; ++i) {
    var hi = hs[i];
    var d = document.createElement("div");
    if (hi.element.id == "")
      hi.element.id = "gen" + i;
    var a = document.createElement("a");
    a.href = "#" + hi.element.id;
    a.appendChild(document.createTextNode(hi.text));
    d.appendChild(a);
    d.className = "level" + hi.level;
    parent.appendChild(d);
  }
}


lapagehtml

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <link rel=stylesheet href="css/toc.css" type="text/css" />
</head>
<script type="text/javascript" src="scripts/toc.js"></script>

<body onload="generate_TOC('toc');">

<div id="toc"></div>

<h1> ... </h1>
... le html en question...

</body>
</html>


Voilà, j'espère que ça va t'aider Smiley smile [/i]
SuD : cette solution a l'air plus solide que la mienne en ce qui concerne le scan du document pour retrouver les titres, mais elle ne génère pas de listes imbriquées.
Modifié par Lanza (09 Nov 2005 - 09:17)
Pages :