Comment écarter un pop-up Twitter Bootstrap en cliquant à l’extérieur?

Pouvons-nous obtenir que les popovers soient rejetables de la même manière que les modaux, c.-à-d. les fermer quand l’utilisateur clique quelque part en dehors d’eux?

Malheureusement, je ne peux pas utiliser le vrai modal au lieu du popover, car modal signifie position: corrigé 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 ne contenant que 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 icons (ce code a un bogue dans Bootstrap 3.3.6, voir le correctif 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 fenêtres pop-up d’être ouvertes en même temps.

Un popover à la fois s’il vous plaît:

Mise à jour: Bootstrap 3.0.x, voir code ou violon http://jsfiddle.net/mattdlockyer/C5GBU/2/

 $('body').on('click', function (e) { $('[data-toggle="popover"]').each(function () { //the 'is' for buttons that sortinggger popups //the 'has' for icons within a button that sortingggers 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 n’ont pas été cliqués.


Mise à jour: Bootstrap 3.3.6, voir violon

Correction du problème où après la fermeture, prend 2 clics pour rouvrir

 $(document).on('click', function (e) { $('[data-toggle="popover"],[data-original-title]').each(function () { //the 'is' for buttons that sortinggger popups //the 'has' for icons within a button that sortingggers 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'); }); } }); 

Cela ferme tous les popovers si vous cliquez n’importe où, sauf sur un popover

La version la plus simple et la plus sûre fonctionne avec toute version bootstrap.

Démo: http://jsfiddle.net/guya/24mmM/

Démo 2: Ne pas ignorer en cliquant dans le contenu du popover http://jsfiddle.net/guya/fjZja/

Démo 3: Popovers multiples: http://jsfiddle.net/guya/6YCjW/


Il suffit d’appeler cette ligne pour rejeter tous les popovers:

 $('[data-original-title]').popover('hide'); 

Rejeter tous les popovers en cliquant à 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 joint 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 lancés avec Javascript, par opposition à d’autres exemples qui ne fonctionneront pas. (voir la démo)

Si vous ne voulez pas rejeter en cliquant dans le contenu popover, utilisez ce code (voir le lien vers la 2è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'); } }); 

Ceci est fondamentalement pas très complexe, mais il y a des vérifications à faire pour éviter les problèmes.

Démo (jsfiddle)

 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'); }); 

Avec bootstrap 2.3.2, vous pouvez définir le déclencheur sur “focus” et ça marche:

 $('#el').popover({sortinggger:'focus'}); 

Aucune des solutions supposées à haut vote n’a fonctionné pour moi correctement. Chacun conduit à un bogue lorsque, après avoir ouvert et fermé (en cliquant sur d’autres éléments) le popover pour la première fois, il ne s’ouvrira plus jusqu’à ce que vous effectuiez deux clics sur le lien de déclenchement 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:

http://jsfiddle.net/3yHTH/

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.

HTML

 Click for popover 

JS

 $('#button').popover({ sortinggger: 'manual', position: 'bottom', title: 'Example', content: 'Popover example for SO' }).click(function(evt) { evt.stopPropagation(); $(this).popover('show'); }); $('html').click(function() { $('#button').popover('hide'); }); 

Cela a déjà été demandé ici . La même réponse que j’ai donnée alors s’applique toujours:

J’avais un besoin similaire, et j’ai trouvé cette superbe petite extension de Twitter Bootstrap Popover de Lee Carmichael, appelée BootstrapX – clickover . Il a également quelques exemples d’utilisation ici . Fondamentalement, il va changer le popover dans 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 à plusieurs popovers ouverts en même temps et un tas d’autres fonctionnalités intéressantes.

C’est tard pour la fête … mais j’ai pensé que je le partagerais. 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 je voudrais. 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-promo gratuite … J’ai saisi le code d’autres personnes tellement de fois dans ma vie, que je voulais faire mes propres efforts. Donnez-lui un tourbillon et voyez si cela fonctionne pour vous.

Selon http://getbootstrap.com/javascript/#popovers ,

  

Utilisez le déclencheur de mise au point pour ignorer les popovers au prochain clic que l’utilisateur effectue.

 $('.popover-dismiss').popover({ sortinggger: 'focus' }) 

Solution acceptée modifiée. Ce que j’ai expérimenté, c’est qu’il fallait cliquer deux fois sur certains popovers pour les afficher à nouveau. Voici ce que j’ai fait pour que le 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 sortinggger popups //the 'has' for icons within a button that sortingggers 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 } } }); }); 
 jQuery("#menu").click(function(){ return false; }); jQuery(document).one("click", function() { jQuery("#menu").fadeOut(); }); 

Vous pouvez également utiliser la diffusion d’événements pour supprimer la fenêtre contextuelle du DOM. C’est un peu sale, mais ça marche bien.

 $('body').on('click touchstart', '.popover-close', function(e) { return $(this).parents('.popover').remove(); }); 

Dans votre fichier HTML, ajoutez la classe .popover-close au contenu du popover qui doit fermer le popover.

Il semble que la méthode “hide” ne fonctionne pas si vous créez le popover avec la délégation de sélecteur, mais que “destroy” doit être utilisé.

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 sortinggger popups //the 'has' for icons within a button that sortingggers a popup if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) { $(this).popover('destroy'); } }); }); 

JSfiddle ici

Nous avons découvert que nous avions un problème avec la solution de @mattdlockyer (merci pour la solution!). Lors de l’utilisation de 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 seconde instance de popover locale à $(this) . Voici notre solution pour éviter que:

 $(document.body).on('click', function (e) { $('[data-toggle="popover"]').each(function () { //the 'is' for buttons that sortinggger popups //the 'has' for icons within a button that sortingggers 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é le $(this).popover('hide'); créera une deuxième instance en raison de l’auditeur délégué. La solution fournie ne cache que les popovers déjà instanciés.

J’espère que je pourrais vous faire gagner du temps.

Bootstrap supporte nativement ceci :

JS Bin Demo

Balisage spécifique requirejs pour le rejet du clic suivant

Pour un comportement approprié entre les navigateurs et les plates-formes, vous devez utiliser la balise , pas la et vous devez également inclure les atsortingbuts role="button" et tabindex .

cette solution se débarrasse du deuxième clic embêtant lors de l’affichage du popover pour la deuxième fois

testé 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(); } }); }); 

ajoutez simplement cet atsortingbut avec l’élément

 data-sortinggger="focus" 

Je retire 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(); }); 

testé avec 3.3.6 et deuxième 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 sortinggger popups //the 'has' for icons within a button that sortingggers a popup if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) { $(this).popover('hide'); } }); }); 

Ajoutez simplement cet atsortingbut à l’élément HTML pour fermer le pop-up au prochain clic.

 data-sortinggger="focus" 

référence de https://getbootstrap.com/docs/3.3/javascript/#popovers

J’ai essayé plusieurs des réponses précédentes, vraiment rien ne fonctionne pour moi mais cette solution a fait:

https://getbootstrap.com/docs/3.3/javascript/#dismiss-on-next-click

Ils recommandent d’utiliser la balise d’ancrage et non le bouton et de prendre soin de role = “button” + data-sortinggger = “focus” + tabindex = “0” atsortingbuts.

Ex:

  Dismissible popover 

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.sortinggger = '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.

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, elle masque tous les autres popovers. L’animation: false est requirejse sinon vous obtiendrez une erreur jquery .remove dans votre console.

 $('.clickable').popover({ sortinggger: 'manual', animation: false }).click (evt) -> $('.clickable').popover('hide') evt.stopPropagation() $(this).popover('show') $('html').on 'click', (evt) -> $('.clickable').popover('hide') 

Ok, ceci est ma première tentative de répondre à quelque chose sur stackoverflow donc rien ne va plus: P

Il semble que ce n’est pas tout à fait clair que cette fonctionnalité fonctionne réellement sur le dernier bootstrap (enfin, si vous êtes prêt à faire des compromis là où l’utilisateur peut cliquer, je ne suis pas sûr que vous deviez cliquer). hover ‘per-se mais sur un iPad, cliquez sur fonctionne comme une bascule.

Le résultat final est que, sur un bureau, vous pouvez survoler ou cliquer (la plupart des utilisateurs survoleront). Sur un appareil tactile, toucher l’élément le soulèvera et le toucher à nouveau le supprimera. Bien sûr, il s’agit d’un léger compromis par rapport à votre exigence initiale, mais au moins votre code est maintenant plus propre 🙂

$ (“. my-popover”). popover ({sortinggger: ‘click hover’});

Je suis arrivé à ceci: Mon scénario incluait plus de popovers sur la même page, et les cacher 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» et vous pouvez 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" 

En prenant le code de Matt Lockyer, j’ai effectué une simple réinitialisation pour que le dom ne soit pas couvert par l’élément sur hide.

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 sortinggger 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 sortinggger popups //the 'has' for icons within a button that sortingggers a popup if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) { $(this).popover('hide'); } }); }); 

Essayez ceci, cela cachera en cliquant en dehors.

 $('body').on('click', function (e) { $('[data-toggle="popover"]').each(function () { //the 'is' for buttons that sortinggger popups //the 'has' for icons within a button that sortingggers a popup if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) { $(this).popover('hide'); } }); }); 

J’avais des problèmes avec la solution de mattdlocky parce que je configurais dynamicment des liens popover en utilisant du code comme celui-ci:

 $('body').popover({ selector : '[rel="popover"]' }); 

J’ai donc dû le modifier comme ça. 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 sortinggger popups //the 'has' for icons within a button that sortingggers 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 détruire se débarrasse de l’élément, donc la partie sélecteur est importante lors de l’initialisation des popovers.

La réponse de @guya fonctionne, sauf si vous avez quelque chose comme un pointeur de temps ou un timepicker dans le popover. Pour corriger cela, c’est 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'); } }