11540 sujets

JavaScript, DOM et API Web HTML5

EDIT : code complet en un seul fichier dans ma 3ème réponse :
http://forum.alsacreations.com/topic-5-61001-1-JS-nagit-plus-sur-un-displaynone-dorigine-en-CSS3.html#p415622

Bonjour et merci d'avance pour toute aide utile à mon pb !
(HTML5 CSS3 Initializr)

J'ouvre et ferme un volet div par un clic sur la barre-titre.
<article id="index_free">
	<a href="#" onclick="return unfold(this);">Cliquer pour ouvrir</a>
		<div class="txt">

- Lorsque ce volet DIV est ouvert dans le CSS (display et visibility à leur valeur par défaut :'' = display:block et visibility:visible), mon code JS fonctionne : j'ouvre et je ferme sans problème.

- Lorsque ce volet est fermé dans le CSS (div {display:none; visibility:hidden} ), mon code JS n'est pas reconnu : pas de bug dans la console JS, mais aucune action visible ! Comme si le div n'existait pas !
function unfold(bouton) {
	if (bouton.parentNode.getElementsByTagName('div')[0].style.display !== ''){
		bouton.parentNode.getElementsByTagName('div')[0].style.display = '';
		bouton.parentNode.getElementsByTagName('div')[0].style.visibility = '';
	} 
	else {
		bouton.parentNode.getElementsByTagName('div')[0].style.display = 'none';
		bouton.parentNode.getElementsByTagName('div')[0].style.visibility = 'hidden';
	}
	return false;
}
// Je ferme le volet à l'ouverture de la page
unfold( document.getElementById("index_free").firstChild );

Le code ci-dessus fonctionne correctement, sauf que la fermeture du volet par JS en entrée de page se voit ! (et puis il est plus logique de le présenter fermé par CSS dès le début)

Hélas, l'ajout de la ligne suivante, dans le CSS du DIV qui doit être caché au début, bloque tout ! Et je ne vois pas pourquoi...
.txt{ display: none; visibility: hidden; }

(évidemment, avec ce CSS, je supprime la fermeture du volet par JS : dernière ligne du code JS ci-dessus)

Je dois oublier un détail quelque part, mais lequel ???
Merci beaucoup pour toute aide !
Modifié par Gill (27 Mar 2012 - 08:56)
Si j'en crois ton code, je pense que ta première vérification ne doit pas être bonne.

Fait des essais avec console.log();

Je pense que mettre en haut de la fonction unfold() un console.log pour vérifier la valeur, ça aiderai :

console.log(bouton.parentNode.getElementsByTagName('div')[0].style.display);


de même que tu pourrais rajouter

console.log('ouvre');

et
console.log('ferme');


dans les 2 conditions.

Tu seras comme ça ce que vaut précisément ce que tu compares et ce qui est fait par le JS.

Selon moi, quand tu passes par le CSS, seul le second doit être exécuté et donc ne jamais s'afficher.
J'avais un petit bug, mais qui n'aurait pas dû empêcher le DIV de s'afficher après 2 clics :
(CSS : display:block au lieu de display:'')
J'ai modifié mon if() en testant style.visibility (que je ne touche jamais dans le CSS), mais rien n'y fait.

La trace autant que le console.log() me disent que j'alterne entre style.visibility='' et style.visibility='hidden', exactement comme désiré (idem pour display='' puis display='none')...

...sauf que l'affichage ne change pas !

(J'ai même supprimé le return false; au cas où...)

Il me vient une idée, que je vais tester de suite : ce ne serait pas un problème de variable transmise par valeur ou par... je ne sais plus ?
unfold(this) >>> unfold(bouton) >>> bouton.parentNode.getElementsByTagName('div')[0].style.display = '';
Ne vaudrait-il pas mieux un truc qui commence par "document." ?

EDIT > Hé bien non ! ça ne marche pas non plus...
document.getElementById('test').style.display = ''; n'affiche rien (div id="test")

Je récapitule :
1) lorsque la page s'ouvre SANS CSS de fermeture
- dans la fonction, les valeurs changent correctement
- dans la page, l'affichage du DIV est modifiable par JS
2) lorsque la page s'ouvre AVEC un CSS {display:none; visibility:hidden;}
- dans la fonction, les valeurs changent aussi correctement
- dans la page, l'affichage du DIV ne peut plus être modifié par JS !
Modifié par Gill (24 Mar 2012 - 18:00)
Tu peux fournir une page d'exemple ou via jsFiddle / JSbin ? (en plaçant les console.log() comme il faut)
Modifié par kenor (25 Mar 2012 - 12:16)
Plom plom :


function unfold(bouton) {

	if (bouton.parentNode.getElementsByTagName('div')[0].style.display != 'block') {
		bouton.parentNode.getElementsByTagName('div')[0].style.display = 'block';
		bouton.parentNode.getElementsByTagName('div')[0].style.visibility = 'visible';
	} else {
		bouton.parentNode.getElementsByTagName('div')[0].style.display = 'none';
		bouton.parentNode.getElementsByTagName('div')[0].style.visibility = 'hidden';
	}
	return false;
}


Si tu le définis à 'none', il n'est plus égale à une chaine vide. Smiley langue

Cela dit la bonne pratique en JS est de masquer l'élément en uniquement pour les personnes qui ont JS (pour que les personnes qui ont désactivés JS puissent quand meme voir ton contenu. Tu peux aussi n'afficher le bouton que pour les personnes qui ont JS.

Et ton lien ne devrait pas en etre un mais plutot un <button> (vu que ce n'est pas un lien).
Modifié par jb_gfx (25 Mar 2012 - 22:00)
Tiens je t'ai fait un exemple. J'en ai profité pour virer le js de ton code HTML pour le bouger dans la partie script (bonne pratique).


<!DOCTYPE html>
<html lang="fr" class="no-js"><head>

	<meta charset="UTF-8">

	<title>Blob et slime</title>
	
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

	<script>
	var doc = document.documentElement;
	doc.className = doc.className.replace('no-js', 'js');

	function unfold(el_class)
	{
		var buttons = document.getElementsByTagName('button');

		// on applique l'action à tous les boutons qui ont la class unfold
		for (var i = 0 ; i < buttons.length ; ++i)
		{
			if (buttons[ i ].className == el_class)
			{
				buttons[ i ].onclick = function()
				{
					var el = this.parentNode.getElementsByTagName('div')[0];
					el.style.display = el.style.display != 'block' ? 'block' : 'none';
		      return false;
				}
			}
		}
	}

	window.onload = function()
	{
		unfold('unfold');
	}
	</script>

	<style>
	.unfold {
		display: none;
	}
	
	.js .unfold {
		display: block;
	}

	.js .txt {
		display: none;
	}
	</style>
	
</head>
<body>
	
	<article id="index_free">

		<button class="unfold">Cliquer pour ouvrir</button>

		<div class="txt">
			texte
		</div>

	</article>
	
</body>
</html>

Modifié par jb_gfx (25 Mar 2012 - 22:34)
Merci jb_gfx de bien vouloir te pencher sur mon cas Smiley smile
(j'ai bien noté tes propositions, button et JS, mais j'aimerais comprendre le pb de départ)

Mais comme un exemple complet vaut mieux que des questions partielles, voici mon test minimaliste en un seul fichier qui continue de me surprendre. Smiley sweatdrop
(petites différences de noms de classes avec mes codes de départ : txt et txt-txt)
Le bug persiste sur tous les navigateurs importants.


<!doctype html>
<html lang="fr">
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible">
	<title>test bug JS et CSS</title>
	<style>
		.txt{ background: #ff9988;}
		.txt>a:first-child, .txt>a:last-child {
			display: block;
			text-align: center;
			color: #fff; background: #7d0303;
		}
		.txt-txt{color: #000;}
		/* si on décommente ça et qu'on commente le unfold() de la fin du script, le code ne fonctionne plus.
		.txt-txt{ display: none; visibility: hidden; }
		.txt>a:last-child {display: none; visibility: hidden; }*/
	</style>
</head>

<body>
	<article id="index_free" class="txt">
		<a href="#" onclick="return unfold(this);">Cliquer pour ouvrir/fermer</a>
		<div id="test" class="txt-txt">
			<p>
				Test du bug CSS qui empêche JS d'ouvrir et fermer le volet.
			</p>
		</div>
		<a href="#" onclick="return unfold(this);">[x]&nbsp; Cliquer pour fermer</a>
	</article>
	<script type="text/javascript">
		function unfold(bouton) {
			if (bouton.parentNode.getElementsByTagName('div')[0].style.visibility != ''){
				bouton.parentNode.getElementsByTagName('div')[0].style.display = '';
				bouton.parentNode.lastChild.previousSibling.style.display = '';
				bouton.parentNode.getElementsByTagName('div')[0].style.visibility = '';
				bouton.parentNode.lastChild.previousSibling.style.visibility = '';
			} 
			else {
				bouton.parentNode.getElementsByTagName('div')[0].style.display = 'none';
				bouton.parentNode.lastChild.previousSibling.style.display = 'none';
				bouton.parentNode.getElementsByTagName('div')[0].style.visibility = 'hidden';
				bouton.parentNode.lastChild.previousSibling.style.visibility = 'hidden';
			}
			return false;
		}
		/* si on commente la ligne ci-dessous, et qu'on décommente le CSS qui cache le volet, ça ne marche plus */
		unfold(document.getElementById("index_free").firstChild);
	</script>
</body>
</html>

Modifié par Gill (26 Mar 2012 - 12:58)
J'ai mis le code en ligne : http://jsbin.com/ogiwun

et ... j'ai testé sous chrome/FF/IE9 ça marche partout ?

(div fermé, je clic sur ouvrir, ça ouvre, si je reclic, ça ferme).

Tu es sûr de ton coup ?
kenor a écrit :
J'ai mis le code en ligne : http://jsbin.com/ogiwun

et ... j'ai testé sous chrome/FF/IE9 ça marche partout ?

(div fermé, je clic sur ouvrir, ça ouvre, si je reclic, ça ferme).

Tu es sûr de ton coup ?

OK, maintenant commente et décommente les lignes CSS et SCRIPT que j'ai signalées dans le code.
Pourquoi ça ne marche pas lorsqu'on cache le volet avec le CSS au lieu de le cacher avec javascript et le DOM ?

http://jsbin.com/ubusos
Modifié par Gill (26 Mar 2012 - 14:17)
jb_gfx a écrit :
Tu as vu que je t'ai répondu dans mon premier post ?

Oui, oui, j'ai vu, en effet Smiley smile .
Je suis justement en train de revoir mon code pour corriger ce que tu m'as dit (button). J'ai appris des trucs très intéressants dans ta proposition, aussi. http://jsbin.com/ubexap
(juste un truc : je ne veux pas ouvrir ou fermer TOUS les volets de la page)

...mais je persiste à vouloir comprendre pourquoi mon code ne marche pas.
Il n'est pas propre, pas accessible... mais il DEVRAIT MARCHER !
Que j'accède aux DOM avec Javascript ou avec CSS, pourquoi le même objet n'est plus modifiable si je le cache avec le CSS ! Le navigateur le cache aussi à Javascript ? Il est supprimé du DOM ? c'est ridicule : ce ne sont que des attributs "style" que je devrais pouvoir modifier à ma guise !

EDIT : j'ai réduit le code au strict minimum, mais je ne comprends toujours pas :
http://jsbin.com/ofoqat/edit#html, live
Modifié par Gill (26 Mar 2012 - 23:08)
Euh... je t'ai donné la réponse, pourquoi ton code ne fonctionne pas, dans le premier post :

a écrit :

Si tu le définis à 'none', il n'est plus égale à une chaine vide. Smiley langue

Modifié par jb_gfx (27 Mar 2012 - 00:58)
jb_gfx a écrit :
Euh... je t'ai donné la réponse, pourquoi ton code ne fonctionne pas, dans le premier post :Si tu le définis à 'none', il n'est plus égale à une chaine vide. Smiley langue
Ah ! OK... J'étais parti sur le fait que tu t'étais trompé et que tu avais dû t'en apercevoir entretemps... Par ailleurs, j'y avais répondu, il me semble.

Pour JS, par défaut, div.style.display = ''; c'est comme div.style.display = 'block'
Tout comme a.style.display = ''; c'est comme div.style.display = 'inline'
Donc mettre à "chaîne vide" la propriété "display", c'est comme lui demander de s'afficher. Puisqu'on impose la propriété par défaut.
Il faut donc spécifier div.style.display = 'none' (et/ou div.style.visibility='hidden') si on veut cacher l'objet.

C'est pourquoi la partie "Javascript" de mon code fonctionne parfaitement.

D'ailleurs, si je change le div.style.display = '' par div.style.display = 'block' dans mon code, hé bien...
heu...
hé bien... Smiley sweatdrop
Hé bien, tu as raison. Smiley lol
C'était donc ça, le problème !

Lorsqu'on code : e.style.display = '';
Le navigateur se débrouille pour retrouver la valeur par défaut et traduit ça par :
e.style.display = 'block'; // ou e.style.display = 'inline' selon le cas
Alors il affiche l'objet à travers le DOM (qui accepte ce principe)

Alors que dans le CSS :
display:''; c'est comme display:nimportequoi; c'est une erreur !!!
Alors il n'affiche rien selon les règles du CSS (qui ne reconnait pas la chaîne vide)

Pfffff ! J'avais trop confiance en un code trouvé sur le net, et j'avais donc "appris" des sonneries...

Merci merci merci jb_gfx ! Je vais pouvoir avancer, maintenant ! Smiley ravi
(et mettre mon RESOLU)