IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Sous menu qui disparait trop rapidement (onmouseouver)


Sujet :

JavaScript

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Par défaut Sous menu qui disparait trop rapidement (onmouseouver)
    Bonjour tout le monde,

    J'ai un menu.

    Le dernier élément de mon menu (Dossiers) devrait être déroulant, j'ai donc ceci :

    http://www.vetecocquereaux.be

    Vous remarquerez que sur le onmouseover, le menu s'affiche, c'est ce que je veux.

    Sur le onmouseout, le menu disparait, c'est aussi ce que je veux.

    Par contre, je voudrais pouvoir sélectionner le sous menu mais pas moyen, le menu disparait.

    Voici le code du dernier élément du menu (Dossiers) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <div class="btn" onmouseover="afficher_masque_sous_menu('afficher');" onmouseout="afficher_masque_sous_menu('masquer');" >
                    	<a href="#" onclick="div_centrale('liens_utiles');" class="btn">Dossiers</a>
                        <div id="sousmenu" style="display:none">
                        	<div class="btn">
                    			<a href="#" onclick="div_centrale('liens_utiles');" class="btn">Chiens</a>
                             </div>
                            <div class="btn">
                                <a href="#" onclick="div_centrale('liens_utiles');" class="btn">Chats</a>
                             </div>
                            <div class="btn">
                                <a href="#" onclick="div_centrale('liens_utiles');" class="btn">NAC</a>
                            </div>
                        </div> 
                    </div>
    Voici le code javascript :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function afficher_masque_sous_menu(action)
    {
    	if(action == 'afficher')
    	{
    		document.getElementById('sousmenu').style.display = 'block';	
    	}
    	else
    	{
    		document.getElementById('sousmenu').style.display = 'none';	
    	}
     
    }
    Je voudrais savoir si il serait possible de pouvoir sélectionner le sous-menu et lorsque je quitte ce sous menu (ou le menu), le menu devrait alors disparaitre.

    Avez-vous une idée ?

    Merci d'avance pour l'aide.

    beegees

  2. #2
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 098
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 098
    Par défaut
    Bonsoir,
    tu connais relatedTarget ? (Ou toElement sous MSIE.) C’est une propriété spécifique aux évènements de « survol ». Le problème c’est qu’en l’état des choses, tu n’y a pas accès car tu lies tes évènements avec des attributs HTML.

    Utilise les gestionnaires d’évènements (une petite recherche dans les tutos de ce site ou sur Google).

    Si ton menu et ton sous-menu sont collés, il suffit de rajouter un test dans la fonction qui masque le menu, pour savoir si le relatedTarget est le sous-menu ou pas.

    Prends bien le temps de comprendre le principe des gestionnaires d’évènements, tu en auras besoin, et en particulier au bouilonnement des évènements, car avec mouseover et mouseout ça joue souvent de mauvais tours ^^

    Je suis pas du genre à donner un code tout fait à quelqu’un qui ne cherche pas à comprendre. Faut mettre les mains dans le cambouis
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  3. #3
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 098
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 098
    Par défaut
    Rebonjour !
    Par égard pour les internautes qui débarquent ici via Google, je vais poste une réponse constructive, quand même (je me suis aperçu qu’il n’y avait pas de tuto sur les event listeners sur ce site)…

    Alors pour commencer, je mets en pièce jointe une petite framework de mon cru dont le simple but est de « lisser » les différences entre MSIE et les autres navigateurs. Ce framework s’appelle Browser (non, ce n’est pas le boss dans Mario) et propose une fonction addListener qui déclenche des events trafiqués pour avoir des propriétés standard même sous IE.

    Les propriétés qui nous intéressent ici sont target et relatedTarget.

    Bien.

    Commençons par le code HTML. On va imaginer un menu simple à seulement un niveau, représenté par des listes :

    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <ul class="menu" id="main-menu">
    	<li>Commodis</li>
    	<li>
    		Amici
    		<ul class="sub-menu">
    			<li>Indigno</li>
    			<li>Quem</li>
    		</ul>
    	</li>
    	<li>
    		Amicorum
    		<ul class="sub-menu">
    			<li>Qit</li>
    			<li>Fruantur</li>
    			<li>Aliquem</li>
    		</ul>
    	</li>
    </ul>

    Par souci d’amélioration progressive, les sous-menus ne sont pas masqués, ils le seront seulement si JavaScript est activé.

    Je passe les détails pour le CSS, on va simplement mettre le strict minimum :
    Code CSS : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    .menu, .sub-menu
    {
    	background: white;
    	border: solid 1px black;
    	list-style: none;
    	padding: 0;
    	width: 10em;
    }
    .sub-menu
    {
    	z-index: 100;
    }
    .menu li:hover
    {
    	background: silver;
    }
    .menu li
    {
    	position: relative;
    }
    .sub-menu
    {
    	position: absolute;
    	top: 0;
    	left: 7em;
    }

    Le script à présent. On commence par la fonction d’initialisation, qui se déclenche à l’évènement load de la page. Dans un premier temps, on masque les sous-menus :
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Browser.addListener(window, 'load', function windowLoad() {
    	var lists = document.getElementsByTagName('ul');
    	for (var i = 0, list; list = lists.item(i); i++) {
    		if (list.className == 'sub-menu') {
    			list.style.display = 'none';
    		};
    	};
    });

    Maintenant, il faut que les mouseover fassent apparaître les éventuels sous-menus. On pourrait attacher un évènement à chaque item de menu, mais il est plus intéressant d’utiliser le principe de la délégation d’évènement : on surveille seulement le menu entier, et on examine le target de l’objet event pour savoir quand agir. Pour cette fonction, je commence par mettre « en cache » le target dans une variable locale, car je vais m’en servir plusieurs fois, et je place le code de la fonction dans un if pour qu’elle n’agisse que sur les items :
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Browser.addListener(window, 'load', function windowLoad() {
    	// …
     
    	var menu = document.getElementById('main-menu');
    	Browser.addListener(menu, 'mouseover', menuMouseover);
    });
     
    function menuMouseover( ev ) {
    	var target = ev.target;
    	if (target.tagName == 'LI') {
    		// … corps de la fonction
    	};
    };

    Chaque item n’a pas forcément un sous-menu, c’est pourquoi il faut en tester la présence avant de l’afficher :
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    		var ulSet;
    		if (ulSet = li.getElementsByTagName('ul')) {
    			var submenu = ulSet.item(0);
    			submenu.style.display = 'block';
    		};
    C’est vrai, je ne suis pas obligé de passer par des variables intermédiaires, mais avouez que c’est plus clair comme ça
    Voici la fonction entière :
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function menuMouseover( ev ) {
    	var target = ev.target;
    	if (target.tagName == 'LI') {
    		var ulSet = target.getElementsByTagName('ul');
    		if (ulSet.length) {
    			var submenu = ulSet.item(0);
    			submenu.style.display = 'block';
    		};
    	};
    };

    À ce stade, on a déjà quelque chose d’intéressant Mais voici le plus dur : gérer le mouseout pour faire disparaître les sous-menus…
    On utilise toujours la délégation :
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Browser.addListener(window, 'load', windowLoad() {
    	// …
     
    	Browser.addListener(menu, 'mouseout', menuMouseout);
    });
     
    function menuMouseout( ev ) {
    	var target = ev.target;
    	// …
    };
    Là vous allez me dire : il suffit d’agir seulement si le target est un sous-menu.
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function menuMouseout( ev ) {
    	var target = ev.target;
    	if (target.className == 'sub-menu') {
    		target.style.display = 'none';
    	};
    };
    Hmm, pas si simple… Par exemple, si l’utilisateur fait des mouvement de souris rapides, le mouseout peut se produire directement entre l’item de sous-menu (<li>) et l’extérieur, sans passer par le sous-menu (<ul>). Vous voyez ce que je veux dire ?

    Nouvelle tentative :
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function menuMouseout( ev ) {
    	var target = ev.target;
    	if (target.className == 'sub-menu') {
    		target.style.display = 'none';
    	} else if (target.tagName == 'LI') {
    		var parent = target.parentNode;
    		if (parent.className == 'sub-menu') {
    			parent.style.display = 'none';
    		};
    	};
    };

    Et là, c’est le drame ! Ça disparaît n’importe quand. C’est là qu’on va avoir besoin de relatedTarget : si le relatedTarget est aussi un item de sous-menu, on ne masque pas le sous-menu. Il faut également prévoir le cas où on a des marges et où on pourrait glisser sur le <ul> dans l’espace entre deux <li> (j’espère que vous suivez toujours)…
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function menuMouseout( ev ) {
    	var target = ev.target;
    	if (target.className == 'sub-menu') {
    		target.style.display = 'none';
    	} else if (target.tagName == 'LI') {
    		var related = ev.relatedTarget;
    		var parent = target.parentNode;
    		if (parent.className == 'sub-menu'
    			&& related != parent
    			&& related.parentNode != parent)
    		{
    			parent.style.display = 'none';
    		};
    	};
    };
    Voilà, on a fait le plus dur. Reste plus qu’à agir aussi quand on quitte l’item du menu principal qui a ouvert le sous-menu, le cas échéant, en testant l’existance de de sous-menu comme dans menuMouseover :
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    function menuMouseout( ev ) {
    	var target = ev.target;
    	if (target.className == 'sub-menu') {
    		target.style.display = 'none';
    	} else if (target.tagName == 'LI') {
    		var related = ev.relatedTarget;
    		var parent = target.parentNode;
    		if (parent.className == 'sub-menu' 
    			&& related != parent
    			&& related.parentNode != parent)
    		{
    			parent.style.display = 'none';
    		} else if (parent.className == 'menu'
    			&& related.className != 'sub-menu'
    			&& related.parentNode.className != 'sub-menu')
    		{
    			var ulSet = target.getElementsByTagName('ul');
    			if (ulSet.length) {
    				var submenu = ulSet.item(0);
    				submenu.style.display = 'none';
    			};
    		};
    	};
    };

    Ça fait un code assez indigeste avec tous ces if imbriqués, mais ça a le mérite de marcher (Cela dit, c’est sans doute optimisable.)

    Voici le code final :
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    Browser.addListener(window, 'load', function windowLoad() {
    	var lists = document.getElementsByTagName('ul');
    	for (var i = 0, list; list = lists.item(i); i++) {
    		if (list.className == 'sub-menu') {
    			list.style.display = 'none';
    		};
    	};
    	var menu = document.getElementById('main-menu');
    	Browser.addListener(menu, 'mouseover', menuMouseover);
    	Browser.addListener(menu, 'mouseout', menuMouseout);
    });
     
    function menuMouseover( ev ) {
    	var target = ev.target;
    	if (target.tagName == 'LI') {
    		var ulSet = target.getElementsByTagName('ul');
    		if (ulSet.length) {
    			var submenu = ulSet.item(0);
    			submenu.style.display = 'block';
    		};
    	};
    };
     
    function menuMouseout( ev ) {
    	var target = ev.target;
    	if (target.className == 'sub-menu') {
    		target.style.display = 'none';
    	} else if (target.tagName == 'LI') {
    		var related = ev.relatedTarget;
    		var parent = target.parentNode;
    		if (parent.className == 'sub-menu' 
    			&& related != parent
    			&& related.parentNode != parent)
    		{
    			parent.style.display = 'none';
    		} else if (parent.className == 'menu'
    			&& related.className != 'sub-menu'
    			&& related.parentNode.className != 'sub-menu')
    		{
    			var ulSet = target.getElementsByTagName('ul');
    			if (ulSet.length) {
    				var submenu = ulSet.item(0);
    				submenu.style.display = 'none';
    			};
    		};
    	};
    };


    Sinon sur la Toile on trouve des techniques de feignasses à base de timeouts pour retarder légèrement le masquage du sous-menu, afin de laisser le temps à la souris d’arriver dessus. Je trouve que ça manque de panache

    Bien entendu, je reste dispo pour les questions.

    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  4. #4
    Membre expérimenté
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Par défaut
    Bonjour Watilin,

    Merci pour ta réponse.

    Cette dernière me semble un peu "gonflée" par rapport au problème que je rencontre.

    En fait, mon sous-menu fonctionne maintenant mais comme d'habitude, ne fonctionne plus avec cette m.... de IE.

    J'ai donc un souci avec onmouseover et onmouseout qui ne semble pas fonctionne avec IE.

    Merci encore pour l'aide et si quelqu'un a une idée, je suis preneur.

    bon WE.

    beegees

    PS: merci de rectifier ton premier post :

    Je suis pas du genre à donner un code tout fait à quelqu’un qui ne cherche pas à comprendre.
    Je n'ai jamais dis que je ne cherchais pas à comprendre !

  5. #5
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 098
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 098
    Par défaut
    salut,
    ça ne t’était pas personnellement adressé. C’était juste pour expliquer pourquoi je n’ai pas donné de code immédiatement.

    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

Discussions similaires

  1. Sous menu qui disparait quand on passe la souris dessus
    Par pasc06 dans le forum Mise en page CSS
    Réponses: 5
    Dernier message: 09/12/2009, 07h23
  2. pb sous menu qui reste ouvert quand je déplace la souris
    Par mouna201 dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 17/02/2007, 14h26
  3. IE6 + menu qui disparait au contact d'un contenu
    Par PuppeT mAsTer dans le forum Général JavaScript
    Réponses: 10
    Dernier message: 09/08/2006, 16h33
  4. [css sous ie] menu qui disparait qd clic sur precedent ...
    Par michaelbob dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 22/02/2006, 14h37
  5. [CSS] Menu qui disparait derriere un champ
    Par Pepito dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 06/09/2005, 10h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo