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

310

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

Чтобы избежать этого, я могу легко добавить обработчик события щелчка в выпадающем меню и просто добавить известное 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) обработчики событий делегируются documentобъекту, clickсобытие в этих элементах ( prev / next control, ...) будет «игнорироваться».

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

Опора на Twitter Bootstrap dropdown hide/ hiddenevents не является решением по следующим причинам:

  • Предоставленный объект события для обоих обработчиков событий не дает ссылку на выбранный элемент
  • У меня нет контроля над содержимым выпадающего меню, поэтому добавить flagкласс или атрибут невозможно

Эта скрипка является нормальным поведением, и эта скрипка с event.stopPropagation()добавленным.

Обновить

Спасибо Роману за ответ . Я также нашел ответ, который вы можете найти ниже .

PHP-DEV
источник
1. Ваш jsfiddle не работает. 2. Чего именно вы хотите достичь?
paulalexandru
1
@paulalexandru, обновил, добавил две скрипки. Одно поведение по умолчанию и одно с модификацией. Попробуйте нажать на кнопку «следующий и предыдущий» или на индикаторы. Для первого примера меню скрывается и слайды карусели. или второй пример: меню остается открытым, но карусель не скользила, поскольку event propagationбыла остановлена.
php-dev
@paulalexandru Понял, верно?
php-dev
@ php-dev: я снова обновил его ради испытания, теперь он идеален ... посмотрите демо.
Лука Философи

Ответы:

373

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

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

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

Рома
источник
2
Это решение работает нормально. Щедрость должна быть присуждена вам, если нет другого ответа.
php-dev
1
Ваше решение работает, универсально, а также «популярно». Награда должна быть присуждена на ваш ответ. Я также нашел ответ, посмотрите на него ниже;)
php-dev
1
@Cichy ... просто измените первый обработчик следующим образом ... $ ('li.dropdown.mega-dropdown a'). On ('click', function (event) {$ ('li.dropdown.mega-dropdown .open '). removeClass (' open '); $ (this) .parent (). toggleClass (' open ');});
дсакет
63
Этот предпочтительный ответ взломать. Вот это да!!! Вот более простой ответ BOOTSTRAP 4 ALPHA для предотвращения внутреннего щелчка в мега-выпадающем меню. // PREVENT INSIDE CLICK DROPDOWN $('.dropdown-menu').on("click.bs.dropdown", function (e) { e.stopPropagation(); e.preventDefault(); });
Фрэнк Туни
7
e.stopPropagation()это лучшее решение.
Начолибре
332

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

$(document).on('click', 'someyourContainer .dropdown-menu', function (e) {
  e.stopPropagation();
});
Arbejdsglæde
источник
33
Я думаю, что это, безусловно, самое простое решение этой проблемы. Недурно - только что проверил этот, и он работает!
Торстен Бартел
13
Это, безусловно, лучшее решение.
тихо
3
Это наиболее распространенное решение, но у меня другое требование. Пожалуйста, внимательно прочитайте мой вопрос :)
php-dev
4
Лучшее решение для простого сохранения меню открытым по кликам.
Мэтт Пирс,
2
Лучшее решение действительно. Лично я использовал для '.dropdown-menu :not(.dropdown-item)'того, чтобы щелкнуть на dropdown-itemзакрывает всплывающее окно, но нажатие на dropdown-headerнет.
Бенджамин
41

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

                 | Это событие вызывается сразу, когда метод экземпляра скрытия
hide.bs.dropdown | был вызван. Переключающий элемент привязки доступен как
                 | relatedTarget свойство события.

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

$('#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;
    }
});
Вартан
источник
2
@Vartan, тоже targetсвойство события есть li.dropdown, это relatedTargetесть a.dropdown-toggle. Таким образом, вы не можете ссылаться на выбранный элемент в hideобработчике событий.
php-dev
2
hasClass принимает имя класса, а не селектор CSS. target.hasClass(".keepopen")должно быть target.hasClass("keepopen"). В противном случае код не будет работать.
Хью Гини
3
Я просканировал Интернет, и это наиболее интеллектуальное решение на сегодняшний день по этой причине ... Но другие методы требуют подхода, который использует остановку события по умолчанию или остановку распространения. эти подходы очень плохие, так как они будут прерывать любые другие инициируемые события внутри выпадающего меню (т.е. мои мобильные элементы формы jquery), используя этот подход, который позволяет вам точно определить, когда закрывается само меню, и позволяет вам предпринимать действия только для этого события. Этот ответ нуждается в таком количестве звезд ....
webfish
3
@webfish Сколько вам понадобилось сканировать интернет? (rofl)
php-dev
2
Возможно, раньше это работало ... но с начальной загрузкой 4 e.target всегда сам выпадающий список. Не выбранная цель. Даже если вы щелкнете вне выпадающего списка, e.target по-прежнему будет выпадающим. Таким образом, вы не можете выполнить этот вид проверки. Кто-нибудь видит способ обойти это?
FredArters
36

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

так твой код

<ul class="dropdown-menu">
  <form>
    <li>
      <div class="menu-item">bla bla bla</div>
    </li>
  </form>
</ul>
Грегори Бауэрс
источник
2
функционально работал великолепно для меня, но сломал стиль
2778
2
это было самое быстрое решение для меня
Джонатан Моралес Велес
15
Это не лучший ответ :) <li>элемент не должен быть внутри <form> элемента.
GETah
2
Это не семантически правильное решение - единственный допустимый дочерний элемент UL - это LI - если что-либо, теги формы должны быть внутри тегов li - но это может не всегда выполнять желаемое действие - в любом случае ul> form> li правильная разметка
gavgrif
2
Спасибо за это быстрое решение
Герман Демсонг
27

Я также нашел решение.

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

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

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

Спасибо за вашу помощь.

PHP-DEV
источник
1
Вот это да!!! работал отлично! У меня были проблемы в течение недели, я использую mCustomeScrollbar и после нажатия на полосу прокрутки в раскрывающемся списке закрывает его, ваш скрипт работает и теперь работает нормально! Бесконечно благодарен.
Eirenaios
прекрасно работает! как это можно расширить, чтобы пользователь мог нажать «ESC» (или даже щелкнуть снаружи) на клавиатуре, чтобы закрыть DD?
Дядя Иро
2
@MaggewDotCom Нажатие клавиши ESC должно все еще работать. То же самое для щелчка снаружи ...
php-dev
Единственным недостатком этого решения является то, что оно не допускает вложенных выпадающих (скажем, у вас есть право внутри выпадающего). Есть ли обходной путь для этого случая?
sdvnksv
26

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

$("dropdownmenuname").click(function(e){
   e.stopPropagation();
})
Bawantha
источник
Это, безусловно, самый простой / лучший ответ, если вы хотите, чтобы пользователь взаимодействовал с элементом пользовательского интерфейса, присутствующим в раскрывающемся меню (например, переключателями), и не хотите, чтобы меню закрывалось при переключении параметров.
Роб
22
$('body').on("click", ".dropdown-menu", function (e) {
    $(this).parent().is(".open") && e.stopPropagation();
});

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

Терри Лин
источник
это должен быть правильный ответ, так как он использует меньше строк кода, чем выбранный ответ
Мухаммед Омер Аслам
@MuhammadOmerAslam Нет! Поскольку это не соответствует моему требованию
php-dev
12

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/

Керри Джонсон
источник
9

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

Я изменил элемент выпадающего меню с <div>на, <form>и он работал хорошо.

<div class="nav-item dropdown" >
  <a href="javascript:;" class="nav-link dropdown-toggle" data-toggle="dropdown">
   Click to open dropdown
 </a>
 <form class="dropdown-menu   ">
  <ul class="list-group text-black">
     <li class="list-group-item"  >
     </li>
     <li class="list-group-item"   >
     </li>
  </ul>
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>


<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>


<div class="nav-item dropdown" >
  <a href="javascript:;" class="nav-link dropdown-toggle" data-toggle="dropdown">
   Click to open dropdown
 </a>
 <form class="dropdown-menu   ">
  <ul class="list-group text-black">
     <li class="list-group-item"  >
      List Item 1
     </li>
     <li class="list-group-item"   >
         LI 2<input class="form-control" />
     </li>
     <li class="list-group-item"   >
        List Item 3
     </li>
  </ul>
</form>

TheVigilant
источник
6

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

Илья
источник
6

Bootstrap решил эту проблему самостоятельно, поддерживая <form>теги в выпадающих списках. Их решение вполне приемлемо, и вы можете прочитать его здесь: https://github.com/twbs/bootstrap/blob/v4-dev/js/src/dropdown.js

Это сводится к предотвращению распространения в элементе документа и делает это только для событий типа, 'click.bs.dropdown.data-api'которые соответствуют селектору '.dropdown .your-custom-class-for-keep-open-on-click-elements'.

Или в коде

$(document).on('click.bs.dropdown.data-api', '.dropdown .keep-open-on-click', (event) => {
    event.stopPropagation();
});
Даниэль Шлауг
источник
1
Спасибо, спасибо, спасибо за ссылку на источник. Для других, интересующихся тем, почему formподход из примеров не работает для вас - я использовал класс dropleft, но он также необходим dropdownдля соответствия селектора формы.
Марк К Коуэн
6

Я изменил ответ @ Vartan, чтобы он работал с Bootstrap 4.3. Его решение больше не работает с последней версией, поскольку targetсвойство всегда возвращает корень выпадающего divменю независимо от того, где был размещен щелчок.

Вот код:

$('.dropdown-keep-open').on('hide.bs.dropdown', function (e) {
  if (!e.clickEvent) {
    // There is no `clickEvent` property in the `e` object when the `button` (or any other trigger) is clicked. 
    // What we usually want to happen in such situations is to hide the dropdown so we let it hide. 
    return true;
  }

  var target = $(e.clickEvent.target);

  return !(target.hasClass('dropdown-keep-open') || target.parents('.dropdown-keep-open').length);
});
<div class="dropdown dropdown-keep-open">
  <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Dropdown button
  </button>
  <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
    <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>
Конрад Калемба
источник
oneline:$('.dropdown-keep-open').on('hide.bs.dropdown', ev => !(ev.clickEvent && $(ev.target).has(ev.clickEvent.target).length))
Матвеев Дмитрий
@ MatveevDmitriy Извините, но никто, просто никто не может прочитать этот лайнер. Написание кода таким способом - плохая практика.
ВИРУСТРИНИ
Последняя строка может быть упрощена с помощью return !target.closest('.dropdown-keep-open').length). Тем не менее, это отличное решение! Нашел это необходимое для решения этой проблемы.
patrick3853
6
$('body').on("click", ".dropdown-menu", function (e) {
    $(this).parent().is(".show") && e.stopPropagation();
});
waza123
источник
Во-первых, спасибо за ваш ответ. На вопрос уже дан ответ. Кроме того, у меня есть другое требование, как описано в вопросе, чем общее требование.
php-dev
4
$('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');
});

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

Лука Философи
источник
Ваше решение является умным из-за его краткости, однако после добавления класса showраскрывающийся список не закрывается при щелчке снаружи, и нам нужно нажать на раскрывающееся-переключение до ... +1 в любом случае
php-dev
Я обновил его, посмотрите на демо. это лучшая причина, поэтому не проверяйте событие щелчка тела каждый раз. влияет только на элемент внутри каждого отдельного элемента навигации, а не за его пределами.
Лука Философи
Мое решение также не полагается на bodyсобытие клика ^^
php-dev
да, он частично передает событие щелчка тела, он пытается проверить, какой элемент был нажат во время делегирования тела. $('body').on('click', function (e) {
Лука Философи
Неа! Это не мой ответ. Мой ответ - последний опубликованный.
php-dev
4

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

// PREVENT INSIDE MEGA DROPDOWN
$('.dropdown-menu').on("click.bs.dropdown", function (e) {
    e.stopPropagation();
    e.preventDefault();                
});
Фрэнк Тоени
источник
1
e.preventDefault();блокирует ссылки, вы можете пропустить это
долго
@czachor ты прав! e.preventDefault (); Запретить ссылку следовать по URL.
Фрэнк Тоени
3

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

Нил
источник
Ваш пример работает нормально, но проблема в том, что раскрывающийся список может содержать любой контент, а не только карусель изображений ...
php-dev
3

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

<div dropdown autoClose="nonInput">

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

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

Нир Судри
источник
2

Я знаю, что этот вопрос был специально для 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>
jtate
источник
6
<div class="dropdown-menu" ng-click="$event.stopPropagation()">у меня работает в 1.2.x
dr3w
2

[Bootstrap 4 Альфа 6] [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;
  });
});

Джеки Тонг
источник
2

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

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

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

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

Взгляните на следующий планер:

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

Устанавливать

uib-dropdown auto-close="disabled" 

Надеюсь это поможет :)

ashwaniKumar
источник
5
Следует четко отметить, что это полезно только для людей ui-bootstrap, которые используют , что, вероятно, не так для очень многих людей, просматривающих этот вопрос.
kevlarr
Вы хорошо описали, но я думаю, что вы должны написать решение как uib-dropdown auto-close="outsideClick". Закрытие меню при щелчке внутри - это просто небольшой дискомфорт, но не закрытие меню при щелчке снаружи - очень огорчает
Вусан
2

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

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

Раду Чобану
источник
@RosdiKasim У меня все работает нормально на сайте с Bootstrap 4.0.0. Не тестировался с 4.1
Раду Чобану
На самом деле это должно выглядеть так: <form class = "dropdown dropdown-item">
Nasser Sadraee
2

Это помогло мне,

$('.dropdown-menu').on('click', function (e) {
     if ($(this).parent().is(".open")) {
         var target = $(e.target);
         if (target.hasClass("keepopen") || target.parents(".keepopen").length){
                    return false; 
                }else{
                    return true;
                }
            }            
});

Ваш выпадающий элемент меню должен быть таким (обратите внимание на классы dropdown-menuи keepopen.

<ul role="menu" class="dropdown-menu topmenu-menu eserv_top_notifications keepopen">

Приведенный выше код предотвращает связывание в целом <body>, вместо специфического элемента с классомdropdown-menu .

Надеюсь, это кому-нибудь поможет.

Спасибо.

Анжана Силва
источник
Спасибо, обновлено согласно Bootstrap 4 $ ('. Dropdown-menu [data-handledropdownclose = "true"]'). On ('click', function (e) {if ($ (this) .parent (). Is (" .show ")) {var target = $ (e.target); return (target.hasClass (" CloseDropDown ") || target.parents (". CloseDropDown "). length);}});
Туласирам
1

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

  • добавление keep-openкласса к элементам, которые не должны вызывать закрытие раскрывающегося списка
  • и этот кусок кода сделает все остальное:
$('.dropdown').on('click', function(e) {
    var target = $(e.target);
    var dropdown = target.closest('.dropdown');
    return !dropdown.hasClass('open') || !target.hasClass('keep-open');
});
Gee-Bee
источник
не могли бы вы помочь мне исправить это stackoverflow.com/questions/51552712/… @ Gee-Bee
Zhu
1

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

       $(document).on('hide.bs.dropdown', function (e) {
        if ($(e.currentTarget.activeElement).hasClass('dropdown-toggle')) {
          $(e.relatedTarget).parent().removeClass('open');
          return true;
        }
        return false;
       });
Майк
источник
1

По .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 и проверку перед закрытием.

Диксан Сантистебан Ферия
источник
1

Я сделал это с этим:

$(element).on({
    'mouseenter': function(event) {
        $(event.currentTarget).data('mouseover', true);
    },
    'mouseleave': function(event) {
        $(event.currentTarget).data('mouseover', false);
    },
    'hide.bs.dropdown': function (event) {
        return !$(event.currentTarget).data('mouseover');
    }
});
Уильям
источник
0
$(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')
    });
});
SNC
источник
0

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

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

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>
Дуди
источник
0

У вас могут возникнуть проблемы, если вы используете метод return false или stopPropagation (), потому что ваши события будут прерваны. Попробуйте этот код, он работает нормально:

$(function() {
    $('.dropdown').on("click", function (e) {
            $('.keep-open').removeClass("show");
    });
    $('.dropdown-toggle').on("click", function () {
            $('.keep-open').addClass("show");
    });

    $( ".closeDropdown" ).click(function() {
        $('.dropdown').closeDropdown();
    });
});
jQuery.fn.extend({
    closeDropdown: function() {
        this.addClass('show')
            .removeClass("keep-open")
            .click()
            .addClass("keep-open");
    }
  });

В HTML:

<div class="dropdown keep-open" id="search-menu" >
    <button  class="btn dropdown-toggle btn  btn-primary" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    <i class="fa fa-filter fa-fw"></i> 
    </button>
    <div class="dropdown-menu">
        <button class="dropdown-item" id="opt1" type="button">Option 1</button>
        <button class="dropdown-item" id="opt2" type="button">Option 2</button>
        <button type="button" class="btn btn-primary closeDropdown">Close</button>
    </div>
</div>

Если вы хотите закрыть dropdrown:

`$('#search-menu').closeDropdown();`
Hchab
источник
0

В Bootstrap 4 вы также можете сделать это:

$('#dd-link').on('hide.bs.dropdown', onListHide)

function onListHide(e)
{
  if(e.clickEvent && $.contains(e.relatedTarget.parentNode, e.clickEvent.target)) {
  e.preventDefault()
  }
}

где #dd-linkякорный элемент или кнопка, которая имеет data-toggle="drowndown"свойство.

Даниил
источник