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?

Travis Northcutt
źródło
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 :-)

Radu Cugut
źródło
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();
});
prbaron
źródło
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();
Miika L.
źródło
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!

RayOnAir
źródło
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>
Andrej Sramko
źródło
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);
}
David Wolever
źródło
+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!

moollaza
źródło
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

Bert-Jan Steerneman
źródło
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();
});
Roshdy
źródło
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');
    });
Luca Vizzi
źródło
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;
        }        
    });
});
Gilles Hemmerlé
źródło
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");
    }

  });
});
nates
źródło
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
    });
});
oBo
źródło
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);
}
Lee Gary
źródło
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

mattdlockyer
źródło
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();
});
Patrick Nogueira
źródło
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');
    }
});
Fernando Caraballo
źródło
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!

foxybagga
źródło
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);
});
keruilin
źródło
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;
  }
});
msa.im
źródło
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();
            });
        });
David
źródło
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"
Adi Nistor
źródło
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;
    }
Mohammad Kashif
źródło
0

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

var openPopup;

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

    }
    openPopup=this;
});
gstarr
źródło
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');
  }
});
Tobias Mühl
źródło
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');
        }
    });
});
inostia
źródło
0
$('.popForm').popover();

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

Aby było jasne, po prostu uruchom popover

poeta
źródło
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ć.
Bart Blast
źródło
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.

Hannes
źródło