11521 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

J'ai un gestionnaire d'évènement relativement simple qui ouvre et ferme un menu au clic sur un bouton. Jusque là tout va bien. Là où je bloque c'est que j'aimerais qu'une fois le menu ouvert, si l'utilisateur clique n'importe où dans la fenêtre du navigateur, le menu se ferme... ça paraît simple je sais mais je bloque.

J'ai essayé de mettre un second gestionnaire d'évènement sur la fenêtre du navigateur, d'abord imbriqué dans le premier gestionnaire qui gère le bouton, puis ensuite j'ai essayé de le placer à l'extérieur du premier gestionnaire... rien à faire.


/* On initialise une fonction pour ouvrir le menu. */
function OPENmenu() {
	/* On ajoute la classe « MENUopened » au menu pour l'ouvrir. */
	MENU.classList.add('MENUopened');
	alert('Tu viens d\'ouvrir le menu !');
}

/* On initialise une fonction pour fermer le menu. */
function CLOSEmenu() {
	/* On supprime la classe « MENUopened » du menu pour le fermer. */
	MENU.classList.remove('MENUopened');
	alert('Tu viens de fermer le menu !');
}

/* On initialise l'écoute sur le bouton du menu. */
BUTTONmenu.addEventListener(
	/* On écoute l'évènement « click ». */
	'click',
	/* Si l'évènement se produit... */
	function() {
		/* Si le menu est fermé... */
		if (MENU.className == 'MENUclosed') {
			/* On utilise la fonction qui ouvre le menu. */
			OPENmenu();
		}
		/* Sinon... */
		else {
			/* On utilise la fonction qui ferme le menu. */
			CLOSEmenu();
		}
	},
	/* On configure la captation de l'évènement sur la phase de capture. */
	true
);


Merci d'avance.
allan00958 a écrit :
Salut,

Il faut faire de la délégation d'évènements. Écouter les évènements sur le document.

Un peu comme ici: https://jsfiddle.net/fg7j4r6x/

API utiles:

https://developer.mozilla.org/fr/docs/Web/API/Node/contains

https://fr.javascript.info/event-delegation


Merci mais ce n'est pas vraiment ce que je recherche.

J'ai modifié un peu mon code et là ça fonctionne. Enfin sauf que... lorsque le menu est ouvert, il se referme bien lorsque l'utilisateur clique n'importe où dans la fenêtre, en revanche si l'utilisateur clique sur le bouton le menu reste ouvert...


/* Sur le bouton du menu principal on ajoute un gestionnaire d'évènement. */
BUTTONmenu.addEventListener(
	/* On écoute l'évènement « click ». */
	'click',
	/* Si l'évènement se produit on initialise une fonction anonyme... */
	function() {
		/* Si le menu principal possède la classe « MENUclosed »... */
		if (MENU.className === 'MENUclosed') {
			/* On utilise la fonction qui ouvre le menu principal. */
			OPENmenu();
		}
		/* Sinon... */
		else {
			/* On utilise la fonction qui ferme le menu principal. */
			CLOSEmenu();
		}
	},
	/* On configure la captation de l'évènement sur la phase de capture. */
	true
);

/* Sur la fenêtre du navigateur on ajoute un gestionnaire d'évènement. */
window.addEventListener(
	/* On écoute l'évènement « click ». */
	'click',
	/* Si l'évènement se produit on initialise une fonction anonyme... */
	function() {
		/* Si le menu principal possède la classe « MENUopened »... */
		if (MENU.className === 'MENUopened') {
			/* On utilise la fonction qui ferme le menu principal. */
			CLOSEmenu();
		}
	},
	/* On configure la captation de l'évènement sur la phase de capture. */
	true
);
Javaslip a écrit :


Merci mais ce n'est pas vraiment ce que je recherche.


alors je n'ai pas compris ta demande non plus..

parce que son code dans le jsfiddle, fait exactement ce que tu demande.
J'ai un peu de mal à comprendre l'attribution de cette variable
var target = e.target;
et la condition
if(target.contains(menu) && menu.style.display === 'block')
.
e.target étant l’élément qui permet de connaitre la cible html sur laquelle tu as cliqué.

le if fait deux chose
avec le contains il regarde si le target (l'élement cliquer) contient
document.getElementById('menu') // variable en début de fichier

et l'autre permet de regarder son style, s'il est un display block.
JENCAL a écrit :
e.target étant l’élément qui permet de connaitre la cible html sur laquelle tu as cliqué.

le if fait deux chose
avec le contains il regarde si le target (l'élement cliquer) contient
document.getElementById('menu') // variable en début de fichier

et l'autre permet de regarder son style, s'il est un display block.


Ok merci je comprends.

En revanche je me mélange complètement les pinceaux entre phase de capture, phase de bouillonnement, et propagation... j'ai bien compris que :
- la phase de capture est la phase "descendante" de lecture du code,
- la phase de bouillonnement est la phase "remontante" de lecture du code qui se produit après la première phase de capture,
- que la propagation suit d'abord la phase de capture, puis la phase de bouillonnement, sauf si on stoppe la propagation avec par exemple un element.stopPropagation();.

Sauf que pour voir les effets dans différents cas de situations je me suis servi de la console de Firefox, j'ai utilisé l'option true en 3ème argument du gestionnaire pour le bloquer en phase de capture, je l'ai également laissé en phase de bouillonnement par défaut, j'ai utilisé la fonction element.stopPropagation();... et j'avoue ne pas parvenir à comprendre les effets. Smiley biggol