11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

Je cherche à faire un questionnaire avec cette structure classique :

<p class="question">quelle est la couleur du cheval blanc d'Henri IV ?</p>
<p><a href="#">afficher/masquer</a></p>
<p id="r1" class="reponse">je crois qu'il était violet</p>


Premièrement, suis-je obligé de passer un id à chaque fois pour afficher masquer l'élément P ? n'y a t il pas plus simple, car lorsque j'ai 40 questions, rentrer 40 fois l'id devient pénible.

Deuxième question : je souhaite donner la possibilité d'afficher toutes les réponses. Une case à cocher permettrait au moment où elle est cochée d'afficher toutes les réponses (donc les éléments ayant la classe réponse) et de tous les masquer au moment où elle est décochée.

Merci pour votre aide.
Modifié par sylvainbucule (01 Sep 2007 - 16:39)
Tu peux tout simplement donner un id genre questionX (X étant un numéro).

Puis ensuite pour tout afficher tu fais une boucle avec document.getElementById('question'+i).... Smiley cligne C'était pourtant simple.

Sinon, tu peux aussi faire ça avec une classe mais ça reviendrais au même.
Si j'utilise la méthode de l'id, je suis obligé de rentrer un id pour chaque question. Cela m'amène à rentrer 40 id pour les questions et 40 id pour les réponses. Par défaut, toutes mes questions ont la même classe. C'est donc en utilisant la classe que je souhaite afficher ou masquer tous les éléments l'ayant pour classe.

Comment faire ?

Autre problème, j'ai affecté à href du lien qui permet d'afficher masquer l'adresse # ce qui donne :

<a href="#">afficher/masquer</a>


Le problème c'est que lorsque je clique, l'affichage remonte tout en haut. Si j'enlève href, le lien n'est plus navigable au clavier. Je ne souhaite pas pointer sur un id car sinon la page remonte également au niveau de l'id pointé.
Comment faire pour évitez ce désagrément ?
Modifié par sylvainbucule (31 Aug 2007 - 12:28)
Bon j'ai avancé, j'ai trouvé comment cliquer sur le lien sans que la page se réaffiche depuis le début.

il faut faire :

<a href="javascript:;">blabla</a>


Il me reste cependant une chose :
Comment via javascript faire en sorte que tous les éléments d'une classe soient masqués suite à un clic?
Fleimard! Un coup de moteur de recherche et paf !

function getElementsByClass(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i ].className) ) {
			classElements[j] = els[i ];
			j++;
		}
	}
	return classElements;
}


Il te suffit donc d'appeller ta fonction ainsi
var elementsACacher = getElementsByClass('reponse');
for(var i=0;i<elementACacher.length;i++) {
    elementsACacher[i ].style.display = 'none';
}

Modifié par MoOx (31 Aug 2007 - 14:28)
Merci beaucoup MoOX, j'avais bien déjà vu cette fonction mais je ne savais pas comment l'exploiter. D'ailleurs je ne la comprend que très très partiellement pour l'instant.

Voici ce que je comprends (j'aime bien utiliser des choses que je comprends)
- création d'une variable de type tableau
- si aucun noeud n'est passé en paramètre, alors le noeud est le document (je crois que c'est cela que tu appelles noeud)
- si aucun tag (balise html) n'est passé en paramètre, alors tag reçois * (je pense que cela veut dire tous les tags de la page)
- els est un tableau qui comprend la liste de tous les éléments ayant pour nom le tag stocké dans la variable tag. (ici, els sera la liste de tous les éléments de la page)
- on récupère la longueure du tableau els
- on crée une expression qui commence par le nom passé en paramètre à searchClass et qui se termine par ce même nom. (par contre, je ne connais pas \\s)
- faire autant de fois qu'il y a d'élément dans le tableau els cela :
- Là je ne comprends plus !

Pourrais tu me donner un peu plus d'explications stp
Smiley ohwell
Sur ce que tu me dis, tu as tout bon.

L'expression régulière (pattern) reconnaîtra tout les chaines qui contiennent la class (une string) cherchée. Etant donnée que dans l'attribut class en html, on peut en mettre plusieurs séparés par des espaces, la regex précise que la string peut être seul et/ou précédé et/ou suivi d'un espace.

Elle est stocké dans une variable, on peux ainsi l'utiliser à chaque tour de boucle.

Sur chaque tour de boucle on teste (pattern.test) si la class (els[i ].className) de l'élement correspond à la regex défini.
Si c'est le cas, on rajoute l'élement au tableau et on incrémente le compteur du tableau correctement.

On pourrait d'ailleurs remplacer
classElements[j] = els[i ];
j++;
par
classElements[j++] = els[i ];

Le X++ veut dire que l'incrémentation se fera après l'instruction. O pourrait la faire avant en mettant ++X

Bonne continuation Smiley cligne
MoOx, tu m'as dit d'appeler la fonction de cette façon :



var elementsACacher = getElementsByClass('reponse');

for(var i=0;i<elementACacher.length;i++) {

    elementsACacher[i ].style.display = 'none';

}


Je l'ai donc mise dans un fichier javascript avec la fonction getElementsByClass.

Mais c'est ensuite que je ne sais pas comment appeler la fonction suite à un évenement.
bonjour,
C'est du tout cuit, non intrusif avec une approche différente. Je suppose que tu n'emploies pas de classes multiples, sinon il faudra modifier pour utiliser la fonction getElementsByClass.

<!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>
		<title>quizz</title>

		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15" /> 
		<meta http-equiv="Content-Script-Type" content="text/javascript" />
		<meta http-equiv="Content-Language" content="fr" />
<style type="text/css">
</style>

		<script type="text/javascript"><!--
var oO =
{
	connect: function(oElem, sEvType, fn, bCapture)
	{
		return document.addEventListener ?
			oElem.addEventListener(sEvType, fn, bCapture):
			oElem.attachEvent ?
				oElem.attachEvent('on' + sEvType, fn):
				false;
	},

	cancelClick: function(e)
	{
	e=e||w.event
	if(e.preventDefault){e.preventDefault();e.stopPropagation();}	// code standard DOM
	else if(e.cancelBubble==false){e.cancelBubble=true; e.returnValue=false;}	// ie
	return false; // pour les autres
	},

	ActionDoc: function(e)
	{
		e = e || window.event;
		var el = e.target || e.srcElement;
		if(el.nodeType==3)el=el.parentNode //saut de ligne

		if(el.className=="note")
			{ // paragraphe suivant
				var ps=el.parentNode.nextSibling
				if(ps.nodeType==3)ps=ps.nextSibling
				ps.style.display=ps.style.display=='block'?'none':'block' //''=determiné par feuille style
				oO.cancelClick(e);
			}

 		if(el.id=="affReponse")
			{
			var montre=el.checked?'block':'none'
			var rep=document.getElementsByTagName('p')
			for(var x=0;x < rep.length;x++)
				{
					if(rep[x].className=="reponse")
						{
						rep[x].style.display=montre;
						}
				}
			}
  }

};

oO.connect(window, 'load', function(){
	var rep=document.getElementsByTagName('p')
			for(var x=0;x < rep.length;x++)
				{
					if(rep[x].className=="reponse")
						{
						rep[x].style.display='none';
						}
				}
}, false);

oO.connect(document, 'click', oO.ActionDoc, false);

		//--></script>
	</head>
	<body>
<form> 
<input type="checkbox" id="affReponse" />Afficher les réponses.
</form>
 <p class="question">quelle est la couleur du cheval blanc d'Henri IV ?</p>
<p><a href="#" class="note">afficher/masquer</a></p>
<p class="reponse">je crois qu'il était violet</p>
<hr />
<p class="question">quelle est le prénom du fils Nékicoul ?</p>
<p><a href="#" class="note">afficher/masquer</a></p>
<p class="reponse">titin</p>
<hr />
<p class="question">quelle est la couleur du cheval blanc d'Henri IV ?</p>
<p><a href="#" class="note">afficher/masquer</a></p>
<p class="reponse">je crois qu'il était violet</p>
<hr />
	</body>
</html>

edit> modifiction pour meilleure portabilité et acces non js
Modifié par chmel (01 Sep 2007 - 00:20)
Salut Chmel,
Excellent ton script comme toujours. Il fonctionne mais pas dans ma page. Je n'ai pourtant aucun autre fichier javascript liés à la page. La voici ici

J'ai placé le checkbox juste au dessous de la table des matières (si tu veux y jeter un oeil)
Modifié par sylvainbucule (31 Aug 2007 - 19:57)
bonsoir Sylvainbucule,
Ton site est bien fait et va m'interesser car mon lave linge me joue des tours Smiley fache
<edit corrigé, ne pas faire >
Je suis parti du principe que les réponses étaient toutes cachées au départ dans la règle css :
.reponse{display:none}

Si tu modifies cette règle dans ton fichier cours.css, le checkbox fonctionne. C'était pour faire simple, mais ceux qui n'ont pas js n'ont pas accès aux réponses. Smiley biggol
</edit>
Pour que la bascule marche, il faut que tu enlèves tous les onclick="bascule.machin" et que tu remplaces
 if(el.firstChild&&el.firstChild.data=="afficher/masquer")//click sur un lien
par
 	if(el.className=="note")


Bon, si on veux être puriste, les liens "afficher/masquer", les réponses et le checkbox n'étant accessibles qu'avec javascript, devraient être créés en éléments DOM via javascript.

edit> J'ai modifié le source proposé avec la class="note" et l'accès aux réponses sans js (window.load) , mais les réponses gagneraient en suspens à ne pas être juste sous les questions.
Modifié par chmel (01 Sep 2007 - 00:28)
En terme d'accessibilité, le mieux est d'utiliser les ancres nommées, je pense
<p class="question">Que signifie le terme Ethernet ? 
<a id="q1" class="note" href="#r1">réponse</a></p>
</p>

<br />
<p class="question">Qu'appelle-t-on trame en informatique ?
<a id="q2" class="note" href="#r2">réponse</a></p>
<hr / >
<p style="height:1000px">Pour simuler une grande page</p>

<h2>Réponses</h2>
<p class="reponse">Ethernet désigne une norme fixant des règles pour permettre la transmission d'informations entre différents
matériels situés sur un réseau local. Ethernet est donc un protocole réseau.
<a  id="r1"  class="note" href="#q1">retour</a></p>

<p class="reponse">Une trame est un bloc d'information
véhiculé au travers d'un support physique (cuivre, fibre optique, etc.)
<a id="r2"  class="note" href="#q2">retour</a>
</p>
et ensuite ajouter du javascript avec la méthode insertbefore() par exemple
Modifié par chmel (01 Sep 2007 - 11:56)
Merci beaucoup chmel, tu m'otes une grande épine du pied. Je suis pris par le temps car la rentrée est toute proche (c'est pas faute d'avoir bossé tout l'été !!!) et là du coup, j'ai mon premier TP utilisable via un vidéo projecteur grâce à l'affichage dynamique des réponses.

Il est vrai qu'il y a une faiblesse en terme d'accessibilité (affichage des éléments créés par javascript), mais pour l'instant je ne m'y connais pas suffisamment pour corriger cette faiblesse. J'ai déjà tout un tas de notions à assimiler dans d'autres domaines informatiques.
POur l'impression, il est mieux pour moi d'avoir les réponses après chaque question, cependant ton idée n'est pas mauvaise du tout. J'opterai pour ta méthode pour le prochain cours je pense. Cela dit, j'ai la fleme de devoir ajouter un id à chaque fois, alors qu'avec la première solution, je peux m'en passer.

En tout cas merci beaucoup.