Pouvons-nous obtenir que les popovers soient licenciables de la même manière que les modaux, c.-à-d. les faire fermer lorsque l'utilisateur clique quelque part en dehors d'eux?
Malheureusement, je ne peux pas simplement utiliser de vrais modaux au lieu de popover, car modal signifie position: fixe et ce ne serait plus un popover. :(
Mise à jour: Une solution légèrement plus robuste: http://jsfiddle.net/mattdlockyer/C5GBU/72/
Pour les boutons contenant uniquement du texte:
$('body').on('click', function (e) {
//did not click a popover toggle or popover
if ($(e.target).data('toggle') !== 'popover'
&& $(e.target).parents('.popover.in').length === 0) {
$('[data-toggle="popover"]').popover('hide');
}
});
Pour les boutons contenant des icônes, utilisez (ce code a un bogue dans Bootstrap 3.3.6, voir la correction ci-dessous dans cette réponse)
$('body').on('click', function (e) {
//did not click a popover toggle, or icon in popover toggle, or popover
if ($(e.target).data('toggle') !== 'popover'
&& $(e.target).parents('[data-toggle="popover"]').length === 0
&& $(e.target).parents('.popover.in').length === 0) {
$('[data-toggle="popover"]').popover('hide');
}
});
Pour les popovers générés par JS Utilisez '[data-original-title]'
à la place de '[data-toggle="popover"]'
Avertissement: La solution ci-dessus permet à plusieurs popovers d'être ouverts en même temps.
Une popover à la fois s'il vous plaît:
Mise à jour: Bootstrap 3.0.x, voir le code ou le violon http://jsfiddle.net/mattdlockyer/C5GBU/2 /
$('body').on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
}
});
});
Cela gère la fermeture des popovers déjà ouverts et non cliqués ou leurs liens non cliqués.
Mise à jour: Bootstrap 3.3.6, voir violon
Correction du problème où après la fermeture, il faut 2 clics pour rouvrir
$(document).on('click', function (e) {
$('[data-toggle="popover"],[data-original-title]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
(($(this).popover('hide').data('bs.popover')||{}).inState||{}).click = false // fix for BS 3.3.6
}
});
});
$('html').on('mouseup', function(e) {
if(!$(e.target).closest('.popover').length) {
$('.popover').each(function(){
$(this.previousSibling).popover('hide');
});
}
});
Ceci ferme tous les popovers si vous cliquez n'importe où sauf sur un popover
PDATE pour Bootstrap 4.1
$("html").on("mouseup", function (e) {
var l = $(e.target);
if (l[0].className.indexOf("popover") == -1) {
$(".popover").each(function () {
$(this).popover("hide");
});
}
});
La plupart des versions les plus simples et les plus sûres fonctionnent avec toutes les versions de bootstrap.
Démo: http://jsfiddle.net/guya/24mmM/
Démo 2: Ne pas ignorer en cliquant dans le contenu popover http://jsfiddle.net/guya/fjZja/
Démo 3: Popovers multiples: http://jsfiddle.net/guya/6YCjW/
Le simple fait d'appeler cette ligne rejettera tous les popovers:
$('[data-original-title]').popover('hide');
Ignorez tous les popovers lorsque vous cliquez à l'extérieur avec ce code:
$('html').on('click', function(e) {
if (typeof $(e.target).data('original-title') == 'undefined') {
$('[data-original-title]').popover('hide');
}
});
L'extrait ci-dessus attache un événement de clic sur le corps. Lorsque l'utilisateur clique sur un popover, il se comporte normalement. Lorsque l'utilisateur clique sur quelque chose qui n'est pas un popover, il ferme tous les popovers.
Cela fonctionnera également avec les popovers initiés avec Javascript, contrairement à d'autres exemples qui ne fonctionneront pas. (voir la démo)
Si vous ne souhaitez pas ignorer lorsque vous cliquez dans le contenu popover, utilisez ce code (voir lien vers la deuxième démo):
$('html').on('click', function(e) {
if (typeof $(e.target).data('original-title') == 'undefined' && !$(e.target).parents().is('.popover.in')) {
$('[data-original-title]').popover('hide');
}
});
Avec bootstrap 2.3.2, vous pouvez définir le déclencheur sur 'focus' et cela fonctionne:
$('#el').popover({trigger:'focus'});
Ce n’est fondamentalement pas très complexe, mais il y a quelques vérifications à faire pour éviter les problèmes.
var $poped = $('someselector');
// Trigger for the popover
$poped.each(function() {
var $this = $(this);
$this.on('hover',function() {
var popover = $this.data('popover');
var shown = popover && popover.tip().is(':visible');
if(shown) return; // Avoids flashing
$this.popover('show');
});
});
// Trigger for the hiding
$('html').on('click.popover.data-api',function() {
$poped.popover('hide');
});
Aucune des supposées solutions à vote élevé ne fonctionnait correctement pour moi. Chaque bogue conduit à un bug lorsque, après avoir ouvert et fermé (en cliquant sur d’autres éléments) le popover pour la première fois, il ne s’ouvre pas à nouveau tant que vous n’avez pas fait deux cliquer sur le lien déclencheur au lieu d’un .
Donc je l'ai légèrement modifié:
$(document).on('click', function (e) {
var
$popover,
$target = $(e.target);
//do nothing if there was a click on popover content
if ($target.hasClass('popover') || $target.closest('.popover').length) {
return;
}
$('[data-toggle="popover"]').each(function () {
$popover = $(this);
if (!$popover.is(e.target) &&
$popover.has(e.target).length === 0 &&
$('.popover').has(e.target).length === 0)
{
$popover.popover('hide');
} else {
//fixes issue described above
$popover.popover('toggle');
}
});
})
J'ai fait un jsfiddle pour vous montrer comment faire:
L'idée est d'afficher le popover lorsque vous cliquez sur le bouton et de masquer le popover lorsque vous cliquez en dehors du bouton.
<a id="button" href="#" class="btn btn-danger">Click for popover</a>
$('#button').popover({
trigger: 'manual',
position: 'bottom',
title: 'Example',
content: 'Popover example for SO'
}).click(function(evt) {
evt.stopPropagation();
$(this).popover('show');
});
$('html').click(function() {
$('#button').popover('hide');
});
Selon http://getbootstrap.com/javascript/#popovers ,
<button type="button" class="popover-dismiss" data-toggle="popover" title="Dismissible popover" data-content="Popover Content">Dismissible popover</button>
Utilisez le déclencheur de focus pour ignorer les occurrences lors du prochain clic de l'utilisateur.
$('.popover-dismiss').popover({
trigger: 'focus'
})
Cela a été demandé auparavant ici . La même réponse que j'ai donnée alors s'applique toujours:
J'avais un besoin similaire et j'ai trouvé ceci grande petite extension de Twitter Bootstrap Popover de Lee Carmichael, appelée BootstrapX - clickover . Il a également quelques exemples d'utilisation ici . Fondamentalement, cela changera la popover en un composant interactif qui se fermera lorsque vous cliquerez ailleurs sur la page, ou sur un bouton de fermeture dans la popover. Cela permettra également d'ouvrir plusieurs popovers à la fois et de nombreuses autres fonctionnalités de Nice.
Solution acceptée modifiée. Ce que j’ai vécu, c’est qu’après avoir caché des popovers, il faudrait cliquer deux fois sur eux pour qu’ils se manifestent à nouveau. Voici ce que j'ai fait pour m'assurer que popover ("hide") ne soit pas appelé sur des popovers déjà cachés.
$('body').on('click', function (e) {
$('[data-original-title]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
var popoverElement = $(this).data('bs.popover').tip();
var popoverWasVisible = popoverElement.is(':visible');
if (popoverWasVisible) {
$(this).popover('hide');
$(this).click(); // double clicking required to reshow the popover if it was open, so perform one click now
}
}
});
});
ajoutez simplement cet attribut avec l'élément
data-trigger="focus"
C'est tard pour la fête ... mais je pensais le partager. J'aime le popover mais il a si peu de fonctionnalités intégrées. J'ai écrit une extension bootstrap. .Bubble () qui correspond à tout ce que j'aimerais que popover soit. Quatre façons de rejeter. Cliquez à l'extérieur, basculez sur le lien, cliquez sur le X et appuyez sur échapper.
Il se positionne automatiquement pour ne jamais sortir de la page.
https://github.com/Itumac/bootstrap-bubble
Ce n'est pas une auto-promotion gratuite ... J'ai saisi le code d'autres personnes si souvent dans ma vie que je voulais offrir mes propres efforts. Donnez-lui un tourbillon et voyez si cela fonctionne pour vous.
cette solution supprime le 2e clic embêtant lors de l'affichage du popover pour la deuxième fois
testé avec avec Bootstrap v3.3.7
$('body').on('click', function (e) {
$('.popover').each(function () {
var popover = $(this).data('bs.popover');
if (!popover.$element.is(e.target)) {
popover.inState.click = false;
popover.hide();
}
});
});
Il semble que la méthode "masquer" ne fonctionne pas si vous créez le popover avec une délégation de sélecteur, mais utilisez plutôt "détruire".
Je l'ai fait fonctionner comme ça:
$('body').popover({
selector: '[data-toggle="popover"]'
});
$('body').on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('destroy');
}
});
});
Vous pouvez également utiliser event bubbling pour supprimer le popup du DOM. C'est un peu sale, mais ça fonctionne bien.
$('body').on('click touchstart', '.popover-close', function(e) {
return $(this).parents('.popover').remove();
});
Dans votre code HTML, ajoutez la classe .popover-close au contenu à l'intérieur du popover qui devrait fermer le popover.
Nous avons découvert que nous avions un problème avec la solution de @mattdlockyer (merci pour la solution!). Lorsque vous utilisez la propriété selector pour le constructeur popover comme ceci ...
$(document.body').popover({selector: '[data-toggle=popover]'});
... la solution proposée pour BS3 ne fonctionnera pas. Au lieu de cela, il crée une deuxième instance popover locale avec sa $(this)
. Voici notre solution pour éviter cela:
$(document.body).on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
var bsPopover = $(this).data('bs.popover'); // Here's where the magic happens
if (bsPopover) bsPopover.hide();
}
});
});
Comme mentionné, la $(this).popover('hide');
créera une seconde instance en raison du programme d'écoute délégué. La solution fournie ne cache que les popovers déjà instanciés.
J'espère que je pourrais vous faire gagner un peu de temps.
jQuery("#menu").click(function(){ return false; });
jQuery(document).one("click", function() { jQuery("#menu").fadeOut(); });
Bootstrap supporte nativement ceci :
Balisage spécifique requis pour un renvoi au prochain clic
Pour un comportement correct entre les navigateurs et les plates-formes, vous devez utiliser la balise
<a>
, et non la balise<button>
, et vous devez également inclure la baliserole="button"
ettabindex
attributs.
testé avec 3.3.6 et le second clic est ok
$('[data-toggle="popover"]').popover()
.click(function () {
$(this).popover('toggle');
});;
$(document).on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
}
});
});
Je supprime simplement les autres popovers actifs avant que le nouveau popover ne soit affiché (bootstrap 3):
$(".my-popover").popover();
$(".my-popover").on('show.bs.popover',function () {
$('.popover.in').remove();
});
J'ai essayé beaucoup de réponses précédentes, vraiment rien ne fonctionne pour moi mais cette solution a:
https://getbootstrap.com/docs/3.3/javascript/#dismiss-on-next-click
Ils recommandent d'utiliser la balise anchor not button et de s'occuper des attributs role = "button" + data-trigger = "focus" + tabindex = "0".
Ex:
<a tabindex="0" class="btn btn-lg btn-danger" role="button" data-toggle="popover"
data-trigger="focus" title="Dismissible popover" data-content="amazing content">
Dismissible popover</a>
Cette solution fonctionne bien:
$("body") .on('click' ,'[data-toggle="popover"]', function(e) {
e.stopPropagation();
});
$("body") .on('click' ,'.popover' , function(e) {
e.stopPropagation();
});
$("body") .on('click' , function(e) {
$('[data-toggle="popover"]').popover('hide');
});
Ok, c’est ma première tentative de répondre à quelque chose sur stackoverflow, donc rien ne se passe: P
Il semble qu'il ne soit pas clair que cette fonctionnalité fonctionne réellement avec le dernier bootstrap (et bien, si vous êtes prêt à faire un compromis où l'utilisateur peut cliquer Je ne suis pas sûr que vous deviez mettre le survol en tant que tel, mais sur un iPad, le clic fonctionne comme une bascule.
Le résultat final est que, sur un bureau, vous pouvez survoler ou cliquer (la plupart des utilisateurs le survolent). Sur un appareil tactile, toucher l'élément le fera apparaître et le toucher à nouveau l'enlèvera. Bien sûr, ceci est un léger compromis par rapport à votre exigence d'origine, mais au moins votre code est maintenant plus propre :)
$ (". my-popover"). popover ({trigger: 'click hover'});
En prenant le code de Matt Lockyer, j'ai fait une simple réinitialisation pour que le dom ne soit pas couvert par l'élément caché.
Le code de Matt: http://mattlockyer.com/2013/04/08/close-a-Twitter-bootstrap-popover-when-clicking-outside/
Violon: http://jsfiddle.net/mrsmith/Wd2qS/
$('body').on('click', function (e) {
//hide popover from dom to prevent covering elements
$('.popover').css('display', 'none');
//bring popover back if trigger element is clicked
$('[data-toggle="popover"]').each(function () {
if ($(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$('.popover').css('display', 'block');
}
});
//hide popover with .popover method
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
}
});
});
démo: http://jsfiddle.net/nessajtr/yxpM5/1/
var clickOver = clickOver || {};
clickOver.uniqueId = $.now();
clickOver.ClickOver = function (selector, options) {
var self = this;
//default values
var isVisible, clickedAway = false;
var callbackMethod = options.content;
var uniqueDiv = document.createElement("div");
var divId = uniqueDiv.id = ++clickOver.uniqueId;
uniqueDiv.innerHTML = options.loadingContent();
options.trigger = 'manual';
options.animation = false;
options.content = uniqueDiv;
self.onClose = function () {
$("#" + divId).html(options.loadingContent());
$(selector).popover('hide')
isVisible = clickedAway = false;
};
self.onCallback = function (result) {
$("#" + divId).html(result);
};
$(selector).popover(options);
//events
$(selector).bind("click", function (e) {
$(selector).filter(function (f) {
return $(selector)[f] != e.target;
}).popover('hide');
$(selector).popover("show");
callbackMethod(self.onCallback);
isVisible = !(clickedAway = false);
});
$(document).bind("click", function (e) {
if (isVisible && clickedAway && $(e.target).parents(".popover").length == 0) {
self.onClose();
isVisible = clickedAway = false;
} else clickedAway = true;
});
}
c'est ma solution pour cela.
Il y a un problème avec la dernière mise à jour de la réponse acceptée: si des info-bulles sont activées et que vous ouvrez une fenêtre pop-up, puis cliquez sur un élément ayant une info-bulle, le texte de cette info-bulle s'affiche sous la forme d'une popover.
Pour éviter cela, ajoutez simplement
if ($(this).data('bs.popover')) {
à l'intérieur de l'instruction if (ou ajoutez-la concaténée avec && à l'instruction if)
// only show one popover at the time and hide on clicking outside
$(document).on('click', function (e) {
$('[data-toggle="popover"],[data-original-title]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
if ($(this).data('bs.popover')) {
(($(this).popover('hide').data('bs.popover') || {}).inState || {}).click = false // fix for BS 3.3.6
}
}
});
});
Essayez ceci, cela va se cacher en cliquant à l'extérieur.
$('body').on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
}
});
});
J'ai trouvé une solution simple et bonne à ce problème. En procédant de cette façon, nous n’avons qu’un écouteur d’événements activé quand il le faut. De plus, le popover n'apparaît pas car un événement qui désarme la popup se déclenche en même temps.
Ajouter le popover au HTML
<input id="popoverId" type="text" data-toggle="popover" data-trigger="manual" data-content="Popover content">
Montrer le popover quand vous voulez.
$('#popoverId').popover('show');
Ajoutez cet auditeur à votre Javascript. Cet écouteur se déclenche dès que le popover est affiché et attache un écouteur au corps qui le masquera lorsque l'utilisateur cliquera n'importe où sur le corps de la page, puis supprimera l'écouteur d'événement jusqu'à ce que le popover s'affiche à nouveau.
$('#popoverId').on('shown.bs.popover', function () {
$('body').click(function () {
$('#popoverId').popover('hide');
$('body').off();
});
});
Je trouvais ceci: mon scénario incluait plus de popovers sur la même page, et les masquer les rendait simplement invisibles. De ce fait, il était impossible de cliquer sur les éléments situés derrière le popover. L'idée est de marquer le lien popover spécifique comme étant "actif" et vous pouvez ensuite simplement "basculer" le popover actif. Cela fermera complètement le popover $ ('. Popover-link'). Popover ({html: true, conteneur: '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"
$(document).on('click', function(e) {
$('[data-toggle="popover"]').each(function() {
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide').data('bs.popover').inState.click = false
}
});
});
La réponse fonctionne très bien, il suffit d'ajouter une directive angular au cas où vous utiliseriez angular comme moi:
app.directive('popover', ['$document', function($document) {
return {
restrict: 'EA',
link: function(scope, elem, attrs) {
$(document).ready(function() {
$('[data-toggle="popover"]').popover();
});
elem.bind('click', function(e) {
$('#notification').popover('toggle');
})
$('body').on('click', function (e) {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!elem.is(e.target)
&& elem.has(e.target).length === 0
&& $('.popover').has(e.target).length === 0) {
elem.popover('hide');
}
});
}
};
}]);
Le code html:
<a popover tabindex="0" role="button"
id="notification"
data-toggle="popover" data-trigger="manual"
data-container="body" data-placement="bottom"
data-content="This is a popover">
Popover button
</a>
Cela aurait dû être aussi simple que d'utiliser data-trigger='click focus'
, car selon bootstrap:
Comment popover est déclenché - cliquez | vol stationnaire | focus | Manuel. Vous pouvez passer plusieurs déclencheurs; séparez-les par un espace. manuel ne peut être combiné à aucun autre déclencheur.
Cependant, utiliser click et focus ensemble ne fonctionne pas pour moi pour une raison inconnue, je dois le basculer manuellement.
La réponse de @guya fonctionne, sauf si vous avez quelque chose comme un sélecteur de date ou un horodatage dans la fenêtre popover. Pour résoudre ce problème, voici ce que j'ai fait.
if (typeof $(e.target).data('original-title') === 'undefined' &&
!$(e.target).parents().is('.popover.in')) {
var x = $(this).parents().context;
if(!$(x).hasClass("datepicker") && !$(x).hasClass("ui-timepicker-wrapper")){
$('[data-original-title]').popover('hide');
}
}
J'avais des problèmes avec la solution de mattdlockyer parce que je configurais des liens popover de manière dynamique en utilisant un code comme celui-ci:
$('body').popover({
selector : '[rel="popover"]'
});
Je devais donc le modifier comme tel. Cela a résolu beaucoup de problèmes pour moi:
$('html').on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('destroy');
}
});
});
Rappelez-vous que destroy supprime l'élément, la partie sélecteur est donc importante lors de l'initialisation des popovers.
Ajoutez simplement cet attribut à un élément HTML pour fermer le popover au prochain clic.
data-trigger="focus"
référence de https://getbootstrap.com/docs/3.3/javascript/#popovers
$('html').on('click.popover', function (e) {
var allpopins = $('.popover.in');
if (allpopins.has(e.target).length > 0 &&
!$('.btn', allpopins).is(e.target))
return;
// recognise pop-up
var id = $(e.target).attr('aria-describedby');
var popin = $("#" + id);
//on any button click in entire pop-up hide this pop-ups
$(popin).on(".btn", function () { popin.remove(); });
// on any place out of entire popup hide all pop-ups
$('.popover.in').not(popin).remove();
});
C'est ma meilleure solution de performance. À votre santé.
Cette approche garantit que vous pouvez fermer un popover en cliquant n'importe où sur la page. Si vous cliquez sur une autre entité cliquable, tous les autres popovers seront masqués. L'animation: false est obligatoire, sinon vous obtiendrez une erreur jquery .remove dans votre console.
$('.clickable').popover({
trigger: 'manual',
animation: false
}).click (evt) ->
$('.clickable').popover('hide')
evt.stopPropagation()
$(this).popover('show')
$('html').on 'click', (evt) ->
$('.clickable').popover('hide')