раскрывающийся список angular-bootstrap при вводе мыши и не позволяйте раскрывающемуся меню скрываться до щелчка.

Во-первых, мне известно об этих сообщениях:
Активация раскрывающегося меню начальной загрузки при наведении курсора
Выпадающий список Bootstrap с наведением
Как сделать раскрывающееся меню начальной загрузки Twitter при наведении, а не при нажатии
И другие, но до сих пор не нашли правильного решения, вот что я сделал до сих пор.
Сначала я использовал атрибут is-open из раскрывающейся директивы angular-bootstrap следующим образом:

<span class="dropdown" dropdown is-open="status.isopen">
  <a
    href
    class="dropdown-toggle"
    ng-mouseenter="status.isopen = true"
    ng-mouseleave="status.isopen = false"
  >
    hover me for a dropdown with angular-bootstrap
  </a>
  <ul
    class="dropdown-menu"
  >
    <li ng-repeat="choice in items">
      <a href>{{choice}}</a>
    </li>
  </ul>
</span>

это, казалось, работало, но появились 2 ошибки:

  • первый - когда щелкают элемент раскрывающегося списка, раскрывающееся меню исчезает, щелкнув снова, оно не вернется, вам нужно выйти из мыши, а затем ввести мышь в раскрывающийся список, чтобы вернуть раскрывающееся меню.
  • Вторая проблема css/html.

Обычно обычное решение css для выпадающего меню выглядит так:

<a class="css-dropdown">
  hover here with css.
  <div class="css-dropdown-menu">
    <p>item 1</p>
    <p>item 2</p>
    <p>item 3</p>
  </div>
</a>

Обратите внимание, что раскрывающееся меню теперь находится внутри элемента раскрывающегося списка, что означает, что при перемещении мыши от раскрывающегося списка к раскрывающемуся меню он перемещается от родительского элемента к дочернему, поэтому в основном мы все еще наводим курсор выпадающее меню, так как мы находимся в его дочернем элементе, что означает, что выпадающее меню по-прежнему будет видно, с другой стороны, выпадающее меню начальной загрузки работает с событием щелчка, поэтому наличие выпадающего меню в качестве дочернего элемента раскрывающегося списка не является необходимо, но теперь, когда кто-то хочет изменить поведение на mouseenter/hover, когда мышь покидает раскрывающийся список, раскрывающееся меню исчезает, поэтому у нас больше нет доступа к элементам раскрывающегося меню, это видно в этом plunker

Чтобы исправить первую ошибку, я просто удалил директиву раскрывающегося списка, а затем заменил директиву is-open директивой ng-class следующим образом.
Измените это:

<span class="dropdown" dropdown is-open="status.isopen">

к этому:

<span class="dropdown" ng-class="{'open': status.isopen}">

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

<ul class="dropdown-menu">

к этому:

<ul
  class="dropdown-menu"
  ng-mouseenter="status.isopen = true"
  ng-mouseleave="status.isopen = false"
>

Это сделало это, но появилась другая ошибка, когда при нажатии на элемент раскрывающегося меню он остается открытым, поэтому я продолжал взламывать, делая это. изменил это:

<li ng-repeat="choice in items">

к этому:

<li ng-repeat="choice in items" ng-click="status.isopen = false">

Это дает мне необходимое поведение plunker.
Тем не менее, это не хорошее решение, поскольку здесь задействовано множество директив для простого визуального эффекта, последний предоставленный мной плункер содержит решение css без участия Bootstrap или AngularJS, хотя это требуемое поведение, а не требуемая структура html или визуальный результат, что Мне нужно, чтобы между выпадающим переключателем и выпадающим меню был пробел, а не заполнение элемента переключения, а просто пустое пространство, что делает решение css недействительным в этой ситуации.
Итак, мой вопрос: есть ли лучший способ сделать это без добавления нового плагина/библиотеки, более чистое и легко повторно используемое решение для раскрывающегося меню при наведении курсора?


person Yahya KACEM    schedule 05.12.2014    source источник
comment
Вы исправили эту проблему? Или он все еще открыт, который, я считаю, должен быть закрыт на данный момент :)   -  person Yameen    schedule 12.03.2015
comment
нет, я не работал над этим, но у меня было слишком много других вещей, он все еще использует тот же хак, о котором я упоминал здесь :(, если у вас есть лучший очиститель решения с меньшим количеством директив, я открыт для предложений.   -  person Yahya KACEM    schedule 12.03.2015
comment
Позвольте мне проверить, я вернусь к вам   -  person Yameen    schedule 12.03.2015
comment
Привет, у тебя есть какое-нибудь хорошее решение, кроме вышеупомянутых?   -  person Avinash Solanki    schedule 07.12.2015
comment
@AvinashSolanki, нет.   -  person Yahya KACEM    schedule 08.12.2015


Ответы (4)


Во-первых, переключите самый верхний родительский элемент (в данном случае <span>)

<span class="btn-group" dropdown is-open="status.isopen" ng-mouseenter="status.isopen = true" ng-mouseleave="status.isopen = false">
  <a class="btn btn-primary dropdown-toggle" dropdown-toggle>
    Button dropdown <span class="caret"></span>
  </a>
  <ul class="dropdown-menu" role="menu">
    <li><a href="#">Action</a></li>
    <li><a href="#">Another action</a></li>
    <li><a href="#">Something else here</a></li>
    <li class="divider"></li>
    <li><a href="#">Separated link</a></li>
  </ul>
</span>

Это позволит вести себя так, как вы хотели, но при этом позволит щелкнуть, чтобы показать/скрыть меню ;-)

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

Итак, во-вторых, добавьте небольшой CSS, чтобы убрать пробел

.dropdown-menu {
    margin-top: 0;
}

См. действие в этом планкере.

person Kenny Ki    schedule 15.07.2015

Я знаю, что вам нужно решение without adding a new plugin/library, но вы (или другие пользователи, которые ищут такое поведение), возможно, захотите попробовать использовать No Close from Dropdown Enhancements lib, чтобы раскрывающийся список оставался открытым даже после нажатия одной из его опций:

Не закрывайте меню при нажатии на радио добавить класс .noclose.

<div class="btn-group">
  <button data-toggle="dropdown" class="btn btn-default dropdown-toggle">
      Checked option <span class="caret"></span>
  </button>
  <ul class="dropdown-menu noclose">
      <li>
          <input type="radio" id="gr1_1" name="gr1" value="1">
          <label for="gr1_1">Option 1</label>
      </li>
      <li>
          <input type="radio" id="gr1_2" name="gr1" value="2">
          <label for="gr1_2">Option 2</label>
      </li>
      <li>
          <input type="radio" id="gr1_3" name="gr1" value="3">
          <label for="gr1_3">Option 3</label>
      </li>
  </ul>
</div>

Также добавьте решение CSS для проблемы зависания:

.btn-group:hover .dropdown-menu.noclose {
    display: block;
}
.dropdown-menu.noclose {
    margin-top: 0px;
}

И, конечно же, не забудьте импортировать библиотеки:


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

person falsarella    schedule 20.03.2015

Попробуйте добавить эту строку в свой css:

.btn-group:hover>.dropdown-menu { display: block; margin-top: 0; }

Вам придется удалить директивы is-open, ng-mouseenter и ng-mouseleave.

person Nick    schedule 14.06.2016

Ниже приведено решение, которое я придумал, работая над той же проблемой.

Я использовал простую пользовательскую директиву, которая:

  • привязывает события mouseenter и mouseleave к раскрывающемуся списку, чтобы правильно отображать/скрывать меню.
  • динамически добавляет пользовательский класс CSS в раскрывающееся меню, чтобы предотвратить исчезновение меню при перемещении курсора с кнопки на меню. Обратите внимание, что это решение имеет то преимущество, что не устраняет визуальный разрыв между кнопкой и меню.
  • предотвращает исчезновение меню при нажатии кнопки.

Правило CSS использует псевдоэлемент before для заполнения промежутка между кнопкой и меню. Я добавил свойство border, которое можно раскомментировать, чтобы легко получить визуальную обратную связь.

.dropdown-hover-menu::before {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
  top: -3px;
  height: 3px;
  /*border: 1px solid black;*/
}

HTML-структура фрагмента основана на доступных примерах в раскрывающемся разделе angular-ui загрузочная документация

angular.module('app', ['ui.bootstrap'])
  .directive('dropdownHover', function() {
    return {
      require: 'uibDropdown',
      link: function(scope, element, attrs, dropdownCtrl) {

        var menu = angular.element(element[0].querySelector('.dropdown-menu')),
          button = angular.element(element[0].querySelector('.dropdown-toggle'));

        menu.addClass('dropdown-hover-menu');

        element.bind('mouseenter', onMouseenter);
        element.bind('mouseleave', onMouseleave);
        button.bind('click', onClick);

        function openDropdown(open) {
          scope.$apply(function() {
            dropdownCtrl.toggle(open);
          });
        }

        function onMouseenter(event) {
          if (!element.hasClass('disabled') && !attrs.disabled) {
            openDropdown(true);
          }
        };

        function onMouseleave(event) {
          openDropdown(false);
        };

        function onClick(event) {
          event.stopPropagation();
        }

        scope.$on('$destroy', function() {
          element.unbind('mouseenter', onMouseenter);
          element.unbind('mouseleave', onMouseleave);
          button.unbind('click', onClick);
        });
      }
    };
  });
.dropdown-hover-menu::before {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
  top: -3px;
  height: 3px;
  /*border: 1px solid black;*/
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.3/ui-bootstrap-tpls.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />

<div ng-app="app">
  <div class="btn-group" uib-dropdown dropdown-hover>
    <button type="button" class="btn btn-primary dropdown-toggle">
      Button dropdown <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" uib-dropdown-menu role="menu">
      <li role="menuitem"><a href="#">Action</a>
      </li>
      <li role="menuitem"><a href="#">Another action</a>
      </li>
      <li role="menuitem"><a href="#">Something else here</a>
      </li>
      <li class="divider"></li>
      <li role="menuitem"><a href="#">Separated link</a>
      </li>
    </ul>
  </div>
</div>

person zoom    schedule 31.07.2016