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.