Mantenha a lista suspensa Bootstrap aberta ao clicar

86

Eu uso uma lista suspensa de bootstrap como um carrinho de compras. No carrinho de compras existe um botão 'remover produto' (um link). Se eu clicar nele, meu script de carrinho de compras remove o produto, mas o menu desaparece. Existe alguma maneira de evitar isso? Tentei o e.startPropagation, mas não funcionou:

<div id="shoppingcart" class="nav-collapse cart-collapse">
 <ul class="nav pull-right">
  <li class="dropdown open">
    <a href="#" data-toggle="dropdown" class="dropdown-toggle">Totaal:
    &acirc;&sbquo;&not; 43,00</a>

    <ul class="dropdown-menu">
      <li class="nav-header">Pakketten</li>

      <li>
       <span class="quantity">1x</span>
       <span class="product-name">Test Product </span>
       <span class="product-remove"><a class="removefromcart" packageid="4" href="#">x</a>
        </span></li>

      <li><a href="#">Total: &euro; 43,00</a></li>

      <li><a href="/checkout">Checkout</a></li>
    </ul>
  </li>
</ul>

Como você pode ver, o elemento com class = "dropwdown-toggle" o tornou um menu suspenso. Outra ideia é que eu apenas reabra clicando de forma programática. Então, se alguém puder me explicar como abrir programaticamente um menu suspenso do Bootstrap, isso ajudaria muito!

Marten Sytema
fonte
1
Vejo que você já tem uma resposta, mas existe uma maneira muito mais simples. Basta envolver o conteúdo do menu em uma tag de formulário. É isso aí. Portanto, em vez de ul.dropdown-menuusar form.dropdown-menu>ul.
rdumont

Respostas:

100

Tente remover a propagação do próprio botão da seguinte maneira:

$('.dropdown-menu a.removefromcart').click(function(e) {
    e.stopPropagation();
});

Editar

Aqui está uma demonstração dos comentários com a solução acima:

http://jsfiddle.net/andresilich/E9mpu/

Código relevante:

JS

$(".removefromcart").on("click", function(e){
    var fadeDelete = $(this).parents('.product');
    $(fadeDelete).fadeOut(function() {
        $(this).remove();
    });

    e.stopPropagation();
});

HTML

<div id="shoppingcart" class="nav-collapse cart-collapse">
 <ul class="nav pull-right">
  <li class="dropdown open">
    <a href="#" data-toggle="dropdown" class="dropdown-toggle">Totaal:
    &acirc;&sbquo;&not; 43,00</a>

    <ul class="dropdown-menu">
      <li class="nav-header">Pakketten</li>
        <li class="product">
            <span class="product-remove"><a class="removefromcart" packageid="2" href="#"><i class="icon-remove"></i></a></span>
            <span class="product-name">Test Product </span>
            <span class="quantity"><span class="badge badge-inverse">1</span></span>
        </li>
        <li class="product">
            <span class="product-remove"><a class="removefromcart" packageid="2" href="#"><i class="icon-remove"></i></a></span>
            <span class="product-name">Test Product </span>
            <span class="quantity"><span class="badge badge-inverse">10</span></span>
        </li>
        <li class="product">
            <span class="product-remove"><a class="removefromcart" packageid="2" href="#"><i class="icon-remove"></i></a></span>
            <span class="product-name">Test Product </span>
            <span class="quantity"><span class="badge badge-inverse">8</span></span>
        </li>
        <li class="product">
            <span class="product-remove"><a class="removefromcart" packageid="2" href="#"><i class="icon-remove"></i></a></span>
            <span class="product-name">Test Product </span>
            <span class="quantity"><span class="badge badge-inverse">3</span></span>
        </li>
        <li class="product">
            <span class="product-remove"><a class="removefromcart" packageid="2" href="#"><i class="icon-remove"></i></a></span>
            <span class="product-name">Test Product </span>
            <span class="quantity"><span class="badge badge-inverse">4</span></span>
        </li>
        <li class="divider"></li>
        <li><a href="#">Total: &euro; 43,00</a></li>
        <li><a href="/checkout">Checkout</a></li>
    </ul>
  </li>
</ul>
Andres Ilich
fonte
Ok, isso funciona, mas agora o botão Remover não está mais funcionando, o que eu poderia ter imaginado. Portanto, provavelmente eu preciso reabrir programaticamente o div. Alguma ideia de como fazer isso?
Marten Sytema
@MartenSytema que tudo depende de como você está removendo os produtos do menu, mas veja isso por exemplo: jsfiddle.net/andresilich/E9mpu , observe como eu implementei o .stopPropagation()método junto com o script de remoção.
Andres Ilich
Obrigado por ajudar! O único problema é que preciso usar o método live jquery para vincular o evento de clique e, como diz o jQuery: Como o método .live () lida com eventos depois que eles se propagam para o topo do documento, não é possível parar a propagação de eventos ao vivo. link
Marten Sytema
@MartenSytema ambos os métodos fazem a mesma coisa. Além disso, .live()está obsoleto a partir da versão 1.7 do jQuery.
Andres Ilich
@MartenSytema esqueceu de mencionar e .live()foi substituído por .on().
Andres Ilich
36

Essa resposta é apenas uma nota à parte da resposta aceita. Graças ao OP e ao Andres por essas perguntas e respostas, isso resolveu meu problema. Mais tarde, entretanto, eu precisava de algo que funcionasse com itens adicionados dinamicamente em meu menu suspenso. Qualquer pessoa que encontrar isso também pode estar interessado em uma solução de variação de Andres que funciona tanto com os elementos iniciais quanto com os elementos adicionados à lista suspensa após o carregamento da página:

$(function() {
    $("ul.dropdown-menu").on("click", "[data-keepOpenOnClick]", function(e) {
        e.stopPropagation();
    });
});

Ou, para menus suspensos criados dinamicamente:

$(document).delegate("ul.dropdown-menu [data-keepOpenOnClick]", "click", function(e) {
    e.stopPropagation();
});

Em seguida, basta colocar o data-keepOpenOnClickatributo em qualquer uma das <li>tags ou seus elementos filhos, dependendo da sua situação. POR EXEMPLO:

<ul class="dropdown-menu">
    <li>
        <-- EG 1: Do not close when clicking on the link -->
        <a href="#" data-keepOpenOnClick>
            ...
        </a>
    </li>
    <li>
        <-- EG 2: Do not close when clicking the checkbox -->
        <input type="checkbox" data-keepOpenOnClick> Pizza
    </li>

    <-- EG 3: Do not close when clicking the entire LI -->
    <li data-keepOpenOnClick>
        ...
    </li>
</ul>
Don Vaughn
fonte
20

No bootstrap 4, quando você coloca um formulário dentro do menu suspenso, ele não entra em colapso ao clicar dentro dele.

Então, isso funcionou melhor para mim:

<div class="dropdown">
    <!-- toggle button/link -->
    <div class="dropdown-menu">
        <form>
            <!-- content -->
        </form>
    </div>
</div>
Hugo Mota
fonte
2
Não sei como, mas isso funciona e deve ser a resposta principal.
Dimitri Mostrey
Muito obrigado por fornecer uma resposta que não usa jQuery! Funciona como um encanto.
Mladen Ristic
13

Resumindo, você pode tentar isso. Está funcionando para mim.

<span class="product-remove">
  <a class="removefromcart" onclick=" event.stopPropagation();" packageid="4" href="#">x</a>
  </span>

fonte
3

O menu é aberto quando você dá showaula ao menu, para que você possa implementar a função sozinho, sem usar data-toggle="dropdown".

<div class="dropdown">
  <button class="btn btn-secondary" type="button">
    Dropdown button
  </button>
  <div class="dropdown-menu">
    <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>
<div id="overlay"></div>
#overlay{
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  z-index: 1000;
  display: none;
}

#overlay.show{
  display: block;
}

.dropdown-menu{
  z-index: 1001;
}
$('button, #overlay').on('click', function(){
  $('.dropdown-menu, #overlay').toggleClass('show')
})

Tente isso no codepen .

Masamoto Miyata
fonte
2

Eu estava tendo o mesmo problema com um submenu acordeão / alternar aninhado em um menu suspenso no Bootstrap 3. Esta sintaxe emprestada do código-fonte para impedir que todos os alternadores de recolhimento fechem o menu suspenso:

$(document).on(
    'click.bs.dropdown.data-api', 
    '[data-toggle="collapse"]', 
    function (e) { e.stopPropagation() }
);

Você pode substituir [data-toggle="collapse"]o que quiser para parar de fechar o formulário, semelhante a como @DonamiteIsTnt adicionou uma propriedade para fazer isso.

Astockwell
fonte
1

Eu escrevi algumas linhas de código que fazem com que ele funcione tão perfeito quanto precisamos, com mais controle sobre ele:

$(".dropdown_select").on('hidden.bs.dropdown', function () {
    if($(this).attr("keep-open") == "true") {
        $(this).addClass("open");
        $(this).removeAttr("keep-open");
    }
});

$(".dropdown_select ul li").bind("click", function (e) {
    // DO WHATEVER YOU WANT
    $(".dropdown_select").attr("keep-open", true);
});
user2991574
fonte