Garder un menu coulissant ouvert au passage de la souris

J’essaie de convertir un système de menus existant chargé de Javascript en ligne en un nouveau code, plus efficace, utilisant uniquement jQuery.

J’ai une barre horizontale avec des images de roulement. J’ai un champ caché dans la page contenant une valeur entière. Lorsqu’une page est chargée, le menu correspondant est chargé avec une version “collante” de l’image et tous les autres éléments du menu permettent d’échanger les images lorsque la souris est entrée / sortie. Il contenait des tonnes de Javascript en ligne et un fichier Javascript monstre qu’il était fastidieux de convertir à chaque fois que je créais un nouveau site.

J’ai réussi à convertir tout cela en jQuery, où j’ai également pu désactiver le clic sur l’élément de menu collant. Maintenant, je peux simplement définir certaines variables et les personnaliser facilement en fonction de la conception de chaque site.

Travailler très bien …

Vient maintenant un nouveau problème. Une conception contient un groupe de tiroirs coulissants sous chaque image de menu. Les animations glissantes sont gérées par un fichier JS externe et les tiroirs de menus ne sont eux-mêmes que des DIV contenant le contenu nested dans un conteneur DIV.

Alors j’ai écrit quelques trucs simples pour jQuery qui animent la DIV et les font glisser vers la souris pour les images du menu.

Le problème est que je n’arrive pas à résoudre le problème de la souris qui s’éloigne de l’image du menu et descend dans le tiroir du menu sans fermer le tiroir. Je comprends le “pourquoi?” … Je quitte l’image qui déclenche l’animation pour fermer le tiroir avant que je puisse entrer à l’intérieur. Si j’applique les animations en survol au conteneur de tiroirs, il crée simplement une zone sous le menu qui déclenche également l’animation, ce que je ne souhaite pas non plus. Cela semble devenir un problème plus complexe avec jQuery. Tout cela fonctionnait bien avec le code Javascript intégré … vous pouvez simplement déplacer votre souris de l’image dans le tiroir ouvert adjacent sans déclencher la fonction permettant de la fermer … comme si la “souris entrante” du tiroir annulait la “laisser la souris” de l’image.

Aucune suggestion?

Je vous remercie!


MODIFIER:

Je crois avoir résolu le problème en utilisant .stop (true, false) lors du passage de l’image dans le tiroir. Cela arrête l’animation avant même qu’elle ne commence. Ensuite, la même chose lorsque vous entrez dans l’image AVANT de lancer l’animation normale … Cela a pour effet d’arrêter l’animation déclenchée en quittant le tiroir et en entrant l’image, mais ne fait rien lorsque vous entrez l’image normalement. Plus de tests et ensuite je posterai un exemple de code.


EDIT # 2:

Je le travaille avec “stop ()” et “delay ()” pour contrôler l’animation, mais il est possible de geler l’ouverture du tiroir si vous pouvez y insérer votre souris plus rapidement que nécessaire. Installé avec 150 ms. mais pour l’instant fixé à 300 ms pour exagérer le problème.

Code pertinent posté ici …

jsfiddle.net/qPLVp/8/


EDIT # 3:

Grâce à Neil, cela fonctionne très bien maintenant. Avec une vitesse d’animation plus rapide, la condition d’une souris dépassant l’image du menu et entrant dans le tiroir sera réduite au minimum. Mais si cela se produit, le tiroir ne se fermera pas, ce qui est bien mieux que de fermer sous votre souris.

http://jsfiddle.net/elusien/PayFw/8/


EDIT # 4:

Encore une fois, grâce à Neil, il s’agit d’une version plus efficace du même code …

http://jsfiddle.net/PayFw/9/

J’ai modifié votre code jsFiddle pour le faire fonctionner. Fondamentalement, j’ai attaché un object de données à votre élément #menu . Lorsque vous ouvrez ce tiroir, l’object est {opening: true} . Lorsque le tiroir est complètement ouvert (animation terminée), l’object est {opening: false} . Je vérifie cela lorsque vous entrez dans le tiroir et s’il est faux, j’arrête l’animation. Si c’est vrai, je n’arrête pas l’animation.

Le code est:

  function enter(event) { // mouseenter IMG // removed image rollover code $('#menu').data({opening: true}).stop(true, false).animate({ top: '0', opacity: 1 },{ duration: 300 // slow the opening of the drawer }, function(){$(this).data({opening: false});} ); }; function leave(event) { // mouseout IMG // removed image rollover code $('#menu').delay(400).animate({ top: '-'+$ht+'px', opacity: 0 },{ duration: 600 }); }; $('#menu').hover( function (){ // mouseenter Menu drawer if (!$(this).data('opening')) { $(this).stop(true, false); } }, function (){ // mouseout Menu drawer $(this).delay(400).animate({ top: '-'+$ht+'px', opacity: 0 },{ duration: 600 }); } ); 

Cela fonctionne maintenant bien. Vous voudrez peut-être refaire une partie de vos “délais” à la lumière de ceci.

Sparky,

J’ai imaginé une manière différente de faire les choses. Fondamentalement, placer un masque transparent sur le “bouton” et la “description” et utiliser un événement “mouseleave” à ce sujet.

HTML:

   

Javascript:

 $(document).ready(function() { $('#menuitem').bind('mouseenter', enter); $('#menumask').bind('mouseleave', leave); $('#menu').css({ height: '500px', position: 'absolute', paddingTop: '50px', width: '200px', backgroundColor: '#080', zIndex: -1 }).hide(); $('#menumask').css({ height: '550px', width: '200px', opacity: 0.99, position: 'absolute', fontSize: '20000px', overflow: 'hidden', zIndex: 2 }).hide(); function enter(){ $('#menumask').show(); $('#menu').stop(true,true).animate({height: 500}, 'slow'); }; function leave(){ $('#menumask').hide(); $('#menu').stop(true,true).slideUp({height: 0}, 'slow');}; }); 

Vous pouvez utiliser cela comme base pour votre système de menus.

Cordialement Neil

Il semble que vous recherchiez la fonction .delegate (), qui attache un gestionnaire à un événement DOM maintenant ou dans le futur:

 $(".menuItem").delegate(".subMenu","hover", function(){ $(this).show(); }); 

Vous pouvez en savoir plus sur la fonction .delegate () et son copain .live () ici: http://api.jquery.com/delegate/

Sans voir le code, il est difficile de savoir si les solutions suivantes fonctionneraient:

hover() prend comme arguments 2 fonctions, la première est exécutée lorsque vous entrez l’image, la seconde; quand vous quittez l’image.

Vous avez probablement configuré la deuxième fonction pour masquer (fermer) le tiroir. J’appendais un petit délai (par exemple, delay(100) ) avant le hide() et définirais un événement de survol sur le tiroir lui-même pour (dans le premier argument de la fonction) arrêter la queue d’animation stop(true, true) – cela arrêtera le tiroir étant fermé et dans la deuxième fonction – fermez le tiroir lorsque vous le quittez.

Hey je suis tombé sur ce post en essayant d’accomplir la même chose. Bien que je puisse laisser ma solution parce que nous .delegate maintenant en 2017, .delegate était obsolète et utiliser des données pour déterminer si une transition était ou non encore effective semblait compliqué.

La clé utilisait l’élément passé dans le rappel de mouseleave pour obtenir l’ element.relatedTarget .

 $('.myMouseoverElements').on('mouseover', function() { activeElements = $('.elements.to.open') activeElements.addClass('open') activeElements.on('mouseleave', function(element) { var sustainElements = $('.elements.to.sustain.mouseover') var drawerShouldClose = !$(element.relatedTarget).is(sustainElements) if (drawerShouldClose) { activeElements.removeClass("open") activeElements.off("mouseleave") } }) }) 

Merci pour l’aide!