11548 sujets

JavaScript, DOM et API Web HTML5

Pages :
Bonjour les Alsa-nautes.

Encore le n00b qui prend le clavier avec ce coup-ci un petit casse-tête... pardon... un petit "casse-ma-tête-à-moi" en JavaScript. C'est mon premier essai et je patouille grave, même avec tout le référentiel du mozilla devlopper sous les yeux, c'est dire...

En gros, l'idée est que j'ai une list à puce de type ul li
- l'ul a un id #first_level
- les liens dedans sont déclarés en CSS display:block et ont une classe LinkIn

L'idée, c'est que chaque lien a une image de fond (plus des images de rollover, enfin bref... la totale quoi) et que je dois changer l'image de fond du dernier lien de la list (donc lastChild, si j'ai bien tout suivis)

Le hic, c'est que je crois que je me mélange un peu les pinceaux dans mes variables, et que je mélange allègrement java (pour lequel je ne suis déjà pas forcément très doué) et javasript (que je découvre depuis hier)

Ma première tentative dont le but était de voir si déjà j'arrivais à récupérer ne serait-ce que le tag du dernier élément (donc au moins un "a" ou un "li", ca aurait déjà été beaucoup mais apparament...).



function parcours() {
	var l1 = document.getElementById("first_level");
	// first_level est une référence à un élément <ul>
	if (first_level.hasChildNodes())
	// On vérifie d'abord si l'objet n'est pas vide, c.-à-d. s'il a des enfants
	{
	  var l1child = first_level.childNodes;
	  for (var i = 0; i < first_level.length; i++) 
	  {
	   // faire quelque chose avec chaque enfant en tant que children[ i ] //EDIT : [ i ] sans les espaces.
		lastChild.getElementByTagname
		alert(lastChild.tagName);
	  }
	}
}



Une bonne bière virtuelle à qui saura me donner ne serait-ce qu'un début de piste...

(je ne demande pas un code complet non plus, le but étant quand même que j'apprenne à me dépatouiller et à ne pas polluer le forum avec des questions à la c*n Smiley cligne )

Merci beaucoup et bonne journée.

EDIT : Oops, petit bug dans le bloc de code.
j'ai un [ i ] qui voulait pas passer.
Modifié par Zzz. (19 Sep 2007 - 11:21)
Modérateur
Salut,

Ceci suffit non ?
var oUl, aAs, oLastA;

oUl = document.getElementById('first_level');
aAs = oUl.getElementsByTagName('a');
oLastA = aAs[aAs.length - 1];

alert(oLastA.nodeName.toLowerCase());

Modifié par koala64 (17 Sep 2007 - 10:45)
Benjamin D.C. a écrit :
Petite question au passage: pourquoi ne pas faire tout simplement cela en css? Smiley sweatdrop



Déjà tenté mais le menu en question est suffisement tordu pour que ça ne soit pas aussi simple, hélas.

@Koala : Merci pour ta proposition mais pourrais-tu stp m'expliquer brièvement le rôle des 2 dernières lignes de ton script ?
Modifié par Zzz. (18 Sep 2007 - 11:26)
En fait, je vais poster mon script après quelques modifs.


window.onload=parcours;

function parcours() {
	
	var flag = false;
	var a1 = document.getElementById("second_level");
	if (a1.hasChildNodes()) {
		var a2 = a1.childNodes;
		for (ii=a2.length-1; ii<0; ii--) {
			if (flag == false) {
				var ntype = a2[ii].nodeTypes;
				if (ntype == 1) {
					var flag = true;
					var dernier = a2[ii];
					ii=-6; // casse la fonction de parcours
					  dernier.style.color = '#00FF00';
					  dernier.setAttribute("color", "#00FF00");
					  document.write("<FONT COLOR='red'>" + dernier +"</FONT>");	
				}
			}
		}
// liaison à trouver pour éviter l'erreur si pas de Troisième niveau dans l'arbo active...	
	
		var flag2 = false;
		var b1 = document.getElementById("third_level");
		if (b1.hasChildNodes()) {
			var b2 = b1.childNodes;
			for (jj=b2.length-1; jj<0; jj--) {
				if (bflag == false) {
					var bntype = b2[jj].nodeTypes;
					if (bntype == 1) {
						var bflag = true;
						var bdernier = b2[jj];
						jj=-6; // casse la fonction de parcours
						bdernier.style.backgroundImage = 'menu_2nd_end.gif'; // probablement faux, c'est ce que je cherche a corriger pour l'heure	
					}
				}
			}
		}
	}
}


Donc là, au #second_level, j'arrive à atteindre l'élément qui me convient, me reste à trouver comment pouvoir lui passer le style.

par contre, le #third_level me pose encore un soucis parce que si l'endroit où l'on se trouve dans le menu ne dispose pas de #third_level, le script me pète une erreur via firebug de type :

a écrit :

b1 has no properties
[Break on this error] if (b1.hasChildNodes()) {


Je continue de tâtonner. Je vais bien finir par y arriver Smiley cligne
Modérateur
Salut,

Zzz. a écrit :
Déjà tenté mais le menu en question est suffisement tordu pour que ça ne soit pas aussi simple, hélas.
En CSS, il n'y a normalement qu'à mettre un identifiant ou une classe sur le dernier lien.

a écrit :
@Koala : Merci pour ta proposition mais pourrais-tu stp m'expliquer brièvement le rôle des 2 dernières lignes de ton script ?

var oUl, aAs, oLastA; [#green]// déclaration des variables[/#]

oUl = document.getElementById('first_level'); [#green]// Sélection du ul ayant pour id "first_level"[/#]
aAs = oUl.getElementsByTagName('a'); [#green]// Sélection des liens de ce ul (renvoie un tableau de liens)[/#]
oLastA = aAs[aAs.length - 1]; [#green]// Sélection du dernier lien du tableau[/#]

alert(oLastA.nodeName.toLowerCase()); [#green]// Alerte du tag[/#]
Bref, pas la peine de s'embêter avec des boucles...
Punaize, mais va vraiment falloir que j'arrête de chercher midi à 14heures quand je code, moi... Smiley eek

Un énorme merci à toi en tout cas Smiley biggrin


Pour revenir sur le css, j'y ai bien pensé en effet mais le menu est généré dynamiquement par un CMS ce qui fait que la dernière entrée est susceptible de changer, mettant l'instruction css à mal puisque la dernière entrée peu devenir l'avant-dernière sans autre forme de préavis du coup.

Alors à moins bien sûr d'une subtilité CSS un tant soit peu dynamique, qui m'ait échappé, je vois pas très bien comment gérer un changement de style sur la dernière et uniquement la dernière entrée du menu... C'était quoi ton idée ?
Modérateur
Zzz. a écrit :
mais le menu est généré dynamiquement par un CMS ce qui fait que la dernière entrée est susceptible de changer, mettant l'instruction css à mal puisque la dernière entrée peu devenir l'avant-dernière sans autre forme de préavis du coup.
oui, donc c'est le principe de génération du menu qu'il faut modifier. En somme, il faut fouiller dans les codes du CMS pour voir comment adapter le programme afin qu'il place l'identifiant (ou la classe) sur le dernier élément.
Exactement. seulement ça je peux pas faire. Même si j'ai accès aux sources XML du menu, on m'a demandé de ne pas y toucher...
Modérateur
Je suppose que le tout est géré via PHP pour transformer le XML en XHTML non ? Smiley smile

Dans ce cas, tu peux intervenir directement sur la partie PHP et non sur la partie XML.
Encore moins, c'est un CMS non-libre.

Non décidément, sur ce coup là, tout à été fait pour me casser les c...pieds ! Smiley langue
Modifié par Zzz. (18 Sep 2007 - 14:17)
bon par contre, firebug me renvoit l'erreur suivante :
oUl has no properties

sur la ligne
aAs = oUl.getElementsByTagName('a'); 


Comme si il n'arrivait pas à retrouver l'élément...
Modifié par Zzz. (18 Sep 2007 - 14:18)
Ben si justement. l'élément first_level est bien là. en fait je crois que c'est cette ligne là qui coince.

a écrit :
dernier.getElementsByTagName is not a function
dernierlien = dernier.getElementsByTagName("a");
Modérateur
Peux-tu donner ton code (JS + XHTML) ainsi que l'erreur retournée ? Ce sera plus simple pour comprendre... Smiley cligne

getElementsByTagName("a") est juste donc le problème doit certainement venir de dernier.
Modifié par koala64 (18 Sep 2007 - 14:47)
XHTML :


<div id="nested"><ul id="first_level">
		<li class="active item1">
			<a href="#" class="LinkIn" ><span>item1</span></a>
			<ul id="second_level">
				<li class="defaultmenu sub-item1">
					<a href="#" class="LinkIn" ><span>sub-item1</span></a>
				</li>
				
				<li class="defaultmenu sub-item2">
					<a href="#" class="LinkIn" ><span>sub-item2</span></a>
				</li>
				<li class="active sub-item3">
					<a href="#" class="LinkIn" ><span>sub-item3</span></a>
					<ul id="third_level">
						<li class="defaultmenu sub2-item1">
							<a href="#" class="LinkIn" ><span> sub2-item1</span></a>
							
						</li>
						<li class="defaultmenu  sub2-item2">
							<a href="#" class="LinkIn" ><span> sub2-item2</span></a>
						</li>
						<!-- Etc Etc Etc ... -->
					</ul>
					
				</li>
				<li class="defaultmenu sub-item4">
					<a href="#" class="LinkIn" ><span>sub-item4</span></a>
				</li>
				<li class="defaultmenu sub-item5">
					<a href="#" class="LinkIn" ><span>sub-item5</span></a>
				</li>
			</ul>
		</li>
		<li class="defaultmenu actualites">
			<a href="/actualites/" class="LinkIn" ><span>Actualités</span></a>
			
		</li>
		<li class="defaultmenu un_autre_truc">
			<a href="/contacts/" class="LinkIn" ><span>Contacts</span></a>
		</li>
		<li class="defaultmenu faq">
			<a href="/faq/" class="LinkIn" ><span>F.A.Q.</span></a>
		</li>
	</ul>
</div>


dans mon script, mon "dernier" correspond à ton "OLastA" . en gros, comme ta version en brut ne marchait pas, j'ai tenté d'adapter avec ce que tu m'as donné le script que j'avais fait précédement :


window.onload=parcours;

function parcours() {
	
	var flag = false;
	var a1 = document.getElementById("second_level");
	alert(a1); // OK
	if ((a1 != null) && (a1.hasChildNodes())) {
		var a2 = a1.childNodes;
		alert("a2 = " + a2.length); // OK		
		for (var ii=(a2.length-1); ii>0; ii--) {
		alert("ii = " + ii); // OK
			if (flag == false) {
				var ntype = a2[ii].nodeType;
				alert("ntype == " + ntype); // OK
				if (ntype == 1) {
					var flag = true;
					var dernier = a2[ii];
					alert("dernier = " + dernier); // OK
					i=-6;
					if (dernier.hasChildNodes) {
						dernier = dernier.childNodes;
						alert("dernier = " + dernier); 
						alert("dernier = " + dernier.getElementsByTagName("a")); 
						dernierlien  = dernier.getElementsByTagName("a");
						alert(dernierlien); // KO
		 				dernierlien.style.color("#00FF00");
					}
				}
			}
		}
	}
}



Et là j'essaie en refaisant intégralement mon script autour du tiens, ça ne me fait pas d'erreur mais ça ne fais rien d'autre non plus... Smiley sweatdrop


function parcours() { // d'après l'idée de Koala

var flag = false;
var a1 = document.getElementById("first_level");
alert(a1); // OK
	if ((a1 != null) && (a1.hasChildNodes())) {
		var list = document.getElementById("second_level"); // Sélection du ul ayant pour id "second_level"
		alert("list = " + list);
		var liens = list.getElementsByTagName("a"); // Sélection des liens de ce ul (renvoie un tableau de liens)
		alert("liens = " + liens)
		var dernier = liens[liens.length - 1]; // Sélection du dernier lien du tableau
		alert(dernier.nodeName.toLowerCase()); // Alerte du tag
	}
}	
	

Modifié par Zzz. (19 Mar 2008 - 12:32)
Modérateur
En repartant uniquement de ton code XHTML, ça fonctionne très bien (voir la méthode alertLink) :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />

		<title>Exemple</title>

		<script type="text/javascript"><!--

var Script, Sp, dernierLien;

Script = function() {};

Sp = Script.prototype =
{
	connect: function(oElem, sEvType, fn, bCapture)
	{
		return document.addEventListener ?
			oElem.addEventListener(sEvType, fn, bCapture):
			oElem.attachEvent ?
				oElem.attachEvent('on' + sEvType, fn):
				false;
	},

	alertLink: function()
	{
		var oUl, aAs, oLastA;

		oUl = document.getElementById('first_level');
		aAs = oUl.getElementsByTagName('a');
		oLastA = aAs[aAs.length - 1];

		return alert(oLastA.firstChild.firstChild.nodeValue);
	},

	init: function()
	{
		Sp.connect(window, 'load', Sp.alertLink, false);
	}
};

var dernierLien = new Script;
dernierLien.init();

		//--></script>
	</head>
	<body>

<div id="nested"><ul id="first_level">
		<li class="active item1">
			<a href="#" class="LinkIn" ><span>item1</span></a>
			<ul id="second_level">
				<li class="defaultmenu sub-item1">
					<a href="#" class="LinkIn" ><span>sub-item1</span></a>
				</li>
				
				<li class="defaultmenu sub-item2">
					<a href="#" class="LinkIn" ><span>sub-item2</span></a>
				</li>
				<li class="active sub-item3">
					<a href="#" class="LinkIn" ><span>sub-item3</span></a>
					<ul id="third_level">
						<li class="defaultmenu sub2-item1">
							<a href="#" class="LinkIn" ><span> sub2-item1</span></a>
							
						</li>
						<li class="defaultmenu  sub2-item2">
							<a href="#" class="LinkIn" ><span> sub2-item2</span></a>
						</li>
						<!-- Etc Etc Etc ... -->
					</ul>
					
				</li>
				<li class="defaultmenu sub-item4">
					<a href="#" class="LinkIn" ><span>sub-item4</span></a>
				</li>
				<li class="defaultmenu sub-item5">
					<a href="#" class="LinkIn" ><span>sub-item5</span></a>
				</li>
			</ul>
		</li>
		<li class="defaultmenu actualites">
			<a href="/actualites/" class="LinkIn" ><span>Actualités</span></a>
			
		</li>
		<li class="defaultmenu un_autre_truc">
			<a href="/contacts/" class="LinkIn" ><span>Contacts</span></a>
		</li>
		<li class="defaultmenu faq">
			<a href="/faq/" class="LinkIn" ><span>F.A.Q.</span></a>
		</li>
	</ul>
</div>

	</body>
</html>
Génial Smiley lol

Bon, je comprends pas tout de ce que je code mais au moins on y arrive (je sature un peu, ca fait 2 semaines que je me prends la tête dessus alors que ca n'aurait pas dû durer plus de 5 minutes... enfin bref...)

Donc du coup, je tente de réadapter à ma structure :


var Script, Sp, dernierLien;
	Script = function() {};
	Sp = Script.prototype = {
		connect: function(oElem, sEvType, fn, bCapture) {
		return document.addEventListener ?
		oElem.addEventListener(sEvType, fn, bCapture):
		oElem.attachEvent ?
		oElem.attachEvent('on' + sEvType, fn):
		false;
	},
	alertLink: function() {
		var oUl, aAs, oLastA, oUl2, oUl3, aAs2, oLastA2;
		oUl = document.getElementById('first_level');
		if (oUl.hasChildNodes) {
			oUl2 = document.getElementById('second_level');
			aAs = oUl2.getElementsByTagName('a');
			oLastA = aAs[aAs.length - 1];
			return alert(oLastA.firstChild.firstChild.nodeValue); // OK
		
			if (oUl2.hasChildNodes) {
				oUl3 = document.getElementById('third_level');
				aAs2 = oUl3.getElementsByTagName('a');
				oLastA2 = aAs2[aAs2.length - 1];
				return alert(oLastA2.firstChild.firstChild.nodeValue);
			}
		}	
	},
	init: function() {
		Sp.connect(window, 'load', Sp.alertLink, false);
	}
};
var dernierLien = new Script;
dernierLien.init();


et là, les liens du second_level passent nickel, mon premier alert ressort bien ce qu'il faut mais j'ai dû me gaufrer dans la liaison pour ressortir ceux du third level.

Et comme je ne comprends pas trop, ni le premier bloc ni le dernier bloc de code, j'avoue ne pas trop savoir comment raboûter tout ça...

je tâtonne... again & again ...

En tout cas un gros merci à toi.
Modérateur
Salut,

En fait, plutôt que de répéter des blocs de code, il vaut mieux passer tes id en tant qu'argument de la méthode alertLink :
var Script, Sp, dernierLien;

Script = function() {};

Sp = Script.prototype =
{
	connect: function(oElem, sEvType, fn, bCapture)
	{
		return document.addEventListener ?
			oElem.addEventListener(sEvType, fn, bCapture):
			oElem.attachEvent ?
				oElem.attachEvent('on' + sEvType, fn):
				false;
	},

	alertLink: function(sId)
	{
		var oUl, aAs, oLastA;

		oUl = document.getElementById(sId);
		aAs = oUl.getElementsByTagName('a');
		oLastA = aAs[aAs.length - 1];

		return alert(oLastA.firstChild.firstChild.nodeValue);
	},

	init: function()
	{
		Sp.connect(window, 'load', function() { Sp.alertLink('first_level'); }, false);
		Sp.connect(window, 'load', function() { Sp.alertLink('second_level'); }, false);
		Sp.connect(window, 'load', function() { Sp.alertLink('third_level'); }, false);
	}
};

var dernierLien = new Script;
dernierLien.init();
La méthode connect permet d'affecter un gestionnaire d'événement au chargement de la page.

C'est, ici au sein de la méthode init, qu'on gère ces appels. Cette méthode fait office de chef d'orchestre du script.

Dans ce tuto, je parle un peu de tout ça. Smiley cligne
Modifié par koala64 (19 Sep 2007 - 05:57)
Pages :