Vermeiden Sie das Schließen des Dropdown-Menüs beim Klicken

310

Ich habe ein Twitter Bootstrap Dropdown-Menü. Wie alle Twitter Bootstrap-Benutzer wissen, wird das Dropdown-Menü beim Klicken geschlossen (sogar beim Klicken).

Um dies zu vermeiden, kann ich einfach einen Klickereignishandler in das Dropdown-Menü einfügen und einfach den berühmten hinzufügen event.stopPropagation().

<ul class="nav navbar-nav">
  <li class="dropdown mega-dropdown">
    <a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown">
      <i class="fa fa-list-alt"></i> Menu item 1
      <span class="fa fa-chevron-down pull-right"></span>
    </a>
    <ul class="dropdown-menu mega-dropdown-menu">
      <li>
        <div id="carousel" class="carousel slide" data-ride="carousel">
          <ol class="carousel-indicators">
            <li data-slide-to="0" data-target="#carousel"></li>
            <li class="active" data-slide-to="1" data-target="#carousel"></li>
          </ol>
          <div class="carousel-inner">
            <div class="item">
              <img alt="" class="img-rounded" src="img1.jpg">
            </div>
            <div class="item active">
              <img alt="" class="img-rounded" src="img2.jpg">
            </div>
          </div>
          <a data-slide="prev" role="button" href="#carousel" 
             class="left carousel-control">
            <span class="glyphicon glyphicon-chevron-left"></span>
          </a>
          <a data-slide="next" role="button" href="#carousel" 
             class="right carousel-control">
            <span class="glyphicon glyphicon-chevron-right"></span>
          </a>
        </div>
      </li>
    </ul>
  </li>
</ul>

Dies sieht jedoch einfach aus und ist ein sehr häufiges Verhalten. Da carousel-controls(sowie carousel indicators) Ereignishandler an das documentObjekt delegiert werden, wird das clickEreignis für diese Elemente ( vorherige / nächste Steuerelemente, ...) "ignoriert".

$('ul.dropdown-menu.mega-dropdown-menu').on('click', function(event){
    // The event won't be propagated up to the document NODE and 
    // therefore delegated events won't be fired
    event.stopPropagation();
});

Das Verlassen auf Twitter Bootstrap Dropdown hide/ hiddenEvents ist aus folgenden Gründen keine Lösung:

  • Das bereitgestellte Ereignisobjekt für beide Ereignishandler verweist nicht auf das angeklickte Element
  • Ich habe keine Kontrolle über den Inhalt des Dropdown-Menüs, daher ist das Hinzufügen einer flagKlasse oder eines Attributs nicht möglich

Diese Geige ist das normale Verhalten und diese Geige ist mit event.stopPropagation()hinzugefügt.

Aktualisieren

Vielen Dank an Roman für seine Antwort . Ich habe auch eine Antwort gefunden, die Sie unten finden können .

PHP-Dev
quelle
1. Ihre jsfiddle funktioniert nicht. 2. Was genau möchten Sie erreichen?
Paulalexandru
1
@paulalexandru, aktualisiert, fügte zwei Geige hinzu. Ein Standardverhalten und eines mit Änderung. Klicken Sie auf die Schaltfläche Weiter und Zurück oder auf Anzeigen. Im ersten Beispiel werden die Menü- und Karussellfolien ausgeblendet. oder das zweite Beispiel: Das Menü bleibt geöffnet, aber das Karussell ist nicht gerutscht, seit das event propagationgestoppt wurde.
PHP-Dev
@ Paulalexandru Verstanden, richtig?
PHP-Dev
@ php-dev: Ich habe es aus Gründen der Herausforderung erneut aktualisiert, jetzt ist es perfekt ... siehe Demo.
Luca Filosofi

Antworten:

373

Das Entfernen data-toggle="dropdown"des Datenattributs und das Implementieren des Öffnens / Schließens der Dropdown-Liste kann eine Lösung sein.

Klicken Sie zunächst auf den Link, um das Dropdown-Menü wie folgt zu öffnen / schließen:

$('li.dropdown.mega-dropdown a').on('click', function (event) {
    $(this).parent().toggleClass('open');
});

und dann die Klicks außerhalb des Dropdowns anhören, um es wie folgt zu schließen:

$('body').on('click', function (e) {
    if (!$('li.dropdown.mega-dropdown').is(e.target) 
        && $('li.dropdown.mega-dropdown').has(e.target).length === 0 
        && $('.open').has(e.target).length === 0
    ) {
        $('li.dropdown.mega-dropdown').removeClass('open');
    }
});

Hier ist die Demo: http://jsfiddle.net/RomaLefrancois/hh81rhcm/2/

Roma
quelle
2
Diese Lösung funktioniert gut. Das Kopfgeld sollte Ihnen gutgeschrieben werden, wenn es keine andere Antwort gibt.
PHP-Dev
1
Ihre Lösung funktioniert, ist allgemein und auch "beliebt". Das Kopfgeld sollte auf Ihre Antwort vergeben werden. Ich habe auch eine Antwort gefunden, sieh sie dir unten an;)
php-dev
1
@Cichy ... ändere einfach den ersten Handler wie folgt ... $ ('li.dropdown.mega-dropdown a'). On ('click', Funktion (Ereignis) {$ ('li.dropdown.mega-dropdown .open '). removeClass (' open '); $ (this) .parent (). toggleClass (' open ');});
Dsaket
63
Diese bevorzugte Antwort ist ein Hack. Beeindruckend!!! Hier ist eine einfachere BOOTSTRAP 4 ALPHA-Antwort, um ein Klicken von innen in einem Mega-Dropdown zu verhindern. // PREVENT INSIDE CLICK DROPDOWN $('.dropdown-menu').on("click.bs.dropdown", function (e) { e.stopPropagation(); e.preventDefault(); });
Frank Thoeny
7
e.stopPropagation()ist die beste Lösung.
Nacholibre
332

Dies sollte auch helfen

$(document).on('click', 'someyourContainer .dropdown-menu', function (e) {
  e.stopPropagation();
});
Arbejdsglæde
quelle
33
Ich denke, das ist mit Sicherheit die einfachste Lösung für dieses Problem. Daumen hoch - habe gerade diesen getestet und es funktioniert!
Torsten Barthel
13
Dies ist bei weitem die beste Lösung.
still
3
Das ist die häufigste Lösung, aber ich habe eine andere Anforderung. Bitte lesen Sie meine Frage sorgfältig durch :)
PHP-Dev
4
Beste Lösung, um das Menü bei Klicks einfach offen zu halten.
Matt Pierce
2
Beste Lösung in der Tat. Ich persönlich habe verwendet, '.dropdown-menu :not(.dropdown-item)'damit das Klicken auf a dropdown-itemdas Popup schließt, das Klicken auf a dropdown-headerjedoch nicht.
Benjamin
41

Bootstrap bietet die folgende Funktion:

                 | Dieses Ereignis wird sofort ausgelöst, wenn die Instanzmethode ausblenden
hide.bs.dropdown | genannt worden. Das umschaltbare Ankerelement ist als verfügbar
                 | relatedTarget-Eigenschaft des Ereignisses.

Daher sollte die Implementierung dieser Funktion in der Lage sein, das Schließen der Dropdown-Liste zu deaktivieren.

$('#myDropdown').on('hide.bs.dropdown', function (e) {
    var target = $(e.target);
    if(target.hasClass("keepopen") || target.parents(".keepopen").length){
        return false; // returning false should stop the dropdown from hiding.
    }else{
        return true;
    }
});
Vartan
quelle
2
@Vartan, auch die Ereigniseigenschaft targetist die li.dropdown, die relatedTargetist die a.dropdown-toggle. Sie können also nicht auf das angeklickte Element im hideEreignishandler verweisen.
PHP-Dev
2
hasClass verwendet einen Klassennamen, keinen CSS-Selektor. target.hasClass(".keepopen")sollte sein target.hasClass("keepopen"). Andernfalls funktioniert der Code nicht.
Hugh Guiney
3
Ich habe das Internet gescannt und dies ist aus diesem Grund die mit Abstand intelligenteste Lösung. Viele andere Methoden erfordern einen Ansatz, bei dem das Standardereignis gestoppt oder die Weitergabe gestoppt wird. Diese Ansätze sind sehr schlecht, da sie alle anderen ausgelösten Ereignisse innerhalb der Dropdown-Liste (dh meine mobilen jquery-Formularelemente) auflösen. Mit diesem Ansatz können Sie genau identifizieren, wann das Menü selbst geschlossen wird, und nur für dieses Ereignis Maßnahmen ergreifen. Diese Antwort braucht so viele Sterne ...
Webfish
3
@webfish Wie viel hast du gebraucht, um das Internet zu scannen? (rofl)
php-dev
2
Vielleicht hat das früher funktioniert ... aber mit Bootstrap 4 ist e.target immer das Dropdown selbst. Nicht das angeklickte Ziel. Selbst wenn Sie außerhalb der Dropdown-Listen klicken, ist e.target immer noch die Dropdown-Liste. Sie können diese Art der Überprüfung also nicht durchführen. Hat jemand einen Weg gefunden, dies zu umgehen?
FredArters
36

Die absolut beste Antwort ist, nach dem Dropdown-Menü der Klasse ein Formular-Tag einzufügen

Ihr Code ist also

<ul class="dropdown-menu">
  <form>
    <li>
      <div class="menu-item">bla bla bla</div>
    </li>
  </form>
</ul>
Gregory Bowers
quelle
2
funktionell hat hervorragend für mich funktioniert, aber das Styling gebrochen
2778
2
Dies war die schnellste Lösung für mich
Jonathan Morales Vélez
15
Dies ist keine beste Antwort :) Ein <li>Element sollte sich nicht in einem <form> Element befinden.
GETah
2
Dies ist keine semantisch korrekte Lösung - das einzig gültige untergeordnete Element eines UL ist ein LI - wenn überhaupt, sollten sich die Formular-Tags innerhalb der li-Tags befinden - aber das kann möglicherweise nicht die gewünschte Aktion bewirken - so oder so ist ein ul> form> li nicht korrektes Markup
Gavgrif
2
Danke für diese schnelle Lösung
Herman Demsong
27

Ich habe auch eine Lösung gefunden.

Unter der Annahme, dass die Twitter Bootstrap Componentszugehörigen Ereignishandler an das documentObjekt delegiert sind , schleife ich die angehängten Handler und überprüfe, ob das aktuell angeklickte Element (oder eines seiner übergeordneten Elemente) von einem delegierten Ereignis betroffen ist.

$('ul.dropdown-menu.mega-dropdown-menu').on('click', function(event){
    var events = $._data(document, 'events') || {};
    events = events.click || [];
    for(var i = 0; i < events.length; i++) {
        if(events[i].selector) {

            //Check if the clicked element matches the event selector
            if($(event.target).is(events[i].selector)) {
                events[i].handler.call(event.target, event);
            }

            // Check if any of the clicked element parents matches the 
            // delegated event selector (Emulating propagation)
            $(event.target).parents(events[i].selector).each(function(){
                events[i].handler.call(this, event);
            });
        }
    }
    event.stopPropagation(); //Always stop propagation
});

Hoffe, es hilft jedem, der nach einer ähnlichen Lösung sucht.

Vielen Dank für Ihre Hilfe.

PHP-Dev
quelle
1
Beeindruckend!!! hat perfekt funktioniert! War eine Woche lang in Schwierigkeiten, ich benutze mCustomeScrollbar und nachdem ich in der Dropdown-Liste auf die Bildlaufleiste geklickt habe, wurde sie geschlossen, Ihr Skript hat funktioniert und jetzt funktioniert es einwandfrei! Tausend Dank.
Eirenaios
funktioniert super! Wie kann man dies erweitern, so dass ein Benutzer immer noch "ESC" (oder sogar nach außen klicken) auf der Tastatur drücken kann, um die DD zu schließen?
Onkel Iroh
2
@MaggewDotCom Der ESC-Tastendruck sollte weiterhin funktionieren. Das gleiche gilt für das Klicken nach draußen ...
PHP-Dev
Der einzige Nachteil dieser Lösung ist, dass sie keine verschachtelten Dropdowns zulässt (sagen wir, Sie haben ein Dropright in einem Dropdown). Gibt es eine Problemumgehung für diesen Fall?
SDVNKSV
26

Dies könnte helfen:

$("dropdownmenuname").click(function(e){
   e.stopPropagation();
})
Bawantha
quelle
Dies ist definitiv die einfachste / beste Antwort, wenn Sie möchten, dass ein Benutzer mit einem in der Dropdown-Liste vorhandenen UI-Element (z. B. Optionsfeldern) interagiert und das Menü nicht geschlossen wird, wenn er die Optionen umschaltet.
Rob
22
$('body').on("click", ".dropdown-menu", function (e) {
    $(this).parent().is(".open") && e.stopPropagation();
});

Dies kann unter allen Bedingungen funktionieren.

Terry Lin
quelle
Dies sollte die richtige Antwort sein, da weniger Codezeilen als die ausgewählte Antwort verwendet werden
Muhammad Omer Aslam
@ MuhammadOmerAslam Nah! Da es meine Anforderung nicht erfüllt
PHP-Dev
12

jQuery:

<script>
  $(document).on('click.bs.dropdown.data-api', '.dropdown.keep-inside-clicks-open', function (e) {
    e.stopPropagation();
  });
</script>

HTML:

<div class="dropdown keep-inside-clicks-open">
  <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
     Dropdown Example
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu">
    <li><a href="#">HTML</a></li>
    <li><a href="#">CSS</a></li>
    <li><a href="#">JavaScript</a></li>
  </ul>
</div>

Demo :

Allgemein: https://jsfiddle.net/kerryjohnson/omefq68b/1/

Ihre Demo mit dieser Lösung: http://jsfiddle.net/kerryjohnson/80oLdtbf/101/

Kerry Johnson
quelle
9

Ich habe dieses einfache Ding ausprobiert und es hat wie ein Zauber funktioniert.

Ich habe das Dropdown-Menüelement von <div>auf geändert <form>und es hat gut funktioniert.

<div class="nav-item dropdown" >
  <a href="javascript:;" class="nav-link dropdown-toggle" data-toggle="dropdown">
   Click to open dropdown
 </a>
 <form class="dropdown-menu   ">
  <ul class="list-group text-black">
     <li class="list-group-item"  >
     </li>
     <li class="list-group-item"   >
     </li>
  </ul>
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>


<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>


<div class="nav-item dropdown" >
  <a href="javascript:;" class="nav-link dropdown-toggle" data-toggle="dropdown">
   Click to open dropdown
 </a>
 <form class="dropdown-menu   ">
  <ul class="list-group text-black">
     <li class="list-group-item"  >
      List Item 1
     </li>
     <li class="list-group-item"   >
         LI 2<input class="form-control" />
     </li>
     <li class="list-group-item"   >
        List Item 3
     </li>
  </ul>
</form>

TheVigilant
quelle
6

Ich habe kürzlich ein ähnliches Problem und habe verschiedene Möglichkeiten ausprobiert, um es zu lösen, indem ich das Datenattribut entfernt data-toggle="dropdown"und clickbeim event.stopPropagation()Aufrufen abgehört habe .

Der zweite Weg sieht vorzuziehen. Auch Bootstrap-Entwickler verwenden diesen Weg. In der Quelldatei habe ich die Initialisierung der Dropdown-Elemente gefunden:

// APPLY TO STANDARD DROPDOWN ELEMENTS
$(document)
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
}(jQuery);

Also, diese Zeile:

.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })

schlägt vor, dass Sie ein formElement mit Klasse .dropdownin den Container einfügen können, um das Schließen des Dropdown-Menüs zu vermeiden.

Ilya
quelle
6

Bootstrap hat dieses Problem selbst gelöst, <form>indem es Tags in Dropdowns unterstützt. Ihre Lösung ist leicht zu verstehen und kann hier gelesen werden: https://github.com/twbs/bootstrap/blob/v4-dev/js/src/dropdown.js

Es läuft darauf hinaus, die Weitergabe am Dokumentelement zu verhindern und dies nur für Ereignisse vom Typ 'click.bs.dropdown.data-api', die mit dem Selektor übereinstimmen '.dropdown .your-custom-class-for-keep-open-on-click-elements'.

Oder im Code

$(document).on('click.bs.dropdown.data-api', '.dropdown .keep-open-on-click', (event) => {
    event.stopPropagation();
});
Daniel Schlaug
quelle
1
Danke, danke, danke für den Link zur Quelle. Für andere, die formsich fragen, warum der Ansatz aus den Beispielen für Sie nicht funktioniert - ich habe Klasse verwendet dropleft, aber er muss auch dropdown, damit die Formularauswahl übereinstimmt.
Mark K Cowan
6

Ich habe die Antwort von @ Vartan geändert, damit sie mit Bootstrap 4.3 funktioniert. Seine Lösung funktioniert mit der neuesten Version nicht mehr, da die targetEigenschaft immer den Stamm der Dropdown-Liste zurückgibt, unabhängig davon, divwo der Klick platziert wurde.

Hier ist der Code:

$('.dropdown-keep-open').on('hide.bs.dropdown', function (e) {
  if (!e.clickEvent) {
    // There is no `clickEvent` property in the `e` object when the `button` (or any other trigger) is clicked. 
    // What we usually want to happen in such situations is to hide the dropdown so we let it hide. 
    return true;
  }

  var target = $(e.clickEvent.target);

  return !(target.hasClass('dropdown-keep-open') || target.parents('.dropdown-keep-open').length);
});
<div class="dropdown dropdown-keep-open">
  <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Dropdown button
  </button>
  <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
    <a class="dropdown-item" href="#">Action</a>
    <a class="dropdown-item" href="#">Another action</a>
    <a class="dropdown-item" href="#">Something else here</a>
  </div>
</div>
Konrad Kalemba
quelle
online:$('.dropdown-keep-open').on('hide.bs.dropdown', ev => !(ev.clickEvent && $(ev.target).has(ev.clickEvent.target).length))
Matveev Dmitriy
@MatveevDmitriy Es tut mir leid, aber niemand, einfach niemand kann diesen einen Liner lesen. Das Schreiben von Code auf diese Weise ist imho eine schlechte Praxis.
ViRuSTriNiTy
Die letzte Zeile kann mit vereinfacht werden return !target.closest('.dropdown-keep-open').length). Das heißt, das ist eine großartige Lösung! Fand dies erforderlich, um dieses Problem zu lösen.
patrick3853
6
$('body').on("click", ".dropdown-menu", function (e) {
    $(this).parent().is(".show") && e.stopPropagation();
});
waza123
quelle
Zunächst vielen Dank für Ihre Antwort. Die Frage ist bereits beantwortet. Außerdem habe ich eine andere Anforderung als in der Frage beschrieben als die gemeinsame Anforderung.
PHP-Dev
4
$('ul.nav.navbar-nav').on('click.bs.dropdown', function(e){
    var $a  = $(e.target), is_a = $a.is('.is_a');
    if($a.hasClass('dropdown-toggle')){   
        $('ul.dropdown-menu', this).toggle(!is_a);
        $a.toggleClass('is_a', !is_a);
    }
}).on('mouseleave', function(){
    $('ul.dropdown-menu',this).hide();
    $('.is_a', this).removeClass('is_a');
});

Ich habe es noch einmal aktualisiert, um so intelligent und funktional wie möglich zu sein. Es wird jetzt geschlossen, wenn Sie außerhalb des Navigationsgeräts schweben, und bleibt geöffnet, während Sie sich darin befinden. einfach perfekt.

Luca Filosofi
quelle
Ihre Lösung ist aufgrund ihrer Kürze intelligent. Nach dem Hinzufügen der Klasse showwird das Dropdown-Menü jedoch nicht geschlossen, wenn Sie nach außen klicken, und wir müssen auf den Dropdown-Schalter klicken, bevor ... +1
php-dev
Ich habe es aktualisiert, schauen Sie sich die Demo an. Dies ist die beste Ursache. Überprüfen Sie nicht jedes Mal das Body-Click-Ereignis. wirken sich nur auf Elemente innerhalb jedes einzelnen Navigationselements aus, nicht außerhalb davon.
Luca Filosofi
Meine Lösung bodybasiert auch nicht auf Klickereignis ^^
php-dev
Ja, es wird teilweise auf ein Body-Click-Ereignis weitergeleitet. Es wird versucht zu überprüfen, auf welches Element durch die Body-Delegation geklickt wurde. $('body').on('click', function (e) {
Luca Filosofi
Nein! Das ist nicht meine Antwort. Meine Antwort ist die zuletzt gepostete.
PHP-Dev
4

Wie zum Beispiel hat Bootstrap 4 Alpha dieses Menüereignis. Warum nicht verwenden?

// PREVENT INSIDE MEGA DROPDOWN
$('.dropdown-menu').on("click.bs.dropdown", function (e) {
    e.stopPropagation();
    e.preventDefault();                
});
Frank Thoeny
quelle
1
e.preventDefault();blockiert Links, können Sie es überspringen
lange
@czachor du hast recht! e.preventDefault (); Verhindern Sie, dass ein Link der URL folgt.
Frank Thoeny
3

Sie können die Weitergabe durch Klicken auf das Dropdown-Menü beenden und die Karussellsteuerelemente mithilfe von Karussell-Javascript-Methoden manuell neu implementieren .

$('ul.dropdown-menu.mega-dropdown-menu').on('click', function(event) {
    event.stopPropagation();
});

$('a.left').click(function () {
    $('#carousel').carousel('prev');
});

$('a.right').click(function () {
    $('#carousel').carousel('next');
});

$('ol.carousel-indicators li').click(function (event) {
    var index = $(this).data("slide-to");
    $('#carousel').carousel(index);
});

Hier ist die jsfiddle .

Neil
quelle
Ihr Beispiel funktioniert gut, aber das Problem ist, dass das Dropdown-Menü jeden Inhalt und nicht nur Bilder Karussell enthalten kann ...
PHP-Dev
3

Mit Angular2 Bootstrap können Sie nonInput für die meisten Szenarien verwenden:

<div dropdown autoClose="nonInput">

nonInput - (Standard) schließt das Dropdown-Menü automatisch, wenn auf eines seiner Elemente geklickt wird - solange das angeklickte Element keine Eingabe oder kein Textbereich ist.

https://valor-software.com/ng2-bootstrap/#/dropdowns

Nir Soudry
quelle
2

Ich weiß, dass diese Frage speziell für jQuery gestellt wurde, aber für alle Benutzer von AngularJS, die dieses Problem haben, können Sie eine Direktive erstellen, die dies behandelt:

angular.module('app').directive('dropdownPreventClose', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
          element.on('click', function(e) {
            e.stopPropagation(); //prevent the default behavior of closing the dropdown-menu
          });
        }
    };
});

Fügen Sie dann einfach das Attribut dropdown-prevent-closezu Ihrem Element hinzu, das das Schließen des Menüs auslöst, und es sollte dies verhindern. Für mich war es ein selectElement, das das Menü automatisch schloss:

<div class="dropdown-menu">
  <select dropdown-prevent-close name="myInput" id="myInput" ng-model="myModel">
    <option value="">Select Me</option>
  </select>
</div>
jtate
quelle
6
<div class="dropdown-menu" ng-click="$event.stopPropagation()">arbeitet für mich in 1.2.x
dr3w
2

[Bootstrap 4 Alpha 6] [Rails] Für Rails-Entwickler e.stopPropagation()führt dies zu unerwünschtem Verhalten link_tobei data-methodungleich, getda standardmäßig alle Ihre Anforderungen als zurückgegeben werden get.

Um dieses Problem zu beheben, schlage ich diese universelle Lösung vor

$('.dropdown .dropdown-menu').on('click.bs.dropdown', function() {
  return $('.dropdown').one('hide.bs.dropdown', function() {
    return false;
  });
});

Jacky Tong
quelle
2

Anstatt Javascript oder JQuery-Code zu schreiben (das Rad neu erfinden). Das obige Szenario kann mit der Option zum automatischen Schließen des Bootstraps verwaltet werden. Sie können einen der Werte zum automatischen Schließen angeben :

  1. always - (Standard) schließt das Dropdown-Menü automatisch, wenn auf eines seiner Elemente geklickt wird.

  2. externClick - schließt die Dropdown-Liste nur dann automatisch, wenn der Benutzer auf ein Element außerhalb der Dropdown-Liste klickt.

  3. deaktiviert - Deaktiviert das automatische Schließen

Schauen Sie sich folgenden Plunkr an:

http://plnkr.co/edit/gnU8M2fqlE0GscUQtCWa?p=preview

einstellen

uib-dropdown auto-close="disabled" 

Hoffe das hilft :)

ashwaniKumar
quelle
5
Es sollte ausdrücklich darauf hingewiesen werden, dass dies nur für Benutzer von Nutzen ist ui-bootstrap, was bei sehr vielen Personen, die diese Frage betrachten, wahrscheinlich nicht der Fall ist.
Kevlarr
Sie gut beschrieben, aber ich denke, Sie sollten Lösung als schreiben uib-dropdown auto-close="outsideClick". Das Schließen des Menüs beim Klicken im Inneren ist nur ein wenig unangenehm, aber das Menü, das beim Klicken im Freien nicht geschlossen wird, ist ziemlich ärgerlich.
Vusan
2

Ich weiß, dass es bereits eine vorherige Antwort gibt, die die Verwendung eines Formulars vorschlägt, aber das bereitgestellte Markup ist nicht korrekt / ideal. Hier ist die einfachste Lösung, es wird überhaupt kein Javascript benötigt und es bricht Ihre Dropdown-Liste nicht. Funktioniert mit Bootstrap 4.

<form class="dropdown-item"> <!-- Your elements go here --> </form>

Radu Ciobanu
quelle
@RosdiKasim Ich habe es auf einer Website mit Bootstrap 4.0.0 gut funktioniert. Habe nicht mit 4.1 getestet
Radu Ciobanu
Eigentlich sollte es so aussehen: <form class = "dropdown dropdown-item">
Nasser Sadraee
2

Das hat mir geholfen,

$('.dropdown-menu').on('click', function (e) {
     if ($(this).parent().is(".open")) {
         var target = $(e.target);
         if (target.hasClass("keepopen") || target.parents(".keepopen").length){
                    return false; 
                }else{
                    return true;
                }
            }            
});

Ihr Dropdown-Menüelement muss folgendermaßen sein (notieren Sie sich die Klassen dropdown-menuund keepopen.

<ul role="menu" class="dropdown-menu topmenu-menu eserv_top_notifications keepopen">

Der obige Code verhindert, dass insgesamt <body>auf das spezifische Element mit der Klasse verzichtet wird dropdown-menu.

Hoffe das hilft jemandem.

Vielen Dank.

Anjana Silva
quelle
Dank Aktualisiert gemäß Bootstrap 4 $ ('. Dropdown-Menü [data-handleropdownclose = "true"]'). On ('click', Funktion (e) {if ($ (this) .parent (). Is (" .show ")) {var target = $ (e.target); return (target.hasClass (" CloseDropDown ") || target.parents (". CloseDropDown "). length);}});
Thulasiram
1

Die einfachste Arbeitslösung für mich ist:

  • Hinzufügen von keep-openKlassen zu Elementen, die kein Dropdown-Schließen verursachen sollen
  • und dieser Code erledigt den Rest:
$('.dropdown').on('click', function(e) {
    var target = $(e.target);
    var dropdown = target.closest('.dropdown');
    return !dropdown.hasClass('open') || !target.hasClass('keep-open');
});
Gee-Bee
quelle
Können Sie mir bitte helfen, dieses Problem zu beheben ? stackoverflow.com/questions/51552712/… @ Gee-Bee
Zhu
1

Ich habe festgestellt, dass keine der Lösungen funktioniert, da ich die Standard-Bootstrap-Navigation verwenden möchte. Hier ist meine Lösung für dieses Problem:

       $(document).on('hide.bs.dropdown', function (e) {
        if ($(e.currentTarget.activeElement).hasClass('dropdown-toggle')) {
          $(e.relatedTarget).parent().removeClass('open');
          return true;
        }
        return false;
       });
Mike
quelle
1

.dropdownSetzen Sie die .keep-openKlasse im Inhalt auf ein beliebiges Etikett wie folgt:

$('.dropdown').on('click', function (e) {
    var target = $(e.target);
    var dropdown = target.closest('.dropdown');
    if (target.hasClass('keep-open')) {
        $(dropdown).addClass('keep-open');
    } else {
        $(dropdown).removeClass('keep-open');
    }
});

$(document).on('hide.bs.dropdown', function (e) {
    var target = $(e.target);
    if ($(target).is('.keep-open')) {
        return false
    }
});

In den vorherigen Fällen wurden die Ereignisse im Zusammenhang mit den Containerobjekten vermieden. Jetzt erbt der Container die Klasse, die geöffnet und überprüft wird, bevor sie geschlossen wird.

Dixán Santiesteban Feria
quelle
1

Ich habe es damit gemacht:

$(element).on({
    'mouseenter': function(event) {
        $(event.currentTarget).data('mouseover', true);
    },
    'mouseleave': function(event) {
        $(event.currentTarget).data('mouseover', false);
    },
    'hide.bs.dropdown': function (event) {
        return !$(event.currentTarget).data('mouseover');
    }
});
Wilhelm
quelle
0
$(function() {
    $('.mega-dropdown').on('hide.bs.dropdown', function(e) {
        var $target = $(e.target);
        return !($target.hasClass("keep-open") || $target.parents(".keep-open").size() > 0);
    });

    $('.mega-dropdown > ul.dropdown-menu').on('mouseenter', function() {
        $(this).parent('li').addClass('keep-open')
    }).on('mouseleave', function() {
        $(this).parent('li').removeClass('keep-open')
    });
});
SNC
quelle
0

Um das Dropdown-Menü nur zu schließen, wenn ein Klickereignis außerhalb des Bootstrap-Dropdowns ausgelöst wurde, hat dies für mich funktioniert:

JS-Datei:

    $('.createNewElement').on('click.bs.dropdown.data-api', '.tags-btn-group.keep-open-dropdown', function (e) {
        var target = $(e.target);
        if (target.hasClass("dropdown-menu") || target.parents(".dropdown-menu").length) {
            e.stopPropagation();
        }
    });

HTML-Datei:

<!-- button: -->
<div class="createNewElement">
                <div class="btn-group tags-btn-group keep-open-dropdown">

                    <div class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">OPEN DROPDOWN</div>

                    <ul class="dropdown-menu">
                        WHAT EVER YOU WANT HERE...
                    </ul>

                </div>
</div>
Dudi
quelle
0

Möglicherweise treten Probleme auf, wenn Sie die Methode return false oder stopPropagation () verwenden, da Ihre Ereignisse unterbrochen werden. Versuchen Sie diesen Code, es funktioniert gut:

$(function() {
    $('.dropdown').on("click", function (e) {
            $('.keep-open').removeClass("show");
    });
    $('.dropdown-toggle').on("click", function () {
            $('.keep-open').addClass("show");
    });

    $( ".closeDropdown" ).click(function() {
        $('.dropdown').closeDropdown();
    });
});
jQuery.fn.extend({
    closeDropdown: function() {
        this.addClass('show')
            .removeClass("keep-open")
            .click()
            .addClass("keep-open");
    }
  });

In HTML:

<div class="dropdown keep-open" id="search-menu" >
    <button  class="btn dropdown-toggle btn  btn-primary" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    <i class="fa fa-filter fa-fw"></i> 
    </button>
    <div class="dropdown-menu">
        <button class="dropdown-item" id="opt1" type="button">Option 1</button>
        <button class="dropdown-item" id="opt2" type="button">Option 2</button>
        <button type="button" class="btn btn-primary closeDropdown">Close</button>
    </div>
</div>

Wenn Sie den Dropdrown schließen möchten:

`$('#search-menu').closeDropdown();`
Hchab
quelle
0

In Bootstrap 4 können Sie dies auch tun:

$('#dd-link').on('hide.bs.dropdown', onListHide)

function onListHide(e)
{
  if(e.clickEvent && $.contains(e.relatedTarget.parentNode, e.clickEvent.target)) {
  e.preventDefault()
  }
}

Wo #dd-linkist das Ankerelement oder die Schaltfläche, die die data-toggle="drowndown"Eigenschaft hat ?

Daniel
quelle