mouseenter 上的 angular-bootstrap 下拉菜单,并在单击之前保持下拉菜单隐藏。

Posted

技术标签:

【中文标题】mouseenter 上的 angular-bootstrap 下拉菜单,并在单击之前保持下拉菜单隐藏。【英文标题】:angular-bootstrap dropdown on mouseenter and keep dropdown-menu from hiding before being clicked. 【发布时间】:2015-02-03 02:10:24 【问题描述】:

首先,我知道这个帖子:Activating bootstrap dropdown menu on hoverBootstrap Dropdown with HoverHow to make twitter bootstrap menu dropdown on hover rather than click 还有其他人,但仍未找到正确的解决方案,这是我到目前为止所做的。 首先,我使用了 angular-bootstrap 下拉指令中的 is-open 属性,如下所示:

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

注意下拉菜单现在位于下拉切换元素内,这意味着当用鼠标从下拉切换到下拉菜单时,它会从父级移动到子级,所以基本上我们仍然悬停在下拉开关上,因为我们是它的孩子,这意味着下拉菜单仍然可见,另一方面,引导下拉菜单与点击事件一起使用,因此将下拉菜单作为下拉菜单的孩子-不需要切换,但是现在当有人想在鼠标离开下拉菜单时将行为更改为鼠标输入/悬停时,下拉菜单会消失,因此我们不再可以访问下拉菜单元素,这在 @987654324 中可见@

为了修复第一个错误,我刚刚删除了下拉指令,然后将 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。 也就是说,这不是一个好的解决方案,因为这里涉及很多指令以获得简单的视觉效果,我提供的最后一个 plunker 包含一个不涉及 Bootstrap 或 AngularJS 的 css 解决方案,尽管它是必需的行为,但不是必需的html 结构或视觉结果,我需要的是在下拉切换和下拉菜单之间有一个空格,而不是切换元素的填充只是一个空白,这使得 css 解决方案在这种情况下无效。 那么,我的问题是否有更好的方法来做到这一点,而无需为悬停下拉菜单添加新的插件/库更干净且易于重用的解决方案?

【问题讨论】:

您解决了这个问题吗?还是它仍然开放,我认为现在应该关闭:) 不,我没有在这方面工作,但我有太多其他的东西,它仍然使用我在这里提到的相同的 hack :(,如果你有一个更好的解决方案清洁器和更少的指令,我接受建议。 让我查一下,我会回复你的 您好,除了上面提到的以外,您还有什么好的解决方案 @AvinashSolanki,没有。 【参考方案1】:

首先,切换最顶层的父元素(在本例中为&lt;span&gt;

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

查看此plunker 中的操作。

【讨论】:

【参考方案2】:

我知道你想要一个解决方案 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;

当然,不要忘记导入库:

&lt;script src="./js/dropdowns-enhancement.min.js"&gt;&lt;/script&gt; &lt;link href="./css/dropdowns-enhancement.css" rel="stylesheet"\&gt;

对于你的情况,我建议你研究一下Dropdown Enhancements's source code,看看它是如何工作的,也许会找到更合适的解决方案。

【讨论】:

【参考方案3】:

尝试将此行添加到您的 css:

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

您必须删除您的 is-open、ng-mouseenter 和 ng-mouseleave 指令。

【讨论】:

【参考方案4】:

以下是我在处理同一问题时提出的解决方案。

我使用了一个简单的自定义指令:

mouseentermouseleave 事件绑定到下拉菜单,以便正确显示/隐藏菜单。 为下拉菜单动态添加自定义 CSS 类,以防止将光标从按钮移动到菜单时菜单消失。 请注意,此解决方案的优点是不会消除按钮和菜单之间的视觉差距。 防止单击按钮时菜单消失。

CSS 规则使用before 伪元素来填充按钮和菜单之间的空隙。我添加了 border 属性,可以取消注释以轻松获得视觉反馈。

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

sn-p 的 HTML 结构基于 dropdown section of the angular-ui bootstrap documentation 中的可用示例

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>

【讨论】:

以上是关于mouseenter 上的 angular-bootstrap 下拉菜单,并在单击之前保持下拉菜单隐藏。的主要内容,如果未能解决你的问题,请参考以下文章

当光标隐藏在其他 HTML 元素后面时如何触发 mouseenter 事件?

jquery hover中嵌套mouseenter,mouseenter函数执行多次的问题解决方案

mouseenter和hover的区别

MouseEnter/MouseMove 面板,包括空格

mouseover和mouseenter的区别

mouseover和mouseenter的区别