web-dev-qa-db-ja.com

ポップオーバーがホバリングされている間、どのようにしてbootstrapポップオーバーを存続させることができますか?

Twitter boostrapのポップオーバーを使用してユーザー情報を表示するホバーカードを作成し、マウスオーバーチェックでポップオーバーをトリガーしていますjsfiddle here。ホバリングされている間、このポップオーバーを生かしたいです。

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

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

Facebookホバーカードの働きを考えることができます。同じようにしたいです。これどうやってするの?

103
vikas devde

私はこれに対する別の解決策の後に来ました...ここにコードがあります

    $('.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);
    });
79
vikas devde

この作業コードをPlunkerで表示

私のユースケースに合わせて、小さな変更(vikasが提供するソリューションから)。
1。ポップオーバーボタンのホバーイベントでポップオーバーを開く
2。ポップオーバーボックスにカーソルを合わせたときにポップオーバーを開いたままにする
3。ポップオーバーボタンまたはポップオーバーボックスのmouseleaveでポップオーバーを閉じます。

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

Plunkerでプレイ

154
OkezieE

私の見解は次のとおりです。 http://jsfiddle.net/WojtekKruszewski/Zf3m7/22/

マウスをポップオーバートリガーから実際のポップオーバーコンテンツに斜めに移動するときに、下の要素にカーソルを合わせます。このような状況に対処したかったのです。タイムアウトが発生する前にポップオーバーコンテンツに到達する限り、安全です(ポップオーバーは消えません)。 delayオプションが必要です。

このハックは、基本的にPopover leave関数をオーバーライドしますが、オリジナル(タイマーを開始してポップオーバーを非表示にします)を呼び出します。次に、一時的なリスナーをmouseenter popoverコンテンツ要素にアタッチします。

マウスがポップオーバーに入ると、タイマーはクリアされます。次に、ポップオーバーでmouseleaveをリッスンし、トリガーされた場合、元のleave関数を呼び出して、タイマーを非表示にします。

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

hoverに設定されたトリガーを使用し、#elementにコンテナセットを指定し、最後にboxの配置をrightに追加しました。

これはあなたのセットアップになります:

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

および#example cssにはposition:relative;が必要です。以下のjsfiddleを確認してください。

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

編集済み

このフィドルには、問題なく動作する両方のリンクがあります http://jsfiddle.net/davidchase03/FQE57/4/

14
David Chase

簡単な方法はこれだと思います:

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

これにより、ポップオーバーはターゲット要素自体の内部に作成されます。そのため、マウスをポップオーバーの上に移動しても、まだ要素の上にあります。 Bootstrap 3.3.2はこれでうまく機能します。古いバージョンではアニメーションに問題がある場合があるため、「animation:false」を無効にすることをお勧めします。

9
Cu Lý

これは、ネット上の他のビットの助けを借りてbootstrap popoverで行った方法です。サイトに表示されるさまざまな製品からタイトルとコンテンツを動的に取得します。各製品またはポップオーバーは一意のIDを取得します。ポップオーバーは、製品($ this .pop)またはポップオーバーを終了すると消えます。タイムアウトは、ポップオーバーではなく製品を終了するまでポップオーバーを表示する場所で使用されます。

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

これは、すべてのポップオーバーをオンにするために通常のBootstrap実装を使用できるようにする一方で、うまく機能するように考案したソリューションです。

元のフィドル: https://jsfiddle.net/eXpressive/hfear592/

この質問に移植:

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

シンプル:)

$('[data-toggle="popover"]').popover( { "container":"body", "trigger":"focus", "html":true });
$('[data-toggle="popover"]').mouseenter(function(){
    $(this).trigger('focus');
});
1
edmc73

David Chase 、Cu Lyなどによって与えられるものを使用するのが最善の方法であることに同意します。これを行う最も簡単な方法は、次のようにcontainer: $(this)プロパティを使用することです。

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

ここで指摘したいのは、この場合のポップオーバーは現在の要素のすべてのプロパティを継承するということです。したがって、たとえば、.btn要素(ブートストラップ)に対してこれを行うと、ポップオーバー内のテキストを選択できなくなります。かなりの時間を費やしてこれに頭を打ちました。

1
forumulator

Vikasの答えは私にとって完璧に機能します。ここでは、遅延(表示/非表示)のサポートも追加します。

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

また、私が変更したことに注意してください:

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

で:

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

開かれたポップオーバーを正確に参照し、他のポップオーバーを参照しないようにします(遅延により、同時に1つ以上が開く可能性があるため)

1
user1993198

選択された答えはworksですが、ポップオーバーがコンテナとしてbodyで初期化されると失敗します。

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

選択した回答に基づくソリューションは、ポップオーバーを使用する前に配置する必要がある次のコードです。

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

ポップオーバーが常に要素の兄弟であることを期待してDOMを走査する代わりに、self.$tipを使用することで、変更は最小限に抑えられます。

1
Rubens Mariuzzo

mouseleaveは、ウィンドウフォーカスが突然変更された後、ユーザーがブラウザーに戻るなど、奇妙なことが起こっても起動しないことがわかりました。そのような場合、mouseleaveは、カーソルが移動して要素を再び離れるまで起動しません。

私が思いついたこの解決策は、mouseenterオブジェクトのwindowに依存しているため、マウスをページ上でanywhere移動すると消えます。

これは、ページ上にそれをトリガーする複数の要素を持つように設計されました(テーブルなど)。

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");
        }
    });
});
0
Gabriel Luci
        $(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);
            });
        }); 
0
Dinesh Sarak

ツールチップについても同じこと:

私にとっては、すべての「マウスエンター」にイベントリスナーを追加するわけではなく、ツールチップを維持するツールチップ要素にホバーすることができるため、次のソリューションが機能します。

$ ->

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

より多くのflexible with 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);
    } 
)
0
Grey Li

このソリューションは私のためにうまくいきました:(現在は防弾);-)

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

これは、遅延のあるダイナミクスのツールチップを表示し、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>");
            }
        });
    }
}
0
Giuliano