Jak mogę utrzymać przy życiu wyskakujące okienka Bootstrap podczas unoszenia się?

114

Używam wyskakującego okienka Bootstrap, aby utworzyć wizytówkę pokazującą informacje o użytkowniku i uruchamiam ją po najechaniu kursorem myszy na przycisk. Chcę utrzymać ten popover przy życiu, gdy sam popover jest najeżdżany, ale znika, gdy tylko użytkownik przestanie najeżdżać na przycisk. W jaki sposób mogę to zrobić?

$('#example').popover({
    html : true,
    trigger : 'manual',
    content : function() {
        return '<div class="box">Popover</div>';
    }
});

$(document).on('mouseover', '#example', function(){
    $('#example').popover('show');
});

$(document).on('mouseleave', '#example', function(){
    $('#example').popover('hide');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.js"></script>
<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>

<a href="#" id="example" class="btn btn-danger" rel="popover" >hover for popover</a>

vikas devde
źródło
chcesz zachować to przy życiu? najechałem na przycisk i został on otwarty?
David Chase,
przeczytaj ostatnią linijkę pytania
vikas devde

Odpowiedzi:

172

Przetestuj z fragmentem kodu poniżej:

Mała modyfikacja (z rozwiązania dostarczonego przez Vikas), aby pasowała do mojego przypadku użycia.

  1. Otwórz zdarzenie Popover on hover dla przycisku Popover
  2. Pozostaw okno popover otwarte po najechaniu kursorem na okienko popover
  3. Zamknij wyskakujące okienko na mouseleave dla przycisku wyskakującego lub okienka podręcznego.

$(".pop").popover({
    trigger: "manual",
    html: true,
    animation: false
  })
  .on("mouseenter", function() {
    var _this = this;
    $(this).popover("show");
    $(".popover").on("mouseleave", function() {
      $(_this).popover('hide');
    });
  }).on("mouseleave", function() {
    var _this = this;
    setTimeout(function() {
      if (!$(".popover:hover").length) {
        $(_this).popover("hide");
      }
    }, 300);
  });
<!DOCTYPE html>
<html>

<head>
  <link data-require="bootstrap-css@*" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
  <script data-require="jquery@*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script data-require="bootstrap@*" data-semver="3.2.0" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.js"></script>

  <link rel="stylesheet" href="style.css" />

</head>

<body>
  <h2 class='text-primary'>Another Great "KISS" Bootstrap Popover example!</h2>
  <p class='text-muted'>KISS = Keep It Simple S....</p>

  <p class='text-primary'>Goal:</p>
  <ul>
    <li>Open popover on hover event for the popover button</li>
    <li>Keep popover open when hovering over the popover box</li>
    <li>Close popover on mouseleave for either the popover button, or the popover box.</li>
  </ul>

  <button type="button" class="btn btn-danger pop" data-container="body" data-toggle="popover" data-placement="right" data-content="Optional parameter: Skip if this was not requested<br>                                    A placement group is a logical grouping of instances within a single Availability                                     Zone. Using placement groups enables applications to get the full-bisection bandwidth                                     and low-latency network performance required for tightly coupled, node-to-node                                     communication typical of HPC applications.<br>                                    This only applies to cluster compute instances: cc2.8xlarge, cg1.4xlarge, cr1.8xlarge, hi1.4xlarge and hs1.8xlarge.<br>                                    More info: <a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html&quot; target=&quot;_blank&quot;>Click here...</a>"
    data-original-title="" title="">
    HOVER OVER ME
    </button>
  <br><br>
  <button type="button" class="btn btn-info pop" data-container="body" data-toggle="popover" data-placement="right" data-content="Optional parameter: Skip if this was not requested<br>                                    A placement group is a logical grouping of instances within a single Availability                                     Zone. Using placement groups enables applications to get the full-bisection bandwidth                                     and low-latency network performance required for tightly coupled, node-to-node                                     communication typical of HPC applications.<br>                                    This only applies to cluster compute instances: cc2.8xlarge, cg1.4xlarge, cr1.8xlarge, hi1.4xlarge and hs1.8xlarge.<br>                                    More info: <a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html&quot; target=&quot;_blank&quot;>Click here...</a>"
    data-original-title="" title="">
    HOVER OVER ME... Again!
    </button><br><br>
  <button type="button" class="btn btn-success pop" data-container="body" data-toggle="popover" data-placement="right" data-content="Optional parameter: Skip if this was not requested<br>                                    A placement group is a logical grouping of instances within a single Availability                                     Zone. Using placement groups enables applications to get the full-bisection bandwidth                                     and low-latency network performance required for tightly coupled, node-to-node                                     communication typical of HPC applications.<br>                                    This only applies to cluster compute instances: cc2.8xlarge, cg1.4xlarge, cr1.8xlarge, hi1.4xlarge and hs1.8xlarge.<br>                                    More info: <a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html&quot; target=&quot;_blank&quot;>Click here...</a>"
    data-original-title="" title="">
    Okay one more time... !
    </button>
  <br><br>
  <p class='text-info'>Hope that helps you... Drove me crazy for a while</p>
  <script src="script.js"></script>
</body>

</html>

OkezieE
źródło
To działa idealnie, zauważyłem, że brakowało ;w tobie sekundy $(_this).popover("hide"). Ale dziękuję, to było takie proste i czyste!
kozioł ofiarny
3
Ta odpowiedź jest niesamowita. Działa świetnie na BS3 od maja 2015 ^^
zdegenerowany
1
Użyłem go w tabeli i dodałem container: 'body'do opcji, ponieważ spowodowało to przesunięcie komórek. Świetna odpowiedź!
Alexander Derck
Popover zostanie ukryty, jeśli wejdziesz do niego, a następnie wrócisz do elementu wyzwalającego wszystko przed 300 ms. Aby to naprawić, sprawdź, czy ZARÓWNO popover, jak i jego wyzwalacz to: hover przed ukryciem go w setTimeout. Użyłbym również setTimeout i tego samego podejścia na mouseleave samego popover, aby naprawić migotanie.
rzb
Upewnij się, że ustawiłeś, animation:falseaby naprawić migotanie - sprawdź link Plunker, który mam powyżej. U mnie działa idealnie.
OkezieE
84

Przyszedłem po innym rozwiązaniu tego ... oto kod

    $('.selector').popover({
        html: true,
        trigger: 'manual',
        container: $(this).attr('id'),
        placement: 'top',
        content: function () {
            $return = '<div class="hover-hovercard"></div>';
        }
    }).on("mouseenter", function () {
        var _this = this;
        $(this).popover("show");
        $(this).siblings(".popover").on("mouseleave", function () {
            $(_this).popover('hide');
        });
    }).on("mouseleave", function () {
        var _this = this;
        setTimeout(function () {
            if (!$(".popover:hover").length) {
                $(_this).popover("hide")
            }
        }, 100);
    });
vikas devde
źródło
6
Jest ważne, aby dodać animation: falseinaczej przesunięcie myszy nad linkiem wielokrotnie spowoduje, że nie działa poprawnie
jasop
5
Mam małą modyfikację twojego kodu @vikas ( gist.github.com/Nitrodist/7913848 ). Po 50 ms ponownie sprawdza stan, aby nie pozostawał otwarty. Oznacza to, że stale sprawdza go ponownie co 50 ms.
Nitrodist,
2
Jak można to dostosować, aby działało na aktywnych elementach właśnie dodanych do dokumentu?
williamsowen
28

Oto moje podejście: http://jsfiddle.net/WojtekKruszewski/Zf3m7/22/

Czasami podczas przesuwania myszy od wyzwalacza wyskakującego okienka do rzeczywistej zawartości okna podręcznego po przekątnej , najeżdżasz na elementy poniżej. Chciałem poradzić sobie z takimi sytuacjami - o ile dotrzesz do zawartości popover, zanim upłynie limit czasu, jesteś bezpieczny (popover nie zniknie). To wymagadelay opcji.

Ten hack zasadniczo zastępuje leavefunkcję Popover , ale wywołuje oryginał (który uruchamia licznik czasu, aby ukryć popover). Następnie dołącza jednorazowy odbiornik do mouseenterpopover elementu zawartości.

Jeśli mysz wejdzie w okienko popover, licznik czasu zostanie wyczyszczony. Następnie włącza nasłuchiwanie mouseleavepo wyskakiwaniu i jeśli jest wyzwalany, wywołuje oryginalną funkcję wyjścia, aby mogła rozpocząć ukrywanie licznika czasu.

var originalLeave = $.fn.popover.Constructor.prototype.leave;
$.fn.popover.Constructor.prototype.leave = function(obj){
  var self = obj instanceof this.constructor ?
    obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
  var container, timeout;

  originalLeave.call(this, obj);

  if(obj.currentTarget) {
    container = $(obj.currentTarget).siblings('.popover')
    timeout = self.timeout;
    container.one('mouseenter', function(){
      //We entered the actual popover – call off the dogs
      clearTimeout(timeout);
      //Let's monitor popover content instead
      container.one('mouseleave', function(){
        $.fn.popover.Constructor.prototype.leave.call(self, self);
      });
    })
  }
};
Wojtek Kruszewski
źródło
5
Znalezienie kontenera można ulepszyć za pomocą W container = self.$tip;ten sposób popover można znaleźć nawet wtedy, gdy containerwłaściwość jest ustawiona. Jest tu skrzypce: jsfiddle.net/dennis_c/xJc65
dbroeks
3
@pferrel Rozwiązałem ten problem w moim widelcu skrzypiec @Wojtek_Kruszewski : jsfiddle.net/HugeHugh/pN26d zobacz część, która sprawdza if (!thisTip.is(':visible'))przed wywołaniemoriginalShow()
H Dog
1
Jeśli popover zostanie zainicjowany z opcją, container: 'body',to rozwiązanie nie będzie działać zgodnie z oczekiwaniami. Zmienna containermusi zostać zastąpiona przez self.$tip. Sprawdź moją odpowiedź, aby uzyskać więcej informacji: stackoverflow.com/a/28731847/439427
Rubens Mariuzzo
1
Znakomity. Działa to w przypadku używania parametru „selector”, w przeciwieństwie do innych odpowiedzi.
jetlej
1
Oto ulepszona wersja, która naprawia błąd przy wyjściu i ponownym wejściu do końcówki nadal ją ukrywała, a także naprawia scenariusz, gdy końcówka jest przymocowana do ciała jsfiddle.net/Zf3m7/1499
Zoltán Tamási
14

Myślę, że prostym sposobem byłoby to:

$('.popover').each(function () {
                    var $this = $(this);
                    $this.popover({
                        trigger: 'hover',
                        content: 'Content Here',
                        container: $this
                    })
                });

W ten sposób popover jest tworzony wewnątrz samego elementu docelowego. więc kiedy przesuniesz kursor myszy nad popover, nadal będzie on nad elementem. Bootstrap 3.3.2 działa z tym dobrze. Starsza wersja może mieć problemy z animacją, więc możesz chcieć wyłączyć „animation: false”

Cu Lý
źródło
Wiem, że ten wątek jest stary, ale to moim zdaniem najlepsze, najczystsze rozwiązanie i powinno być wyżej. Jedynym zastrzeżeniem jest to, że to się zepsuje, jeśli umieścisz popover (w dziwny sposób) „z dala” od elementu wyzwalającego. Ale dopóki odległość między nimi wynosi zero (np. Zachodzą na siebie), działa to pięknie i nie wymaga żadnego niestandardowego JS. Dziękuję Ci!
JohnGalt
To jak dotąd najlepsze, czyste i najłatwiejsze rozwiązanie. Powinien być wyżej w rankingu! Dodałem delay: { "hide": 400 }trochę opóźnienia przed ukryciem i działa świetnie! 👍
coorasse
14

Użyłem wyzwalacza ustawionego na hoveri dałem zestaw kontenera na #elementi ostatecznie dodając umieszczenie elementu boxto right.

To powinna być Twoja konfiguracja:

$('#example').popover({
    html: true,
    trigger: 'hover',
    container: '#example',
    placement: 'right',
    content: function () {
        return '<div class="box"></div>';
    }
});

a #examplecss musi position:relative;sprawdzić poniższy jsfiddle:

https://jsfiddle.net/9qn6pw4p/1/

Edytowano

To skrzypce ma oba linki, które działają bez problemów http://jsfiddle.net/davidchase03/FQE57/4/

David Chase
źródło
hmm to działa, mogę użyć jquery ajax w contentopcji, aby zabrać zawartość z serwera side..will że pracy lub muszę zrobić kilka dodatkowych prac za to
Vikas devde
@vikasdevde tak można użyć ajaxw treści, ale musisz ustawić się za to do pracy ... proszę zaznaczyć odpowiedź rację jeśli to rozwiązało OP.. więc inni mogą korzystać
David Chase
ale jeśli używamy samego łącza jako pojemnik następnie cała popover staje link .... spróbować
Vikas devde
jeśli umieścisz link w pudełku, będzie on nadal znajdował się… prawda?
David Chase,
2
Żaden z jsfiddle nie działa dla mnie. Chrome 20 marca 2014 r.
pferrel
7

Tak zrobiłem z popover bootstrap z pomocą innych bitów w sieci. Dynamicznie pobiera tytuł i treść z różnych produktów wyświetlanych na stronie. Każdy produkt lub popover otrzymuje unikalny identyfikator. Popover zniknie po wyjściu z produktu ($ this .pop) lub popover. Limit czasu jest używany, gdy wyświetli popover do wyjścia przez produkt zamiast popover.

$(".pop").each(function () {
        var $pElem = $(this);
        $pElem.popover(
            {
                html: true,
                trigger: "manual",
                title: getPopoverTitle($pElem.attr("id")),
                content: getPopoverContent($pElem.attr("id")),
                container: 'body',
                animation:false
            }
        );
    }).on("mouseenter", function () {
        var _this = this;
        $(this).popover("show");
        console.log("mouse entered");
        $(".popover").on("mouseleave", function () {
            $(_this).popover('hide');
        });
    }).on("mouseleave", function () {
        var _this = this;
        setTimeout(function () {
            if (!$(".popover:hover").length) {
                $(_this).popover("hide");
            }
        }, 100);
    });
    function getPopoverTitle(target) {
        return $("#" + target + "_content > h3.popover-title").html();
    };

    function getPopoverContent(target) {
        return $("#" + target + "_content > div.popover-content").html();
    };
hoektoe
źródło
Działa to również, jeśli popover nie jest elementem podrzędnym elementu docelowego. +1
Taha Paksu
6

Oto rozwiązanie, które wymyśliłem, które wydaje się działać dobrze, a jednocześnie umożliwia użycie normalnej implementacji Bootstrap do włączania wszystkich okien popover.

Oryginalne skrzypce: https://jsfiddle.net/eXpressive/hfear592/

Przeniesiony do tego pytania:

<a href="#" id="example" class="btn btn-danger" rel="popover" >hover for popover</a>

$('#example').popover({
    html : true,
    trigger : 'hover',
    content : function() {
        return '<div class="box"></div>';
    }
}).on('hide.bs.popover', function () {
    if ($(".popover:hover").length) {
      return false;
    }                
}); 

$('body').on('mouseleave', '.popover', function(){
    $('.popover').popover('hide');
});
eXpressiveDesign
źródło
2

Zgadzam się, że najlepiej jest skorzystać z tego, który podali: David Chase , Cu Ly i inni, że najprostszym sposobem jest użycie container: $(this)właściwości w następujący sposób:

$(selectorString).each(
  var $this = $(this);
  $this.popover({
    html: true,
    placement: "top",
    container: $this,
    trigger: "hover",
    title: "Popover",
    content: "Hey, you hovered on element"
  });
);

Chcę tutaj zaznaczyć, że popover w tym przypadku odziedziczy wszystkie właściwości bieżącego elementu . Na przykład, jeśli zrobisz to dla .btnelementu (bootstrap), nie będziesz w stanie zaznaczyć tekstu w wyskakującym okienku . Chciałem to tylko nagrać, ponieważ spędziłem trochę czasu, waląc w to głową.

forumulator
źródło
1

Odpowiedź Vikasa działa u mnie idealnie, tutaj dodam również obsługę opóźnienia (pokaż / ukryj).

var popover = $('#example');
var options = {
    animation : true,
    html: true,
    trigger: 'manual',
    placement: 'right',
    delay: {show: 500, hide: 100}
};   
popover
    .popover(options)
    .on("mouseenter", function () {

        var t = this;
        var popover = $(this);    
        setTimeout(function () {

            if (popover.is(":hover")) {

                popover.popover("show");
                popover.siblings(".popover").on("mouseleave", function () {
                    $(t).popover('hide');
                });
            }
        }, options.delay.show);
    })
    .on("mouseleave", function () {
        var t = this;
        var popover = $(this);

        setTimeout(function () {
            if (popover.siblings(".popover").length && !popover.siblings(".popover").is(":hover")) {
                $(t).popover("hide")
            }
        }, options.delay.hide);
    });     

Zwróć też uwagę, że zmieniłem:

if (!$(".popover:hover").length) {

z:

if (popover.siblings(".popover").length && !popover.siblings(".popover").is(":hover")) {

tak, że odwołuje się dokładnie do tego otwartego okna popover, a nie do żadnego innego (ponieważ teraz, z powodu opóźnienia, więcej niż 1 może być otwarte w tym samym czasie)

user1993198
źródło
Komentarz, który zrobiłem na końcu, w rzeczywistości nie jest właściwy, gdy używam container: body, jeśli tak, nadal muszę użyć rozwiązania Vikasa dla tej jednej linii
user1993198
1

Wybrana odpowiedź działa, ale zakończy się niepowodzeniem, jeśli popover zostanie zainicjowany z bodykontenerem.

$('a').popover({ container: 'body' });

Rozwiązaniem opartym na wybranej odpowiedzi jest poniższy kod, który należy umieścić przed użyciem popover.

var originalLeave = $.fn.popover.Constructor.prototype.leave;
$.fn.popover.Constructor.prototype.leave = function(obj) {
    var self = obj instanceof this.constructor ? obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type);
    originalLeave.call(this, obj);

    if (obj.currentTarget) {
        self.$tip.one('mouseenter', function() {
            clearTimeout(self.timeout);
            self.$tip.one('mouseleave', function() {
                $.fn.popover.Constructor.prototype.leave.call(self, self);
            });
        })
    }
};

Zmiana jest minimalna przy użyciu self.$tipzamiast przechodzenia przez DOM, oczekując, że popover będzie zawsze rodzeństwem elementu.

Rubens Mariuzzo
źródło
0

To samo dotyczy podpowiedzi:

Dla mnie poniższe rozwiązanie działa, ponieważ nie dodaje detektorów zdarzeń na każdym „środku myszy” i można ponownie najechać kursorem na element podpowiedzi, który utrzymuje etykietkę przy życiu.

$ ->

  $('.element').tooltip({
    html: true,
    trigger: 'manual'
  }).
  on 'mouseenter', ->
    clearTimeout window.tooltipTimeout
    $(this).tooltip('show') unless $('.tooltip:visible').length > 0
  .
  on 'mouseleave', ->
    _this = this
    window.tooltipTimeout = setTimeout ->
      $(_this).tooltip('hide')
    , 100

$(document).on 'mouseenter', '.tooltip', ->
  clearTimeout window.tooltipTimeout

$(document).on 'mouseleave', '.tooltip', ->
  trigger = $($(this).siblings('.element')[0])
  window.tooltipTimeout = setTimeout ->
    trigger.tooltip('hide')
  , 100
phlppn
źródło
0

To rozwiązanie zadziałało dla mnie dobrze: (teraz jest kuloodporne) ;-)

function enableThumbPopover() {
    var counter;

    $('.thumbcontainer').popover({
        trigger: 'manual',
        animation: false,
        html: true,
        title: function () {
            return $(this).parent().find('.thumbPopover > .title').html();
        },
        content: function () {
            return $(this).parent().find('.thumbPopover > .body').html();
        },
        container: 'body',
        placement: 'auto'
    }).on("mouseenter",function () {
        var _this = this; // thumbcontainer

        console.log('thumbcontainer mouseenter')
        // clear the counter
        clearTimeout(counter);
        // Close all other Popovers
        $('.thumbcontainer').not(_this).popover('hide');

        // start new timeout to show popover
        counter = setTimeout(function(){
            if($(_this).is(':hover'))
            {
                $(_this).popover("show");
            }
            $(".popover").on("mouseleave", function () {
                $('.thumbcontainer').popover('hide');
            });
        }, 400);

    }).on("mouseleave", function () {
        var _this = this;

        setTimeout(function () {
            if (!$(".popover:hover").length) {
                if(!$(this).is(':hover'))
                {
                    $(_this).popover('hide');
                }
            }
        }, 200);
    });
}
Johannes Ferner
źródło
0
        $(function() {
            $("[data-toggle = 'popover']").popover({
                placement: 'left',
                html: true,
                trigger: "  focus",
            }).on("mouseenter", function() {
                var _this = this;
                $(this).popover("show");
                $(this).siblings(".popover").on("mouseleave", function() {
                    $(_this).popover('hide');
                });
            }).on("mouseleave", function() {
                var _this = this;
                setTimeout(function() {
                    if (!$(".popover:hover").length) {
                        $(_this).popover("hide")
                    }
                }, 100);
            });
        }); 
Dinesh Sarak
źródło
0

Zauważyłem, że mouseleavenie uruchomi się, gdy zdarzają się dziwne rzeczy, na przykład nagle zmienia się fokus okna, a następnie użytkownik wraca do przeglądarki. W takich przypadkachmouseleave nigdy się nie uruchomi, dopóki kursor nie przejdzie i nie opuści elementu.

To rozwiązanie, które wymyśliłem, opiera się mouseenterna windowobiekcie, więc znika, gdy mysz zostanie przesunięta w inne miejsce strony.

Zostało to zaprojektowane do pracy z wieloma elementami na stronie, które ją wywołają (jak w tabeli).

var allMenus = $(".menus");
allMenus.popover({
    html: true,
    trigger: "manual",
    placement: "bottom",
    content: $("#menuContent")[0].outerHTML
}).on("mouseenter", (e) => {
    allMenus.not(e.target).popover("hide");
    $(e.target).popover("show");
    e.stopPropagation();
}).on("shown.bs.popover", () => {
    $(window).on("mouseenter.hidepopover", (e) => {
        if ($(e.target).parents(".popover").length === 0) {
            allMenus.popover("hide");
            $(window).off("mouseenter.hidepopover");
        }
    });
});
Gabriel Luci
źródło
0

Będzie bardziej elastyczny dzięki hover():

$(".my-popover").hover(
    function() {  // mouse in event
        $this = $(this);
        $this.popover({
            html: true,
            content: "Your content",
            trigger: "manual",
            animation: false
            });
        $this.popover("show");
        $(".popover").on("mouseleave", function() {
            $this.popover("hide");
        });
    },
    function() {  // mouse out event
        setTimeout(function() {
            if (!$(".popover:hover").length) {
                $this.popover("hide");
            }
        }, 100);
    } 
)
Gray Li
źródło
0

Prosty :)

$('[data-toggle="popover"]').popover( { "container":"body", "trigger":"focus", "html":true });
$('[data-toggle="popover"]').mouseenter(function(){
    $(this).trigger('focus');
});
edmc73
źródło
0

Niedawno potrzebowałem, aby to działało z KO, a powyższe rozwiązania nie działały dobrze, gdy miałem opóźnienia w pokazaniu i ukryciu. Poniższe informacje powinny to naprawić. Na podstawie tego, jak działają podpowiedzi bootstrap. Mam nadzieję, że to komuś pomoże.

var options = {
                delay: { show: 1000, hide: 50 },
                trigger: 'manual',                      
                html: true
            };
var $popover = $(element).popover(options);

$popover.on('mouseenter', function () { // This is entering the triggering element
    var self = this;

    clearTimeout(self.timeout);
    self.hoverState = 'in';

    self.timeout = setTimeout(function () {
        if (self.hoverState == 'in') {
            $(self).popover("show");

            $(".popover, .popover *").on('mouseover', function () { // This is moving over the popover
                clearTimeout(self.timeout);
            });                                                                 

            $(".popover").on('mouseleave', function () { // This is leaving the popover
                self.timeout = setTimeout(function () {
                    if (self.hoverState == 'out') {
                        $(self).popover('hide');
                    }
                }, options.delay.hide);
            });
        }
    }, options.delay.show);
}).on('mouseleave', function (event) { // This is leaving the triggering element
    var self = this;

    clearTimeout(self.timeout);
    self.hoverState = 'out';

    self.timeout = setTimeout(function () {                             
        if (self.hoverState == 'out') {
            $(self).popover('hide');
        }

    }, options.delay.hide);
});
Zarthost Boman
źródło
-1

To jest mój kod do wyświetlania podpowiedzi dynamiki z opóźnieniem i ładowany przez ajax.

$(window).on('load', function () {
    generatePopovers();
    
    $.fn.dataTable.tables({ visible: true, api: true }).on('draw.dt', function () {
        generatePopovers();
    });
});

$(document).ajaxStop(function () {
    generatePopovers();
});

function generatePopovers() {
var popover = $('a[href*="../Something.aspx"]'); //locate the elements to popover

popover.each(function (index) {
    var poplink = $(this);
    if (poplink.attr("data-toggle") == null) {
        console.log("RENDER POPOVER: " + poplink.attr('href'));
        poplink.attr("data-toggle", "popover");
        poplink.attr("data-html", "true");
        poplink.attr("data-placement", "top");
        poplink.attr("data-content", "Loading...");
        poplink.popover({
            animation: false,
            html: true,
            trigger: 'manual',
            container: 'body',
            placement: 'top'
        }).on("mouseenter", function () {
            var thispoplink = poplink;
            setTimeout(function () {
                if (thispoplink.is(":hover")) {
                    thispoplink.popover("show");
                    loadDynamicData(thispoplink); //load data by ajax if you want
                    $('body .popover').on("mouseleave", function () {
                        thispoplink.popover('hide');
                    });
                }
            }, 1000);
        }).on("mouseleave", function () {
            var thispoplink = poplink;
            setTimeout(function () {
                if (!$("body").find(".popover:hover").length) {
                    thispoplink.popover("hide");
                }
            }, 100);
        });
    }
});

function loadDynamicData(popover) {
    var params = new Object();
    params.somedata = popover.attr("href").split("somedata=")[1]; //obtain a parameter to send
    params = JSON.stringify(params);
    //check if the content is not seted
    if (popover.attr("data-content") == "Loading...") {
        $.ajax({
            type: "POST",
            url: "../Default.aspx/ObtainData",
            data: params,
            contentType: "application/json; charset=utf-8",
            dataType: 'json',
            success: function (data) {
                console.log(JSON.parse(data.d));
                var dato = JSON.parse(data.d);
                if (dato != null) {
                    popover.attr("data-content",dato.something); // here you can set the data returned
                    if (popover.is(":hover")) {
                        popover.popover("show"); //use this for reload the view
                    }
                }
            },

            failure: function (data) {
                itShowError("- Error AJAX.<br>");
            }
        });
    }
}

Giuliano
źródło