Evite fechar o menu suspenso ao clicar dentro


310

Eu tenho um menu suspenso Twitter Bootstrap. Como todos os usuários do Twitter Bootstrap sabem, o menu suspenso se fecha ao clicar (mesmo clicando dentro dele).

Para evitar isso, posso anexar facilmente um manipulador de eventos de clique no menu suspenso e simplesmente adicionar o 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>

Isso parece fácil e um comportamento muito comum, no entanto, e como carousel-controls(assim como carousel indicators) os manipuladores de eventos são delegados ao documentobjeto, o clickevento nesses elementos ( controles anteriores / próximos , ...) será "ignorado".

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

Contar com o menu suspenso hide/ hiddeneventos do Bootstrap do Twitter não é uma solução pelos seguintes motivos:

  • O objeto de evento fornecido para os dois manipuladores de eventos não fornece referência ao elemento clicado
  • Como não tenho controle sobre o conteúdo do menu suspenso, flagnão é possível adicionar uma classe ou atributo

Este violino é o comportamento normal e esse violino é event.stopPropagation()adicionado.

Atualizar

Agradeço a Roman por sua resposta . Eu também encontrei uma resposta que você pode encontrar abaixo .


1. Seu jsfiddle não está funcionando. 2. O que exatamente você deseja alcançar?
— paulalexandru

1
@paulalexandru, Atualizado, adicionou dois violinos. Um comportamento padrão e outro com modificação. Tente clicar no botão próximo e anterior ou nos indicadores. Para o primeiro exemplo, o menu oculta e o carrossel desliza. ou o segundo exemplo: o menu permanece aberto, mas o carrossel não deslizou desde que o event propagationitem foi parado.
— Php-dev

@paulalexandru Entendi, certo?
— Php-dev

@ php-dev: atualizei-o novamente por uma questão de desafio, agora é perfeito ... veja a demonstração.
— Luca Filosofi 12/08

Respostas:


373

Remover o atributo de dados data-toggle="dropdown"e implementar a abertura / fechamento da lista suspensa pode ser uma solução.

Primeiro, manipule o clique no link para abrir / fechar o menu suspenso assim:

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

e depois ouvir os cliques fora do menu suspenso para fechá-lo assim:

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

Aqui está a demonstração: http://jsfiddle.net/RomaLefrancois/hh81rhcm/2/


2
Esta solução está funcionando bem. A recompensa deve ser concedida a você se não houver outra resposta.
— Php-dev

1
Sua solução está funcionando, genérica e também "popular". A recompensa deve ser concedida à sua resposta. Eu também achei uma resposta, olhada abaixo;)
— php-dev

1
@ Cichy ... apenas modifique o primeiro manipulador como este ... $ ('li.dropdown.mega-dropdown a'). On ('click', function (event) {$ ('li.dropdown.mega-dropdown Abra o arquivo .class () e abra o arquivo .class ();
— dsaket

63
Essa resposta preferida é um hack. Uau!!! Aqui está uma resposta mais simples do BOOTSTRAP 4 ALPHA para evitar cliques internos em um mega menu suspenso. // PREVENT INSIDE CLICK DROPDOWN $('.dropdown-menu').on("click.bs.dropdown", function (e) { e.stopPropagation(); e.preventDefault(); });
— precisa

7
e.stopPropagation()é a melhor solução.
— Nacholibre 29/03/19

332

Isso deve ajudar também

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

33
Eu acho que é com certeza a solução mais simples para esse problema. Polegares para cima - apenas testei este e ele funciona!
— Torsten Barthel

13
Esta é de longe a melhor solução.
— silencioso

3
Essa é a solução mais comum, mas eu tenho um requisito diferente. Por favor, leia atentamente a minha pergunta :)
— php-dev

4
A melhor solução para simplesmente manter o menu aberto em cliques.
— Matt Pierce

2
Melhor solução, de fato. Eu pessoalmente usei '.dropdown-menu :not(.dropdown-item)'para que clicar em um dropdown-itemfecha o pop-up, mas clicar em um dropdown-headernão.
— Benjamin

41

O Bootstrap fornece a seguinte função:

                 | Este evento é acionado imediatamente quando o método de instância hide
hide.bs.dropdown | tem sido chamado. O elemento de âncora de alternância está disponível como o
                 | propriedade relatedTarget do evento.

Portanto, a implementação dessa função deve poder desativar o fechamento da lista suspensa.

$('#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, também a targetpropriedade do evento é a li.dropdown, relatedTargeté a a.dropdown-toggle. Portanto, você não pode se referir ao elemento clicado no hidemanipulador de eventos.
— Php-dev

2
O hasClass usa um nome de classe, não um seletor de CSS. target.hasClass(".keepopen")deveria ser target.hasClass("keepopen"). Caso contrário, o código não funcionará.
— Hugh Guiney

3
Examinei a Internet e essa é a solução mais inteligente, de longe, por esse motivo ... outros métodos exigem uma abordagem que use a interrupção do evento padrão ou a propagação. essas abordagens são muito ruins, pois interromperão qualquer outro evento acionado dentro da lista suspensa (ou seja, meus elementos de formulário móvel do jquery). Essa abordagem permite identificar especificamente quando o menu em si está sendo fechado e permitir que você execute ações somente nesse evento. esta resposta precisa de tantas estrelas ....
— webfish

3
@webfish Quanto você levou para escanear a internet? (rofl)
— php-dev

2
Talvez isso funcionasse .. mas com o bootstrap 4, o e.target é sempre o próprio menu suspenso. Não é o destino clicado. Mesmo se você clicar fora das listas suspensas, e.target ainda será a lista suspensa. Portanto, você não pode executar esse tipo de verificação. Alguém vê uma maneira de contornar isso?
— 21918 FredArters

36

A melhor resposta absoluta é colocar uma tag de formulário após o menu suspenso da classe

então seu código é

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

2
funcionalmente trabalhou esplendidamente para mim, mas quebrou o styling
— 2778

2
esta foi a solução mais rápida para mim #
— Jonathan Morales Vélez

15
Esta não é a melhor resposta :) um <li>elemento não deve estar dentro de um <form> elemento.
— Getah

2
Esta não é uma solução semanticamente correta - o único filho válido de um UL é um LI - se alguma coisa as tags de formulário estiverem dentro das tags li - mas isso não pode impedir a ação desejada - de qualquer maneira uma ul> form> li não é marcação correta
— gavgrif

2
Thnaks para esta solução rápida
— Herman Demsong

27

Eu também encontrei uma solução.

Supondo que os Twitter Bootstrap Componentsmanipuladores de eventos relacionados sejam delegados ao documentobjeto, faço um loop nos manipuladores anexados e verifico se o elemento clicado atual (ou um de seus pais) está relacionado a um evento delegado.

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

Espero que ajude quem procura uma solução semelhante.

Obrigado a todos por sua ajuda.


1
Uau!!! funcionou perfeitamente! Estava com problemas por uma semana, estou usando o mCustomeScrollbar e, depois de clicar na barra de rolagem, ele estava sendo fechado, seu script funcionou e agora está funcionando bem! Graças um milhão.
— eirenaios

funciona bem! como se estende isso, para que um usuário ainda possa pressionar "ESC" (ou até clicar fora) no teclado para fechar o DD?
— Tio Iroh

2
@ MaggewDotCom A tecla ESC ainda deve funcionar. O mesmo para clicar fora ...
— php-dev

A única desvantagem desta solução é que ela não permite dropdowns aninhados (digamos que você tenha um direito dentro de um dropdown). Existe uma solução alternativa para este caso?
— Sdvnksv 26/10/19

26

Isso pode ajudar:

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

Essa é definitivamente a resposta mais simples / melhor se você deseja que um usuário interaja com um elemento da interface do usuário presente no menu suspenso (por exemplo, botões de opção) e não deseja que o menu seja fechado quando alternar as opções.
— 1526 Rob

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

Isso pode funcionar para qualquer condição.


esta deve ser a resposta correcta, uma vez que usa menos linhas de código em vez da resposta escolhida
— Muhammad Omer Aslam

@MuhammadOmerAslam Nah! Como ele não cumprir a minha obrigação
— 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 :

Genérico: https://jsfiddle.net/kerryjohnson/omefq68b/1/

Sua demonstração com esta solução: http://jsfiddle.net/kerryjohnson/80oLdtbf/101/


9

Eu tentei essa coisa simples e funcionou como um encanto.

Alterei o elemento do menu suspenso de <div>para <form>e funcionou bem.

<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

Eu tenho um problema semelhante recentemente e tentou diferentes maneiras de resolvê-lo com a remoção do atributo de dados data-toggle="dropdown"e ouvindo clickcom event.stopPropagation()ligando.

A segunda maneira parece mais preferível. Os desenvolvedores de Bootstrap também usam dessa maneira. No arquivo de origem, encontrei a inicialização dos elementos suspensos:

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

Então, esta linha:

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

sugere que você possa colocar um formelemento dentro do contêiner com a classe .dropdownpara evitar fechar o menu suspenso.


6

O Bootstrap resolveu esse problema eles mesmos no suporte a <form>tags em listas suspensas. A solução deles é bastante compreensível e você pode lê-lo aqui: https://github.com/twbs/bootstrap/blob/v4-dev/js/src/dropdown.js

Tudo se resume a impedir a propagação no elemento do documento e fazê-lo apenas para eventos do tipo 'click.bs.dropdown.data-api'que correspondem ao seletor '.dropdown .your-custom-class-for-keep-open-on-click-elements'.

Ou no código

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

1
Obrigado obrigado obrigado pelo link para a fonte. Para outros que se perguntam por que a formabordagem dos exemplos não está funcionando para você - eu estava usando a classe dropleft, mas também precisa dropdownpara que o seletor de formulários corresponda.
— Mark K Cowan

6

Modifiquei a resposta do @ Vartan para fazê-lo funcionar com o Bootstrap 4.3. Sua solução não funciona mais com a versão mais recente, pois a targetpropriedade sempre retorna a raiz do menu suspenso, divnão importa onde o clique foi colocado.

Aqui está o código:

$('.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 Sinto muito, mas ninguém, simplesmente ninguém pode ler este forro. Escrever código dessa maneira é uma prática ruim.
— ViRuSTriNiTy 9/03

A última linha pode ser simplificada usando return !target.closest('.dropdown-keep-open').length). Dito isto, esta é uma ótima solução! Achei isso necessário para resolver esse problema.
— patrick3853

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

Primeiro, obrigado pela sua resposta. A pergunta já está respondida. Além disso, tenho um requisito diferente, conforme descrito na pergunta, do que o requisito comum.
— 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');
});

Atualizei-o novamente para ser o mais inteligente e funcional possível. agora fecha quando você passa o mouse fora da nav, permanecendo aberto enquanto estiver dentro dela. simplesmente perfeita.


Sua solução é inteligente devido à sua falta, no entanto, após a adição da classe show, o menu suspenso não fecha ao clicar fora, e precisamos clicar no menu suspenso antes de ... +1 de qualquer maneira
— php-dev

Eu atualizei, veja a demonstração. é a melhor causa, não verifique o evento de clique no corpo toda vez. afetam apenas o elemento dentro de cada elemento nav não fora dele.
— Luca Filosofi 12/08

Minha solução também não dependem de bodyevento clique ^^
— php-dev

sim, ele retransmite parcialmente o evento de clique no corpo, tenta verificar em qual elemento foi clicado através da delegação do corpo. $('body').on('click', function (e) {
— Luca Filosofi

Nah! Essa não é a minha resposta. Minha resposta é a última postada.
— Php-dev

4

Como por exemplo, o Bootstrap 4 Alpha possui este Menu Event. Por que não usar?

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

1
e.preventDefault();bloqueia links, você pode ignorá-lo
— long

@czachor você está certo! e.preventDefault (); Impedir que um link siga o URL.
— 24518 Frank Thoeny

3

Você pode interromper a propagação da lista suspensa e reimplementar manualmente os controles do carrossel usando métodos javascript do carrossel .

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

Aqui está o jsfiddle .


Seu exemplo funciona bem, mas o problema é que o menu suspenso pode conter qualquer conteúdo e não só imagens carrossel ...
— php-dev

3

Com o Angular2 Bootstrap, você pode usar nonInput na maioria dos cenários:

<div dropdown autoClose="nonInput">

nonInput - (padrão) fecha automaticamente a lista suspensa quando qualquer um de seus elementos é clicado - desde que o elemento clicado não seja uma entrada ou uma área de texto.

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


2

Eu sei que esta pergunta foi especificamente para jQuery, mas para quem usa AngularJS com esse problema, você pode criar uma diretiva que lida com isso:

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

Em seguida, basta adicionar o atributo dropdown-prevent-closeao seu elemento que está acionando o menu para fechar, e isso deve impedi-lo. Para mim, foi um selectelemento que fechou automaticamente o 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()">funciona para mim no 1.2.x
— dr3w 06/07

2

[Bootstrap 4 Alpha 6] [Rails] para o Rails desenvolvedor, e.stopPropagation()vai levar a um comportamento indesejável para link_tocom data-methodnão é igual a getuma vez que, por padrão, devolver todo o seu pedido oget .

Para remediar esse problema, sugiro esta solução, que é universal

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


2

Em vez de escrever algum código javascript ou jquery (reinventar a roda). O cenário acima pode ser gerenciado pela opção de fechamento automático de autoinicialização. Você pode fornecer um dos valores para fechar automaticamente :

  1. sempre - (Padrão) fecha automaticamente o menu suspenso quando qualquer um dos seus elementos é clicado.

  2. outsideClick - fecha a lista suspensa automaticamente somente quando o usuário clica em qualquer elemento fora da lista suspensa.

  3. desabilitado - desativa o fechamento automático

Dê uma olhada no seguinte plunkr:

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

Conjunto

uib-dropdown auto-close="disabled" 

Espero que isto ajude :)


5
Deve-se notar explicitamente que isso é bom apenas para as pessoas que usam ui-bootstrap, o que provavelmente não é o caso de muitas pessoas que visualizam essa pergunta.
— precisa saber é o seguinte

Você descreveu bem, mas acho que deveria escrever a solução como uib-dropdown auto-close="outsideClick". O menu fechar ao clicar dentro é apenas um pouco desconfortável, mas o menu não fecha ao clicar fora é bastante perturbador.
— vusan

2

Sei que já existe uma resposta anterior sugerindo o uso de um formulário, mas a marcação fornecida não está correta / ideal. Aqui está a solução mais fácil, não é necessário javascript e isso não interrompe o seu menu suspenso. Funciona com o Bootstrap 4.

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


@RosdiKasim Estou funcionando bem em um site com o Bootstrap 4.0.0. Não testei com 4,1
— Radu Ciobanu

Na verdade, deve ser como: <form class = "dropdown dropdown-item">
— Nasser Sadraee

2

Isso me ajudou,

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

Seu elemento do menu suspenso precisa ser assim (observe as classes dropdown-menue keepopen.

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

O código acima evita a espera geral <body>, em vez do elemento específico da classe dropdown-menu.

Espero que isso ajude alguém.

Obrigado.


Agradecimentos atualizados conforme o Bootstrap 4 $ ('. Menu suspenso [data-handledropdownclose = "true"]'). On ('clique', função (e) {if ($ (this) .parent (). Is (" .show ")) {var target = $ (e.target); return (target.hasClass (" CloseDropDown ") || target.parents (". CloseDropDown "). length);}});
— Thulasiram 29/04

1

A solução de trabalho mais simples para mim é:

  • adicionando keep-openclasse a elementos que não devem causar fechamento suspenso
  • e este pedaço de código faz o resto:
$('.dropdown').on('click', function(e) {
    var target = $(e.target);
    var dropdown = target.closest('.dropdown');
    return !dropdown.hasClass('open') || !target.hasClass('keep-open');
});

você pode por favor me ajudar a consertar esse stackoverflow.com/questions/51552712/… @ Gee-Bee
— Zhu

1

Descobri que nenhuma das soluções funcionou como gostaria de usar a navegação padrão de inicialização. Aqui está minha solução para esse 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

No .dropdownconteúdo, coloque a .keep-openclasse em qualquer etiqueta da seguinte forma:

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

Os casos anteriores evitavam os eventos relacionados aos objetos de contêiner, agora o contêiner herda a classe keep-open e check antes de ser fechado.


1

Eu fiz isso com isso:

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

Para fechar a lista suspensa apenas se um evento de clique foi acionado fora da lista suspensa de inicialização, é isso que funcionou para mim:

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

Arquivo 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

Você pode ter alguns problemas se usar o método return false ou stopPropagation () porque seus eventos serão interrompidos. Experimente este código, funciona bem:

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

Em 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 você deseja fechar o dropdrown:

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

0

No Bootstrap 4, você também pode fazer isso:

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

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

onde #dd-linké o elemento âncora ou botão que possui a data-toggle="drowndown"propriedade

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.