javascript plugin - Evitar cerrar el menú desplegable al hacer clic dentro





dropdown bootstrap (22)


Con Angular2 Bootstrap, puede usar nonInput para la mayoría de los escenarios:

<div dropdown autoClose="nonInput">

nonInput: (predeterminado) cierra automáticamente el menú desplegable cuando se hace clic en cualquiera de sus elementos, siempre que el elemento en el que se haga clic no sea una entrada o un área de texto.

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

Tengo un menú desplegable de Twitter Bootstrap. Como todos los usuarios de Twitter Bootstrap saben, el menú desplegable se cierra al hacer clic (incluso al hacer clic en é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 es un comportamiento muy común, y como carousel-controls eventos carousel-controls (así como los carousel indicators ) se delegan al objeto del 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 Twitter Bootstrap desplegable hide / eventos hidden no es una solución por las siguientes razones:

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

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

Actualizar

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




Bootstrap ha resuelto este problema ellos mismos en su compatibilidad con las etiquetas <form> en los menús desplegables. Su solución es bastante comprensible y puede leerla aquí: https://github.com/twbs/bootstrap/blob/v4-dev/js/src/dropdown.js

Se reduce a prevenir la propagación en el elemento del documento y solo lo hace para eventos del tipo 'click.bs.dropdown.data-api' que coinciden con el selector '.dropdown .your-custom-class-for-keep-open-on-click-elements' .

O en codigo

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



Sé que ya hay una respuesta anterior que sugiere utilizar un formulario, pero el marcado proporcionado no es correcto / ideal. Aquí está la solución más fácil, no se necesita javascript en absoluto y no rompe su menú desplegable. Funciona con Bootstrap 4.

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




Para cerrar la lista desplegable solo si se activó un evento de clic fuera de la lista 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>



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



La mejor respuesta absoluta es colocar una etiqueta de formulario después del menú desplegable de la clase

entonces tu código es

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



En el contenido de .dropdown , coloque la clase .keep-open en cualquier etiqueta, de esta 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
    }
});

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




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

esto funciona en 2018




Esto podría ayudar:

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



La solución de trabajo más simple para mí es:

  • agregando la clase keep-open a los elementos que no deberían causar el cierre desplegable
  • Y esta pieza de código hace el resto:
$('.dropdown').on('click', function(e) {
    var target = $(e.target);
    var dropdown = target.closest('.dropdown');
    return !dropdown.hasClass('open') || !target.hasClass('keep-open');
});



En lugar de escribir algún código javascript o jquery (reinventar la rueda). El escenario anterior se puede gestionar 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 - desactiva el cierre automático

Echa un vistazo a la siguiente plunkr:

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

Conjunto

uib-dropdown auto-close="disabled" 

Espero que esto ayude :)




$('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 ser el más inteligente y funcional posible. ahora se cierra cuando se desplaza fuera del navegador, permaneciendo abierto mientras está dentro de él. Simplemente perfecto.




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>

Demostración :

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

Su demostración con esta solución: http://jsfiddle.net/kerryjohnson/80oLdtbf/101/




No he encontrado ninguna de las soluciones que funcionen como me gustaría usar el bootstrap nav 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;
       });



Tengo un problema similar recientemente e intenté diferentes maneras de resolverlo eliminando el atributo de data-toggle="dropdown" y escuchando haciendo click con el event.stopPropagation() llamando.

La segunda forma se ve más preferible. También los desarrolladores de Bootstrap usan de esta manera. En el archivo fuente encontré la inicialización de los elementos desplegables:

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

Por lo tanto, esta línea:

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

sugiere que puede colocar un elemento de form dentro del contenedor con la clase .dropdown para evitar cerrar el menú desplegable.




Esto debería ayudar también

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



Puede dejar de hacer clic en el menú desplegable de propagación y luego volver a implementar manualmente los controles del carrusel utilizando los métodos de javascript del carrusel .

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




Sé que esta pregunta fue específicamente para jQuery, pero para cualquier persona que use AngularJS que tenga este problema, puede crear una directiva que maneje esto:

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

Luego simplemente agregue el atributo dropdown-prevent-close a su elemento que está activando el cierre del menú, y debería evitarlo. Para mí, fue un elemento de select que cerró automáticamente el menú:

<div class="dropdown-menu">
  <select dropdown-prevent-close name="myInput" id="myInput" ng-model="myModel">
    <option value="">Select Me</option>
  </select>
</div>



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

});




Bootstrap proporciona la siguiente función:

                 | This event is fired immediately when the hide instance method 
hide.bs.dropdown | has been called. The toggling anchor element is available as the 
                 | relatedTarget property of the event.

Por lo tanto, la implementación de esta función debería poder desactivar el menú desplegable de cierre.

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



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



Puede usar selectElement.value para obtener el valor de la opción seleccionada de la selección.

document.getElementById("idOfSelect").value;

var res = document.querySelector('p');
var select = document.querySelector('select');
res.textContent = "Selected Value: "+select.value;
select.addEventListener("change", function(e){
  res.textContent = "Selected Value: "+select.value;
});
<select>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
Change value of the select to show the value.
<p>
</p>





javascript jquery html twitter-bootstrap-3 drop-down-menu