Evita menu a tendina chiudi al clic all’interno

Ho un menu a tendina Bootstrap su Twitter. Come tutti gli utenti di Twitter Bootstrap sanno, il menu a tendina si chiude sul clic (facendo clic anche all’interno di esso).

Per evitare ciò, posso facilmente colbind un gestore di eventi click nel menu a discesa e aggiungere semplicemente il famoso event.stopPropagation() .

  

Questo sembra facile e un comportamento molto comune, tuttavia, e poiché i gestori di eventi di carousel indicators (così come gli carousel indicators ) sono delegati all’object del document , l’evento click su questi elementi (controlli prev / next , …) 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 a Twitter Bootstrap dropdown hide / hidden events non è una soluzione per i seguenti motivi:

  • L’evento fornito per entrambi i gestori di eventi non fornisce alcun riferimento all’elemento selezionato
  • Il contenuto del menu a discesa viene generato dynamicmente, quindi non è ansible aggiungere una class flag

Questo violino è il comportamento normale e questo violino è con event.stopPropagation() aggiunto.

Aggiornare

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

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

Innanzitutto gestendo il clic sul link 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/

Questo dovrebbe aiutare pure

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

Bootstrap fornisce la seguente funzione:

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

Pertanto, l’implementazione di questa funzione dovrebbe essere in grado di disabilitare il menu a discesa dalla chiusura.

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

La migliore risposta in assoluto è inserire un tag form dopo il menu a discesa della class

quindi il tuo codice è

  

Ho anche trovato una soluzione.

Supponendo che i gestori di eventi relativi ai Twitter Bootstrap Components siano delegati all’object document , eseguo il loop dei gestori collegati e verifica se l’elemento su cui si fa clic (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.

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

Questo può funzionare per qualsiasi condizione.

Questo potrebbe aiutare:

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

jQuery:

  

HTML:

  

Demo :

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

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

 $('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 essere il più intelligente e funzionale ansible. ora si chiude quando si passa il mouse fuori dal nav, rimanendo aperti mentre ci si trova all’interno. semplicemente perfetto.

Recentemente ho avuto un problema simile e ho provato diversi modi per risolverlo rimuovendo i dati degli attributi dei data-toggle="dropdown" e ascolto click con event.stopPropagation() .

Il secondo modo sembra più preferibile. Anche gli sviluppatori Bootstrap usano questo modo. Nel file sorgente ho trovato l’inizializzazione degli elementi del menu 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 elemento del form all’interno del contenitore con class .dropdown per evitare di chiudere il menu a discesa.

Puoi interrompere il clic sul menu a discesa dalla propagazione e quindi reimplementare manualmente i controlli del carosello utilizzando i metodi javascript di 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 .

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

 

nonInput: (predefinito) chiude automaticamente il menu a discesa quando viene fatto clic su uno qualsiasi degli elementi, a condizione che l’elemento su cui si fa clic non sia un input o un’area di testo.

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

Ad esempio, Bootstrap 4 Alpha ha questo Evento di menu. Perché non usare?

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

So che questa domanda era specifica per jQuery, ma per chiunque usi AngularJS che ha questo problema è ansible 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-close al tuo elemento che sta triggersndo il menu per chiuderlo, e dovrebbe prevenirlo. Per me, era un elemento di select che chiudeva automaticamente il menu:

  

[Bootstrap 4 Alpha 6] [Rails] Per lo sviluppatore di rails, e.stopPropagation() porterà a comportamenti indesiderati per link_to con data-method diverso da get dato che per impostazione predefinita restituirà tutte le richieste come get .

Per ovviare 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; }); }); 
 $('.dropdown .dropdown-menu').on('click.bs.dropdown', function() { return $('.dropdown').one('hide.bs.dropdown', function() { return false; }); }); 
      

La soluzione di lavoro più semplice per me è:

  • aggiungere la class keep-open 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'); }); 

Non ho trovato nessuna delle soluzioni ha funzionato come vorrei utilizzare il bootstrap di default. 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; }); 

Invece di scrivere un codice javascript o jquery (reinventando la ruota). Lo scenario sopra può essere gestito dall’opzione di chiusura automatica del bootstrap. Puoi fornire uno dei valori alla chiusura automatica :

  1. sempre – (Predefinito) chiude automaticamente il menu a discesa quando viene fatto clic su uno qualsiasi degli elementi.

  2. outsideClick – chiude automaticamente il menu a discesa solo quando l’utente fa clic su un 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 🙂

Nel contenuto .dropdown metti la class .keep-open 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 container, ora il contenitore eredita la class keep-open e controlla prima di essere chiusa.

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

Per chiudere il menu a discesa solo se un evento click è stato triggersto al di fuori del menu a discesa di avvio, 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:

  

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

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

questo funziona nel 2018

 $(function() { var closeble = false; $('body').on('click', function (e) { if (!$(event.target).is("a.dropdown-toggle")) { closeble = false; } }); $('.dropdown').on({ "click": function(event) { if ($(event.target).closest('.dropdown-toggle').length) { closeble = true; } else { closeble = false; } }, "hide.bs.dropdown": function() { return closeble; } }); 

});