2012-10-25 3 views
0

J'essaie de créer un menu multi-couches qui a des effets de glissement/de fondu. À l'heure actuelle, cela fonctionne sur mon premier clic, mais après cela, il échoue.jQuery difficultés de menu coulissant

HTML

<ul id="menu"> 
<li> 
    Development 
    <div> 
     <ul> 
      <li>Sub 1</li> 
      <li>Sub 2</li> 
     </ul> 
    </div> 
</li> 
<li> 
    Story 
    <div> 
     <ul> 
      <li>Sub 1</li> 
      <li>Sub 2</li> 
     </ul> 
    </div> 
</li> 
<li> 
    News 
    <div> 
     <ul> 
      <li>Sub 1</li> 
      <li>Sub 2</li> 
     </ul> 
    </div> 
</li> 
</ul>​ 

JavaScript

var observeClicks = function(){ 
    var lis = $('#menu').children('li'); 

    lis.click(function(){ 
     lis.unbind(); 
     var $this = $(this); 
     var $div = $($this.children('div')[0]); 
     var $ul = $($div.children('ul')[0]); 

     var clone = $ul.clone(true, true) 
      .css({visibility: 'hidden', display: 'block'}); 
     clone.attr('style', clone.attr('style').replace('block', 'block !important')) 
      .insertAfter($ul); 

     setTimeout(function(){ 
      $ul.css({height: clone.css('height')}); 
      $div.css({height: clone.css('height')}); 
      clone.remove(); 
     }, 0); 

     if(!lis.hasClass('current')){ 
      $this.addClass('current'); 
      $div.slideDown(350, function(){ 
       $ul.fadeIn(350); 
       observeClicks(); 
      }); 
     }else{ 
      if(!$this.hasClass('current')){ 
       $current = $($('.current')[0]); 
       $cdiv = $($current.children('div')[0]); 
       $cul = $($cdiv.children('ul')[0]); 

       $cdiv.css({height: $cul.css('height')}); 

       $this.addClass('current'); 
       $current.removeClass('current'); 
       $cul.fadeOut(350, function(){ 
        $cdiv.slideUp(350, function(){ 
         $div.slideDown(350, function(){ 
          $ul.fadeIn(350); 
          observeClicks(); 
         }); 
        }); 
       }); 
      }else{ 
       observeClicks(); 
      } 
     } 
    }); 
} 
observeClicks(); 

CSS

#menu { 
    cursor: pointer; 
    width: 150px; 
} 

#menu div { 
    display: none; 
    width: 100%; 
} 

#menu li ul { 
    display: none; 
    margin-left: 25px; 
} 

Le premier problème intéressant que je r Au lieu de glisser, mon menu ne faisait que «sauter». C'était parce que le div ne prenait pas de place jusqu'à ce que les éléments qui s'y trouvaient soient visibles. J'ai donc surmonté cela en lui donnant une zone fixe. (La largeur est définie en CSS et la hauteur est définie en JavaScript). Je pense que c'est là que le problème peut se trouver, j'insère un élément fictif, je lis sa hauteur, j'attribue cela à la div, puis je retire l'élément. C'est sommaire, je sais mais je ne pouvais pas trouver un meilleur moyen.

De toute façon, lorsque je clique sur un élément de menu, cela fonctionne parfaitement. Mais dès que j'essaie mon second clic, il semble que la hauteur ne soit pas définie pour la div, et il n'y a pas d'effet de glissement.

Vous remarquerez peut-être qu'au lieu d'essayer de faire le tour avec .stop() pour les animations, il suffit de dissocier le gestionnaire de clic, puis de les relier une fois toutes les animations terminées. C'était délibéré, et j'avais ce problème avant d'ajouter cela. Si quelqu'un pouvait me montrer ce qu'il fallait réparer, ce serait très apprécié.

+0

Je l'ai fait il y a un moment. Peut-être utile si vous voulez moins de code pour un menu similaire: http://jsfiddle.net/aCaEG/ – Johan

Répondre

1

Il coutures que le problème est dans la pièce de hauteur de clone code. Je ne sais pas pourquoi il ne fonctionne que avec le premier élément cliqué, mais vous pouvez le réparer en réglant simplement cette hauteur éléments css:

#menu div { 
    display: none; 
    width: 100%; 
    height: 40px; 
} 

#menu li ul { 
    display: none; 
    margin-left: 25px; 
    height: 40px; 
} 

et en supprimant le code js ce clone et hauteurs ASIGN, Il regarde ok dans jsfiddle: http://jsfiddle.net/j7EHu/

+0

Je suppose que je pourrais le faire de cette façon, mais j'espérais trouver une manière automatique d'obtenir la hauteur alors quand j'ajoute/enlève des choses de mon menu, je n'ai pas à m'inquiéter de bidouiller le CSS encore et encore. – Aust

+0

Vous pouvez simplement assigner une hauteur aux composants avec une opération lineheight-dépendante simple: $ div.css ({height: $ ul.children(). Longueur * $ ul.css ('lineHeight')}); Vous n'avez pas besoin du clonage et du minuteur, qui sont beaucoup plus complexes. –

0

S'il vous plaît utiliser au lieu de votre code:

#menu { 
    cursor: pointer; 
    width: 150px; 
} 

#menu div { 
    display: none; 
    width: 100%; 
} 

#menu li ul { 
    margin-left: 25px; 
} 

JS

$("#menu > li").click(function(){ 
     $('#menu .active').slideUp(350).removeClass('active'); 
     $(this).find('div').slideDown(350,function() { 
      $(this).addClass('active'); 
     }); 
}); 

Sí Voici une démo: http://jsfiddle.net/yL944/12/

+0

J'essaie d'obtenir l'effet de glisser vers le bas, puis de disparaître, pas simplement glisser vers le bas. – Aust