Mantenga abierto el menú desplegable de Bootstrap al hacer clic

85

Utilizo un menú desplegable bootstrap como carrito de compras. En el carrito de compras hay un botón de 'eliminar producto' (un enlace). Si hago clic en él, la secuencia de comandos de mi carrito de compras elimina el producto, pero el menú desaparece. ¿Hay alguna forma de prevenir esto? Probé e.startPropagation, pero eso no pareció funcionar:

<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 puede ver, el elemento con class = "dropwdown-toggle" lo convirtió en un menú desplegable. Otra idea fue que simplemente lo volviera a abrir al hacer clic mediante programación. Entonces, si alguien me puede explicar cómo abrir programáticamente un menú desplegable de Bootstrap, ¡sería de gran ayuda!

Marten Sytema
fuente
1
Veo que ya tienes una respuesta, pero hay una forma mucho más sencilla. Simplemente envuelva el contenido del menú en una etiqueta de formulario. Eso es. Entonces, en lugar de ul.dropdown-menu, use form.dropdown-menu>ul.
rdumont

Respuestas:

100

Intente eliminar la propagación en el botón de esta manera:

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

Editar

Aquí hay una demostración de los comentarios con la solución anterior:

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>
Andrés Ilich
fuente
Está bien, esto funciona, pero ahora el botón de eliminar ya no funciona, lo cual podría haber pensado en mí mismo. Entonces probablemente NECESITO volver a abrir programáticamente el div. ¿Alguna idea de cómo hacerlo?
Marten Sytema
@MartenSytema, todo depende de cómo elimine los productos del menú, pero tome esto por ejemplo: jsfiddle.net/andresilich/E9mpu , observe cómo implementé el .stopPropagation()método junto con el script de eliminación.
Andres Ilich
¡Gracias por ayudar! El único problema es que necesito usar el método jquery en vivo para vincular el evento de clic, y como dice jQuery: Dado que el método .live () maneja los eventos una vez que se han propagado a la parte superior del documento, no es posible detener la propagación de eventos en vivo. enlace
Marten Sytema
@MartenSytema ambos métodos hacen lo mismo. Además, .live()ha quedado obsoleto a partir de la versión 1.7 de jQuery.
Andres Ilich
@MartenSytema olvidó mencionar, .live()fue reemplazado por .on().
Andres Ilich
36

Esta respuesta es solo una nota al margen de la respuesta aceptada. Gracias tanto al OP como a Andrés por esta sesión de preguntas y respuestas, resolvió mi problema. Más tarde, sin embargo, necesitaba algo que funcionara con elementos agregados dinámicamente en mi menú desplegable. Cualquiera que se encuentre con este también podría estar interesado en una variante de la solución de Andrés que funciona tanto con los elementos iniciales como con los elementos agregados al menú desplegable después de que se haya cargado la página:

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

O, para menús desplegables creados dinámicamente:

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

Luego, coloque el data-keepOpenOnClickatributo en cualquier lugar de cualquiera de las <li>etiquetas o sus elementos secundarios, dependiendo de su situación. P.EJ:

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

En bootstrap 4, cuando coloca un formulario dentro del menú desplegable, no se colapsará al hacer clic dentro de él.

Entonces esto funcionó mejor para mí:

<div class="dropdown">
    <!-- toggle button/link -->
    <div class="dropdown-menu">
        <form>
            <!-- content -->
        </form>
    </div>
</div>
Hugo Mota
fuente
2
No sé cómo, pero esto funciona y debería ser la mejor respuesta.
Dimitri Mostrey
¡Muchas gracias por proporcionar una respuesta que no usa jQuery! Funciona de maravilla.
Mladen Ristic
13

En resumen, puedes probar esto. Me está funcionando.

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

fuente
3

El menú se abre cuando le das showclase al menú, por lo que puedes implementar la función tú mismo sin 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')
})

Pruebe esto en codepen .

Masamoto Miyata
fuente
2

Estaba teniendo el mismo problema con un submenú de acordeón / alternar que estaba anidado dentro de un menú desplegable en Bootstrap 3. Tomé prestada esta sintaxis del código fuente para evitar que todas las alternancias de colapso cierren el menú desplegable:

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

Puede reemplazar [data-toggle="collapse"]con lo que desee para dejar de cerrar el formulario, de manera similar a cómo @DonamiteIsTnt agregó una propiedad para hacerlo.

Astockwell
fuente
1

Escribí algunas líneas de código que hacen que funcione tan perfecto como necesitamos con más control sobre él:

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