Jak ustawić menu rozwijane Twitter Bootstrap po najechaniu myszą, a nie kliknięciu

1181

Chciałbym, aby moje menu Bootstrap automatycznie opuszczało się po najechaniu myszą, zamiast konieczności klikania tytułu menu. Chciałbym również zgubić małe strzałki obok tytułów menu.

wahać się
źródło
9
Jest na to rozwiązanie, więc odpowiedź mikko jest poprawna, ale teraz zawiera wtyczkę do konkretnej sytuacji. bootstrap-hover-dropdown
HenryW
2
Zobacz moją nowo opublikowaną odpowiednią wtyczkę, która zapobiega problemom z poniższymi rozwiązaniami CSS i js, i działa dobrze na iOS i na nowoczesnych przeglądarkach stacjonarnych ze zdarzeniami dotykowymi. Nawet atrybuty arii działają dobrze z tym: github.com/istvan-ujjmeszaros/bootstrap-dropdown-hover
István Ujj-Mészáros
Zrobiłem czysty rozwijany CSS3 z paskiem nawigacyjnym bootstrap sprawdź to na CodePen Pure CSS3 rozwijany
Gothburz
18
Pomyśl dwa razy, jeśli naprawdę tego potrzebujesz? Bootstrap używa do witryn adaptacyjnych. Oznacza to, że będą one również używane na urządzeniach z dotykowym sterowaniem. Dlatego został zaprojektowany w ten sposób. Na ekranach dotykowych nie ma „aktywowania”.
Serj.by
Możliwy duplikat listy rozwijanej Bootstrap z Hover
slugster

Odpowiedzi:

590

Stworzyłem menu rozwijane wyłącznie po najechaniu kursorem w oparciu o najnowszą (v2.0.2) platformę Bootstrap, która obsługuje wiele podmenu i pomyślałem, że opublikuję ją dla przyszłych użytkowników:

body {
  padding-top: 60px;
  padding-bottom: 40px;
}

.sidebar-nav {
  padding: 9px 0;
}

.dropdown-menu .sub-menu {
  left: 100%;
  position: absolute;
  top: 0;
  visibility: hidden;
  margin-top: -1px;
}

.dropdown-menu li:hover .sub-menu {
  visibility: visible;
}

.dropdown:hover .dropdown-menu {
  display: block;
}

.nav-tabs .dropdown-menu,
.nav-pills .dropdown-menu,
.navbar .dropdown-menu {
  margin-top: 0;
}

.navbar .sub-menu:before {
  border-bottom: 7px solid transparent;
  border-left: none;
  border-right: 7px solid rgba(0, 0, 0, 0.2);
  border-top: 7px solid transparent;
  left: -7px;
  top: 10px;
}

.navbar .sub-menu:after {
  border-top: 6px solid transparent;
  border-left: none;
  border-right: 6px solid #fff;
  border-bottom: 6px solid transparent;
  left: 10px;
  top: 11px;
  left: -6px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet" />

<div class="navbar navbar-fixed-top">
  <div class="navbar-inner">
    <div class="container-fluid">
      <a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </a>
      <a href="#" class="brand">Project name</a>
      <div class="nav-collapse">
        <ul class="nav">
          <li class="active"><a href="#">Home</a></li>
          <li><a href="#">Link</a></li>
          <li><a href="#">Link</a></li>
          <li><a href="#">Link</a></li>
          <li class="dropdown">
            <a data-toggle="dropdown" class="dropdown-toggle" href="#">Dropdown <b class="caret"></b></a>
            <ul class="dropdown-menu">
              <li>
                <a href="#">2-level Dropdown <i class="icon-arrow-right"></i></a>
                <ul class="dropdown-menu sub-menu">
                  <li><a href="#">Action</a></li>
                  <li><a href="#">Another action</a></li>
                  <li><a href="#">Something else here</a></li>
                  <li class="divider"></li>
                  <li class="nav-header">Nav header</li>
                  <li><a href="#">Separated link</a></li>
                  <li><a href="#">One more separated link</a></li>
                </ul>
              </li>
              <li><a href="#">Another action</a></li>
              <li><a href="#">Something else here</a></li>
              <li class="divider"></li>
              <li class="nav-header">Nav header</li>
              <li><a href="#">Separated link</a></li>
              <li><a href="#">One more separated link</a></li>
            </ul>
          </li>
        </ul>
        <form action="" class="navbar-search pull-left">
          <input type="text" placeholder="Search" class="search-query span2">
        </form>
        <ul class="nav pull-right">
          <li><a href="#">Link</a></li>
          <li class="divider-vertical"></li>
          <li class="dropdown">
            <a class="#" href="#">Menu</a>
          </li>
        </ul>
      </div>
      <!-- /.nav-collapse -->
    </div>
  </div>
</div>

<hr>

<ul class="nav nav-pills">
  <li class="active"><a href="#">Regular link</a></li>
  <li class="dropdown">
    <a href="#" data-toggle="dropdown" class="dropdown-toggle">Dropdown <b class="caret"></b></a>
    <ul class="dropdown-menu" id="menu1">
      <li>
        <a href="#">2-level Menu <i class="icon-arrow-right"></i></a>
        <ul class="dropdown-menu sub-menu">
          <li><a href="#">Action</a></li>
          <li><a href="#">Another action</a></li>
          <li><a href="#">Something else here</a></li>
          <li class="divider"></li>
          <li class="nav-header">Nav header</li>
          <li><a href="#">Separated link</a></li>
          <li><a href="#">One more separated link</a></li>
        </ul>
      </li>
      <li><a href="#">Another action</a></li>
      <li><a href="#">Something else here</a></li>
      <li class="divider"></li>
      <li><a href="#">Separated link</a></li>
    </ul>
  </li>
  <li class="dropdown">
    <a href="#">Menu</a>
  </li>
  <li class="dropdown">
    <a href="#">Menu</a>
  </li>
</ul>

Próbny

Andres Ilich
źródło
54
decyzja bootstrap o podjęciu decyzji o tym, aby nie otwierać
list
18
tak dobrze! Usunąłem również class="dropdown-toggle" data-toggle="dropdown", aby tylko najechanie kursorem myszy, a nie kliknięcie, uruchomiło menu. Zwróć uwagę, że gdy używasz responsywnych stylów, menu wciąż są przesuwane do małego przycisku w prawym górnym rogu, który jest nadal uruchamiany przez kliknięcie. Wielkie dzięki!
ptim
11
Aby uniknąć automatycznego rozwijania się na mniejszych urządzeniach (takich jak telefony) i pozwolić tylko na minimalną szerokość np. 768px do @media (min-width: 768px) {.dropdown-menu li:hover .sub-menu {visibility: visible;}}i@media (min-width: 768px) {.dropdown:hover .dropdown-menu {display: block;}}
Chris Aelbrecht
1
Również, aby link do dzieci był klikalny, musisz usunąć „data-toggle = 'dropdown'” na znaczniku <a>.
joan16v
2
Oto kod, który działa z najnowszą wersją Bootstrap 3: jsfiddle.net/sgruenwald/2tt8f8xg
Stefan Gruenwald
910

Aby menu było automatycznie upuszczane po najechaniu myszą, można to osiągnąć za pomocą podstawowego CSS. Musisz wypracować selektor do ukrytej opcji menu, a następnie ustawić go tak, aby wyświetlał się jako blok po linajechaniu kursorem na odpowiedni znacznik. Biorąc przykład ze strony startowej Twittera, selektor wyglądałby następująco:

ul.nav li.dropdown:hover > ul.dropdown-menu {
    display: block;    
}

Jeśli jednak używasz responsywnych funkcji Bootstrap, nie będziesz chciał tej funkcji na zwiniętym pasku nawigacyjnym (na mniejszych ekranach). Aby tego uniknąć, zawiń powyższy kod w zapytaniu o media:

@media (min-width: 979px) {
  ul.nav li.dropdown:hover > ul.dropdown-menu {
    display: block;
  }
}

Aby ukryć strzałkę (karetkę), robi się to na różne sposoby, w zależności od tego, czy używasz Twitter Bootstrap w wersji 2 i niższej czy w wersji 3:

Bootstrap 3

Aby usunąć daszek w wersji 3, wystarczy usunąć HTML <b class="caret"></b>z .dropdown-toggleelementu zakotwiczenia:

<a class="dropdown-toggle" data-toggle="dropdown" href="#">
    Dropdown
    <b class="caret"></b>    <-- remove this line
</a>

Bootstrap 2 i niższe

Aby usunąć daszek w wersji 2, potrzebujesz trochę więcej wglądu w CSS i sugeruję przyjrzeć się :afterbardziej szczegółowo działaniu pseudoelementu. Aby rozpocząć pracę na drodze do zrozumienia, celowania i usuwania strzałek w przykładzie bootowania na Twitterze, użyj następującego selektora CSS i kodu:

a.menu:after, .dropdown-toggle:after {
    content: none;
}

Będzie to działało na twoją korzyść, jeśli przyjrzysz się bliżej ich działaniu, a nie tylko skorzystasz z odpowiedzi, które ci dałem.

Podziękowania dla @CocaAkat za zwrócenie uwagi, że brakuje nam dziecinnego kombinatora „>”, aby zapobiec wyświetlaniu podmenu w oknie nadrzędnym

Boli mnie głowa
źródło
79
Musiałem także dodać margin: 0;, w przeciwnym razie powyższy margines 1px .dropdown-menuspowoduje nieprawidłowe działanie.
Salman von Abbas,
12
Proste rozwiązanie, ale łącza nadrzędnego nadal nie można kliknąć. Używam najnowszego bootstrapu z motywem root.
Krunal,
5
Uwaga: Tak, działa - zadziała w każdej przeglądarce obsługiwanej przez Twitter Bootstrap. @GeorgeEdison To jest podstawowy CSS - która część nie byłaby obsługiwana przez IE8? Jeśli masz problemy, opublikuj pytanie, a nie wprowadzające w błąd komentarze.
Moja głowa boli
3
@MyHeadHurts: Po kilku dalszych badaniach - okazało się, że był to rzeczywiście błąd Bootstrap i został naprawiony dopiero pięć dni temu.
Nathan Osman,
5
@Krunal, aby móc kliknąć link, musisz usunąć data-toggle="dropdown"atrybut.
Pherrymason
230

Oprócz odpowiedzi z „My Head Hurts” (co było świetne):

ul.nav li.dropdown:hover ul.dropdown-menu{
    display: block;    
}

Istnieją 2 problemy z utrzymaniem się:

  1. Kliknięcie łącza rozwijanego spowoduje otwarcie menu rozwijanego. I pozostanie otwarty, dopóki użytkownik nie kliknie gdzieś indziej lub nie zatrzyma się nad nim, tworząc niezręczny interfejs użytkownika.
  2. Między linkiem rozwijanym a menu rozwijanym jest margines 1px. Powoduje to ukrycie menu rozwijanego, jeśli powoli poruszasz się między menu rozwijanym a menu rozwijanym.

Rozwiązaniem (1) jest usunięcie elementów „class” i „data-toggle” z linku nawigacyjnego

<a href="#">
     Dropdown
     <b class="caret"></b>
</a>

Daje to również możliwość utworzenia linku do strony nadrzędnej - co nie było możliwe przy domyślnej implementacji. Możesz po prostu zastąpić „#” dowolną stroną, którą chcesz wysłać użytkownikowi.

Rozwiązaniem (2) jest usunięcie marginesu na selektorze menu .dropdown

.navbar .dropdown-menu {
    margin-top: 0px;
}
Cena Cory
źródło
15
Aby naprawić celowe kliknięcie, właśnie usunąłem data-toggle="dropdown"atrybut, który wydawał się działać.
Anthony Briggs
5
Rozwiązanie (2) dla przycisków nawigacyjnych:.nav-pills .dropdown-menu { margin-top: 0px; }
Loren,
1
Aby rozwiązać problem, o którym wspomniałem powyżej li.dropdown: hover> ul.dropdown-menu
Archimedes Trajano
12
usuwając „klasa” i „data-Przełącz” atrybuty z nav linki uczynić go zatrzymać grzywnę pracy w mobilnych i tabletów :(
Mosijava
1
Jeśli usunąłeś atrybut data-toggle = "menu rozwijane", nie będziesz w stanie rozwinąć menu rozwijanego za pomocą klawiatury. Nie będzie więc zgodny z 508. Jak możesz wyłączyć kliknięcie, ale zachować funkcjonalność klawiatury?
duyn9uyen
130

Użyłem trochę jQuery:

// Add hover effect to menus
jQuery('ul.nav li.dropdown').hover(function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn();
}, function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut();
});
John Montgomery
źródło
13
Lubię to. W każdym razie korzystam z JQuery z funkcjami Bootstrap i nadal pozwala na domyślną funkcję „klikania” w urządzeniach z ekranem dotykowym.
Duck in Custard
Użyłem tego. Podoba mi się, że nadal pozwala na funkcję kliknięcia, również na telefony komórkowe, ale dla komputerów stacjonarnych hover jest idealny.
Stuart
1
Użyłem tego, ale rozszerzyłem go również o rozwijane menu, które nie są w nawigacji. Dodaję klasy dropdown-hover do div btn-group i użyłem tej wyszukiwarki jQuery $ ('ul.nav li.dropdown, .dropdown-hover'). Hover (funkcja () {. Dzięki!
Brandon
Użyłem tego, miłego i małego. Wersja css nie pozwalała na wyświetlanie podmenu, a $('ul.nav li.dropdown').hover(function() { $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn(); }, function() { $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut().hover(function() { $(this).stop(true, true); }); });200 ms było zbyt szybkie, więc zmieniłem go na : Kiedy podmenu jest zatrzymane, zatrzymaj zanikanie
Damien
wydaje się, że to nie działa z jqLite, który jest dołączony do anguraljs
nuander
70

Tutaj jest wiele naprawdę dobrych rozwiązań. Ale pomyślałem, że pójdę naprzód i postawię tu moją jako kolejną alternatywę. Jest to prosty fragment kodu jQuery, który robi to tak, jak bootstrap, gdyby obsługiwał najechanie kursorem zamiast list rozwijanych. Przetestowałem to tylko z wersją 3, więc nie wiem, czy będzie działać z wersją 2. Zapisz go jako fragment kodu w swoim edytorze i trzymaj go za naciśnięciem klawisza.

<script>
    $(function() {
        $(".dropdown").hover(
            function(){ $(this).addClass('open') },
            function(){ $(this).removeClass('open') }
        );
    });
</script>

Zasadniczo mówi tylko, że kiedy najedziesz kursorem na rozwijaną klasę, doda do niej klasę otwartą. To po prostu działa. Kiedy przestaniesz unosić się nad rodzimym li z rozwijaną klasą lub potomnymi ul / li, usuwa ono klasę otwartą. Oczywiście jest to tylko jedno z wielu rozwiązań i można do niego dodać, aby działało tylko w określonych przypadkach .dropdown. Lub dodaj przejście do rodzica lub dziecka.

stereoscience
źródło
2
Świetne rozwiązanie! Usunąłem również atrybut data-toggle = "dropdown" z linku, aby umożliwić kliknięcie górnego linku.
Sergey
To dobra wskazówka, Siergiej. Zawsze upewniam się, że górny link nie prowadzi do nikąd, więc działa również na tabletach i telefonach.
stereoscience
1
@Sergey Nie polecam tego robić. Zepsułbyś funkcjonalność użytkownikom mobilnym. Nie mogą użyć funkcji aktywowania, aby otworzyć menu i muszą mieć możliwość kliknięcia.
Paul
2
Jest to niezwykle krótkie i łatwe, a jednocześnie kompatybilne wstecz z ekranami dotykowymi. Powinny być oceniane znacznie więcej.
Maks.
To wygląda naprawdę dobrze. Masz pomysł, jak dodać trochę animacji za pomocą przejść CSS?
Fred Rocha,
69

Po prostu dostosuj swój styl CSS w trzech liniach kodu

.dropdown:hover .dropdown-menu {
   display: block;
}
Ranjith
źródło
22

Jeśli masz element z taką dropdownklasą (na przykład):

<ul class="list-unstyled list-inline">
    <li class="dropdown">
        <a data-toggle="dropdown" href="#"><i class="fa fa-bars"></i> Dropdown 1</a>
        <ul class="dropdown-menu">
            <li><a href="">Item 1</a></li>
            <li><a href="">Item 2</a></li>
            <li><a href="">Item 3</a></li>
            <li><a href="">Item 4</a></li>
            <li><a href="">Item 5</a></li>
        </ul>
    </li>
    <li class="dropdown">
        <a data-toggle="dropdown" href="#"><i class="fa fa-user"></i> Dropdown 2</a>
        <ul class="dropdown-menu">
            <li><a href="">Item A</a></li>
            <li><a href="">Item B</a></li>
            <li><a href="">Item C</a></li>
            <li><a href="">Item D</a></li>
            <li><a href="">Item E</a></li>
        </ul>
    </li>
</ul>

Następnie możesz ustawić menu rozwijane, aby było automatycznie rozwijane po najechaniu myszą, zamiast klikania jego tytułu, za pomocą tego fragmentu kodu jQuery:

<script>
    $('.dropdown').hover(
        function() {
            $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn();
        },
        function() {
            $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut();
        }
    );

    $('.dropdown-menu').hover(
        function() {
            $(this).stop(true, true);
        },
        function() {
            $(this).stop(true, true).delay(200).fadeOut();
        }
    );
</script>

Oto demo

Ta odpowiedź polegała na odpowiedzi @Michael. Wprowadziłem pewne zmiany i dodałem kilka dodatków, aby menu rozwijane działało poprawnie

Amr
źródło
Doskonały. Wielkie dzięki.
antikbd
20

[Aktualizacja] Wtyczka działa na GitHub i pracuję nad kilkoma ulepszeniami (np. Używaj tylko z atrybutami danych (nie wymaga JS). Zostawiłem poniższy kod, ale nie jest taki sam jak na GitHub.

Podobała mi się wersja czysto CSS, ale miło jest mieć opóźnienie, zanim się zamknie, ponieważ zwykle jest to lepsze doświadczenie użytkownika (tj. Nie jest karane za poślizg myszy, który wychodzi 1 px poza listę rozwijaną itp.), I jak wspomniano w komentarzach , masz 1 piksel marginesu, z którym masz do czynienia, lub czasami nawigacja zamyka się nieoczekiwanie, gdy przechodzisz do menu rozwijanego od oryginalnego przycisku itp.

Stworzyłem szybką, małą wtyczkę, której używałem na kilku stronach i działa dobrze. Każdy element nawigacyjny jest obsługiwany niezależnie, więc mają własne liczniki opóźnień itp.

JS

// outside the scope of the jQuery plugin to
// keep track of all dropdowns
var $allDropdowns = $();

// if instantlyCloseOthers is true, then it will instantly
// shut other nav items when a new one is hovered over
$.fn.dropdownHover = function(options) {

    // the element we really care about
    // is the dropdown-toggle's parent
    $allDropdowns = $allDropdowns.add(this.parent());

    return this.each(function() {
        var $this = $(this).parent(),
            defaults = {
                delay: 500,
                instantlyCloseOthers: true
            },
            data = {
                delay: $(this).data('delay'),
                instantlyCloseOthers: $(this).data('close-others')
            },
            options = $.extend(true, {}, defaults, options, data),
            timeout;

        $this.hover(function() {
            if(options.instantlyCloseOthers === true)
                $allDropdowns.removeClass('open');

            window.clearTimeout(timeout);
            $(this).addClass('open');
        }, function() {
            timeout = window.setTimeout(function() {
                $this.removeClass('open');
            }, options.delay);
        });
    });
};  

delayParametr jest dość oczywista, a instantlyCloseOthersnatychmiast zamknąć wszystkie inne Dropdowns które są otwarte po najechaniu na nową.

Nie czysty CSS, ale mam nadzieję, że pomoże komuś innemu o tak późnej porze (tj. Jest to stary wątek).

Jeśli chcesz, możesz zobaczyć różne procesy, przez które przeszedłem (w dyskusji na #concrete5IRC), aby zmusić go do działania, wykonując różne kroki w tej liście: https://gist.github.com/3876924

Podejście do schematu wtyczek jest znacznie bardziej przejrzyste, aby obsługiwać indywidualne liczniki itp.

Zobacz post na blogu, aby uzyskać więcej.

CWSpear
źródło
16

To działało dla mnie:

.dropdown:hover .dropdown-menu {
    display: block;
}
Amay Kulkarni
źródło
1
Jednak z telefonem komórkowym - to dziwne.
Radmation,
Margines między menu a menu rozwijanym czyni to bezużytecznym.
antikbd
15

Jest to wbudowane w Bootstrap 3. Po prostu dodaj to do swojego CSS:

.dropdown:hover .dropdown-menu {
    display: block;
}
BSUK
źródło
10

Jeszcze lepiej z jQuery:

jQuery('ul.nav li.dropdown').hover(function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).show();
  jQuery(this).addClass('open');
}, function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).hide();
  jQuery(this).removeClass('open');
});
caarlos0
źródło
3
Zmieniłem twój kod na, jQuery('ul.nav li.dropdown').hover(function() { jQuery(this).closest('.dropdown-menu').stop(true, true).show(); jQuery(this).addClass('open'); }, function() { jQuery(this).closest('.dropdown-menu').stop(true, true).hide(); jQuery(this).removeClass('open'); });aby podmenu nie było wyświetlane po najechaniu myszą.
farjam
Ten kod nie będzie już działał z najnowszymi wydaniami.
Paul
9

Możesz użyć domyślnej $().dropdown('toggle')metody, aby przełączyć menu rozwijane po najechaniu myszką:

$(".nav .dropdown").hover(function() {
  $(this).find(".dropdown-toggle").dropdown("toggle");
});
sdvnksv
źródło
9

Chcę tylko dodać, że jeśli masz wiele list rozwijanych (tak jak ja), powinieneś napisać:

ul.nav li.dropdown:hover > ul.dropdown-menu {
    display: block;    
}

I będzie działać poprawnie.

Maxim Filippov
źródło
Moje menu .dropdown miało na margin: 2px 0 0;myśli powolną mysz Wprowadzanie z góry przedwcześnie ukrywało menu. ul.dropdown-menu{ margin-top: 0; }
Alastair
8

Moim zdaniem najlepszy sposób jest taki:

;(function($, window, undefined) {
    // Outside the scope of the jQuery plugin to
    // keep track of all dropdowns
    var $allDropdowns = $();

    // If instantlyCloseOthers is true, then it will instantly
    // shut other nav items when a new one is hovered over
    $.fn.dropdownHover = function(options) {

        // The element we really care about
        // is the dropdown-toggle's parent
        $allDropdowns = $allDropdowns.add(this.parent());

        return this.each(function() {
            var $this = $(this),
                $parent = $this.parent(),
                defaults = {
                    delay: 500,
                    instantlyCloseOthers: true
                },
                data = {
                    delay: $(this).data('delay'),
                    instantlyCloseOthers: $(this).data('close-others')
                },
                settings = $.extend(true, {}, defaults, options, data),
                timeout;

            $parent.hover(function(event) {

                // So a neighbor can't open the dropdown
                if(!$parent.hasClass('open') && !$this.is(event.target)) {
                    return true;
                }

                if(settings.instantlyCloseOthers === true)
                    $allDropdowns.removeClass('open');

                window.clearTimeout(timeout);
                $parent.addClass('open');
            }, function() {
                timeout = window.setTimeout(function() {
                    $parent.removeClass('open');
                }, settings.delay);
            });

            // This helps with button groups!
            $this.hover(function() {
                if(settings.instantlyCloseOthers === true)
                    $allDropdowns.removeClass('open');

                window.clearTimeout(timeout);
                $parent.addClass('open');
            });

            // Handle submenus
            $parent.find('.dropdown-submenu').each(function(){
                var $this = $(this);
                var subTimeout;
                $this.hover(function() {
                    window.clearTimeout(subTimeout);
                    $this.children('.dropdown-menu').show();

                    // Always close submenu siblings instantly
                    $this.siblings().children('.dropdown-menu').hide();
                }, function() {
                    var $submenu = $this.children('.dropdown-menu');
                    subTimeout = window.setTimeout(function() {
                        $submenu.hide();
                    }, settings.delay);
                });
            });
        });
    };

    $(document).ready(function() {
        // apply dropdownHover to all elements with the data-hover="dropdown" attribute
        $('[data-hover="dropdown"]').dropdownHover();
    });
})(jQuery, this);

Przykładowy znacznik:

<li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" data-delay="1000" data-close-others="false">
        Account <b class="caret"></b>
    </a>
    <ul class="dropdown-menu">
        <li><a tabindex="-1" href="#">My Account</a></li>
        <li class="divider"></li>
        <li><a tabindex="-1" href="#">Change Email</a></li>
        <li><a tabindex="-1" href="#">Change Password</a></li>
        <li class="divider"></li>
        <li><a tabindex="-1" href="#">Logout</a></li>
    </ul>
</li>
Alex
źródło
5
To dzieło Camerona Speara, pomyślałem, że dam mu wykrzyknik: cameronspear.com/blog/bootstrap-dropdown-on-hover-plugin
kelpie
8

Najlepszym sposobem jest wywołanie zdarzenia kliknięcia Bootstrap za pomocą najechania kursorem. W ten sposób powinien pozostać przyjazny dla urządzenia dotykowego.

$('.dropdown').hover(function(){ 
  $('.dropdown-toggle', this).trigger('click'); 
});
Mark Williams
źródło
Niepożądany wynik: kliknięcie myszką, kliknięcie i myszy spowoduje pozostawienie menu otwartego. Nie tego chcę ...
Wietse,
Korzystając z tego, uruchamia funkcję ładowania początkowego, aby otworzyć menu rozwijane. Ta funkcja robi wiele innych rzeczy, takich jak aria-expanded = "true"
Farhad Sakhaei
7

Udało mi się to w następujący sposób:

$('ul.nav li.dropdown').hover(function(){
       $(this).children('ul.dropdown-menu').slideDown(); 
    }, function(){
       $(this).children('ul.dropdown-menu').slideUp(); 
});

Mam nadzieję, że to pomoże komuś ...

Mehdi Maghrooni
źródło
5

Dodano także margin-top: 0, aby zresetować margines css ładowania początkowego dla .dropdown-menu, aby lista menu nie znikała, gdy użytkownik powoli unosi się z rozwijanego menu do listy menu.

ul.nav li.dropdown:hover > ul.dropdown-menu {
    display: block;    
}

.nav .dropdown-menu {
    margin-top: 0;
}
Sudharshan
źródło
2
to jest poprawna odpowiedź, bootstrap jest gotowy do najechania kursorem na rozwijanym menu, jeśli mysz nie wyjdzie poza menu rozwijane. Usunięcie marginesu pozwala przejść od linku do menu bez przerwy, a więc bez automatycznego zamykania menu. To rozwiązanie pozwala zachować prawidłowe działanie urządzeń dotykowych
Nicolas Janel,
5

Jest to prawdopodobnie głupi pomysł, ale aby usunąć strzałkę skierowaną w dół, możesz usunąć

<b class="caret"></b>

To jednak nic nie robi dla osoby wskazującej w górę ...

stinaq
źródło
5

Opublikowałem odpowiednią wtyczkę dla funkcji rozwijania menu rozwijanego Bootstrap 3, w której możesz nawet zdefiniować, co dzieje się po kliknięciu dropdown-toggleelementu (kliknięcie można wyłączyć):

https://github.com/istvan-ujjmeszaros/bootstrap-dropdown-hover


Dlaczego to zrobiłem, skoro jest już wiele rozwiązań?

Miałem problemy ze wszystkimi poprzednimi rozwiązaniami. Proste CSS nie używają tej .openklasy na .dropdown, więc nie będzie opinii na temat elementu przełączającego rozwijanego, gdy menu rozwijane jest widoczne.

Te js przeszkadzają w kliknięciu .dropdown-toggle , więc menu pojawia się po najechaniu myszką, a następnie ukrywa je po kliknięciu otwartego menu rozwijanego, a wysunięcie myszy spowoduje wyświetlenie menu rozwijanego. Niektóre rozwiązania js łamią kompatybilność z iOS, niektóre wtyczki nie działają w nowoczesnych przeglądarkach komputerowych, które obsługują zdarzenia dotykowe.

Dlatego stworzyłem wtyczkę Bootstrap Dropdown Hover, która zapobiega wszystkim tym problemom, używając tylko standardowego interfejsu API javascript Bootstrap, bez żadnego włamania . Nawet atrybuty Aria działają dobrze z tą wtyczką.

István Ujj-Mészáros
źródło
Co sądzisz o github.com/vadikom/smartmenus ? Nie mogę się zdecydować, obie biblioteki wydają się być naprawdę dobre.
Csaba Toth
2
Smartmenus wygląda naprawdę dobrze, może być lepszy dla menu. Moja wtyczka jest tylko małym dodatkiem do menu rozwijanych bootstrap, nie ogranicza się do otwierania menu po najechaniu myszką, podczas gdy smartmenu obsługuje również podmenu i robi inne wymyślne rzeczy.
István Ujj-Mészáros
1
Dzięki. Widzę, że kod smartmenu jest bardzo obszerny i jest też dużo CSS. Do tej pory poszedłem z bootstrap-dropdown-hover, ponieważ wydaje się, że wykonuje pracę i jest bardziej kompaktowy. Buduję lądowisko z lewym paskiem nawigacyjnym.
Csaba Toth
4

Użyj tego kodu, aby otworzyć podmenu po najechaniu myszką (tylko na komputerze):

$('ul.nav li.dropdown').hover(function () {
    if ($(window).width() > 767) {
        $(this).find('.dropdown-menu').show();
    }
}, function () {
    if ($(window).width() > 767) {
        $(this).find('.dropdown-menu').hide().css('display','');
    }
});

A jeśli chcesz, aby menu pierwszego poziomu było klikalne, nawet na urządzeniach mobilnych dodaj:

    $('.dropdown-toggle').click(function() {
    if ($(this).next('.dropdown-menu').is(':visible')) {
        window.location = $(this).attr('href');
    }
});

Podmenu (menu rozwijane) zostanie otwarte po najechaniu myszką na pulpicie oraz kliknięciu / dotknięciu na telefonie komórkowym i tablecie. Po otwarciu podmenu drugie kliknięcie pozwoli otworzyć link. Dzięki temu if ($(window).width() > 767)podmenu zajmie pełną szerokość ekranu na urządzeniach mobilnych.

Jibato
źródło
Chciałbym użyć twojego kodu, ale mam problem z poprawnym działaniem. Po pierwsze, jak usunąć hover () na komórki i używać go tylko na komputery? Kiedy używam twojego kodu i zmieniam rozmiar okna na urządzenie mobilne, otrzymuję zarówno funkcję hover (), jak i click (). Ale jeszcze bardziej dziwne ... to, że to zachowanie się zatrzyma Kiedy odświeżę przeglądarkę, ha! Czy możesz mi pokazać, jak to naprawić? Potrzebuję podmenu pulpitu, aby wyświetlić na hover () i kliknij (), aby wyświetlić podmenu na telefonie komórkowym bez konieczności odświeżania przeglądarki nawet przy zmianie rozmiaru okna, aby działał poprawnie. Mam nadzieję, że to jasne
Chris22
ok, to ma sens, a ja postaram się uruchomić twoje rozwiązanie zgodnie z zaleceniami. Dzięki!
Chris22,
Użyj tej najlepszej metody: @falter
Farhad Sakhaei
4
$('.dropdown').hover(function(e){$(this).addClass('open')})
Савостьянов Максим
źródło
1
Podaj kilka szczegółów swojej odpowiedzi.
Arnold Daniels
3

To ukryje te

.navbar .dropdown-menu:before {
   display:none;
}
.navbar .dropdown-menu:after {
   display:none;
}
allochi
źródło
3

To powinno ukryć listy rozwijane i ich opiekę, jeśli są mniejsze niż tablet.

@media (max-width: 768px) {
    .navbar ul.dropdown-menu, .navbar li.dropdown b.caret {
        display: none;
    }
}
Kevin Nuut
źródło
Dlaczego chcesz to ukryć? Teraz użytkownicy mobilni nie mają dostępu do linków znajdujących się w podmenu. Lepiej wyłączyć efekt aktywowania na urządzeniu mobilnym i pozostawić menu rozwijane nienaruszone. W ten sposób mogą go otworzyć, klikając go.
Paul
3

Rozwiązanie jQuery jest dobre, ale będzie musiało poradzić sobie ze zdarzeniami związanymi z kliknięciem (na telefonie komórkowym lub tablecie), ponieważ hover nie będzie działał poprawnie ... Może może wykryć zmianę rozmiaru okna?

Odpowiedź Andresa Ilicha wydaje się działać dobrze, ale należy ją zawrzeć w zapytaniu medialnym:

@media (min-width: 980px) {

    .dropdown-menu .sub-menu {
        left: 100%;
        position: absolute;
        top: 0;
        visibility: hidden;
        margin-top: -1px;
    }

    .dropdown-menu li:hover .sub-menu {
        visibility: visible;
    }

    .dropdown:hover .dropdown-menu {
        display: block;
    }

    .nav-tabs .dropdown-menu, .nav-pills .dropdown-menu, .navbar .dropdown-menu {
        margin-top: 0;
    }

    .navbar .sub-menu:before {
        border-bottom: 7px solid transparent;
        border-left: none;
        border-right: 7px solid rgba(0, 0, 0, 0.2);
        border-top: 7px solid transparent;
        left: -7px;
        top: 10px;
    }
    .navbar .sub-menu:after {
        border-top: 6px solid transparent;
        border-left: none;
        border-right: 6px solid #fff;
        border-bottom: 6px solid transparent;
        left: 10px;
        top: 11px;
        left: -6px;
    }
}
Fizex
źródło
3

Bardzo proste rozwiązanie dla wersji 2, tylko CSS. Zachowuje tę samą przyjazną funkcjonalność dla telefonu komórkowego i tabletu.

@media (min-width: 980px) {
    .dropdown:hover .dropdown-menu {
       display: block;
    }
}
Kash
źródło
Nie działa to świetnie w przypadku niektórych motywów, w których istnieje luka między pozycją menu a menu rozwijanym. Menu zniknie, gdy mysz znajdzie się w tej szczelinie.
ndbroadbent
2

Zastąp bootstrap.js tym skryptem.

jQuery(document).ready(function ($) {
$('.navbar .dropdown').hover(function() {
    $(this).addClass('extra-nav-class').find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
}, function() {
    var na = $(this)
    na.find('.dropdown-menu').first().stop(true, true).delay(100).slideUp('fast', function(){ na.removeClass('extra-nav-class') })
});

$('.dropdown-submenu').hover(function() {
    $(this).addClass('extra-nav-class').find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
}, function() {
    var na = $(this)
    na.find('.dropdown-menu').first().stop(true, true).delay(100).slideUp('fast', function(){ na.removeClass('extra-nav-class') })
});

}); 
Hari Krishnan
źródło
2

Oto moja technika, która dodaje niewielkie opóźnienie przed zamknięciem menu po zatrzymaniu najechania na menu lub przycisku przełączania. <button>Które normalnie kliknij, aby wyświetlić menu NAV #nav_dropdown.

$(function() {
  var delay_close_it, nav_menu_timeout, open_it;
  nav_menu_timeout = void 0;
  open_it = function() {
    if (nav_menu_timeout) {
      clearTimeout(nav_menu_timeout);
      nav_menu_timeout = null;
    }
    return $('.navbar .dropdown').addClass('open');
  };
  delay_close_it = function() {
    var close_it;
    close_it = function() {
      return $('.navbar .dropdown').removeClass('open');
    };
    return nav_menu_timeout = setTimeout(close_it, 500);
  };
  $('body').on('mouseover', '#nav_dropdown, #nav_dropdown *', open_it).on('mouseout', '#nav_dropdown', delay_close_it);
  return $('body').on('mouseover', '.navbar .dropdown .dropdown-menu', open_it).on('mouseout', '.navbar .dropdown .dropdown-menu', delay_close_it);
});
Sarah Vessels
źródło
2

Aby ulepszyć odpowiedź Sudharshana, zawijam to w kwerendę medialną, aby zapobiec najechaniu kursorem na szerokości wyświetlania XS ...

@media (min-width:768px)
{
    ul.nav li.dropdown:hover > ul.dropdown-menu {
        display: block;    
    }

    .nav .dropdown-menu {
        margin-top: 0;
    }
}

Również kursor w znacznikach nie jest wymagany, tylko klasa rozwijana dla li .

johna
źródło
2

Działa to w przypadku WordPress Bootstrap:

.navbar .nav > li > .dropdown-menu:after,
.navbar .nav > li > .dropdown-menu:before {
    content: none;
}
Fred K.
źródło
2

Więc masz ten kod:

<a class="dropdown-toggle" data-toggle="dropdown">Show menu</a>

<ul class="dropdown-menu" role="menu">
    <li>Link 1</li>
    <li>Link 2</li> 
    <li>Link 3</li>                                             
</ul>

Zwykle działa na zdarzenie kliknięcia i chcesz, aby działało na zdarzeniu najechania kursorem. Jest to bardzo proste, wystarczy użyć tego kodu JavaScript / jQuery:

$(document).ready(function () {
    $('.dropdown-toggle').mouseover(function() {
        $('.dropdown-menu').show();
    })

    $('.dropdown-toggle').mouseout(function() {
        t = setTimeout(function() {
            $('.dropdown-menu').hide();
        }, 100);

        $('.dropdown-menu').on('mouseenter', function() {
            $('.dropdown-menu').show();
            clearTimeout(t);
        }).on('mouseleave', function() {
            $('.dropdown-menu').hide();
        })
    })
})

Działa to bardzo dobrze i oto wyjaśnienie: mamy przycisk i menu. Po najechaniu myszką na przycisk wyświetlamy menu, a po najechaniu myszką na przycisk ukrywamy menu po 100 ms. Jeśli zastanawiasz się, dlaczego go używam, to dlatego, że potrzebujesz czasu, aby przeciągnąć kursor z przycisku nad menu. Po przejściu do menu czas jest resetowany i możesz tam pozostać tyle czasu, ile chcesz. Po wyjściu z menu natychmiast ukryjemy menu, bez żadnego limitu czasu.

Użyłem tego kodu w wielu projektach, jeśli napotkasz jakiś problem z jego użyciem, możesz zadawać mi pytania.

Crisan Raluca Teodora
źródło