Wie man ein Twitter-Bootstrap-Popover durch das Klicken von draußen klärt?

Können wir Popovers auf die gleiche Art und Weise wie Modals, dh. Schließen Sie sie, wenn der Benutzer irgendwo außerhalb von ihnen klickt?

Leider kann ich nicht einfach Real Modal anstelle von Popover verwenden, denn Modal bedeutet Position: Fixed und das wäre kein Popover mehr. 🙁

Update: Eine etwas robustere Lösung: http://jsfiddle.net/mattdlockyer/C5GBU/72/

Für Schaltflächen, die nur Text enthalten:

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

Für Schaltflächen mit Symbolen verwenden Sie (dieser Code hat einen Fehler in Bootstrap 3.3.6, siehe das Update unten in dieser Antwort)

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

Für JS Generated Popovers Verwenden Sie '[data-original-title]' anstelle von '[data-toggle="popover"]'

Vorbehalt: Die obige Lösung ermöglicht es, mehrere Popovers auf einmal zu öffnen.

Ein Popover nach dem anderen bitte:

Update: Bootstrap 3.0.x, siehe Code oder Geige 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'); } }); }); 

Dies ermöglicht das Schließen bereits geöffneter und nicht angeklickter Pop-Oops, oder es wurde nicht auf deren Links geklickt.


Update: Bootstrap 3.3.6, siehe Geige

Behebt ein Problem, bei dem nach dem Schließen 2 Klicks zum erneuten Öffnen benötigt werden

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

Dies schließt alle Popovers, wenn Sie irgendwo anders als auf ein Popover klicken

Die einfachste, meist errorssichere Version funktioniert mit jeder Bootstrap-Version.

Demo: http://jsfiddle.net/guya/24mmM/

Demo 2: Nicht ablehnen, wenn man in den Popover-Inhalt klickt http://jsfiddle.net/guya/fjZja/

Demo 3: Mehrere Popovers: http://jsfiddle.net/guya/6YCjW/


Wenn Sie diese Zeile aufrufen, werden alle Popovers geschlossen:

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

Schließen Sie alle Popovers, wenn Sie mit diesem Code nach draußen klicken:

 $('html').on('click', function(e) { if (typeof $(e.target).data('original-title') == 'undefined') { $('[data-original-title]').popover('hide'); } }); 

Das obige Snippet hängt ein Klickereignis an den Körper an. Wenn der Benutzer auf ein Popover klickt, verhält es sich wie gewohnt. Wenn der Benutzer auf etwas klickt, das kein Popover ist, werden alle Popovers geschlossen.

Es funktioniert auch mit Popovers, die mit Javascript initiiert werden, im Gegensatz zu einigen anderen Beispielen, die nicht funktionieren. (siehe die Demo)

Wenn Sie beim Klicken in den Popover-Inhalt nicht ablehnen möchten, verwenden Sie diesen Code (siehe Link zur 2. Demo):

 $('html').on('click', function(e) { if (typeof $(e.target).data('original-title') == 'undefined' && !$(e.target).parents().is('.popover.in')) { $('[data-original-title]').popover('hide'); } }); 

Dies ist im Grunde nicht sehr komplex, aber es gibt einige Überprüfungen, um Fehler zu vermeiden.

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

Mit Bootstrap 2.3.2 können Sie den Trigger auf “Fokus” setzen und es funktioniert einfach:

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

Keine der angenommenen Lösungen mit hoher Wahl hat für mich richtig funktioniert. Jedes führt zu einem Fehler, wenn nach dem Öffnen und Schließen (durch Klicken auf andere Elemente) das Popover zum ersten Mal geöffnet wird, es öffnet sich erst wieder, wenn Sie zwei Klicks auf den auslösenden Link statt auf einen machen.

Also habe ich es leicht modifiziert:

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

Ich machte ein Spiel, um Ihnen zu zeigen, wie es geht:

http://jsfiddle.net/3yHTH/

Die Idee besteht darin, das Popover anzuzeigen, wenn Sie auf die Schaltfläche klicken, und das Popover auszublenden, wenn Sie außerhalb der Schaltfläche klicken.

HTML

 Click for popover 

JS

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

Dies wurde zuvor hier gefragt. Die selbe Antwort, die ich damals gegeben habe, gilt immer noch:

Ich hatte ein ähnliches Bedürfnis und fand diese großartige kleine Erweiterung des Twitter Bootstrap Popover von Lee Carmichael, genannt BootstrapX – Clickover . Er hat hier auch einige Anwendungsbeispiele. Grundsätzlich wird das Popover in eine interaktive Komponente umgewandelt, die geschlossen wird, wenn Sie auf eine andere Stelle auf der Seite oder auf eine Schließen-Schaltfläche im Popover klicken. Dies ermöglicht auch mehrere Popovers auf einmal geöffnet und eine Reihe von anderen netten functionen.

Das ist spät zur Party … aber ich dachte, ich würde es teilen. Ich liebe das Popover, aber es hat so wenig eingebaute functionalität. Ich schrieb eine Bootstrap-Erweiterung .bubble (), das ist alles, was ich gerne Popover sein würde. Vier Möglichkeiten zu entlassen. Klicke auf den Link, klicke auf den Link, klicke auf das X und drücke die Escape-Taste.

Es positioniert sich automatisch so, dass es niemals von der Seite verschwindet.

https://github.com/Itumac/bootstrap-bubble

Dies ist keine unnötige Eigenwerbung … Ich habe den Code anderer Leute so oft in meinem Leben gepackt, dass ich meine eigenen Bemühungen anbieten wollte. Mach einen Wirbel und schau, ob es für dich funktioniert.

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

  

Verwenden Sie den Fokus-Auslöser, um Popovers beim nächsten Klick des Benutzers zu schließen.

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

Modifizierte akzeptierte Lösung. Was ich erlebt habe war, dass nachdem einige Popovers versteckt waren, sie zweimal angeklickt werden mussten, um wieder aufzutauchen. Hier ist, was ich getan habe, um sicherzustellen, dass Popover (“Verstecken”) nicht auf bereits versteckte Popovers aufgerufen wurde.

 $('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 } } }); }); 
 jQuery("#menu").click(function(){ return false; }); jQuery(document).one("click", function() { jQuery("#menu").fadeOut(); }); 

Sie können Event-Bubbling auch verwenden, um das Popup aus dem DOM zu entfernen. Es ist ein bisschen schmutzig, aber funktioniert gut.

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

Fügen Sie in Ihrem HTML-Code die class .popover-close dem Inhalt im Popover hinzu, der das Popover schließen soll.

Es scheint, dass die ‘Verstecken’-Methode nicht funktioniert, wenn Sie das Popover mit Selektordelegierung erstellen, stattdessen muss’ destroy ‘verwendet werden.

Ich habe es so gemacht:

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

JSchleichen Sie hier

Wir haben festgestellt, dass wir ein Problem mit der Lösung von @mattdlockyer hatten (Danke für die Lösung!). Wenn Sie die Selektor-Eigenschaft für den Popover-Konstruktor wie folgt verwenden …

 $(document.body').popover({selector: '[data-toggle=popover]'}); 

… die vorgeschlagene Lösung für BS3 wird nicht funktionieren. Stattdessen erstellt es eine zweite Popover-Instanz, die lokal zu $(this) . Hier ist unsere Lösung um das zu verhindern:

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

Wie schon erwähnt $(this).popover('hide'); erstellt aufgrund des delegierten Listeners eine zweite Instanz. Die zur Verfügung gestellte Lösung verbirgt nur Popovers, die bereits instanziiert sind.

Ich hoffe, ich könnte euch einige Zeit retten.

Bootstrap unterstützt dies nativ :

JS Bin Demo

Spezifisches Markup erforderlich für den nächsten Klick

Für ein ordnungsgemäßes browser- und plattformübergreifendes Verhalten müssen Sie das -Tag und nicht das -Tag verwenden. Außerdem müssen tabindex Attribute role="button" und tabindex .

Diese Lösung beseitigt den lästigen zweiten Klick, wenn das Popover zum zweiten Mal angezeigt wird

getestet mit 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(); } }); }); 

Fügen Sie dieses Attribut einfach mit dem Element hinzu

 data-trigger="focus" 

Ich entferne einfach andere aktive Popovers, bevor das neue Popover angezeigt wird (Bootstrap 3):

 $(".my-popover").popover(); $(".my-popover").on('show.bs.popover',function () { $('.popover.in').remove(); }); 

getestet mit 3.3.6 und zweiten Klick ist in Ordnung

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

Fügen Sie dieses Attribut einfach dem HTML-Element hinzu, um das Popover beim nächsten Klick zu schließen.

 data-trigger="focus" 

Referenz von https://getbootstrap.com/docs/3.3/javascript/#popovers

Ich habe viele der vorherigen Antworten ausprobiert, wirklich nichts funktioniert für mich, aber diese Lösung hat:

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

Sie empfehlen, den Anchor-Tag nicht zu verwenden und die Attribute role = “button” + data-trigger = “focus” + tabindex = “0” zu beachten.

Ex:

  Dismissible popover 

demo: 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; }); 

}

Das ist meine Lösung dafür.

Dieser Ansatz stellt sicher, dass Sie ein Popover schließen können, indem Sie auf eine beliebige Stelle auf der Seite klicken. Wenn Sie auf eine andere anklickbare Entität klicken, werden alle anderen Popovers ausgeblendet. Die Animation: false ist erforderlich, sonst erhalten Sie einen jquery .remove-Fehler in Ihrer Konsole.

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

Ok, das ist mein erster Versuch, tatsächlich etwas auf Stackoverflow zu beantworten, also geht hier gar nichts: P

Es scheint, dass es nicht ganz klar ist, dass diese functionalität beim neuesten Bootstrapping tatsächlich funktioniert (gut, wenn Sie bereit sind, Kompromisse einzugehen, auf die der Benutzer klicken kann. Ich bin mir nicht sicher, ob Sie einen Klick machen müssen Hover ‘per se, aber auf einem iPad, klicken Sie auf funktioniert als Umschalttaste.

Das Endergebnis ist, auf einem Desktop können Sie den Mauszeiger bewegen oder klicken (die meisten Benutzer bewegen sich). Auf einem Touch-Gerät wird das Element durch Berühren berührt und durch erneutes Berühren wird es wieder entfernt. Natürlich ist dies ein kleiner Kompromiss von Ihrer ursprünglichen Anforderung, aber zumindest ist Ihr Code jetzt sauberer 🙂

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

Ich kam dazu: Mein Szenario beinhaltete mehr Popovers auf derselben Seite, und durch das Verstecken wurden sie nur unsichtbar und deshalb war es nicht möglich, auf Objekte hinter dem Popover zu klicken. Die Idee ist, den spezifischen Popover-Link als ‘aktiv’ zu markieren und dann einfach das aktive Popover ‘umzuschalten’. Dies schließt das Popover vollständig $ (‘. 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" 

Nachdem ich den Code von Matt Lockyer genommen habe, habe ich einen einfachen Reset durchgeführt, damit das dom nicht durch das Element in hide verdeckt wird.

Matts Code: http://mattlockyer.com/2013/04/08/close-a-twitter-bootstrap-popover-when-clicking-outside/

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

Versuchen Sie dies, dies wird sich verstecken, indem Sie nach draußen klicken.

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

Ich hatte Probleme mit der Lösung von Mattdlockyer, weil ich Popover-Links dynamisch mit Code wie diesem eingerichtet habe:

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

Also musste ich es so modifizieren. Es hat viele Probleme für mich behoben:

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

Denken Sie daran, dass destroy das Element löscht, daher ist der Selektor bei der Initialisierung der Popovers wichtig.

Die Antwort von @guya funktioniert, es sei denn, Sie haben so etwas wie einen Datepicker oder einen Timepicker im Popover. Um das zu beheben, habe ich das getan.

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