Comment puis-je fermer un popover Twitter Bootstrap en un clic de n'importe où (ailleurs) sur la page?

155

J'utilise actuellement des popovers avec Twitter Bootstrap, initiés comme ceci:

$('.popup-marker').popover({
        html: true,
        trigger: 'manual'
    }).click(function(e) {
        $(this).popover('toggle');
        e.preventDefault();
    });

Comme vous pouvez le voir, ils sont déclenchés manuellement et cliquer sur .popup-marker (qui est un div avec une image d'arrière-plan) fait basculer un popover. Cela fonctionne très bien, mais j'aimerais également pouvoir fermer le popover en un clic n'importe où ailleurs sur la page (mais pas sur le popover lui-même!).

J'ai essayé plusieurs choses différentes, y compris les suivantes, mais sans résultats à montrer:

$('body').click(function(e) {
    $('.popup-marker').popover('hide');
});

Comment puis-je fermer le popover avec un clic n'importe où ailleurs sur la page, mais pas avec un clic sur le popover lui-même?

Travis Northcutt
la source
Hm, je pense que cela fonctionnerait ... avez-vous un lien vers cela en ligne par hasard?
thatryan

Réponses:

102

En supposant qu'un seul popover peut être visible à tout moment, vous pouvez utiliser un ensemble d'indicateurs pour marquer le moment où un popover est visible, puis les masquer.

Si vous définissez l'écouteur d'événements sur le corps du document, il se déclenchera lorsque vous cliquerez sur l'élément marqué avec 'popup-marker'. Alors tu devras appelerstopPropagation() l'objet événement. Et appliquez la même astuce en cliquant sur le popover lui-même.

Vous trouverez ci-dessous un code JavaScript fonctionnel qui fait cela. Il utilise jQuery> = 1.7

jQuery(function() {
    var isVisible = false;

    var hideAllPopovers = function() {
       $('.popup-marker').each(function() {
            $(this).popover('hide');
        });  
    };

    $('.popup-marker').popover({
        html: true,
        trigger: 'manual'
    }).on('click', function(e) {
        // if any other popovers are visible, hide them
        if(isVisible) {
            hideAllPopovers();
        }

        $(this).popover('show');

        // handle clicking on the popover itself
        $('.popover').off('click').on('click', function(e) {
            e.stopPropagation(); // prevent event for bubbling up => will not get caught with document.onclick
        });

        isVisible = true;
        e.stopPropagation();
    });


    $(document).on('click', function(e) {
        hideAllPopovers();
        isVisible = false;
    });
});

http://jsfiddle.net/AFffL/539/

La seule mise en garde est que vous ne pourrez pas ouvrir 2 popovers en même temps. Mais je pense que ce serait déroutant pour l'utilisateur, de toute façon :-)

Radu Cugut
la source
1
En cliquant sur le popover lui-même dans ce jsfiddle, le popover se cache - pas tout à fait ce que tnorthcutt a demandé.
Jonathon Hill
1
@RaduCugut c'est une excellente solution. Mais il y a un bug. Cliquez une fois sur zzzzz et le popover apparaît. Cliquez maintenant une fois sur le fond blanc. Le popup disparaît. Cliquez à nouveau sur le fond blanc. Et maintenant, cliquez à nouveau sur zzzz et cela ne fonctionne pas. : - |
Houman
1
@Kave vous avez raison, j'ai modifié le violon et la réponse pour corriger cela. jsfiddle.net/AFffL/177
Radu Cugut
3
Pourquoi ne pas simplement lancer $ ('. Popup-marker'). Popover ('hide') (pour les masquer tous) avant $ (this) .popover ('show'), ce qui supprime le besoin de toutes les variables isVisible et clickedAway?
Nathan Hangen
1
Cette solution m'a posé quelques problèmes (en cliquant sur l'élément '.popup-marker' du popover ouvert, les popovers ne fonctionnaient pas par la suite). J'ai trouvé une autre solution (publiée ci-dessous) qui a fonctionné pour moi et qui semble plus simple (j'utilise Bootstrap 2.3.1).
RayOnAir
76

C'est encore plus simple:

$('html').click(function(e) {
    $('.popup-marker').popover('hide');
});

$('.popup-marker').popover({
    html: true,
    trigger: 'manual'
}).click(function(e) {
    $(this).popover('toggle');
    e.stopPropagation();
});
Prbaron
la source
D'accord. Et au moins pour moi, c'est la bonne façon de faire. La première option semble être une «solution rapide».
Denis Lins
4
Je souhaitais l'utiliser mais pour une raison quelconque, cela n'a pas fonctionné. Les événements de clic n'ont jamais été atteints à htmlcause de e.stopPropagation();Au lieu de cela, j'ai utilisé quelque chose comme $('.popup-marker').on('show', function(event) { $('.popup-marker').filter(function(index, element) { return element != event.target; }).popover('hide'); });qui a bien fait le travail aussi (je ne sais pas s'il y a une différence de performance)
Cornelis
1
C'est la meilleure réponse de l'OMI.
Loolooii
1
La compilation des réponses @pbaron et @Cornelis fonctionne mieux. Ce que j'ai ajouté est le code de Cornelis dans la deuxième fonction de «clic» (juste avant la $(this).popover('toggle');partie. Ensuite, si vous avez plusieurs objets de «marqueur contextuel», cliquer sur chacun d'eux fermera les autres.
alekwisnia
2
Le seul problème avec ceci est que le popover est toujours là, juste caché. Ainsi, par exemple, si vous avez des liens dans le popover, vous pouvez placer votre curseur là où il se trouvait et toujours faire changer le curseur sur ces liens.
Glacials
48

J'avais un besoin similaire et j'ai trouvé cette super petite extension du Twitter Bootstrap Popover de Lee Carmichael, appelée BootstrapX - clickover . Il a également quelques exemples d'utilisation ici . Fondamentalement, cela changera le popover en un composant interactif qui se fermera lorsque vous cliquez ailleurs sur la page, ou sur un bouton de fermeture dans le popover. Cela permettra également d'ouvrir plusieurs popovers à la fois et un tas d'autres fonctionnalités intéressantes.

Le plugin peut être trouvé ici .

Exemple d'utilisation

<button rel="clickover" data-content="Show something here. 
    <button data-dismiss='clickover'
    >Close Clickover</button>"
>Show clickover</button>

javascript:

// load click overs using 'rel' attribute
$('[rel="clickover"]').clickover();
Miika L.
la source
1
C'est vraiment génial. Super facile.
Doug le
Excellent plugin! Merci pour le lien.
Matt Wilson du
1
Je viens de lui donner une chance et cela fonctionne très bien. C'était aussi simple que de changer simplement le rel d'un popover existant de "popover" à "clickover".
Dmase05
Fonctionnant sur Bootstrap v2.3.1, aucun problème.
Kevin Dewalt
37

La solution acceptée m'a posé quelques problèmes (en cliquant sur l'élément '.popup-marker' du popover ouvert, les popovers ne fonctionnaient pas par la suite). J'ai trouvé cette autre solution qui fonctionne parfaitement pour moi et c'est assez simple (j'utilise Bootstrap 2.3.1):

$('.popup-marker').popover({
    html: true,
    trigger: 'manual'
}).click(function(e) {
    $('.popup-marker').not(this).popover('hide');
    $(this).popover('toggle');
});
$(document).click(function(e) {
    if (!$(e.target).is('.popup-marker, .popover-title, .popover-content')) {
        $('.popup-marker').popover('hide');
    }
});

MISE À JOUR: Ce code fonctionne également avec Bootstrap 3!

RayOnAir
la source
1
C'est une excellente solution. Je vous remercie.
Gavin
1
Bonne solution. Pourquoi n'utilisez-vous pas de if (!$(e.target).is('.popup-marker') && !$(e.target).parents('.popover').length > 0)cette façon, la fenêtre contextuelle ne se fermera pas même si elle contient du contenu HTML
ykay dit Réintégrer Monica
2
Ou mieuxif (!$(e.target).is('.popup-marker') && $(e.target).closest('.popover').length === 0)
fabdouglas
19

lire «Ignorer au prochain clic» ici http://getbootstrap.com/javascript/#popovers

Vous pouvez utiliser le déclencheur de focus pour rejeter les popovers au prochain clic, mais vous devez utiliser la <a>balise, pas la <button>balise, et vous devez également inclure un tabindexattribut ...

Exemple:

<a href="#" tabindex="0" class="btn btn-lg btn-danger"
  data-toggle="popover" data-trigger="focus" title="Dismissible popover"
  data-content="And here's some amazing content. It's very engaging. Right?">
  Dismissible popover
</a>
Andrej Sramko
la source
2
La question indiquait qu'il ne voulait pas qu'elle soit rejetée si le clic était sur le popover. Cela le rejette à tout clic n'importe où.
Fred
1
L'ajout de data-trigger = "focus" a arrêté mes popovers de se lancer jusqu'à ce que je lis ce post et ai ajouté l'attribut tabindex. Maintenant ça marche!
PixelGraph
2
Pour information, cela fonctionne également avec tooltip, même si ce n'est pas clairement mentionné sur la doc.
AlexB
7

Toutes les réponses existantes sont assez faibles, car elles reposent sur la capture de tous les événements du document, puis sur la recherche de popovers actifs ou sur la modification de l'appel à.popover() .

Une bien meilleure approche consiste à écouter les show.bs.popoverévénements sur le corps du document, puis à réagir en conséquence. Vous trouverez ci-dessous le code qui fermera les popovers lorsque le document est cliqué ou escpressé, liant uniquement les écouteurs d'événements lorsque les popovers sont affichés:

function closePopoversOnDocumentEvents() {
  var visiblePopovers = [];

  var $body = $("body");

  function hideVisiblePopovers() {
    $.each(visiblePopovers, function() {
      $(this).popover("hide");
    });
  }

  function onBodyClick(event) {
    if (event.isDefaultPrevented())
      return;

    var $target = $(event.target);
    if ($target.data("bs.popover"))
      return;

    if ($target.parents(".popover").length)
      return;

    hideVisiblePopovers();
  }

  function onBodyKeyup(event) {
    if (event.isDefaultPrevented())
      return;

    if (event.keyCode != 27) // esc
      return;

    hideVisiblePopovers();
    event.preventDefault();
  }

  function onPopoverShow(event) {
    if (!visiblePopovers.length) {
      $body.on("click", onBodyClick);
      $body.on("keyup", onBodyKeyup);
    }
    visiblePopovers.push(event.target);
  }

  function onPopoverHide(event) {
    var target = event.target;
    var index = visiblePopovers.indexOf(target);
    if (index > -1) {
      visiblePopovers.splice(index, 1);
    }
    if (visiblePopovers.length == 0) {
      $body.off("click", onBodyClick);
      $body.off("keyup", onBodyKeyup);
    }
  }

  $body.on("show.bs.popover", onPopoverShow);
  $body.on("hide.bs.popover", onPopoverHide);
}
David Wolever
la source
+1 C'est la solution la plus propre et la plus extensible. Si vous utilisez également un framework comme backbone, vider simplement ceci dans votre code d'initialisation et il se chargera de gérer les popovers.
JohnP
Cette réponse ajoute également des problèmes de performances et permet de gérer du HTML plus complexe dans le popover.
Ricardo
Excellente solution; a pu l'intégrer assez facilement dans une méthode de réaction. Une suggestion, ajoutez $(event.target).data("bs.popover").inState.click = false;à la fonction onPopoverHide afin que vous n'ayez pas besoin de cliquer deux fois pour rouvrir après la fermeture.
sco_tt
Curieux de savoir si vous pourriez en faire un violon avec deux popups. Dans mon application, lorsque j'ai implémenté votre code, j'ai pu cliquer sur popup pour popup et plusieurs sont apparus, puis cliquer sur le `` corps '' ne supprimait que le dernier affiché.
Terry
2

Pour une raison quelconque, aucune des autres solutions ici n'a fonctionné pour moi. Cependant, après beaucoup de dépannage, je suis finalement arrivé à cette méthode qui fonctionne parfaitement (pour moi du moins).

$('html').click(function(e) {
  if( !$(e.target).parents().hasClass('popover') ) {
    $('#popover_parent').popover('destroy');
  }
});

Dans mon cas, j'ajoutais un popover à une table et je le positionnais absolument au-dessus / en dessous de celui sur tdlequel on avait cliqué. La sélection de la table a été gérée par jQuery-UI Selectable, donc je ne suis pas sûr que cela interfère. Cependant, chaque fois que je cliquais dans le popover, mon gestionnaire de clics qui ciblait $('.popover')ne fonctionnait jamais et la gestion des événements était toujours déléguée au $(html)gestionnaire de clics. Je suis assez nouveau dans JS alors peut-être que je manque juste quelque chose?

Quoi qu'il en soit, j'espère que cela aide quelqu'un!

moollaza
la source
BTW, je ne sais pas si cela compte, mais j'ai utilisé cette méthode pour Bootstrap 2. Je suppose que cela fonctionnera pour Bootstrap 3, mais je n'ai pas confirmé.
moollaza
2

Je donne à tous mes popovers les ancres de la classe activate_popover. Je les active tous en même temps lors du chargement

$('body').popover({selector: '.activate-popover', html : true, container: 'body'})

pour faire fonctionner la fonctionnalité Click Away que j'utilise (dans le script coffee):

$(document).on('click', (e) ->
  clickedOnActivate = ($(e.target).parents().hasClass("activate-popover") || $(e.target).hasClass("activate-popover"))
  clickedAway = !($(e.target).parents().hasClass("popover") || $(e.target).hasClass("popover"))
if clickedAway && !clickedOnActivate
  $(".popover.in").prev().popover('hide')
if clickedOnActivate 
  $(".popover.in").prev().each () ->
    if !$(this).is($(e.target).closest('.activate-popover'))
      $(this).popover('hide')
)

Ce qui fonctionne parfaitement avec bootstrap 2.3.1

Bert-Jan Steerneman
la source
Cela a fonctionné pour moi, sauf que je devais m'en débarrasser .prev()dans le premier ifarticle. J'utilise Bootstrap 3.2.0.2, il y a peut-être une différence? En outre, vous pouvez simplement omettre la deuxième ifclause entière si vous souhaitez pouvoir ouvrir plusieurs fenêtres contextuelles en même temps. Cliquez simplement n'importe où qui n'est pas un élément d'activation de popover (classe 'activate-popover' dans cet exemple) pour fermer tous les popovers ouverts. Fonctionne très bien!
Andrew Swihart
2

Même s'il y a beaucoup de solutions ici, j'aimerais également proposer la mienne, je ne sais pas s'il y a une solution là-haut qui résout tout, mais j'en ai essayé 3 et elles ont eu des problèmes, comme cliquer sur le popover, il le fait lui-même se cacher, d'autres que si j'avais un autre bouton popover cliqué sur les deux / plusieurs popovers apparaissaient toujours (comme dans la solution sélectionnée), Cependant, celui-ci a tout corrigé

var curr_popover_btn = null;
// Hide popovers function
function hide_popovers(e)
{
    var container = $(".popover.in");
    if (!container.is(e.target) // if the target of the click isn't the container...
        && container.has(e.target).length === 0) // ... nor a descendant of the container
    {
        if( curr_popover_btn != null )
        {
            $(curr_popover_btn).popover('hide');
            curr_popover_btn = null;
        }
        container.hide();
    }
}
// Hide popovers when out of focus
$('html').click(function(e) {
    hide_popovers(e);
});
$('.popover-marker').popover({
    trigger: 'manual'
}).click(function(e) {
    hide_popovers(e);
    var $popover_btns = $('.popover-marker');
    curr_popover_btn = this;
    var $other_popover_btns = jQuery.grep($($popover_btns), function(popover_btn){
                return ( popover_btn !== curr_popover_btn );
            });
    $($other_popover_btns).popover('hide');
    $(this).popover('toggle');
    e.stopPropagation();
});
Roshdy
la source
2

Je mettrais l'accent sur le pop-over nouvellement créé et le supprimerais en cas de flou. De cette façon, il n'est pas nécessaire de vérifier quel élément du DOM a été cliqué et le pop-over peut être cliqué, et sélectionné aussi: il ne perdra pas son focus et ne disparaîtra pas.

Le code:

    $('.popup-marker').popover({
       html: true,
       trigger: 'manual'
    }).click(function(e) {
       $(this).popover('toggle');
       // set the focus on the popover itself 
       jQuery(".popover").attr("tabindex",-1).focus();
       e.preventDefault();
    });

    // live event, will delete the popover by clicking any part of the page
    $('body').on('blur','.popover',function(){
       $('.popup-marker').popover('hide');
    });
Luca Vizzi
la source
1

Voici la solution qui a très bien fonctionné pour moi, si cela peut aider:

/**
* Add the equals method to the jquery objects
*/
$.fn.equals = function(compareTo) {
  if (!compareTo || this.length !== compareTo.length) {
    return false;
  }
  for (var i = 0; i < this.length; ++i) {
    if (this[i] !== compareTo[i]) {
      return false;
    }
  }
  return true;
};

/**
 * Activate popover message for all concerned fields
 */
var popoverOpened = null;
$(function() { 
    $('span.btn').popover();
    $('span.btn').unbind("click");
    $('span.btn').bind("click", function(e) {
        e.stopPropagation();
        if($(this).equals(popoverOpened)) return;
        if(popoverOpened !== null) {
            popoverOpened.popover("hide");            
        }
        $(this).popover('show');
        popoverOpened = $(this);
        e.preventDefault();
    });

    $(document).click(function(e) {
        if(popoverOpened !== null) {
            popoverOpened.popover("hide");   
            popoverOpened = null;
        }        
    });
});
Gilles Hemmerlé
la source
1

Voici ma solution, pour ce que ça vaut:

// Listen for clicks or touches on the page
$("html").on("click.popover.data-api touchend.popover.data-api", function(e) {

  // Loop through each popover on the page
  $("[data-toggle=popover]").each(function() {

    // Hide this popover if it's visible and if the user clicked outside of it
    if ($(this).next('div.popover:visible').length && $(".popover").has(e.target).length === 0) {
      $(this).popover("hide");
    }

  });
});
nates
la source
1

J'ai eu un problème pour le faire fonctionner sur bootstrap 2.3.2. Mais je l'ai fait de cette façon:

$(function () {
  $(document).mouseup(function (e) {
        if(($('.popover').length > 0) && !$(e.target).hasClass('popInfo')) {
            $('.popover').each(function(){
                $(this).prev('.popInfo').popover('hide');
            });
        }
    });

    $('.popInfo').popover({
        trigger: 'click',
        html: true
    });
});
oBo
la source
1

légèrement modifié la solution @David Wolever:

function closePopoversOnDocumentEvents() {
  var visiblePopovers = [];

  var $body = $("body");

  function hideVisiblePopovers() {
    /* this was giving problems and had a bit of overhead
      $.each(visiblePopovers, function() {
        $(this).popover("hide");
      });
    */
    while (visiblePopovers.length !== 0) {
       $(visiblePopovers.pop()).popover("hide");
    }
  }

  function onBodyClick(event) {
    if (event.isDefaultPrevented())
      return;

    var $target = $(event.target);
    if ($target.data("bs.popover"))
      return;

    if ($target.parents(".popover").length)
      return;

    hideVisiblePopovers();
  }

  function onBodyKeyup(event) {
    if (event.isDefaultPrevented())
      return;

    if (event.keyCode != 27) // esc
      return;

    hideVisiblePopovers();
    event.preventDefault();
  }

  function onPopoverShow(event) {
    if (!visiblePopovers.length) {
      $body.on("click", onBodyClick);
      $body.on("keyup", onBodyKeyup);
    }
    visiblePopovers.push(event.target);
  }

  function onPopoverHide(event) {
    var target = event.target;
    var index = visiblePopovers.indexOf(target);
    if (index > -1) {
      visiblePopovers.splice(index, 1);
    }
    if (visiblePopovers.length == 0) {
      $body.off("click", onBodyClick);
      $body.off("keyup", onBodyKeyup);
    }
  }

  $body.on("show.bs.popover", onPopoverShow);
  $body.on("hide.bs.popover", onPopoverHide);
}
Lee Gary
la source
1

Cette question a également été posée ici et ma réponse fournit non seulement un moyen de comprendre les méthodes de traversée DOM jQuery, mais également 2 options pour gérer la fermeture des popovers en cliquant à l'extérieur.

Ouvrez plusieurs popovers à la fois ou un popover à la fois.

De plus, ces petits extraits de code peuvent gérer la fermeture des boutons contenant des icônes!

https://stackoverflow.com/a/14857326/1060487

mattdlockyer
la source
1

Celui-ci fonctionne comme un charme et je l'utilise.

Il ouvrira le popover lorsque vous cliquez et si vous cliquez à nouveau, il se fermera, même si vous cliquez en dehors du popover, le popover sera fermé.

Cela fonctionne également avec plus d'un popover.

    function hideAllPopovers(){
    $('[data-toggle="popover"]').each(function() {
        if ($(this).data("showing") == "true"){
            $(this).data("showing", "false");
            $(this).popover('hide');                
        }
    });
}
$('[data-toggle="popover"]').each(function() {
        $(this).popover({
            html: true,
            trigger: 'manual'
        }).click(function(e) {
            if ($(this).data("showing") !=  "true"){
                hideAllPopovers();
                $(this).data("showing", "true");
                $(this).popover('show');
            }else{
                hideAllPopovers();
            }
            e.stopPropagation();
        });
});

$(document).click(function(e) {
    hideAllPopovers();
});
Patrick Nogueira
la source
C'est le seul qui a fonctionné pour moi. Bootstrap 3.20. Merci.
Telegard
1

Une autre solution, elle couvrait le problème que j'avais en cliquant sur les descendants du popover:

$(document).mouseup(function (e) {
    // The target is not popover or popover descendants
    if (!$(".popover").is(e.target) && 0 === $(".popover").has(e.target).length) {
        $("[data-toggle=popover]").popover('hide');
    }
});
Fernando Caraballo
la source
0

Je le fais comme ci-dessous

$("a[rel=popover]").click(function(event){
    if(event.which == 1)
    {   
        $thisPopOver = $(this);
        $thisPopOver.popover('toggle');
        $thisPopOver.parent("li").click(function(event){
            event.stopPropagation();
            $("html").click(function(){
                $thisPopOver.popover('hide');
            });
        });
    }
});

J'espère que cela t'aides!

foxybagga
la source
0

Si vous essayez d'utiliser le popover bootstrap de Twitter avec pjax, cela a fonctionné pour moi:

App.Utils.Popover = {

  enableAll: function() {
    $('.pk-popover').popover(
      {
        trigger: 'click',
        html : true,
        container: 'body',
        placement: 'right',
      }
    );
  },

  bindDocumentClickEvent: function(documentObj) {
    $(documentObj).click(function(event) {
      if( !$(event.target).hasClass('pk-popover') ) {
        $('.pk-popover').popover('hide');
      }
    });
  }

};

$(document).on('ready pjax:end', function() {
  App.Utils.Popover.enableAll();
  App.Utils.Popover.bindDocumentClickEvent(this);
});
kéruiline
la source
0

@RayOnAir, j'ai le même problème avec les solutions précédentes. Je me rapproche aussi de la solution @RayOnAir. Une chose qui s'est améliorée est de fermer le popover déjà ouvert lorsque vous cliquez sur un autre marqueur de popover. Donc mon code est:

var clicked_popover_marker = null;
var popover_marker = '#pricing i';

$(popover_marker).popover({
  html: true,
  trigger: 'manual'
}).click(function (e) {
  clicked_popover_marker = this;

  $(popover_marker).not(clicked_popover_marker).popover('hide');
  $(clicked_popover_marker).popover('toggle');
});

$(document).click(function (e) {
  if (e.target != clicked_popover_marker) {
    $(popover_marker).popover('hide');
    clicked_popover_marker = null;
  }
});
msa.im
la source
0

J'ai trouvé que c'était une solution modifiée de la suggestion de pbaron ci-dessus, car sa solution activait le popover ('hide') sur tous les éléments avec la classe 'popup-marker'. Cependant, lorsque vous utilisez popover () pour le contenu html au lieu du contenu de données, comme je le fais ci-dessous, tout clic à l'intérieur de ce popup html active réellement le popover ('hide'), qui ferme rapidement la fenêtre. Cette méthode ci-dessous itère à travers chaque élément de. Toutes les autres divs sont masquées ...

        $(function(){
            $('html').click(function(e) {
                // this is my departure from pbaron's code above
                // $('.popup-marker').popover('hide');
                $('.popup-marker').each(function() {
                    if ($(e.target).parents().children('.popup-marker').attr('id')!=($(this).attr('id'))) {
                        $(this).popover('hide');
                    }
                });
            });

            $('.popup-marker').popover({
                html: true,
                // this is where I'm setting the html for content from a nearby hidden div with id="html-"+clicked_div_id
                content: function() { return $('#html-'+$(this).attr('id')).html(); },
                trigger: 'manual'
            }).click(function(e) {
                $(this).popover('toggle');
                e.stopPropagation();
            });
        });
David
la source
0

Je suis venu avec ceci:

Mon scénario incluait plus de popovers sur la même page, et les masquer les rendait simplement invisibles et à cause de cela, cliquer sur les éléments derrière le popover n'était pas possible. L'idée est de marquer le lien popover spécifique comme «actif», puis vous pouvez simplement «basculer» le popover actif. Cela fermera complètement le popover.

$('.popover-link').popover({ html : true, container: 'body' })

$('.popover-link').popover().on 'shown.bs.popover', ->
  $(this).addClass('toggled')

$('.popover-link').popover().on 'hidden.bs.popover', ->
  $(this).removeClass('toggled')

$("body").on "click", (e) ->
  $openedPopoverLink = $(".popover-link.toggled")
  if $openedPopoverLink.has(e.target).length == 0
    $openedPopoverLink.popover "toggle"
    $openedPopoverLink.removeClass "toggled"
Adi Nistor
la source
0

J'essayais de trouver une solution simple à un problème simple. Les messages ci-dessus sont bons mais tellement compliqués pour un problème simple. Alors j'ai fait une chose simple. Je viens d'ajouter un bouton de fermeture. C'est parfait pour moi.

            $(".popover-link").click(function(){
                $(".mypopover").hide();
                $(this).parent().find(".mypopover").show();
        })
        $('.close').click(function(){
    $(this).parents('.mypopover').css('display','none');
});



          <div class="popover-content">
        <i class="fa fa-times close"></i>
    <h3 class="popover-title">Title here</h3>
your other content here
        </div>


   .popover-content {
    position:relative;
    }
    .close {
        position:absolute;
        color:#CCC;
        right:5px;
        top:5px;
        cursor:pointer;
    }
Mohammad Kashif
la source
0

J'aime ça, simple mais efficace.

var openPopup;

$('[data-toggle="popover"]').on('click',function(){
    if(openPopup){
        $(openPopup).popover('hide');

    }
    openPopup=this;
});
Gstarr
la source
0

Ajoutez une btn-popoverclasse à votre bouton / lien popover qui ouvre le popover. Ce code fermera les popovers en cliquant en dehors de celui-ci.

$('body').on('click', function(event) {
  if (!$(event.target).closest('.btn-popover, .popover').length) {
    $('.popover').popover('hide');
  }
});
Tobias Mühl
la source
0

Une solution encore plus simple, il suffit de parcourir tous les popovers et de les masquer sinon this.

$(document).on('click', '.popup-marker', function() {
    $(this).popover('toggle')
})

$(document).bind('click touchstart', function(e) {
    var target = $(e.target)[0];
    $('.popup-marker').each(function () {
        // hide any open popovers except for the one we've clicked
        if (!$(this).is(target)) {
            $(this).popover('hide');
        }
    });
});
Inostia
la source
0
$('.popForm').popover();

$('.conteneurPopForm').on("click",".fermePopover",function(){
    $(".popForm").trigger("click");
});

Pour être clair, il suffit de déclencher le popover

poète
la source
0

Cela devrait fonctionner dans Bootstrap 4:

$("#my-popover-trigger").popover({
  template: '<div class="popover my-popover-content" role="tooltip"><div class="arrow"></div><div class="popover-body"></div></div>',
  trigger: "manual"
})

$(document).click(function(e) {
  if ($(e.target).closest($("#my-popover-trigger")).length > 0) {
    $("#my-popover-trigger").popover("toggle")
  } else if (!$(e.target).closest($(".my-popover-content")).length > 0) {
    $("#my-popover-trigger").popover("hide")
  }
})

Explication:

  • La première section contient le popover selon la documentation: https://getbootstrap.com/docs/4.0/components/popovers/
  • Le premier "si" de la deuxième section vérifie si l'élément cliqué est un descendant de # my-popover-trigger. Si cela est vrai, il bascule le popover (il gère le clic sur le déclencheur).
  • Le deuxième "si" dans la deuxième section vérifie si l'élément cliqué est un descendant de la classe de contenu popover qui a été définie dans le modèle init. Si ce n'est pas le cas, cela signifie que le clic ne se trouvait pas dans le contenu du popover et que le popover peut être masqué.
Bart Blast
la source
Pourriez-vous s'il vous plaît élaborer sur votre code? Ajoutez une explication à ce que vous faites?
Death Waltz
@DeathWaltz Je viens d'ajouter une explication dans la réponse.
Bart Blast
-1

Essayez data-trigger="focus"au lieu de "click".

Cela a résolu le problème pour moi.

Hannes
la source