Как я могу сохранить bootstrap popover живым, пока popover зависает?


Я использую поповер twitter boostrap для создания карты наведения, чтобы показать информацию о пользователе, и я запускаю поповер при проверке мыши jsfiddle здесь. Я хочу сохранить этот поповер живым, пока он парит.

<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 hover card. Я хочу сделать это таким же образом. Как я могу это сделать?

16 88

16 ответов:

просмотр этого рабочего кода в Plunker

небольшая модификация (из решения, предоставленного vikas) в соответствии с моим вариантом использования.
1. Открытый пирог на событие наведения на кнопку диалогового окна
2. Сохранить диалоговое окно открывается при наведении на поле диалогового окна
3. Закройте popover на mouseleave для кнопки popover или окна popover.

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

Я пришел после другого решения этой проблемы...вот код

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

вот мое мнение:http://jsfiddle.net/WojtekKruszewski/Zf3m7/22/

иногда при движении мыши из окна спусковой крючок, чтобы реальное содержание диалогового окна по диагонали, наведите указатель мыши на элементы ниже. Я хотел справиться с такими ситуациями – пока вы достигаете содержимого popover до того, как тайм-аут срабатывает, вы в безопасности (popover не исчезнет). Это требует .

этот хак в основном переопределяет Popover

я использовал триггер, установленный в 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/

редактировать

эта скрипка имеет обе ссылки, которые работают с no проблемы http://jsfiddle.net/davidchase03/FQE57/4/

Я думаю, что простой способ будет следующим:

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

таким образом, popover создается внутри самого целевого элемента. поэтому, когда вы наводите курсор мыши на popover, он все еще находится над элементом. В Bootstrap 3.3.2 хорошо работает с этим. Более старая версия может иметь некоторые проблемы с анимацией, поэтому вы можете отключить "animation:false"

вот как я сделал с bootstrap popover с помощью других битов вокруг сети. Динамически получает заголовок и содержимое от различных продуктов, отображаемых на сайте. Каждый продукт или popover получает уникальный идентификатор. Popover исчезнет при выходе из продукта( $this .поп) или пирог. Тайм-аут используется, где будет отображаться поповер до выхода через продукт вместо поповера.

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

вот решение, которое я разработал, которое, кажется, работает хорошо, а также позволяет использовать обычную реализацию 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');
});

ответ 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")) {

Так что он ссылается именно на этот открытый popover, а не на любой другой (так как теперь, через задержку, более 1 может быть открыт одновременно)

выбранный ответ работает но не получится, если popover инициализируется с помощью body как контейнер.

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

решение, основанное на выбранном ответе, - это следующий код, который необходимо поместить перед использованием 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);
            });
        })
    }
};

изменение минимально с помощью self.$tip вместо того, чтобы пересекать DOM, ожидая, что popover всегда будет братьями и сестрами элемента.

просто :)

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

то же самое для подсказки:

для меня следующее решение работает, потому что оно не добавляет прослушиватели событий на каждом "mouseenter", и можно навести указатель мыши на элемент tooltip, который поддерживает всплывающую подсказку.

$ ->

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

Это решение отлично сработало для меня: (теперь его пуленепробиваемый); -)

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

Я согласен, что лучший способ-использовать тот, который дается:Дэвид Чейз, 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"
  });
);

Я хочу отметить здесь, что popover в этом случае унаследует все свойства текущего элемента. Так, например, если вы делаете это для .btn элемент (bootstrap),вы не сможете выбрать текст внутри popover. Просто хотел записать так что я провел некоторое время биться головой об это.

нашел mouseleave не будет срабатывать, когда происходят странные вещи, например, фокус окна внезапно меняется, а затем пользователь возвращается в браузер. В таких случаях, mouseleave никогда не будет срабатывать, пока курсор не перейдет и снова не покинет элемент.

это решение я придумал полагается на mouseenter на window объект, поэтому он исчезает при перемещении мыши нигде на странице.

Это было разработано для работы с несколькими элементы на странице, которые будут вызывать его (как в таблице).

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

это будет больше гибкий С 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);
    } 
)