如何修改 ui.bootstrap.dropdown 以响应鼠标悬停在下拉按钮上?
How can I modify ui.bootstrap.dropdown to respond to a mouse hover over the drop button?
我想使用 ui.bootstrap.dropdown 消息框以类似于 ui.bootstrap.popover 的方式显示文本信息(不是链接)。我想修改这个指令,因为它完成了我需要的 99%,我不想添加弹出窗口所需的所有额外 JS。
换句话说,我希望 "dropdown list area" 在用户将鼠标悬停在向下箭头上时显示,然后在他们将鼠标从向下箭头移开时消失。
有没有一种方法可以向 ui.bootstrap.dropdown 添加一个选项,以便将鼠标悬停在箭头上会显示和隐藏下拉框。我不想在此框中放置任何链接。
我希望有人有一些想法可以帮助我建议我如何更改 ui.bootstrap.dropdown 附带的指令:
.directive('dropdownToggle', function () {
return {
require: '?^dropdown',
link: function (scope, element, attrs, dropdownCtrl) {
if (!dropdownCtrl) {
return;
}
dropdownCtrl.toggleElement = element;
var toggleDropdown = function (event) {
event.preventDefault();
if (!element.hasClass('disabled') && !attrs.disabled) {
scope.$apply(function () {
dropdownCtrl.toggle();
});
}
};
element.bind('click', toggleDropdown);
// WAI-ARIA
element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
scope.$watch(dropdownCtrl.isOpen, function (isOpen) {
element.attr('aria-expanded', !!isOpen);
});
scope.$on('$destroy', function () {
element.unbind('click', toggleDropdown);
});
}
};
这只需要一点点额外的 CSS 就可以完成。您没有在问题中提供标记,所以我只是使用文档中的按钮组示例。如果您提供特定标记,我会相应地调整此答案。
@import "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css";
.btn-group:hover>.dropdown-menu {
display: block;
}
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.js"></script>
</head>
<body>
<div ng-controller="DropdownCtrl">
<!-- Single button -->
<div class="btn-group" dropdown is-open="status.isopen">
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle ng-disabled="disabled">
Button dropdown <span class="caret"></span>
</button>
<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>
</div>
<!-- Split button -->
<div class="btn-group" dropdown>
<button type="button" class="btn btn-danger">Action</button>
<button type="button" class="btn btn-danger dropdown-toggle" dropdown-toggle>
<span class="caret"></span>
<span class="sr-only">Split button!</span>
</button>
<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>
</div>
</div>
<script>
angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('DropdownCtrl', function($scope, $log) {
$scope.items = [
'The first choice!',
'And another choice for you.',
'but wait! A third!'
];
$scope.status = {
isopen: false
};
$scope.toggled = function(open) {
$log.log('Dropdown is now: ', open);
};
$scope.toggleDropdown = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.status.isopen = !$scope.status.isopen;
};
});
</script>
</body>
</html>
实际上,下拉菜单所做的只是在单击时向父元素添加 open
class。 Bootstrap CSS 包含一个规则,该规则导致带有 .dropdown-menu class 的子元素的显示 属性 设置为阻止:
.open>.dropdown-menu {
display: block;
}
因此,要在悬停时显示菜单,您可以使用 CSS 中的 :hover 伪 class 来实现同样的效果。在此示例中,我将规则附加到 .btn-group 父元素,如下所示:
.btn-group:hover>.dropdown-menu {
display: block;
}
您可以修饰指令。
通过这种方式,您不必修改原始代码,并且可以保持原始行为。
HTML
<a href="#" class="open-dropdown-on-hover" dropdown-toggle></a>
JS
angular.module('app').config(uiDropdownToggleDecorate);
uiDropdownToggleDecorate.$inject = ['$provide'];
function uiDropdownToggleDecorate($provide) {
// the trick here is you have to put 'Directive' after the original directive name
$provide.decorator('dropdownToggleDirective', uiDropdownToggleDecorator);
uiDropdownToggleDecorator.$inject = ['$delegate'];
function uiDropdownToggleDecorator($delegate) {
var directive = $delegate[0];
var link = directive.link;
directive.compile = function() {
return function(scope, elem, attrs, ctrl) {
link.apply(this, [scope, elem, attrs, ctrl]);
function toggle() {
if (elem.hasClass('open-dropdown-on-hover')) {
scope.$apply(function() {
ctrl.toggle();
});
}
}
elem.hover(function() {
toggle();
}, function() {
toggle();
});
};
};
return $delegate;
}
}
给is-open添加一个范围变量然后添加属性ng-mouseover="status.isopen = true"
<div class="btn-group" uib-dropdown ng-mouseover="status.isopen = true" is-open="status.isopen">
或者,您可以使用 ng-mouseenter="status.isopen = true" 和 ng-mouseleave="status.isopen = false" 但这有时会导致下拉菜单在您进入下拉菜单时关闭。
这是我的简单但低保真的解决方案。在顶级列表项上使用 Mouseover 和 mouseleave 是我最大的 Eureka,因此它们作用于组:
<li uib-dropdown is-open="status.isopen" ng-mouseover="status.isopen = true" ng-mouseleave="status.isopen = false">
<a ui-sref="abc">ABC</a>
<ul uib-dropdown-menu role="menu">
<li role="menuitem"><a ui-sref="def">DEF</a></li>
</ul>
</li>
我想使用 ui.bootstrap.dropdown 消息框以类似于 ui.bootstrap.popover 的方式显示文本信息(不是链接)。我想修改这个指令,因为它完成了我需要的 99%,我不想添加弹出窗口所需的所有额外 JS。
换句话说,我希望 "dropdown list area" 在用户将鼠标悬停在向下箭头上时显示,然后在他们将鼠标从向下箭头移开时消失。
有没有一种方法可以向 ui.bootstrap.dropdown 添加一个选项,以便将鼠标悬停在箭头上会显示和隐藏下拉框。我不想在此框中放置任何链接。
我希望有人有一些想法可以帮助我建议我如何更改 ui.bootstrap.dropdown 附带的指令:
.directive('dropdownToggle', function () {
return {
require: '?^dropdown',
link: function (scope, element, attrs, dropdownCtrl) {
if (!dropdownCtrl) {
return;
}
dropdownCtrl.toggleElement = element;
var toggleDropdown = function (event) {
event.preventDefault();
if (!element.hasClass('disabled') && !attrs.disabled) {
scope.$apply(function () {
dropdownCtrl.toggle();
});
}
};
element.bind('click', toggleDropdown);
// WAI-ARIA
element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
scope.$watch(dropdownCtrl.isOpen, function (isOpen) {
element.attr('aria-expanded', !!isOpen);
});
scope.$on('$destroy', function () {
element.unbind('click', toggleDropdown);
});
}
};
这只需要一点点额外的 CSS 就可以完成。您没有在问题中提供标记,所以我只是使用文档中的按钮组示例。如果您提供特定标记,我会相应地调整此答案。
@import "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css";
.btn-group:hover>.dropdown-menu {
display: block;
}
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.js"></script>
</head>
<body>
<div ng-controller="DropdownCtrl">
<!-- Single button -->
<div class="btn-group" dropdown is-open="status.isopen">
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle ng-disabled="disabled">
Button dropdown <span class="caret"></span>
</button>
<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>
</div>
<!-- Split button -->
<div class="btn-group" dropdown>
<button type="button" class="btn btn-danger">Action</button>
<button type="button" class="btn btn-danger dropdown-toggle" dropdown-toggle>
<span class="caret"></span>
<span class="sr-only">Split button!</span>
</button>
<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>
</div>
</div>
<script>
angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('DropdownCtrl', function($scope, $log) {
$scope.items = [
'The first choice!',
'And another choice for you.',
'but wait! A third!'
];
$scope.status = {
isopen: false
};
$scope.toggled = function(open) {
$log.log('Dropdown is now: ', open);
};
$scope.toggleDropdown = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.status.isopen = !$scope.status.isopen;
};
});
</script>
</body>
</html>
实际上,下拉菜单所做的只是在单击时向父元素添加 open
class。 Bootstrap CSS 包含一个规则,该规则导致带有 .dropdown-menu class 的子元素的显示 属性 设置为阻止:
.open>.dropdown-menu {
display: block;
}
因此,要在悬停时显示菜单,您可以使用 CSS 中的 :hover 伪 class 来实现同样的效果。在此示例中,我将规则附加到 .btn-group 父元素,如下所示:
.btn-group:hover>.dropdown-menu {
display: block;
}
您可以修饰指令。
通过这种方式,您不必修改原始代码,并且可以保持原始行为。
HTML
<a href="#" class="open-dropdown-on-hover" dropdown-toggle></a>
JS
angular.module('app').config(uiDropdownToggleDecorate);
uiDropdownToggleDecorate.$inject = ['$provide'];
function uiDropdownToggleDecorate($provide) {
// the trick here is you have to put 'Directive' after the original directive name
$provide.decorator('dropdownToggleDirective', uiDropdownToggleDecorator);
uiDropdownToggleDecorator.$inject = ['$delegate'];
function uiDropdownToggleDecorator($delegate) {
var directive = $delegate[0];
var link = directive.link;
directive.compile = function() {
return function(scope, elem, attrs, ctrl) {
link.apply(this, [scope, elem, attrs, ctrl]);
function toggle() {
if (elem.hasClass('open-dropdown-on-hover')) {
scope.$apply(function() {
ctrl.toggle();
});
}
}
elem.hover(function() {
toggle();
}, function() {
toggle();
});
};
};
return $delegate;
}
}
给is-open添加一个范围变量然后添加属性ng-mouseover="status.isopen = true"
<div class="btn-group" uib-dropdown ng-mouseover="status.isopen = true" is-open="status.isopen">
或者,您可以使用 ng-mouseenter="status.isopen = true" 和 ng-mouseleave="status.isopen = false" 但这有时会导致下拉菜单在您进入下拉菜单时关闭。
这是我的简单但低保真的解决方案。在顶级列表项上使用 Mouseover 和 mouseleave 是我最大的 Eureka,因此它们作用于组:
<li uib-dropdown is-open="status.isopen" ng-mouseover="status.isopen = true" ng-mouseleave="status.isopen = false">
<a ui-sref="abc">ABC</a>
<ul uib-dropdown-menu role="menu">
<li role="menuitem"><a ui-sref="def">DEF</a></li>
</ul>
</li>