web-dev-qa-db-fra.com

Comment puis-je garder Twitter Bootstrap Popover ouvert jusqu'à ce que ma souris y pénètre?

J'ai un lien qui utilise le Twitter Bootstrap Popover version 1.3.0 pour afficher des informations. Cette information inclut un lien, mais chaque fois que je déplace ma souris du lien au popover, le popover disparaît.

Comment puis-je maintenir popover ouvert suffisamment longtemps pour permettre à la souris de s'y déplacer? Puis, quand la souris sort du lien et saute, cache-le?

Ou y a-t-il un autre plugin qui peut faire cela?

50
Tinyfool

Maintenant, je viens de passer à webuiPopover, ça fonctionne.

0
Tinyfool

Avec bootstrap (testé avec la version 2), j'ai compris le code suivant: 

$("a[rel=popover]")
            .popover({
                offset: 10,
                trigger: 'manual',
                animate: false,
                html: true,
                placement: 'left',
                template: '<div class="popover" onmouseover="$(this).mouseleave(function() {$(this).hide(); });"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'

            }).click(function(e) {
                e.preventDefault() ;
            }).mouseenter(function(e) {
                $(this).popover('show');
            });

L'essentiel est de remplacer le modèle avec mouseleave () enabler. J'espère que ça aide.

31
marchello

Pour ajouter à l’exemple de Marchello, si vous voulez que le popover disparaisse si l’utilisateur éloigne sa souris du lien popover et / source, essayez ceci.

var timeoutObj;
$('.nav_item a').popover({
    offset: 10,
    trigger: 'manual',
    html: true,
    placement: 'right',
    template: '<div class="popover" onmouseover="clearTimeout(timeoutObj);$(this).mouseleave(function() {$(this).hide();});"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
}).mouseenter(function(e) {
    $(this).popover('show');
}).mouseleave(function(e) {
    var ref = $(this);
    timeoutObj = setTimeout(function(){
        ref.popover('hide');
    }, 50);
});
26
Kevin Lawrence

Bootstrap 3 et plus

Simple, il suffit d'utiliser l'option container et de l'avoir comme élément qui appelle le popover. De cette façon, le popover est un enfant de l'élément qui l'appelle. Par conséquent, techniquement, vous survolez toujours le parent, car l'enfant popover lui appartient.

Par exemple:

HTML:

<div class="pop" data-content="Testing 12345">This has a popover</div>
<div class="pop" data-content="Testing 12345">This has a popover</div>
<div class="pop" data-content="Testing 12345">This has a popover</div>

jQuery:

Exécution d'une boucle $.each() sur chacun de mes éléments pour lesquels un popover doit être lié à son parent. Dans ce cas, chaque élément a la classe pop.

$('.pop').each(function () {
    var $elem = $(this);
    $elem.popover({
        placement: 'top',
        trigger: 'hover',
        html: true,
        container: $elem
    });
});

CSS:

Cette partie est facultative, mais recommandée. Il déplace le popover de 7 pixels vers le bas pour un accès plus facile.

.pop .popover {
    margin-top:7px;
}

DEMO DE TRAVAIL

26
Fizzix

C'est un peu compliqué, mais en me basant sur l'exemple de marchello, je l'ai fait (pas besoin de modèle):

$(".trigger-link").popover({
  trigger: "manual",
}).on("click", function(e) {
  e.preventDefault();
}).on("mouseenter", function() {
  var _this = this;
  $(this).popover("show");
  $(this).siblings(".popover").on("mouseleave", function() {
    $(_this).popover('hide');
  });
}).on("mouseleave", function() {
  var _this = this;
  setTimeout(function() {
    if (!$(".popover:hover").length) {
      $(_this).popover("hide")
    }
  }, 100);
});

La variable setTimeout permet de s’assurer qu’il reste suffisamment de temps pour passer du lien de déclenchement au popover.

19
clem

Cette question sur le github bootstrap repo traite de ce problème. Fat a souligné le placement expérimental "en haut/en bas/à gauche/à droite". Cela fonctionne plutôt bien, mais vous devez vous assurer que le déclencheur popover n’est pas positionné de manière statique avec css. Sinon, le popover n'apparaîtra pas où vous le souhaitez.

HTML:

<span class="myClass" data-content="lorem ipsum content" data-original-title="pop-title">Hover me to show a popover.</span> 

CSS:

/*CSS */
.myClass{ position: relative;}

JS:

$(function(){
  $('.myClass').popover({placement: 'in top'});
});  
11
stevendaniels

Voici ce que je pense: http://jsfiddle.net/WojtekKruszewski/Zf3m7/22/

Parfois, lorsque vous déplacez la souris d'un déclencheur popover au contenu popover actuel diagonalement, vous survolez les éléments ci-dessous. Je voulais gérer de telles situations - tant que vous atteignez le contenu de Popover avant le délai expiré, vous êtes sauvegardé (le popover ne disparaît pas). Il nécessite l'option delay.

Ce hack annule fondamentalement la fonction Popover leave, mais appelle l'original (qui démarre le minuteur pour masquer la popover). Ensuite, il attache un auditeur unique à l'élément de contenu mouseenter popover.

Si la souris entre dans le popover, la minuterie est effacée. Ensuite, il passe à l'écoute de mouseleave lors du popover et s'il est déclenché, il appelle la fonction de congé d'origine afin qu'il puisse démarrer masquer le minuteur.

var originalLeave = $.fn.popover.Constructor.prototype.leave;
$.fn.popover.Constructor.prototype.leave = function(obj){
  var self = obj instanceof this.constructor ?
    obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
  var container, timeout;

  originalLeave.call(this, obj);

  if(obj.currentTarget) {
    container = $(obj.currentTarget).siblings('.popover')
    timeout = self.timeout;
    container.one('mouseenter', function(){
      //We entered the actual popover – call off the dogs
      clearTimeout(timeout);
      //Let's monitor popover content instead
      container.one('mouseleave', function(){
        $.fn.popover.Constructor.prototype.leave.call(self, self);
      });
    })
  }
};
4
Wojtek Kruszewski

La solution a fonctionné pour nous pour Bootstrap 3.

var timeoutObj;
$('.list-group a').popover({
    offset: 10,
    trigger: 'manual',
    html: true,
    placement: 'right',
    template: '<div class="popover" onmouseover="$(this).mouseleave(function() {$(this).hide();});"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
}).mouseenter(function(e) {
    $(this).popover('show');
}).mouseleave(function(e) {
    var _this = this;
    setTimeout(function() {
        if (!$(".popover:hover").length) {
            $(_this).popover("hide");
        }
    }, 100);
}); 
4
Opcrat

Voici ce que j'ai fait:

e = $("a[rel=popover]")
e.popover({
    content: d, 
    html:true, 
    trigger:'hover',
    delay: {hide: 500},
    placement: 'bottom',
    container: e, 
})

Ceci est une solution très simple et géniale à ce problème, que j’ai découvert en consultant le code de l’info-bulle de bootstrap. Dans Bootstrap v3.0.3, voici la ligne de code que j'ai remarquée:

this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)

ceci indique que si la propriété container de popover est définie, il obtiendra l'élément appendTo () au lieu d'élément insertAfter (), vous devez simplement transmettre l'élément en tant que propriété de conteneur. En raison de appendTo (), le popover devient une partie du lien sur lequel l'événement survolé a été lié et le maintient ainsi ouvert lorsque la souris le déplace.

1
vinit

Enfin je résous ce problème. Popover disparaît parce que Popover n'est pas un nœud enfant du lien, mais un nœud enfant du corps.

Alors corrigez-le, c'est facile, changez le contenu de bootstrap-twipsy.js:

remplacez .prependTo(document.body) par .prependTo(this.$element)

et corrige le problème de position par changement.

et certains utilisent link tiger popover causera popover avec link aussi, ajoutez donc un lien contient le lien, donc le problème est résolu.

1
Tinyfool

Cela fonctionne pour moi sur BootStrap 3 :

el.popover({
  delay: {hide: 100}
}).on("shown.bs.popover", function(){
  el.data("bs.popover").tip().off("mouseleave").on("mouseleave", function(){
    setTimeout(function(){
      el.popover("hide");
    }, 100);
  });
}).on("hide.bs.popover", function(ev){
  if(el.data("bs.popover").tip().is(":hover"))
    ev.preventDefault();
});
1
ShogunPanda

Ceci est une version de la solution Wojtek Kruszewski. Cette version gère le clignotement lorsque la souris retourne au déclencheur. http://jsfiddle.net/danielgatis/QtcpD/

(function($) {
      var originalLeave = $.fn.popover.Constructor.prototype.leave;
      $.fn.popover.Constructor.prototype.leave = function(obj) {
        var self = (obj instanceof this.constructor ? obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data("bs." + this.type));
        originalLeave.call(this, obj);
        if (obj.currentTarget) {
          var current = $(obj.currentTarget);
          var container = current.siblings(".popover");
          container.on("mouseenter", function() {
            clearTimeout(self.timeout);
          });
          container.on("mouseleave", function() {
            originalLeave.call(self, self);
          });
        }
      };

      var originalEnter = $.fn.popover.Constructor.prototype.enter;
      $.fn.popover.Constructor.prototype.enter = function(obj) {
        var self = (obj instanceof this.constructor ? obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data("bs." + this.type));
        clearTimeout(self.timeout);
        if (!$(obj.currentTarget).siblings(".popover:visible").length) {
          originalEnter.call(this, obj);
        }
      };
    })(jQuery);
1
danielgatis

J'ai essayé les solutions de @Wotjek Kruszewski et @danielgatis, mais cela n'a pas fonctionné pour moi. Avertissement: J'utilise Bootstrap v2.1.0, pas v3. Cette solution est en coffeescript (pourquoi les gens utilisent-ils encore javascript??).

(($) ->
  originalLeave = $.fn.popover.Constructor::leave
  $.fn.popover.Constructor::leave = (e) ->
    self = $(e.currentTarget)[@type](@_options).data(@type)
    originalLeave.call @, e

    if e.currentTarget
      container = $(".popover")
      container.one "mouseenter", ->
        clearTimeout self.timeout

        container.one "mouseleave", ->
          originalLeave.call self, e
) jQuery
1
Micah Winkelspecht

À la fin de la conversation, reliée par @stevendaniels, vous trouverez un lien vers une extension Twitter Bootstrap appelée BootstrapX - clickover de Lee Carmichael. Cela modifie le survol d'une info-bulle trop volumineuse en un contrôle interactif, que vous pouvez fermer en cliquant ailleurs sur le formulaire, sur un bouton de fermeture ou après un délai d'attente. Il est facile à utiliser et a très bien fonctionné pour le projet dont j’avais besoin. Vous pouvez trouver quelques exemples de son utilisation ici .

0
Miika L.

Je n’ai aimé aucune des réponses que j’ai trouvées, aussi j’ai combiné des réponses proches du code suivant. Cela vous permet de simplement taper $(selector).pinnablepopover(options); chaque fois que vous voulez créer un popover 'pinnable'.

Un code qui facilite les choses:

$.fn.popoverHoverShow = function ()
{
    if(this.data('state') !== 'pinned')
    {
        if(!this.data('bs.popover').$tip || (this.data('bs.popover').$tip && this.data('bs.popover').$tip.is(':hidden')))
        {
            this.popover('show');
        }
    }
};
$.fn.popoverHoverHide = function ()
{
    if (this.data('state') !== 'pinned')
    {
        var ref = this;
        this.data('bs.popover').$tip.data('timeout', setTimeout(function(){ ref.popover('hide') }, 100))
        .on('mouseenter', function(){ clearTimeout($(this).data('timeout')) })
        .on('mouseleave', function(){ $(this).data('timeout', setTimeout(function(){ ref.popover('hide') }, 100)) });
        this.on('mouseenter', function(){ clearTimeout($(this).data('timeout')) });
    }
};
$.fn.popoverClickToggle = function ()
{
    if (this.data('state') !== 'pinned')
    {
        this.data('state', 'pinned');
    }
    else
    {
        this.data('state', 'hover')
    }
};
$.fn.pinnablepopover = function (options)
{
    options.trigger = manual;
    this.popover(options)
    .on('mouseenter', function(){ $(this).popoverHoverShow() })
    .on('mouseleave', function(){ $(this).popoverHoverHide() })
    .on('click', function(){ $(this).popoverClickToggle() });
};

Exemple d'utilisation:

$('[data-toggle=popover]').pinnablepopover({html: true, container: 'body'});
0
Timothy Zorn

Après avoir vu toutes les réponses, je pense que cela sera utile. Vous pouvez gérer tout ce dont vous avez besoin . Beaucoup de réponses ne font pas apparaître le temps que j’utilise. Son travail est très gentil dans mon projet
/****** /************************************ ************************** /

<div class='thumbnail' data-original-title=''  style='width:50%'>    
 <div id='item_details' class='popper-content hide'>
    <div>
        <div style='height:10px'> </div>
        <div class='title'>Bad blood </div>
        <div class='catagory'>Music </div>
    </div>

  </div>
  HELLO POPOVER
</div>"

/ ***************** CODE SCRIPT ****************** VEUILLEZ L'UTILISER À PARTIR DE L'OUVERTURE ****** /

$(".thumbnail").popover({
trigger: "manual" ,
html: true,
animation:true,
container: 'body',
placement: 'auto right',
content: function () {
    return $(this).children('.popper-content').html();
}}) .on("mouseenter", function () {
var _this = this;

$('.thumbnail').each(function () {
    $(this).popover('hide');
});
setTimeout(function(){
    if ($(_this).is(':hover')) {
        $(_this).popover("show");
    }
},1000);
$(".popover").on("mouseleave", function () {
    $('.thumbnail').each(function () {
        $(this).popover('hide');
    });
    $(_this).popover('hide');
 }); }).on("mouseleave", function () {
    var _this = this;
    setTimeout(function () {
        if (!$(".popover:hover").length) {
            $(_this).popover("hide");
        }
    }, 100); });
0