it-swarm.com.de

Wie kann ich ein Twitter Bootstrap Popover mit einem Klick von irgendwo anders auf der Seite schließen?

Ich verwende derzeit Popovers mit Twitter Bootstrap, die folgendermaßen initiiert wurden:

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

Wie Sie sehen, werden sie manuell ausgelöst, und durch Klicken auf .popup-marker (ein Div mit einem Hintergrundbild) wird ein Popover umgeschaltet. Das funktioniert prima, aber ich möchte das Popover auch mit einem Klick an einer anderen Stelle auf der Seite schließen können (aber nicht auf dem Popover selbst!).

Ich habe ein paar verschiedene Dinge ausprobiert, darunter die folgenden, aber keine Ergebnisse, die ich zeigen könnte:

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

Wie kann ich das Popover mit einem Klick an einer anderen Stelle auf der Seite schließen, aber nicht mit einem Klick auf das Popover selbst?

153

Unter der Annahme, dass immer nur ein Popover sichtbar sein kann, können Sie mithilfe einer Reihe von Flags markieren, wann ein Popover sichtbar ist, und diese dann ausblenden.

Wenn Sie den Ereignis-Listener auf den Dokumentkörper setzen, wird er ausgelöst, wenn Sie auf das mit 'Popup-Marker' markierte Element klicken. Sie müssen also stopPropagation() für das Ereignisobjekt aufrufen. Und wenden Sie denselben Trick an, wenn Sie auf das Popover selbst klicken.

Unten finden Sie einen funktionierenden JavaScript-Code, der dies ausführt. Es wird jQuery> = 1.7 verwendet

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/

Die einzige Einschränkung ist, dass Sie nicht zwei Popovers gleichzeitig öffnen können. Aber ich denke, das wäre für den Benutzer sowieso verwirrend :-)

100
Radu Cugut

Das ist noch einfacher:

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

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

Ich hatte ein ähnliches Bedürfnis und fand dieses große kleine Erweiterung des Twitter Bootstrap Popover von Lee Carmichael, genannt BootstrapX - clickover . Er hat auch einige Verwendungsbeispiele - hier . 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 innerhalb des Popovers klicken andere nette Eigenschaften.

Plugin finden Sie hier .

Anwendungsbeispiel

<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();
48
Miika L.

Die akzeptierte Lösung brachte einige Probleme mit sich (durch Klicken auf das Element '.popup-marker' des geöffneten Popovers funktionierten die Popovers danach nicht mehr). Ich habe mir diese andere Lösung ausgedacht, die perfekt für mich funktioniert und recht einfach ist (ich verwende 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');
    }
});

UPDATE: Dieser Code funktioniert auch mit Bootstrap 3!

37
RayOnAir

lesen Sie "Beim nächsten Klick schließen" hier http://getbootstrap.com/javascript/#popovers

Sie können den Fokus-Trigger verwenden, um Popovers beim nächsten Klick zu entfernen, müssen jedoch den <a> Tag, nicht das <button> Tag, und Sie müssen auch ein tabindex Attribut einfügen ...

Beispiel:

<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>
19
Andrej Sramko

Alle vorhandenen Antworten sind ziemlich schwach, da sie darauf beruhen, alle Dokumentereignisse zu erfassen, dann aktive Popovers zu finden oder den Aufruf von .popover() zu ändern.

Ein viel besserer Ansatz ist es, auf show.bs.popover - Ereignisse im Dokumentkörper zu warten und dann entsprechend zu reagieren. Unten ist Code, der Popovers schließt, wenn auf oder geklickt wird esc gedrückt wird, nur bindet Ereignis-Listener, wenn Popovers angezeigt werden:

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);
}
7
David Wolever

https://github.com/lecar-red/bootstrapx-clickover

Es ist eine Erweiterung von Twitter bootstrap popover und wird das Problem sehr einfach lösen.

5
Ibrahim

Ich gebe allen meinen Popover-Ankern die Klasse activate_popover. Ich aktiviere sie alle auf einmal onload

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

damit die Click-Away-Funktion funktioniert, die ich verwende (im Kaffeeskript):

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

Was mit bootstrap 2.3.1

2

Obwohl es hier viele Lösungen gibt, möchte ich auch meine vorschlagen, ich weiß nicht, ob es eine Lösung gibt, die alles löst, aber ich habe 3 davon ausprobiert und sie hatten Probleme, wie das Klicken Auf dem Popover macht es sich versteckt, andere, dass, wenn ich andere Popover-Schaltflächen angeklickt hätte, beide/mehrere Popover immer noch erscheinen würden (wie in der ausgewählten Lösung), Wie auch immer,Dieses reparierte alles

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

Aus irgendeinem Grund hat keine der anderen Lösungen hier für mich funktioniert. Nach einer Menge Fehlerbehebung bin ich jedoch endlich zu dieser Methode gekommen, die perfekt funktioniert (zumindest für mich).

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

In meinem Fall habe ich ein Popover zu einer Tabelle hinzugefügt und es absolut über/unter dem angeklickten td positioniert. Die Tabellenauswahl wurde von jQuery-UI Selectable vorgenommen, daher bin ich mir nicht sicher, ob dies störend war. Wann immer ich jedoch in das Popover klickte, funktionierte mein Click-Handler, der auf $('.popover') abzielte, nie und die Ereignisbehandlung wurde immer an den Click-Handler $(html) delegiert. Ich bin ziemlich neu in JS, also fehlt mir vielleicht nur etwas?

Wie auch immer, ich hoffe das hilft jemandem!

2
moollaza

Ich würde den Fokus auf das neu erstellte Pop-Over setzen und es bei Unschärfe entfernen. Auf diese Weise muss nicht überprüft werden, auf welches Element des DOM geklickt wurde, und das Popup kann angeklickt und auch ausgewählt werden: Es verliert nicht den Fokus und verschwindet nicht.

Der 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');
    });
1
Luca Vizzi

Dieser wirkt wie ein Zauber und ich benutze ihn.

Es öffnet das Popover, wenn Sie darauf klicken, und wenn Sie erneut darauf klicken, wird es geschlossen, auch wenn Sie außerhalb des Popovers klicken, wird das Popover geschlossen.

Dies funktioniert auch mit mehr als einem 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();
});
1

Hier ist die Lösung, die für mich sehr gut funktioniert hat, wenn es helfen kann:

/**
* 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;
        }        
    });
});
1

Ich hatte ein Problem damit bootstrap 2.3.2. Aber ich habe es so gelöst:

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

Diese Frage wurde auch hier gestellt und meine Antwort bietet nicht nur eine Möglichkeit, die jQuery DOM-Traversal-Methoden zu verstehen, sondern auch zwei Optionen, um das Schließen von Popovers durch Klicken nach außen zu handhaben.

Öffnen Sie mehrere Popovers gleichzeitig oder jeweils ein Popover.

Außerdem können diese kleinen Codefragmente das Schließen von Schaltflächen mit Symbolen handhaben!

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

1
mattdlockyer

Eine andere Lösung, die das Problem abdeckte, das ich beim Klicken auf Nachkommen des Popovers hatte:

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

Hier ist meine Lösung für das, was es wert ist:

// 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");
    }

  });
});
1
nates

@David Wolever-Lösung leicht überarbeitet:

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);
}
1
Lee Gary
$('.popForm').popover();

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

Lösen Sie einfach das Popover aus

0
poete

Ich mache es wie unten

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

Hoffe das hilft!

0
foxybagga

Eine noch einfachere Lösung, durchlaufen Sie einfach alle Popovers und blenden Sie sie aus, wenn nicht 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');
        }
    });
});
0
inostia

Hinzufügen btn-popover Klasse für die Popover-Schaltfläche/den Popover-Link. Dieser Code schließt die Popovers, wenn Sie außerhalb davon klicken.

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

@RayOnAir, ich habe das gleiche Problem mit früheren Lösungen. Ich komme auch der @RayOnAir-Lösung sehr nahe. Eine Sache, die sich verbessert hat, ist das bereits geöffnete Popover, wenn Sie auf einen anderen Popover-Marker klicken. Mein Code lautet also:

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;
  }
});
0
msa7

Wenn Sie versuchen, Twitter bootstrap popover mit pjax zu verwenden, hat dies bei mir funktioniert:

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);
});
0
keruilin

Ich mag das, einfach und doch effektiv.

var openPopup;

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

    }
    openPopup=this;
});
0
gstarr

Das habe ich mir ausgedacht:

In meinem Szenario waren mehr Popovers auf derselben Seite enthalten, und das Ausblenden machte sie nur unsichtbar. Aus diesem Grund war es nicht möglich, auf Elemente hinter dem Popover zu klicken. Die Idee ist, den spezifischen Popover-Link als "aktiv" zu markieren und dann den aktiven Popover einfach "umzuschalten". Dadurch wird das Popover vollständig geschlossen.

$('.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"
0
Adi Nistor

Ich habe versucht, eine einfache Lösung für ein einfaches Problem zu finden. Die obigen Beiträge sind gut, aber für eine einfache Ausgabe so kompliziert. Also habe ich eine einfache Sache gemacht. Habe gerade einen Schließen-Button hinzugefügt. Es ist perfekt für mich.

            $(".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;
    }
0
Mohammad Kashif

Ich fand dies eine modifizierte Lösung des obigen Vorschlags von pbaron, da seine Lösung das Popover ('hide') für alle Elemente mit der Klasse 'popup-marker' aktivierte. Wenn Sie jedoch popover () anstelle des Dateninhalts für HTML-Inhalte verwenden, wie im Folgenden beschrieben, aktivieren alle Klicks in diesem HTML-Popup tatsächlich das Popover ('hide'), wodurch das Fenster sofort geschlossen wird. Diese Methode iteriert durch jedes Popup-Marker-Element und erkennt zuerst, ob das übergeordnete Element mit der angeklickten Popup-Marker-ID verknüpft ist. Wenn dies der Fall ist, wird sie nicht ausgeblendet. Alle anderen Divs sind versteckt ...

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