Evita il menu a discesa vicino al clic all'interno


310

Ho un menu a discesa Twitter Bootstrap. Come tutti gli utenti di Bootstrap di Twitter sanno, il menu a discesa si chiude al clic (anche facendo clic al suo interno).

Per evitarlo, posso facilmente collegare un gestore di eventi click nel menu a discesa e aggiungere semplicemente il famoso 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>

Questo sembra facile e un comportamento molto comune, tuttavia, e poiché carousel-controls(così come carousel indicators) i gestori di eventi sono delegati documentall'oggetto, l' clickevento su questi elementi ( controlli precedente / successivo , ...) sarà “ignorato”.

$('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();
});

Affidarsi al menu a discesa hide/ hiddeneventi Bootstrap di Twitter non è una soluzione per i seguenti motivi:

  • L'oggetto evento fornito per entrambi i gestori eventi non fa riferimento all'elemento cliccato
  • Non ho il controllo sul contenuto del menu a discesa, quindi flagnon è possibile aggiungere una classe o un attributo

Questo violino è il comportamento normale e questo violino è con l' event.stopPropagation()aggiunta.

Aggiornare

Grazie a Roman per la sua risposta . Ho anche trovato una risposta che puoi trovare qui sotto .


1. Il tuo jsfiddle non funziona. 2. Che cosa esattamente vuoi ottenere?
— paulalexandru,

1
@paulalexandru, Aggiornato, ha aggiunto due violini. Un comportamento predefinito e uno con modifica. Prova a fare clic sul pulsante successivo e precedente o sugli indicatori. Per il primo esempio, il menu si nasconde e le diapositive della giostra. o il secondo esempio: il menu rimane aperto, ma la giostra non è scivolata da quando event propagationè stata interrotta.
— php-dev,

@paulalexandru Capito, vero?
— php-dev,

@ php-dev: l'ho aggiornato di nuovo per motivi di sfida, ora è perfetto ... guarda la demo.
— Luca Filosofi,

Risposte:


373

La rimozione dell'attributo di dati data-toggle="dropdown"e l'implementazione dell'apertura / chiusura del menu a discesa può essere una soluzione.

Innanzitutto gestendo il clic sul collegamento per aprire / chiudere il menu a discesa in questo modo:

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

e quindi ascoltando i clic all'esterno del menu a discesa per chiuderlo in questo modo:

$('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');
    }
});

Ecco la demo: http://jsfiddle.net/RomaLefrancois/hh81rhcm/2/


2
Questa soluzione funziona bene. La taglia dovrebbe essere assegnata a te se non ci sono altre risposte.
— php-dev

1
La tua soluzione funziona, generica e anche "popolare". La taglia dovrebbe essere assegnata alla tua risposta. Ho anche trovato una risposta, guardala qui sotto;)
— php-dev

1
@Cichy ... basta modificare il primo gestore in questo modo ... $ ('li.dropdown.mega-dropdown a'). On ('click', function (event) {$ ('li.dropdown.mega-dropdown .open '). removeClass (' open '); $ (this) .parent (). toggleClass (' open ');});
— dsaket,

63
Questa risposta preferita è un hack. Wow!!! Ecco una risposta ALPHA BOOTSTRAP 4 più semplice per impedire il clic interno in un mega menu a discesa. // PREVENT INSIDE CLICK DROPDOWN $('.dropdown-menu').on("click.bs.dropdown", function (e) { e.stopPropagation(); e.preventDefault(); });
— Frank Thoeny,

7
e.stopPropagation()è la soluzione migliore.
— nacholibre,

332

Anche questo dovrebbe aiutare

$(document).on('click', 'someyourContainer .dropdown-menu', function (e) {
  e.stopPropagation();
});

33
Penso che sia sicuramente la soluzione più semplice a questo problema. Pollice in alto - ho appena provato questo e funziona!
— Torsten Barthel,

13
Questa è di gran lunga la soluzione migliore.
— silenzioso

3
Questa è la soluzione più comune, ma ho un requisito diverso. Per favore leggi attentamente la mia domanda :)
— php-dev,

4
La migliore soluzione per tenere semplicemente il menu aperto sui clic.
— Matt Pierce,

2
La migliore soluzione davvero. Ho usato personalmente in '.dropdown-menu :not(.dropdown-item)'modo tale che facendo clic su a dropdown-itemsi chiuda il popup, ma facendo clic su a dropdown-headernon lo fa.
— Benjamin,

41

Bootstrap offre la seguente funzione:

                 | Questo evento viene generato immediatamente quando il metodo hide dell'istanza
hide.bs.dropdown | è stato chiamato. L'elemento di ancoraggio attiva / disattiva è disponibile come
                 | relatedTarget proprietà dell'evento.

Pertanto, l'implementazione di questa funzione dovrebbe essere in grado di disabilitare la chiusura del menu a discesa.

$('#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;
    }
});

2
@Vartan, Anche la targetproprietà dell'evento è the li.dropdown, the relatedTargetis the a.dropdown-toggle. Quindi non puoi fare riferimento all'elemento cliccato all'interno del hidegestore eventi.
— php-dev

2
hasClass accetta un nome di classe, non un selettore CSS. target.hasClass(".keepopen")dovrebbe essere target.hasClass("keepopen"). Altrimenti il ​​codice non funzionerà.
— Hugh Guiney,

3
Ho scansionato Internet e questa è di gran lunga la soluzione più intelligente, per questo motivo ... altri metodi richiedono un approccio che utilizza l'interruzione dell'evento predefinito o l'interruzione della propagazione. questi approcci sono molto cattivi in ​​quanto interrompono qualsiasi altro evento innescato all'interno del menu a discesa (ovvero i miei elementi del modulo mobile jquery) utilizzando questo approccio consente di identificare in modo specifico quando il menu stesso si sta chiudendo e consente di agire solo su quell'evento. questa risposta ha bisogno di così tante stelle ....
— webfish

3
@webfish Quanto tempo hai impiegato per scansionare Internet? (rofl)
— php-dev,

2
Forse questo funzionava .. ma con bootstrap 4, e.target è sempre il menu a discesa stesso. Non la destinazione cliccata. Anche se fai clic al di fuori dei menu a discesa, e.target è comunque il menu a discesa. Quindi non è possibile eseguire questo tipo di controllo. Qualcuno vede un modo per aggirare questo?
— FredArters,

36

La risposta migliore in assoluto è inserire un tag del modulo dopo il menu a discesa della classe

quindi il tuo codice è

<ul class="dropdown-menu">
  <form>
    <li>
      <div class="menu-item">bla bla bla</div>
    </li>
  </form>
</ul>

2
funzionalmente ha funzionato magnificamente per me, ma ha rotto lo stile
— 2778

2
questa è stata la soluzione più veloce per me
— Jonathan Morales Vélez,

15
Questa non è una risposta migliore :) un <li>elemento non dovrebbe essere all'interno di un <form> elemento.
— GETah

2
Questa non è una soluzione semanticlicamente corretta - l'unico figlio valido di un UL è un LI - semmai i tag del modulo dovrebbero trovarsi all'interno dei tag li - ma ciò potrebbe non consentire sempre l'azione desiderata - in entrambi i casi un ul> form> li non è markup corretto
— gavgrif,

2
Grazie per questa soluzione rapida
— Herman Demsong,

27

Ho anche trovato una soluzione.

Supponendo che i Twitter Bootstrap Componentsgestori di eventi correlati siano delegati documentall'oggetto, eseguo il ciclo dei gestori associati e controllo se l'elemento selezionato corrente (o uno dei suoi genitori) è interessato da un evento delegato.

$('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
});

Spero che aiuti chiunque cerchi una soluzione simile.

Grazie a tutti per il vostro aiuto.


1
Wow!!! ha funzionato perfettamente! Sono stato nei guai per una settimana, sto usando mCustomeScrollbar e dopo aver fatto clic sulla barra di scorrimento nel menu a discesa lo stava chiudendo, il tuo script ha funzionato e ora funziona bene! Grazie mille.
— eirenaios,

funziona alla grande! come si estende questo, in modo che un utente possa ancora premere "ESC" (o anche fare clic all'esterno) sulla tastiera per chiudere il DD?
— Zio Iroh,

2
@MaggewDotCom La pressione del tasto ESC dovrebbe ancora funzionare. Lo stesso per fare clic all'esterno ...
— php-dev,

L'unico aspetto negativo di questa soluzione è che non consente i menu a discesa nidificati (si supponga di disporre di un indicatore appropriato all'interno di un menu a discesa). C'è una soluzione alternativa per questo caso?
— sdvnksv,

26

Questo potrebbe aiutare:

$("dropdownmenuname").click(function(e){
   e.stopPropagation();
})

Questa è sicuramente la risposta più semplice / migliore se desideri che un utente interagisca con un elemento dell'interfaccia utente presente nel menu a discesa (ad es. Pulsanti di opzione) e non desideri che il menu si chiuda quando attiva / disattiva le opzioni.
— Rob,

22
$('body').on("click", ".dropdown-menu", function (e) {
    $(this).parent().is(".open") && e.stopPropagation();
});

Questo può funzionare per qualsiasi condizione.


questa dovrebbe essere la risposta corretta in quanto utilizza meno righe di codice anziché la risposta selezionata
— Muhammad Omer Aslam

@MuhammadOmerAslam Nah! Poiché non soddisfa i miei requisiti
— php-dev il

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 :

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

La tua demo con questa soluzione: http://jsfiddle.net/kerryjohnson/80oLdtbf/101/


9

Ho provato questa cosa semplice e ha funzionato come un fascino.

Ho cambiato l' elemento del menu a discesa da <div>a <form>e ha funzionato bene.

<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>


6

Recentemente ho avuto un problema simile e ho provato diversi modi per risolverlo rimuovendo l'attributo di dati data-toggle="dropdown"e ascoltando clickcon la event.stopPropagation()chiamata.

Il secondo modo sembra più preferibile. Anche gli sviluppatori Bootstrap usano questo modo. Nel file di origine ho trovato l'inizializzazione degli elementi a discesa:

// 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);

Quindi, questa linea:

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

suggerisce di inserire un formelemento all'interno del contenitore con classe .dropdownper evitare la chiusura del menu a discesa.


6

Bootstrap ha risolto questo problema da solo nel supporto dei <form>tag nei menu a discesa. La loro soluzione è abbastanza comprensibile e puoi leggerla qui: https://github.com/twbs/bootstrap/blob/v4-dev/js/src/dropdown.js

Si riduce a impedire la propagazione sull'elemento del documento e lo fa solo per eventi di tipo 'click.bs.dropdown.data-api'che corrispondono al selettore '.dropdown .your-custom-class-for-keep-open-on-click-elements'.

O nel codice

$(document).on('click.bs.dropdown.data-api', '.dropdown .keep-open-on-click', (event) => {
    event.stopPropagation();
});

1
Grazie grazie grazie per il link alla fonte. Per altri si chiedono perché l' formapproccio dagli esempi non dropleftfunzioni per te: stavo usando la classe , ma ha anche bisogno dropdownche il selettore di form corrisponda.
— Mark K Cowan,

6

Ho modificato la risposta di @ Vartan per farlo funzionare con Bootstrap 4.3. La sua soluzione non funziona più con l'ultima versione poiché la targetproprietà restituisce sempre la radice del menu a discesa, divindipendentemente da dove è stato posizionato il clic.

Ecco il codice:

$('.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>

on line:$('.dropdown-keep-open').on('hide.bs.dropdown', ev => !(ev.clickEvent && $(ev.target).has(ev.clickEvent.target).length))
— Matveev Dmitriy

@MatveevDmitriy Mi dispiace ma nessuno, semplicemente nessuno può leggere questa copertina. Scrivere codice in questo modo è una cattiva pratica.
— ViRuSTriNiTy

L'ultima riga può essere semplificata usando return !target.closest('.dropdown-keep-open').length). Detto questo, questa è un'ottima soluzione! Trovato questo necessario per risolvere questo problema.
— patrick3853,

6
$('body').on("click", ".dropdown-menu", function (e) {
    $(this).parent().is(".show") && e.stopPropagation();
});

Innanzitutto, grazie per la risposta. La domanda ha già una risposta. Inoltre, ho un requisito diverso come descritto nella domanda rispetto al requisito comune.
— 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');
});

l'ho aggiornato ancora una volta per renderlo il più intelligente e funzionale possibile. ora si chiude quando si passa al di fuori del nav, rimanendo aperto mentre ci si trova dentro. semplicemente perfetto.


La tua soluzione è intelligente per la sua mancanza, tuttavia, dopo aver aggiunto la classe show, il menu a discesa non si chiude facendo clic all'esterno e dobbiamo fare clic sul menu a discesa prima di ... +1 comunque
— php-dev

l'ho aggiornato, guarda la demo. è la causa migliore non controllare ogni volta che si verifica l'evento click body. influisce solo sull'elemento all'interno di ogni singolo elemento nav non esterno.
— Luca Filosofi,

Anche la mia soluzione non si basa bodysull'evento click ^^
— php-dev

sì, inoltra in parte all'evento click del corpo, prova a verificare quale elemento è stato cliccato attraverso la delega del corpo. $('body').on('click', function (e) {
— Luca Filosofi,

Nah! Questa non è la mia risposta. La mia risposta è l'ultima pubblicata.
— php-dev,

4

Come ad esempio Bootstrap 4 Alpha ha questo Evento Menu. Perché non usare?

// PREVENT INSIDE MEGA DROPDOWN
$('.dropdown-menu').on("click.bs.dropdown", function (e) {
    e.stopPropagation();
    e.preventDefault();                
});

1
e.preventDefault();blocca i collegamenti, puoi saltarlo
— lungo

@czachor hai ragione! e.preventDefault (); Impedire a un collegamento di seguire l'URL.
— Frank Thoeny,

3

Puoi interrompere la propagazione del menu a discesa e quindi reimplementare manualmente i controlli del carosello utilizzando i metodi javascript del carosello .

$('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);
});

Ecco il jsfiddle .


Il tuo esempio funziona bene, ma il problema è che il menu a discesa può contenere qualsiasi contenuto e non solo immagini carosello ...
— php-dev

3

Con Angular2 Bootstrap, è possibile utilizzare nonInput per la maggior parte degli scenari:

<div dropdown autoClose="nonInput">

nonInput: (impostazione predefinita) chiude automaticamente il menu a discesa quando si fa clic su uno dei suoi elementi, purché l'elemento su cui si fa clic non sia un input o un'area di testo.

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


2

So che questa domanda era specifica per jQuery, ma per chiunque usi AngularJS che ha questo problema puoi creare una direttiva che gestisca questo:

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
          });
        }
    };
});

Quindi aggiungi l'attributo dropdown-prevent-closeal tuo elemento che sta attivando la chiusura del menu e dovrebbe impedirlo. Per me, è stato un selectelemento che ha chiuso automaticamente il menu:

<div class="dropdown-menu">
  <select dropdown-prevent-close name="myInput" id="myInput" ng-model="myModel">
    <option value="">Select Me</option>
  </select>
</div>

6
<div class="dropdown-menu" ng-click="$event.stopPropagation()">funziona per me in
— 1.2.x

2

[Bootstrap 4 Alpha 6] [Guide] per Rails sviluppatori, e.stopPropagation()porterà ad un comportamento indesiderato per link_tocon data-methoddiverso da getquanto sarà dal ritorno di default tutte le vostre richieste come get.

Per porre rimedio a questo problema, suggerisco questa soluzione, che è universale

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


2

Invece di scrivere un codice javascript o jquery (reinventando la ruota). Lo scenario sopra può essere gestito dall'opzione di chiusura automatica bootstrap. È possibile fornire uno dei valori per la chiusura automatica :

  1. sempre - (Predefinito) chiude automaticamente il menu a discesa quando si fa clic su uno dei suoi elementi.

  2. outsideClick: chiude automaticamente il menu a discesa solo quando l'utente fa clic su qualsiasi elemento esterno al menu a discesa.

  3. disabilitato: disabilita la chiusura automatica

Dai un'occhiata al seguente plunkr:

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

Impostato

uib-dropdown auto-close="disabled" 

Spero che questo ti aiuti :)


5
Va notato esplicitamente che questo è positivo solo per le persone che usano ui-bootstrap, il che probabilmente non è il caso per molte persone che vedono questa domanda.
— kevlarr,

Hai ben descritto ma penso che dovresti scrivere la soluzione come uib-dropdown auto-close="outsideClick". La chiusura del menu al clic all'interno è solo un po 'di disagio, ma il menu non vicino al clic all'esterno è abbastanza sconvolgente.
— vusan,

2

So che esiste già una risposta precedente che suggerisce di utilizzare un modulo ma il markup fornito non è corretto / ideale. Ecco la soluzione più semplice, non è necessario javascript e non interrompe il tuo menu a discesa. Funziona con Bootstrap 4.

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


@RosdiKasim Ho funzionato bene su un sito Web con Bootstrap 4.0.0. Non ho testato con 4.1
— Radu Ciobanu,

In realtà dovrebbe essere come: <form class = "dropdown dropdown-item">
— Nasser Sadraee

2

Questo mi ha aiutato,

$('.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;
                }
            }            
});

L'elemento del menu a discesa deve essere simile a questo (prendere nota delle classi dropdown-menue keepopen.

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

Il codice sopra evita il biding nel suo complesso <body>, anziché l'elemento specfic con la classe dropdown-menu.

Spero che questo aiuti qualcuno.

Grazie.


Grazie Aggiornato come da Bootstrap 4 $ ('. Menu a discesa [data-handledropdownclose = "true"]'). On ('click', function (e) {if ($ (this) .parent (). Is (" .show ")) {var target = $ (e.target); return (target.hasClass (" CloseDropDown ") || target.parents (". CloseDropDown "). length);}});
— Thulasiram,

1

La soluzione di lavoro più semplice per me è:

  • aggiungendo keep-openclasse agli elementi che non dovrebbero causare la chiusura del menu a discesa
  • e questo pezzo di codice fa il resto:
$('.dropdown').on('click', function(e) {
    var target = $(e.target);
    var dropdown = target.closest('.dropdown');
    return !dropdown.hasClass('open') || !target.hasClass('keep-open');
});

potete per favore aiutarmi a risolvere questo stackoverflow.com/questions/51552712/… @ Gee-Bee
— Zhu

1

Ho scoperto che nessuna delle soluzioni ha funzionato come vorrei usare il nav bootstrap predefinito. Ecco la mia soluzione a questo problema:

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

1

Nel .dropdowncontenuto metti la .keep-openclasse su qualsiasi etichetta in questo modo:

$('.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
    }
});

I casi precedenti evitavano gli eventi relativi agli oggetti contenitore, ora il contenitore eredita la classe keep-open e controlla prima di essere chiuso.


1

L'ho fatto con questo:

$(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');
    }
});

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')
    });
});

0

Per chiudere il menu a discesa solo se è stato attivato un evento clic all'esterno del menu a discesa Bootstrap, questo è ciò che ha funzionato per me:

File JS:

    $('.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();
        }
    });

File HTML:

<!-- 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>

0

Potresti avere dei problemi se usi il metodo return false o stopPropagation () perché i tuoi eventi verranno interrotti. Prova questo codice, funziona benissimo:

$(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>

Se vuoi chiudere il dropdrown:

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

0

In Bootstrap 4 puoi anche fare questo:

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

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

dove si #dd-linktrova l'elemento di ancoraggio o il pulsante che ha la data-toggle="drowndown"proprietà.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.