Jak zamknąć okienko wyskakujące Twitter Bootstrap jednym kliknięciem z dowolnego (innego) miejsca na stronie?


154

Obecnie używam popoverów w Twitter Bootstrap, zainicjowanych w ten sposób:

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

Jak widać, są uruchamiane ręcznie, a kliknięcie .popup-marker (który jest elementem div z obrazem w tle) włącza okienko. To działa świetnie, ale chciałbym również móc zamknąć popover jednym kliknięciem w dowolnym innym miejscu na stronie (ale nie w samym popover!).

Wypróbowałem kilka różnych rzeczy, w tym poniższe, ale bez wyników do wyświetlenia:

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

Jak zamknąć okno popover jednym kliknięciem w dowolnym innym miejscu strony, ale nie jednym kliknięciem samego okna popover?


Hm, myślę, że to zadziała ... czy masz przypadek link do tego w Internecie?
thatryan

Odpowiedzi:


102

Zakładając, że tylko jedno okno popover może być widoczne w dowolnym momencie, możesz użyć zestawu flag, aby zaznaczyć, kiedy widoczne jest popover, a dopiero potem je ukryć.

Jeśli ustawisz detektor zdarzeń w treści dokumentu, będzie on uruchamiany po kliknięciu elementu oznaczonego „popup-marker”. Musisz więc wywołać stopPropagation()obiekt zdarzenia. I zastosuj tę samą sztuczkę, klikając sam popover.

Poniżej znajduje się działający kod JavaScript, który to robi. Używa 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/

Jedynym zastrzeżeniem jest to, że nie będziesz w stanie otworzyć dwóch okien popover w tym samym czasie. Ale myślę, że to i tak byłoby mylące dla użytkownika :-)


1
Kliknięcie samego popovera w tym jsfiddle powoduje ukrycie go - nie do końca o co pytał tnorthcutt.
Jonathon Hill

1
@RaduCugut to świetne rozwiązanie. Ale ma błąd. Kliknij raz na zzzzz, a pojawi się wyskakujące okienko. Teraz kliknij raz na białym tle. Wyskakujące okienko znika. Teraz kliknij ponownie na białym tle. A teraz kliknij ponownie na zzzz i to nie działa. : - |
Houman,

1
@Kave, masz rację, zmodyfikowałem skrzypce i odpowiedź, aby to poprawić. jsfiddle.net/AFffL/177
Radu Cugut

3
Dlaczego nie uruchomić po prostu $ ('. Popup-marker'). Popover ('hide') (aby ukryć je wszystkie) przed $ (this) .popover ('show'), co eliminuje potrzebę stosowania zmiennych isVisible i clickedAway?
Nathan Hangen

1
To rozwiązanie spowodowało pewne problemy (kliknięcie elementu „.popup-marker” w otwartym oknie popover sprawiło, że popover przestał działać). Wymyśliłem jeszcze jedno rozwiązanie (zamieszczone poniżej), które zadziałało i wydaje się prostsze (używam Bootstrap 2.3.1).
RayOnAir

76

To jest jeszcze łatwiejsze:

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

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

Zgoda. I przynajmniej dla mnie to właściwy sposób. Pierwsza opcja wydaje się być „szybką naprawą”.
Denis Lins

4
Chciałem tego użyć, ale z jakiegoś powodu nie wyszło. Zdarzenia kliknięcia nigdy nie osiągnęły, htmlponieważ e.stopPropagation();Zamiast tego użyłem czegoś takiego, $('.popup-marker').on('show', function(event) { $('.popup-marker').filter(function(index, element) { return element != event.target; }).popover('hide'); });co również wykonało pracę (nie wiem, czy jest różnica w wydajności)
Cornelis

1
To najlepsza odpowiedź IMO.
Loolooii

1
Kompilacja odpowiedzi @pbaron i @Cornelis działa najlepiej. Co Dodałem jest kod Cornelis wewnątrz drugiej funkcji „click” (tuż przed $(this).popover('toggle');częścią Następnie, jeśli masz wiele obiektów „popup-marker”, klikając każdy z nich będzie zamknięcie innych..
alekwisnia

2
Jedynym problemem jest to, że popover wciąż tam jest, tylko ukryty. Na przykład, jeśli masz linki w wyskakującym okienku, możesz najechać kursorem w miejsce, w którym był, i nadal zmieniać kursor na te linki.
Glacials

48

Miałem podobną potrzebę i znalazłem to świetne, małe rozszerzenie Twitter Bootstrap Popover autorstwa Lee Carmichaela, o nazwie BootstrapX - clickover . Ma też kilka przykładów wykorzystania tutaj . Zasadniczo zmieni popover w interaktywny komponent, który zamknie się po kliknięciu w innym miejscu strony lub na przycisku zamykania w wyskakującym okienku. Pozwoli to również na jednoczesne otwarcie wielu okien popover i kilka innych fajnych funkcji.

Wtyczkę można znaleźć tutaj .

Przykład użycia

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

1
To jest naprawdę świetne. Super łatwe.
Doug

Doskonała wtyczka! Dzięki za link.
Matt Wilson,

1
Po prostu spróbowałem i działa świetnie. Było tak proste, jak zmiana istniejącego elementu rel z „popover” na „clickover”.
Dmase05

Działa na Bootstrap v2.3.1, żadnych problemów.
Kevin Dewalt

37

Zaakceptowane rozwiązanie przyniosło mi pewne problemy (kliknięcie elementu „.popup-marker” w otwartym oknie popover sprawiło, że popover przestał działać). Wymyśliłem inne rozwiązanie, które działa idealnie dla mnie i jest dość proste (używam 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: Ten kod działa również z Bootstrap 3!


1
To świetne rozwiązanie. Dziękuję Ci.
Gavin

1
Dobre rozwiązanie. Dlaczego nie użyjesz w if (!$(e.target).is('.popup-marker') && !$(e.target).parents('.popover').length > 0)ten sposób, wyskakujące okienko nie zamknie się, nawet jeśli ma zawartość HTML
ykay mówi Przywróć Monikę

2
Albo lepiejif (!$(e.target).is('.popup-marker') && $(e.target).closest('.popover').length === 0)
fabdouglas

19

przeczytaj „Zamknij po następnym kliknięciu” tutaj http://getbootstrap.com/javascript/#popovers

Możesz użyć aktywatora fokusu, aby odrzucić wyskakujące okienka przy następnym kliknięciu, ale musisz użyć <a>tagu, a nie <button>tagu, a także musisz dołączyć tabindexatrybut ...

Przykład:

<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>

2
Pytanie brzmiało, że nie chce, aby zostało odrzucone, jeśli kliknięcie było w popover. To odrzuca go po każdym kliknięciu w dowolnym miejscu.
Fred

1
Dodanie data-trigger = "focus" zatrzymało uruchamianie moich wyskakujących okienek, dopóki nie przeczytałem tego postu i nie dodałem atrybutu tabindex. Teraz działa!
PixelGraph,

2
Dla informacji, to również działa tooltip, nawet jeśli nie jest to wyraźnie wymienione w rzeczywistym dokumencie.
AlexB

7

Wszystkie istniejące odpowiedzi są dość słabe, ponieważ polegają na przechwytywaniu wszystkich zdarzeń w dokumencie, a następnie znajdowaniu aktywnych okien popover lub modyfikowaniu wywołania .popover().

Znacznie lepszym podejściem jest nasłuchiwanie show.bs.popoverwydarzeń w treści dokumentu, a następnie odpowiednia reakcja. Poniżej znajduje się kod, który zamyka wyskakujące okienka po kliknięciu lub escnaciśnięciu dokumentu, tylko wiążące nasłuchiwania zdarzeń, gdy wyświetlane są wyskakujące okienka:

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

+1 To najczystsze i najbardziej rozszerzalne rozwiązanie. Jeśli używasz frameworka takiego jak szkielet, po prostu zrzuć to do swojego kodu inicjalizacyjnego, a zajmie się obsługą okien popover.
JohnP,

Ta odpowiedź powoduje również obawy związane z wydajnością i umożliwia obsługę bardziej złożonego kodu HTML w popover.
Ricardo

Świetne rozwiązanie; był w stanie dość łatwo wprowadzić go do metody reagowania. Jedna sugestia, dodaj $(event.target).data("bs.popover").inState.click = false;do funkcji onPopoverHide, aby nie trzeba było dwukrotnie klikać, aby ponownie otworzyć po zamknięciu.
sco_tt,

Ciekawe, czy dasz radę zrobić to z dwoma wyskakującymi okienkami. W mojej aplikacji, kiedy zaimplementowałem twój kod, mogłem kliknąć wyskakujące okienko i pojawiło się wiele, a następnie kliknięcie „treści” usunęło tylko ostatnią wyświetlaną.
Terry


2

Z jakiegoś powodu żadne inne rozwiązanie tutaj nie zadziałało. Jednak po wielu rozwiązywaniu problemów w końcu dotarłem do tej metody, która działa idealnie (przynajmniej dla mnie).

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

W moim przypadku dodawałem popover do tabeli i ustawiałem go absolutnie powyżej / poniżej tego, tdco zostało kliknięte. Wybór tabeli był obsługiwany przez jQuery-UI Selectable, więc nie jestem pewien, czy to przeszkadzało. Jednak za każdym razem, gdy kliknąłem wewnątrz popover, mój program obsługi kliknięcia, który był ukierunkowany, $('.popover')nigdy nie działał, a obsługa zdarzenia była zawsze delegowana do modułu $(html)obsługi kliknięcia. Jestem całkiem nowy w JS, więc może po prostu czegoś mi brakuje?

W każdym razie mam nadzieję, że to komuś pomoże!


Przy okazji nie jestem pewien, czy to ma znaczenie, ale użyłem tej metody dla Bootstrap 2. Zakładam, że będzie działać dla Bootstrap 3, ale nie potwierdziłem.
moollaza

2

Daję wszystkim moim kotwicom popover klasę activate_popover. Włączam je wszystkie na raz onload

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

aby funkcja Click away działała, której używam (w skrypcie kawy):

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

Co działa doskonale z bootstrapem 2.3.1


U mnie to zadziałało, z wyjątkiem tego, że musiałem się go pozbyć .prev()w pierwszej ifklauzuli. Używam Bootstrap 3.2.0.2, może jest jakaś różnica? Możesz też po prostu pominąć całą drugą ifklauzulę, jeśli chcesz mieć możliwość jednoczesnego otwierania wielu wyskakujących okienek. Po prostu kliknij w dowolnym miejscu, które nie jest elementem aktywującym okienko popover (w tym przykładzie klasa „aktywuj-popover”), aby zamknąć wszystkie otwarte okna popover. Działa świetnie!
Andrew Swihart

2

Chociaż jest tu wiele rozwiązań, chciałbym również zaproponować moje, nie wiem, czy jest tam jakieś rozwiązanie, które rozwiązuje wszystko, ale wypróbowałem 3 z nich i mieli problemy, takie jak klikanie w wyskakującym okienku sam się ukrywa, inne, że gdybym miał inny przycisk popover, kliknął oba / wiele okienek popover, nadal pojawiałyby się (tak jak w wybranym rozwiązaniu), Jednak ten naprawił to wszystko

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

Skupiłbym się na nowo utworzonym wyskakującym okienku i usunąłem go w przypadku rozmycia. Dzięki temu nie trzeba sprawdzać, który element DOM został kliknięty, a pop-over można kliknąć, a także zaznaczyć: nie straci on swojej aktywności i nie zniknie.

Kod:

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

Oto rozwiązanie, które zadziałało dla mnie bardzo dobrze, jeśli może pomóc:

/**
* 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

Oto moje rozwiązanie, jakie jest warte:

// 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

Miałem problem z uruchomieniem go na bootstrap 2.3.2. Ale zrobiłem to w ten sposób:

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

nieznacznie poprawiono rozwiązanie @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);
}

1

To pytanie również zostało tutaj zadane, a moja odpowiedź dostarcza nie tylko sposobu na zrozumienie metod przechodzenia przez jQuery DOM, ale także 2 opcje obsługi zamykania okien popover przez kliknięcie na zewnątrz.

Otwieraj wiele okien podręcznych jednocześnie lub jedno okno podręczne na raz.

Dodatkowo te małe fragmenty kodu mogą obsługiwać zamykanie przycisków zawierających ikony!

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


1

Ten działa jak urok i używam go.

Otworzy popover po kliknięciu, a jeśli klikniesz ponownie, zamknie się, również jeśli klikniesz poza popover, popover zostanie zamknięty.

Działa to również z więcej niż 1 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();
});

To jedyny, który działał dla mnie. Bootstrap 3.20. Dziękuję Ci.
Telegard

1

Inne rozwiązanie, obejmowało problem, który miałem z klikaniem potomków 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');
    }
});

0

Robię to jak poniżej

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

Mam nadzieję że to pomoże!


0

Jeśli próbujesz użyć wyskakującego okienka bootstrap na Twitterze z pjaxem, to zadziałało:

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

@RayOnAir, mam ten sam problem z poprzednimi rozwiązaniami. Zbliżam się również do rozwiązania @RayOnAir. Jedną z ulepszeń jest zamykanie już otwartego okna popover po kliknięciu innego znacznika. Więc mój kod to:

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

Okazało się, że jest to zmodyfikowane rozwiązanie powyższej sugestii pbarona, ponieważ jego rozwiązanie aktywowało popover („ukryj”) na wszystkich elementach z klasą „popup-marker”. Jednakże, gdy używasz popover () do treści html zamiast danych-content, jak robię to poniżej, wszelkie kliknięcia wewnątrz tego wyskakującego okienka HTML faktycznie aktywują wyskakujące okienko („ukryj”), które natychmiast zamyka okno. Poniższa metoda iteruje przez każdy element .popup-marker i najpierw odkrywa, czy element nadrzędny jest powiązany z identyfikatorem klikniętego znacznika .popup-markera, a jeśli tak, to go nie ukrywa. Wszystkie inne elementy DIV są ukryte ...

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

Wymyśliłem to:

Mój scenariusz obejmował więcej wyskakujących okienek na tej samej stronie i ukrycie ich po prostu sprawiło, że stały się niewidoczne iz tego powodu klikanie elementów za wyskakującym okienkiem nie było możliwe. Chodzi o to, aby oznaczyć określony link popover jako „aktywny”, a następnie po prostu „przełączyć” aktywny popover. Spowoduje to całkowite zamknięcie 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"

0

Próbowałem znaleźć proste rozwiązanie prostego problemu. Powyższe posty są dobre, ale tak skomplikowane, jak na prosty problem. Zrobiłem więc prostą rzecz. Właśnie dodałem przycisk zamykania. To dla mnie idealne.

            $(".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

Podoba mi się to, proste, ale skuteczne ...

var openPopup;

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

    }
    openPopup=this;
});

0

Dodaj btn-popoverklasę do przycisku / linku popover, który otwiera okienko. Ten kod zamknie wyskakujące okienka po kliknięciu poza nim.

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

0

Jeszcze łatwiejsze rozwiązanie, po prostu przejrzyj wszystkie wyskakujące okienka i ukryj, jeśli nie 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
$('.popForm').popover();

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

Aby było jasne, po prostu uruchom popover


0

To powinno działać w 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")
  }
})

Wyjaśnienie:

  • Pierwsza sekcja uruchamia popover zgodnie z dokumentacją: https://getbootstrap.com/docs/4.0/components/popovers/
  • Pierwsze „if” w drugiej sekcji sprawdza, czy kliknięty element jest potomkiem elementu # my-popover-trigger. Jeśli to prawda, przełącza popover (obsługuje kliknięcie spustu).
  • Drugie „if” w drugiej sekcji sprawdza, czy kliknięty element jest potomkiem klasy treści popover, która została zdefiniowana w szablonie init. Jeśli tak nie jest, oznacza to, że kliknięcie nie znajdowało się w treści popover i można je ukryć.

Czy mógłbyś rozwinąć swój kod? Dodać wyjaśnienie do tego, co robisz?
Death Waltz

@DeathWaltz Właśnie dodałem wyjaśnienie w odpowiedzi.
Bart Blast

-1

Spróbuj data-trigger="focus"zamiast "click".

To rozwiązało problem.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.