[javascript] Evite el menú desplegable al hacer clic en el interior



Answers

Esto también debería ayudar

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

Tengo un menú desplegable de Twitter Bootstrap. Como todos los usuarios de Twitter Bootstrap saben, el menú desplegable se cierra al hacer clic (incluso haciendo clic dentro de él).

Para evitar esto, puedo adjuntar fácilmente un controlador de eventos de clic en el menú desplegable y simplemente agregar el 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>

Sin embargo, esto parece fácil y un comportamiento muy común, y dado que carousel-controls eventos de carousel-controls (así como carousel indicators ) se delegan en el objeto de document , el evento de click en estos elementos (controles anterior / siguiente , ...) 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();
});

Confiar en hidden eventos hidden / hidden Bootstrap en Twitter no es una solución por las siguientes razones:

  • El evento proporcionado para ambos controladores de eventos no le da referencia al elemento cliqueado
  • El contenido del menú desplegable se genera dinámicamente, por lo que no es posible agregar una clase de flag

Este violín es el comportamiento normal y este violín es con event.stopPropagation() agregado.

Actualizar

Gracias a Roman por su respuesta . También encontré una respuesta que puedes encontrar a continuación .




Como, por ejemplo, Bootstrap 4 Alpha tiene este evento de menú. ¿Por qué no usar?

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



Puede dejar de hacer clic en el menú desplegable para propagar y luego volver a implementar manualmente los controles del carrusel utilizando los métodos de carrusel de JavaScript .

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

Aquí está el jsfiddle .




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



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

Esto puede funcionar para cualquier condición.




Para cerrar el menú desplegable solo si se activó un evento de clic fuera del menú desplegable de arranque, esto es lo que funcionó para mí:

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

Archivo 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>



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

lo he actualizado una vez más para que sea lo más inteligente y funcional posible. ahora se cierra cuando pasas el navegador, permaneciendo abierto mientras estás dentro de él. Simplemente perfecto.




En .dropdown content coloca la clase .keep-open en cualquier etiqueta como esta:

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

Los casos anteriores evitaron los eventos relacionados con los objetos del contenedor, ahora el contenedor hereda la clase keep-open y check antes de ser cerrada.




También encontré una solución.

Suponiendo que los manejadores de eventos relacionados con los Twitter Bootstrap Components estén delegados en el objeto del document , hago un ciclo en los manejadores adjuntos y verifico si el elemento al que se hace clic actualmente (o uno de sus padres) está afectado por un 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 ayude a cualquiera que busque una solución similar.

Gracias por toda tu ayuda.




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

});




En lugar de escribir algún código javascript o jquery (reinventar la rueda). El escenario anterior se puede administrar mediante la opción de cierre automático de arranque. Puede proporcionar cualquiera de los valores para cerrar automáticamente :

  1. siempre - (Predeterminado) cierra automáticamente el menú desplegable cuando se hace clic en cualquiera de sus elementos.

  2. OutsideClick: cierra el menú desplegable automáticamente solo cuando el usuario hace clic en cualquier elemento fuera del menú desplegable.

  3. deshabilitado - deshabilita el cierre automático

Eche un vistazo al siguiente plunkr:

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

Conjunto

uib-dropdown auto-close="disabled" 

Espero que esto ayude :)




No he encontrado ninguna de las soluciones trabajadas, ya que me gustaría usar el navegador bootstrap predeterminado. Aquí está mi solución a este problema:

       $(document).on('hide.bs.dropdown', function (e) {
        if ($(e.currentTarget.activeElement).hasClass('dropdown-toggle')) {
          $(e.relatedTarget).parent().removeClass('open');
          return true;
        }
        return false;
       });





Related