Избегайте выпадающего меню закрыть по щелчку внутри



у меня есть выпадающее меню Twitter Bootstrap. Как знают все пользователи Twitter Bootstrap, выпадающее меню закрывается при щелчке (даже щелчок внутри него).



чтобы избежать этого, я могу легко прикрепить обработчик событий click в выпадающем меню и просто добавить знаменитый 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>


это выглядит легко и очень распространенное поведение, впрочем, и с carousel-controls (а также carousel indicators) обработчики событий делегируются

1281   24  

24 ответов:

удаление данных атрибута data-toggle="dropdown" и реализация open / close выпадающего списка может быть решением.

во-первых, обработав щелчок по ссылке, чтобы открыть / закрыть раскрывающийся список следующим образом:

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

а затем слушать щелчки за пределами выпадающего списка, чтобы закрыть его следующим образом:

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

вот демо : http://jsfiddle.net/RomaLefrancois/hh81rhcm/2/

Это тоже должно помочь

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

Bootstrap предоставляет следующую функцию:

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

таким образом, реализация этой функции должна быть в состоянии отключить выпадающее меню от закрытия.

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

абсолютный лучший ответ-поставить тег формы после выпадающего меню класса

Итак, ваш код

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

Я нашел решение.

предполагая, что Twitter Bootstrap Components обработчики связанных событий делегируются document объект, я зацикливаю прикрепленные обработчики и проверяю, связан ли текущий элемент clicked (или один из его родителей) с делегированным событием.

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

надеюсь, что это поможет любому, кто ищет подобное решение.

спасибо всем за помощь.

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

Это может работать на любых условиях.

Это может помочь:

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

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>

демо:

универсальный: https://jsfiddle.net/kerryjohnson/omefq68b/1/

ваша демонстрация с этим решением:http://jsfiddle.net/kerryjohnson/80oLdtbf/101/

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

я обновил его еще раз, чтобы быть самым умным и функциональным. теперь он закрывается, когда вы зависаете за пределами навигатора, оставаясь открытым, пока вы находитесь внутри него. просто идеально.

недавно у меня была аналогичная проблема, и я пробовал разные способы ее решения с удалением атрибута данных data-toggle="dropdown" и прослушивания click С event.stopPropagation() призвание.

второй способ выглядит предпочтительнее. Также Разработчики Bootstrap используют этот способ. В исходном файле я нашел инициализацию выпадающих элементов:

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

Итак, эта строка:

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

предлагает вам поставить form элемент внутри контейнера с классом .dropdown чтобы избежать закрытие выпадающего меню.

вы можете остановить щелчок на выпадающем списке от распространения, а затем вручную переопределить элементы управления каруселью с помощью карусель 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);
});

здесь jsfiddle.

С Angular2 Bootstrap, вы можете использовать nonInput для большинства сценариев:

<div dropdown autoClose="nonInput">

nonInput - (по умолчанию) автоматически закрывает выпадающий список при нажатии любого из его элементов-до тех пор, пока щелкнутый элемент не является входом или текстовым полем.

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

как, например, Bootstrap 4 Alpha имеет это событие меню. Почему бы не использовать?

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

Я знаю, что этот вопрос был специально для jQuery, но для тех, кто использует AngularJS, у которого есть эта проблема, вы можете создать директиву, которая обрабатывает это:

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

тогда просто добавьте атрибут dropdown-prevent-close к вашему элементу, который запускает меню, чтобы закрыть, и он должен предотвратить его. Для меня это было select элемент, который автоматически закрывается меню:

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

[Bootstrap 4 Alpha 6][Rails] Для разработчика rails,e.stopPropagation() приведет к нежелательному поведению для link_to С data-method не равно get так как он будет по умолчанию возвращать все ваши запросы как get.

чтобы исправить эту проблему, я предлагаю такое решение, которое является универсальным

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

$('.dropdown .dropdown-menu').on('click.bs.dropdown', function() {
  return $('.dropdown').one('hide.bs.dropdown', function() {
    return false;
  });
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>

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

самое простое рабочее решение для меня-это:

  • добавлять keep-open класс для элементов, которые не должны вызвать выпадающее закрытия
  • и этот кусок кода делает все остальное:
$('.dropdown').on('click', function(e) {
    var target = $(e.target);
    var dropdown = target.closest('.dropdown');
    return !dropdown.hasClass('open') || !target.hasClass('keep-open');
});

Я не нашел ни одного из решений, которые работали бы так, как я хотел бы использовать по умолчанию bootstrap nav. Вот мое решение этой проблемы:

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

вместо написания кода javascript или jquery(изобретение колеса). Вышеприведенный сценарий может управляться опцией автоматического закрытия начальной загрузки. Вы можете указать любое из значений для закрыть:

  1. всегда - (по умолчанию) автоматически закрывает выпадающий список при нажатии любого из его элементов.

  2. outsideClick - закрывает выпадающий список автоматически только тогда, когда пользователь щелкает любой элемент за пределами раскрывающийся.

  3. disabled-отключает автоматическое закрытие

взгляните на следующих plunkr :

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

Set

uib-dropdown auto-close="disabled" 

надеюсь, что это помогает :)

на .dropdown содержание поставить .keep-open класс на любой метке вот так:

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

предыдущие случаи избежали событий, связанных с объектами контейнера, теперь контейнер наследует класс keep-open и проверяет перед закрытием.

Я знаю, что уже есть в предыдущем ответе, предложив использовать форму, но синтаксис не правильный/идеальный. Вот самое простое решение, не требуется javascript вообще, и это не нарушает ваш выпадающий список. Работы с Bootstrap 4.

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

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

это работает в 2018 году

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

для закрытия выпадающего списка только в том случае, если событие click было вызвано вне раскрывающегося списка bootstrap, это то, что сработало для меня:

JS file:

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

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

});

Comments

    Ничего не найдено.