web-dev-qa-db-fra.com

Comment puis-je modifier ui.bootstrap.dropdown pour répondre à un survol de la souris sur le bouton de la liste déroulante?

J'aimerais utiliser la boîte de message ui.bootstrap.dropdown pour afficher des informations textuelles (et non des liens) de manière similaire à ui.bootstrap.popover. Je voudrais modifier cette directive car elle représente 99% de ce dont j'ai besoin et je ne souhaite pas ajouter tous les JS supplémentaires requis par le popover.

En d'autres termes, j'aimerais que la "zone de liste déroulante" s'affiche lorsque l'utilisateur passe la souris sur la flèche vers le bas, puis s'en éloigne lorsqu'il s'éloigne de la flèche. 

Existe-t-il un moyen d’ajouter une option à ui.bootstrap.dropdown afin que le survol de la souris sur la flèche affiche et masque le menu déroulant? Je ne veux pas placer de liens dans cette case. 

J'espère que quelqu'un a des idées qui pourraient m'aider à suggérer comment je pourrais changer cette directive fournie avec 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);
            });
        }
    };
16
Alan2

Cela nécessite seulement un peu de CSS supplémentaire à accomplir. Vous n'avez pas fourni de balisage dans la question, je n'utilise donc que les exemples de groupes de boutons de la doc. Si vous fournissez votre marge spécifique, je modifierai cette réponse en conséquence.

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

En réalité, la liste déroulante ajoute une classe open à l'élément parent lorsque l'utilisateur clique dessus. Bootstrap CSS contient une règle selon laquelle la propriété display de l'élément enfant avec la classe .dropdown-menu doit être bloquée: 

.open>.dropdown-menu {
  display: block;
}

Par conséquent, pour que le menu s'affiche lorsque vous survolez, vous pouvez utiliser la pseudo-classe: hover en CSS pour faire de même. Dans cet exemple, j'ai attaché la règle à l'élément parent .btn-group en tant que tel:

.btn-group:hover>.dropdown-menu {
  display: block;
}
37
jme11

Voici ma solution simple mais lo-fi. Avoir le Mouseover et le laisserle de souris en haut de la liste était mon plus grand Eureka, alors ils agissent sur le groupe:

 <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>
9
Nathan Marrache

Vous pouvez décorer des directives.

De cette façon, vous ne devez pas toucher le code d'origine et vous pouvez conserver le comportement d'origine.

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;
    }
}
6
cstuncsik

Ajoutez simplement une variable de portée à is-open, puis ajoutez l'attribut ng-mouseover = "status.isopen = true"

<div class="btn-group" uib-dropdown ng-mouseover="status.isopen = true" is-open="status.isopen">

Vous pouvez également utiliser ng-mouseenter = "status.isopen = true" et ng-mouseleave = "status.isopen = false". Toutefois, cela peut parfois entraîner la fermeture de la liste déroulante à mesure que vous descendez. 

1
Aaron Klaser