Dodanie efektu slajdu do listy rozwijanej bootstrap

80

Używam bootstrap i chciałbym dodać animację do listy rozwijanej. Chcę dodać do niego animację, zjeżdżać w dół i cofać się, gdy ją opuszczam. Jak mogłem to zrobić?

Rzeczy, które próbowałem:

Zmiana rozwijanego pliku Js w następujący sposób:

Jak mogę sprawić, aby menu rozwijane nawigacji Bootstrap przesuwały się płynnie w górę iw dół?

Ben Beri
źródło
1
czy umieściłeś gdzieś plik bootstrap-dropdown.js? nie widzę tego w nagłówku ... i awwww te ciasta. Jestem teraz taki głodny!
ablm
Hmm, jest w środku boostrap.js, włączyłem go, ale nie zadziałał, więc go usunąłem, ale dodałem go ponownie i tak, jeśli usunę mini, to w ogóle nie zadziała
Ben Beri
EDYCJA: o tak, to jest włączone.
ablm
Umm. Domyślne menu nie przesuwa się; W zmodyfikowanej wersji (z linków) znajduje się $ el.parent (). SlideToggle (); który wywołuje animację JQuery.
ablm
A tak przy okazji, nie rozumiem, dlaczego dołączasz bootstrap 2 razy. bootstrap.min.js to zminimalizowana wersja.
ablm

Odpowiedzi:

150

Jeśli zaktualizujesz Bootstrap 3 (BS3), ujawnili wiele zdarzeń Javascript, z którymi przyjemnie jest powiązać pożądaną funkcjonalność. W BS3 ten kod nada wszystkim rozwijanym menu efekt animacji, którego szukasz:

  // Add slideDown animation to Bootstrap dropdown when expanding.
  $('.dropdown').on('show.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
  });

  // Add slideUp animation to Bootstrap dropdown when collapsing.
  $('.dropdown').on('hide.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
  });

Możesz przeczytać o wydarzeniach BS3 tutaj, a konkretnie o wydarzeniach rozwijanych tutaj .

cogell
źródło
4
Mam problem z częścią slideUp tego. W trybie zwiniętym (Chrome) szerokość listy rozwijanej powraca do szerokości, tak jakby była wyświetlana na pełnym ekranie. Podczas korzystania z FF przesuwa się w dół, ale chowa się zamiast przesuwać się w górę.
ScubaSteve
3
Ja też widzę ten problem, właściwie stworzyłem kolejny wątek z pytaniem konkretnie o to… stackoverflow.com/questions/26267207/… ale nie wiem dokładnie, jak to naprawić. Wydaje mi się, że klasa Dropdown nie czeka na zakończenie przejścia przed przetworzeniem hidden.bs.dropdownzdarzenia.
Kyle Johnson
3
to działa i robi to, co chcę, ale w widoku mobilnym rozwijane menu podmenu znika szybko i wygląda na nierówne - jednak dzięki za udostępnienie!
Wujek Iroh
Nie mogę sprawić, żeby to zadziałało. Ciągle pojawia się następujący błąd: „Uncaught TypeError: $ (...). Find (...). First (...). Stop is not a function”. Nie rozumiem, dlaczego .stop () nie jest funkcją, chyba że animacja jeszcze się nie zaczęła, gdy zdarzenie jest uruchamiane? czego mi brakuje?
John
Zapoznaj się z odpowiedzią Slipocha poniżej, aby uzyskać informacje o rozwiązaniu mobilnym.
Tashows
72

Można również uniknąć używania JavaScript do rozwijania efektu i użyć przejścia CSS3, dodając ten mały fragment kodu do swojego stylu:

.dropdown .dropdown-menu {
    -webkit-transition: all 0.3s;
    -moz-transition: all 0.3s;
    -ms-transition: all 0.3s;
    -o-transition: all 0.3s;
    transition: all 0.3s;

    max-height: 0;
    display: block;
    overflow: hidden;
    opacity: 0;
}

.dropdown.open .dropdown-menu { /* For Bootstrap 4, use .dropdown.show instead of .dropdown.open */
    max-height: 300px;
    opacity: 1;
}

Jedynym problemem związanym z tym sposobem jest ręczne określenie maksymalnej wysokości. Jeśli ustawisz bardzo dużą wartość, Twoja animacja będzie bardzo szybka.

Działa to jak urok, jeśli znasz przybliżoną wysokość swoich list rozwijanych, w przeciwnym razie nadal możesz użyć javascript, aby ustawić dokładną wartość maksymalnej wysokości.

Oto mały przykład: DEMO


! W tym rozwiązaniu jest mały błąd z dopełnieniem, sprawdź komentarz Jacoba Stamm'a z rozwiązaniem.

MadisonTrash
źródło
2
Niezłe rozwiązanie, doceniam to.
Lalit Narayan Mishra
Uwielbiam to, ale niestety animacja zsuwania działa tylko raz. Jeśli zamknę menu i otworzę je ponownie bez odświeżania strony, po prostu otworzy się natychmiast. Czy ktoś jeszcze ma ten problem?
Nathan R
8
Świetne rozwiązanie. Niestety jest mały błąd. Pierwszy element w menu jest nadal klikalny, nawet gdy jest zwinięty. Możesz to sprawdzić, najeżdżając nieco poniżej zwiniętego menu. W tym przypadku nic wielkiego, ponieważ pierwszą opcją jest zwykły tekst. Jednak gdy jest to link, jest to problem. Moim rozwiązaniem jest „ożywienie” również widoczności, ale opóźnienie nastąpi po zakończeniu animacji innych rzeczy. Sprawdź to: jsfiddle.net/stamminator/kjLe1tfs/1
Jacob Stamm
Dzięki za wskazanie tego błędu, Jacob. Wygląda na to, że jest to problem z dopełnieniem listy. Jeśli nie masz nic przeciwko, dodam Twoje rozwiązanie do odpowiedzi.
MadisonTrash
1
Można też dodać pointer-events:nonedo zwiniętej wersji, a następnie dodać point-events: alldo menu, gdy już ma.show
Gray Ayer
23

Robię coś takiego, ale po najechaniu kursorem zamiast kliknięciu .. To jest kod, którego używam, możesz go nieco poprawić, aby działał po kliknięciu

$('.navbar .dropdown').hover(function() {
  $(this).find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
}, function() {
  $(this).find('.dropdown-menu').first().stop(true, true).delay(100).slideUp()
});
Yohn
źródło
To działa świetnie! Ale czy jest jakiś sposób na pracę z nim po najechaniu myszą zamiast kliknięciem?
arefin2k
Kod, który zamieściłem powyżej, znajduje się po najechaniu myszą, a nie po kliknięciu.
Yohn
Dobry ! Dzięki.
ilmk
Nie działa dla mnie. Dodałem to pod <script>tagami, ale nic się nie stało
YaddyVirus
16

Nie wiem, czy mogę podnieść ten wątek, ale znalazłem szybką naprawę wizualnego błędu, który występuje, gdy klasa otwarta jest usuwana zbyt szybko. Zasadniczo wystarczy dodać funkcję OnComplete do zdarzenia slideUp i zresetować wszystkie aktywne klasy i atrybuty. Idzie mniej więcej tak:

Oto wynik: przykład Bootply

Javascript / Jquery:

$(function(){
    // ADD SLIDEDOWN ANIMATION TO DROPDOWN //
    $('.dropdown').on('show.bs.dropdown', function(e){
        $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
    });

    // ADD SLIDEUP ANIMATION TO DROPDOWN //
    $('.dropdown').on('hide.bs.dropdown', function(e){
        e.preventDefault();
        $(this).find('.dropdown-menu').first().stop(true, true).slideUp(400, function(){
            //On Complete, we reset all active dropdown classes and attributes
            //This fixes the visual bug associated with the open class being removed too fast
            $('.dropdown').removeClass('show');
            $('.dropdown-menu').removeClass('show');
            $('.dropdown').find('.dropdown-toggle').attr('aria-expanded','false');
        });
    });
});
IndieRok
źródło
W wersji demonstracyjnej jedno menu blokuje się po kliknięciu kilku z rzędu.
SventoryMang
@DOTang tak, myślę, że nie był idealny, stąd szybka naprawa, myślę, że trochę refaktoryzacji poprawiłoby to. Miejmy nadzieję, że zanim wyjdzie Bootstrap4,
naprawią
11

oto moje rozwiązanie dla efektu slide & fade:

   // Add slideup & fadein animation to dropdown
   $('.dropdown').on('show.bs.dropdown', function(e){
      var $dropdown = $(this).find('.dropdown-menu');
      var orig_margin_top = parseInt($dropdown.css('margin-top'));
      $dropdown.css({'margin-top': (orig_margin_top + 10) + 'px', opacity: 0}).animate({'margin-top': orig_margin_top + 'px', opacity: 1}, 300, function(){
         $(this).css({'margin-top':''});
      });
   });
   // Add slidedown & fadeout animation to dropdown
   $('.dropdown').on('hide.bs.dropdown', function(e){
      var $dropdown = $(this).find('.dropdown-menu');
      var orig_margin_top = parseInt($dropdown.css('margin-top'));
      $dropdown.css({'margin-top': orig_margin_top + 'px', opacity: 1, display: 'block'}).animate({'margin-top': (orig_margin_top + 10) + 'px', opacity: 0}, 300, function(){
         $(this).css({'margin-top':'', display:''});
      });
   });
Vedmant
źródło
Dzięki. Twój kod działa doskonale. Jednak nie do końca rozumiem, dlaczego musimy mieć $(this).css({'margin-top':''});@Vedmant
DucCuong
Ma to na celu usunięcie parametru margin-top po zakończeniu animacji, na wypadek, gdyby listy rozwijane miały dodane marginesy w niestandardowych stylach (jak w moim motywie) .Musi działać bez niego, ponieważ animuje do orig_margin_top z powrotem, ale jest czystsze, aby nie pozostawiać dodatkowych style wbudowane po zakończeniu animacji.
Vedmant
9

Zaktualizuj 2018 Bootstrap 4

W Boostrap 4 .openklasa została zastąpiona przez .show. Chciałem to zaimplementować używając tylko tranzystorów CSS bez potrzeby dodatkowego JS lub jQuery ...

.show > .dropdown-menu {
  max-height: 900px;
  visibility: visible;
}

.dropdown-menu {
  display: block;
  max-height: 0;
  visibility: hidden;
  transition: all 0.5s ease-in-out;
  overflow: hidden;
}

Demo: https://www.codeply.com/go/3i8LzYVfMF

Uwaga: max-heightmożna ustawić dowolną dużą wartość, która wystarczy, aby pomieścić zawartość rozwijanego menu.

Zim
źródło
To działa doskonale. Dla mnie nie musiałem nawet określać maksymalnej wysokości, ponieważ próbowałem osiągnąć inny efekt za pomocą margin-top.
Supreme Dolphin
Podoba mi się to, potrzebujesz tylko css bez kilku kodów js ..
aswzen
8

Po kliknięciu można to zrobić za pomocą poniższego kodu

$('.dropdown-toggle').click(function() {
  $(this).next('.dropdown-menu').slideToggle(500);
});
Abhimanyu Rana
źródło
Działa to ładnie, ale gdy stracisz koncentrację, menu pozostaje otwarte, co nie jest normalne.
Barry Michael Doyle
7

Używam powyższego kodu, ale zmieniłem efekt opóźnienia przez slideToggle.

Przesuwa menu po najechaniu kursorem z animacją.

$('.navbar .dropdown').hover(function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideToggle(400);
    }, function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideToggle(400)
    });
Augusto Triste
źródło
1
tak naprawdę nie trzeba tego definiować dwa razy. przy użyciu przełącznika będzie działać bez drugiego.
Dallas
3

Rozszerzona odpowiedź była moją pierwszą odpowiedzią, więc wymówką, jeśli wcześniej nie było wystarczająco dużo szczegółów.

W przypadku Bootstrap 3.x osobiście preferuję animacje CSS i używam animate.css i razem z hakami JavaScript w Bootstrap Dropdown. Chociaż może nie mieć dokładnie takiego efektu, jakiego szukasz, jest to dość elastyczne podejście.

Krok 1: Dodaj animate.css do swojej strony za pomocą tagów head:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.4.0/animate.min.css">

Krok 2: Użyj standardowego kodu HTML Bootstrap na wyzwalaczu:

<div class="dropdown">
  <button type="button" data-toggle="dropdown">Dropdown trigger</button>

  <ul class="dropdown-menu">
    ...
  </ul>
</div>

Krok 3: Następnie dodaj 2 niestandardowe atrybuty danych do elementu dropdrop-menu; menu rozwijane danych dla animacji wejściowej i menu rozwijane danych dla animacji wyjściowej. Mogą to być dowolne efekty animate.css, takie jak fadeIn lub fadeOut

<ul class="dropdown-menu" data-dropdown-in="fadeIn" data-dropdown-out="fadeOut">
......
</ul>

Krok 4: Następnie dodaj następujący kod JavaScript, aby odczytać atrybuty danych wchodzących / wychodzących z listy rozwijanej i reagować na zaczepy / zdarzenia interfejsu Bootstrap JavaScript API ( http://getbootstrap.com/javascript/#dropdowns-events ):

var dropdownSelectors = $('.dropdown, .dropup');

// Custom function to read dropdown data
// =========================
function dropdownEffectData(target) {
  // @todo - page level global?
  var effectInDefault = null,
      effectOutDefault = null;
  var dropdown = $(target),
      dropdownMenu = $('.dropdown-menu', target);
  var parentUl = dropdown.parents('ul.nav'); 

  // If parent is ul.nav allow global effect settings
  if (parentUl.size() > 0) {
    effectInDefault = parentUl.data('dropdown-in') || null;
    effectOutDefault = parentUl.data('dropdown-out') || null;
  }

  return {
    target:       target,
    dropdown:     dropdown,
    dropdownMenu: dropdownMenu,
    effectIn:     dropdownMenu.data('dropdown-in') || effectInDefault,
    effectOut:    dropdownMenu.data('dropdown-out') || effectOutDefault,  
  };
}

// Custom function to start effect (in or out)
// =========================
function dropdownEffectStart(data, effectToStart) {
  if (effectToStart) {
    data.dropdown.addClass('dropdown-animating');
    data.dropdownMenu.addClass('animated');
    data.dropdownMenu.addClass(effectToStart);    
  }
}

// Custom function to read when animation is over
// =========================
function dropdownEffectEnd(data, callbackFunc) {
  var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
  data.dropdown.one(animationEnd, function() {
    data.dropdown.removeClass('dropdown-animating');
    data.dropdownMenu.removeClass('animated');
    data.dropdownMenu.removeClass(data.effectIn);
    data.dropdownMenu.removeClass(data.effectOut);

    // Custom callback option, used to remove open class in out effect
    if(typeof callbackFunc == 'function'){
      callbackFunc();
    }
  });
}

// Bootstrap API hooks
// =========================
dropdownSelectors.on({
  "show.bs.dropdown": function () {
    // On show, start in effect
    var dropdown = dropdownEffectData(this);
    dropdownEffectStart(dropdown, dropdown.effectIn);
  },
  "shown.bs.dropdown": function () {
    // On shown, remove in effect once complete
    var dropdown = dropdownEffectData(this);
    if (dropdown.effectIn && dropdown.effectOut) {
      dropdownEffectEnd(dropdown, function() {}); 
    }
  },  
  "hide.bs.dropdown":  function(e) {
    // On hide, start out effect
    var dropdown = dropdownEffectData(this);
    if (dropdown.effectOut) {
      e.preventDefault();   
      dropdownEffectStart(dropdown, dropdown.effectOut);   
      dropdownEffectEnd(dropdown, function() {
        dropdown.dropdown.removeClass('open');
      }); 
    }    
  }, 
});

Krok 5 (opcjonalnie): Jeśli chcesz przyspieszyć lub zmienić animację, możesz to zrobić za pomocą CSS w następujący sposób:

.dropdown-menu.animated {
  /* Speed up animations */
  -webkit-animation-duration: 0.55s;
  animation-duration: 0.55s;
  -webkit-animation-timing-function: ease;
  animation-timing-function: ease;
}

Napisałem artykuł zawierający więcej szczegółów i plik do pobrania, jeśli ktoś jest zainteresowany: artykuł: http://bootbites.com/tutorials/bootstrap-dropdown-effects-animatecss

Mam nadzieję, że to pomocne, a ten drugi artykuł ma poziom szczegółowości potrzebny Tomowi

Tom James
źródło
3
Dobrze byłoby przynajmniej zawrzeć w odpowiedzi kilka szczegółów - samo umieszczanie linków do Twojej witryny nie jest tak naprawdę dobrą odpowiedzią.
ajshort
@GeraldSchneider zaktualizował odpowiedź, dodając więcej szczegółów. To była moja pierwsza odpowiedź na temat stackoverflow, więc doceniaj opinie.
Tom James
2
$('.navbar .dropdown').hover(function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
}, function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
});

Ten kod działa, jeśli chcesz wyświetlać listy rozwijane po najechaniu kursorem.

Właśnie zmienił .slideTogglesię .slideDowni .slideUp, i usunął (400)rozrządu

ChapDaddy65
źródło
1

Oto ładne proste rozwiązanie, jQueryktóre działa ładnie:

$('.dropdown-toggle').click(function () {
    $(this).next('.dropdown-menu').slideToggle(300);
});

$('.dropdown-toggle').focusout(function () {
    $(this).next('.dropdown-menu').slideUp(300);
})

Przełączanie animacji slajdu następuje po kliknięciu i zawsze przesuwa się w górę po utracie ostrości.

Zmień 300wartość na dowolną, im niższa liczba, tym szybsza animacja.

Edytować:

To rozwiązanie będzie działać tylko w przypadku widoków pulpitu. Będzie wymagać dalszych modyfikacji, aby ładnie wyświetlać się na urządzeniach mobilnych.

Barry Michael Doyle
źródło
To działa dla mnie, ale po przesunięciu myszy na podmenu (tj. Z dala od dropdown-toggle) ponownie znika, co oznacza, że ​​nie mogę wybrać elementów podmenu
Bassie
1

BOOTSTRAP 3 REFERENCE

Dodano, ponieważ rozwiązanie w tym wątku łapie mnie i za każdym razem mnie to napycha.

Zasadniczo lista rozwijana BS natychmiast usuwa rozszerzenie .open klasę z rodzica, więc przesuwanie się nie działa.

Użyj tego samego bitu, co inne rozwiązania dla slideDown ();

// ADD SLIDEUP ANIMATION TO DROPDOWN //
$('.dropdown').on('hide.bs.dropdown', function(e){
  e.preventDefault();
  $(this).find('.dropdown-menu').first().stop(true, true).slideUp(300, function(){
    $(this).parent().removeClass('open');
  });
});
Slipoch
źródło
1

Intro

W chwili pisania tego tekstu oryginalna odpowiedź ma 8 lat. Wciąż czuję, że nie ma jeszcze właściwego rozwiązania pierwotnego pytania.

Od tamtej pory Bootstrap przeszedł długą drogę i jest teraz na poziomie 4.5.2 . Ta odpowiedź dotyczy właśnie tej wersji.

Problem ze wszystkimi dotychczasowymi rozwiązaniami

Problem ze wszystkimi innymi odpowiedziami polega na tym, że podczas podłączania się do show.bs.dropdown/ hide.bs.dropdown, zdarzenia następcze shown.bs.dropdown/ hidden.bs.dropdownsą albo uruchamiane zbyt wcześnie (animacja nadal trwa), albo w ogóle nie odpalają, ponieważ zostały stłumione ( e.preventDefault()).

Czyste rozwiązanie

Ponieważ implementacja show()iw klasie hide()Bootstraps Dropdownma pewne podobieństwa, zgrupowałem je razem toggleDropdownWithAnimation()podczas naśladowania oryginalnego zachowania i dodałem małe funkcje pomocnicze QoL do showDropdownWithAnimation()i hideDropdownWithAnimation().
toggleDropdownWithAnimation()tworzy shown.bs.dropdown/ hidden.bs.dropdownzdarzenie w taki sam sposób, jak robi to Bootstrap. To zdarzenie jest następnie uruchamiane po zakończeniu animacji - tak, jak można się spodziewać.

/**
 * Toggle visibility of a dropdown with slideDown / slideUp animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {boolean} show Show (true) or hide (false) the dropdown menu.
 * @param {number} duration Duration of the animation in milliseconds
 */
function toggleDropdownWithAnimation($containerElement, show, duration = 300): void {
    // get the element that triggered the initial event
    const $toggleElement = $containerElement.find('.dropdown-toggle');
    // get the associated menu
    const $dropdownMenu = $containerElement.find('.dropdown-menu');
    // build jquery event for when the element has been completely shown
    const eventArgs = {relatedTarget: $toggleElement};
    const eventType = show ? 'shown' : 'hidden';
    const eventName = `${eventType}.bs.dropdown`;
    const jQueryEvent = $.Event(eventName, eventArgs);

    if (show) {
        // mimic bootstraps element manipulation
        $containerElement.addClass('show');
        $dropdownMenu.addClass('show');
        $toggleElement.attr('aria-expanded', 'true');
        // put focus on initial trigger element
        $toggleElement.trigger('focus');
        // start intended animation
        $dropdownMenu
            .stop() // stop any ongoing animation
            .hide() // hide element to fix initial state of element for slide down animation
            .slideDown(duration, () => {
            // fire 'shown' event
            $($toggleElement).trigger(jQueryEvent);
        });
    }
    else {
        // mimic bootstraps element manipulation
        $containerElement.removeClass('show');
        $dropdownMenu.removeClass('show');
        $toggleElement.attr('aria-expanded', 'false');
        // start intended animation
        $dropdownMenu
            .stop() // stop any ongoing animation
            .show() // show element to fix initial state of element for slide up animation
            .slideUp(duration, () => {

            // fire 'hidden' event
            $($toggleElement).trigger(jQueryEvent);
        });
    }
}

/**
 * Show a dropdown with slideDown animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {number} duration Duration of the animation in milliseconds
 */
function showDropdownWithAnimation($containerElement, duration = 300) {
    toggleDropdownWithAnimation($containerElement, true, duration);
}

/**
 * Hide a dropdown with a slideUp animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {number} duration Duration of the animation in milliseconds
 */
function hideDropdownWithAnimation($containerElement, duration = 300) {
    toggleDropdownWithAnimation($containerElement, false, duration);
}

Bind Event Listeners

Teraz, gdy napisaliśmy odpowiednie wywołania zwrotne do pokazywania / ukrywania listy rozwijanej z animacją, powiążmy je z odpowiednimi zdarzeniami.

Częstym błędem, który widziałem wiele w innych odpowiedziach, jest bezpośrednie wiązanie detektorów zdarzeń z elementami. Chociaż działa to dobrze w przypadku elementów DOM obecnych w momencie rejestracji detektora zdarzeń, nie wiąże się to z elementami dodanymi później.

Dlatego generalnie lepiej jest wiązać bezpośrednio z document:

$(function () {

    /* Hook into the show event of a bootstrap dropdown */
    $(document).on('show.bs.dropdown', '.dropdown', function (e) {
        // prevent bootstrap from executing their event listener
        e.preventDefault();
        
        showDropdownWithAnimation($(this));
    });

    /* Hook into the hide event of a bootstrap dropdown */
    $(document).on('hide.bs.dropdown', '.dropdown', function (e) {
        // prevent bootstrap from executing their event listener
        e.preventDefault();
          
        hideDropdownWithAnimation($(this));
    });

});
Tobias Wicker
źródło
0

W przypadku Bootstrap 3 ta odmiana powyższych odpowiedzi sprawia, że slideUp()animacja mobilna jest płynniejsza; powyższe odpowiedzi mają przerywaną animację, ponieważ Bootstrap .opennatychmiast usuwa klasę z elementu nadrzędnego przełącznika, więc ten kod przywraca klasę do zakończenia slideUp()animacji.

// Add animations to topnav dropdowns
// based on https://stackoverflow.com/a/19339162
// and https://stackoverflow.com/a/52231970

$('.dropdown')
  .on('show.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown(300);
  })
  .on('hide.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, false).slideUp(300, function() {
      $(this).parent().removeClass('open');
    });
  })
  .on('hidden.bs.dropdown', function() {
    $(this).addClass('open');
  });

Kluczowe różnice:

  • W programie hide.bs.dropdownobsługi zdarzeń używam .stop()domyślnej wartości ( false) jako drugiego argumentu (jumpToEnd )
  • Procedura hidden.bs.dropdownobsługi zdarzeń przywraca .openklasę do elementu nadrzędnego przełącznika rozwijanego i robi to prawie natychmiast po pierwszym usunięciu klasy. W międzyczasie slideUp()animacja nadal działa i tak jak w odpowiedziach powyżej, jej wywołanie zwrotne „animacja-zakończona” jest odpowiedzialne za ostateczne usunięcie .openklasy z jej rodzica.
  • Metody są połączone w łańcuch, ponieważ selektor dla każdego programu obsługi zdarzeń jest taki sam
Jordan Bradford
źródło