Как убрать щебетать Twitter-загрузчика, нажав на него?

Можем ли мы получить popovers для увольнения так же, как модалы, т.е. закрыть их, когда пользователь нажимает где-то за их пределами?

К сожалению, я не могу просто использовать настоящий модальный вместо popover, потому что модальная позиция означает: исправлена, и это больше не будет popover.: (

Ответ 1

Обновление: Несколько более надежное решение: http://jsfiddle.net/mattdlockyer/C5GBU/72/

Для кнопок, содержащих только текст:

$('body').on('click', function (e) {
    //did not click a popover toggle or popover
    if ($(e.target).data('toggle') !== 'popover'
        && $(e.target).parents('.popover.in').length === 0) { 
        $('[data-toggle="popover"]').popover('hide');
    }
});

Для кнопок, содержащих значки, используйте (этот код имеет ошибку в Bootstrap 3.3.6, см. исправление ниже в этом ответе)

$('body').on('click', function (e) {
        //did not click a popover toggle, or icon in popover toggle, or popover
        if ($(e.target).data('toggle') !== 'popover'
            && $(e.target).parents('[data-toggle="popover"]').length === 0
            && $(e.target).parents('.popover.in').length === 0) { 
            $('[data-toggle="popover"]').popover('hide');
        }
    });

Для JS Generated Popovers Используйте '[data-original-title]' вместо '[data-toggle="popover"]'

Предостережение: Вышеупомянутое решение позволяет сразу открывать несколько popovers.

Один постер в любое время:

Обновление: Bootstrap 3.0.x, см. код или скрипт http://jsfiddle.net/mattdlockyer/C5GBU/2/

$('body').on('click', function (e) {
    $('[data-toggle="popover"]').each(function () {
        //the 'is' for buttons that trigger popups
        //the 'has' for icons within a button that triggers a popup
        if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
            $(this).popover('hide');
        }
    });
});

Это обрабатывает закрытие всплывающих окон, которые уже открыты и не нажаты, или их ссылки не были нажаты.


Обновление: Bootstrap 3.3.6, см. скрипку

Исправлена ​​проблема, когда после закрытия требуется 2 щелчка для повторного открытия

$(document).on('click', function (e) {
    $('[data-toggle="popover"],[data-original-title]').each(function () {
        //the 'is' for buttons that trigger popups
        //the 'has' for icons within a button that triggers a popup
        if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {                
            (($(this).popover('hide').data('bs.popover')||{}).inState||{}).click = false  // fix for BS 3.3.6
        }

    });
});

Ответ 2

$('html').on('mouseup', function(e) {
    if(!$(e.target).closest('.popover').length) {
        $('.popover').each(function(){
            $(this.previousSibling).popover('hide');
        });
    }
});

Это закрывает все popovers, если вы нажимаете где-либо, кроме как на popover

ОБНОВЛЕНИЕ для Bootstrap 4.1

$("html").on("mouseup", function (e) {
    var l = $(e.target);
    if (l[0].className.indexOf("popover") == -1) {
        $(".popover").each(function () {
            $(this).popover("hide");
        });
    }
});

Ответ 3

Самая простая, наиболее безопасная версия, работает с любой версией начальной загрузки.

Демо: http://jsfiddle.net/guya/24mmM/

Демонстрация 2: не отклонение при нажатии внутри содержимого popover http://jsfiddle.net/guya/fjZja/

Демо 3: Несколько popovers: http://jsfiddle.net/guya/6YCjW/


Просто вызов этой строки убьет все popovers:

$('[data-original-title]').popover('hide');

Отклонить все popovers при нажатии на внешний вид с помощью этого кода:

$('html').on('click', function(e) {
  if (typeof $(e.target).data('original-title') == 'undefined') {
    $('[data-original-title]').popover('hide');
  }
});

Фрагмент выше прикрепляет событие click на теле. Когда пользователь нажимает на popover, он будет вести себя как обычно. Когда пользователь нажимает на то, что не является popover, оно закрывает все popovers.

Он также будет работать с popovers, которые инициируются Javascript, в отличие от некоторых других примеров, которые не будут работать. (см. демонстрацию)

Если вы не захотите уклоняться при нажатии внутри содержимого popover, используйте этот код (см. ссылку на 2-ю демо):

$('html').on('click', function(e) {
  if (typeof $(e.target).data('original-title') == 'undefined' && !$(e.target).parents().is('.popover.in')) {
    $('[data-original-title]').popover('hide');
  }
});

Ответ 4

С помощью бутстрапа 2.3.2 вы можете установить триггер на "фокус", и он просто работает:

$('#el').popover({trigger:'focus'});

Ответ 5

Это в основном не очень сложно, но есть некоторая проверка, чтобы избежать сбоев.

Демо (jsfiddle)

var $poped = $('someselector');

// Trigger for the popover
$poped.each(function() {
    var $this = $(this);
    $this.on('hover',function() {
            var popover = $this.data('popover');
            var shown = popover && popover.tip().is(':visible');
            if(shown) return;        // Avoids flashing
            $this.popover('show');
    });
});

// Trigger for the hiding
 $('html').on('click.popover.data-api',function() {
    $poped.popover('hide');
});

Ответ 6

Ни один из предполагаемых высоко разрешенных решений не работал у меня правильно. Каждый из них приводит к ошибке, когда после открытия и закрытия (щелкнув по другим элементам) popover в первый раз, он не открывается снова, пока вы не сделаете два клика на триггерной ссылке вместо одной.

Итак, я немного изменил его:

$(document).on('click', function (e) {
    var
        $popover,
        $target = $(e.target);

    //do nothing if there was a click on popover content
    if ($target.hasClass('popover') || $target.closest('.popover').length) {
        return;
    }

    $('[data-toggle="popover"]').each(function () {
        $popover = $(this);

        if (!$popover.is(e.target) &&
            $popover.has(e.target).length === 0 &&
            $('.popover').has(e.target).length === 0)
        {
            $popover.popover('hide');
        } else {
            //fixes issue described above
            $popover.popover('toggle');
        }
    });
})

Ответ 7

Я сделал jsfiddle, чтобы показать вам, как это сделать:

http://jsfiddle.net/3yHTH/

Идея состоит в том, чтобы показать popover, когда вы нажимаете кнопку, и скрывать popover, когда вы нажимаете кнопку за пределами кнопки.

HTML

<a id="button" href="#" class="btn btn-danger">Click for popover</a>

JS

$('#button').popover({
    trigger: 'manual',
    position: 'bottom',
    title: 'Example',
    content: 'Popover example for SO'
}).click(function(evt) {
    evt.stopPropagation();
    $(this).popover('show');
});

$('html').click(function() {
    $('#button').popover('hide');
});

Ответ 8

Это задано перед here. Тот же ответ, который я дал, по-прежнему применяется:

У меня была аналогичная потребность, и я нашел это большое небольшое расширение Twitter Bootstrap Popover от Lee Carmichael, названное BootstrapX - clickover. Он также имеет некоторые примеры использования здесь. В основном это изменит popover на интерактивный компонент, который закроется, когда вы нажмете в другом месте на странице или на кнопке закрытия внутри popover. Это также позволит открывать сразу несколько popovers и множество других приятных функций.

Ответ 9

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

Он позиционируется автоматически, чтобы он никогда не покидал страницу.

https://github.com/Itumac/bootstrap-bubble

Это не беспроигрышная самопомощь... Я много раз забирал у других людей код в своей жизни, я хотел предложить свои собственные усилия. Дайте ему вихрь и посмотрите, работает ли оно для вас.

Ответ 10

Согласно http://getbootstrap.com/javascript/#popovers,

<button type="button" class="popover-dismiss" data-toggle="popover" title="Dismissible popover" data-content="Popover Content">Dismissible popover</button>

Используйте триггер фокуса, чтобы отклонять popovers при следующем щелчке, который делает пользователь.

$('.popover-dismiss').popover({
    trigger: 'focus'
})

Ответ 11

Модифицированное принятое решение. То, что я испытал, было то, что после того, как некоторые popovers были спрятаны, их нужно было бы дважды щелкнуть, чтобы снова появиться. Вот что я сделал, чтобы гарантировать, что popover ('hide') не вызывается на уже скрытые popovers.

$('body').on('click', function (e) {
    $('[data-original-title]').each(function () {
        //the 'is' for buttons that trigger popups
        //the 'has' for icons within a button that triggers a popup
        if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
            var popoverElement = $(this).data('bs.popover').tip();
            var popoverWasVisible = popoverElement.is(':visible');

            if (popoverWasVisible) {
                $(this).popover('hide');
                $(this).click(); // double clicking required to reshow the popover if it was open, so perform one click now
            }
        }
    });
});

Ответ 12

просто добавьте этот атрибут с элементом

data-trigger="focus"

Ответ 13

jQuery("#menu").click(function(){ return false; });
jQuery(document).one("click", function() { jQuery("#menu").fadeOut(); });

Ответ 14

Вы также можете использовать пузырьки событий, чтобы удалить всплывающее окно из DOM. Это немного грязно, но отлично работает.

$('body').on('click touchstart', '.popover-close', function(e) {
  return $(this).parents('.popover').remove();
});

В html добавьте класс .popover-close к содержимому внутри popover, которое должно закрыть popover.

Ответ 15

Кажется, что метод 'hide' не работает, если вы создаете popover с делегированием селектора, вместо этого нужно использовать "destroy".

Я сделал это так:

$('body').popover({
    selector: '[data-toggle="popover"]'
});

$('body').on('click', function (e) {
    $('[data-toggle="popover"]').each(function () {
        //the 'is' for buttons that trigger popups
        //the 'has' for icons within a button that triggers a popup
        if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
            $(this).popover('destroy');
        }
    });
});

JSfiddle здесь

Ответ 16

Мы выяснили, что у нас была проблема с решением от @mattdlockyer (спасибо за решение!). При использовании свойства selector для конструктора popover, подобного этому...

$(document.body').popover({selector: '[data-toggle=popover]'});

... предлагаемое решение для BS3 не будет работать. Вместо этого он создает второй экземпляр popover, локальный для своего $(this). Вот наше решение, чтобы предотвратить это:

$(document.body).on('click', function (e) {
    $('[data-toggle="popover"]').each(function () {
        //the 'is' for buttons that trigger popups
        //the 'has' for icons within a button that triggers a popup
        if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
            var bsPopover = $(this).data('bs.popover'); // Here where the magic happens
            if (bsPopover) bsPopover.hide();
        }
    });
});

Как уже упоминалось, $(this).popover('hide'); создаст второй экземпляр из-за делегированного прослушивателя. Решение предоставило только скрытые popovers, которые уже были созданы.

Надеюсь, я смогу сэкономить вам время.

Ответ 17

Bootstrap изначально поддерживает это:

JS Bin Demo

Конкретная разметка, необходимая для перехода к следующему клику

Для правильного кросс-браузерного и кросс-платформенного поведения вы должны использовать тег <a>, а не тег <button>, а также должны включать атрибуты role="button" и tabindex.

Ответ 18

это решение избавляется от досадного второго щелчка при показе popover во второй раз

с помощью Bootstrap v3.3.7

$('body').on('click', function (e) {
    $('.popover').each(function () {
        var popover = $(this).data('bs.popover');
        if (!popover.$element.is(e.target)) {
            popover.inState.click = false;
            popover.hide();                
        }
    });
});

Ответ 19

Я просто удаляю другие активные popovers перед показом нового popover (bootstrap 3):

$(".my-popover").popover();

$(".my-popover").on('show.bs.popover',function () {
    $('.popover.in').remove();
});              

Ответ 20

проверено с 3.3.6, а второй щелчок в порядке

        $('[data-toggle="popover"]').popover()
            .click(function () {
            $(this).popover('toggle');
        });;

        $(document).on('click', function (e) {
            $('[data-toggle="popover"]').each(function () {
                //the 'is' for buttons that trigger popups
                //the 'has' for icons within a button that triggers a popup
                if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
                    $(this).popover('hide');
                }
            });
        });

Ответ 21

Я пробовал многие из предыдущих ответов, на самом деле для меня ничего не работает, но это решение получило:

https://getbootstrap.com/docs/3.3/javascript/#dismiss-on-next-click

Они рекомендуют использовать якорный тэг not button и позаботиться о параметрах role = "button" + data-trigger = "focus" + tabindex = "0".

Пример:

<a tabindex="0" class="btn btn-lg btn-danger" role="button" data-toggle="popover" 
data-trigger="focus" title="Dismissible popover" data-content="amazing content">
Dismissible popover</a>

Ответ 22

demo: http://jsfiddle.net/nessajtr/yxpM5/1/

var clickOver = clickOver || {};
clickOver.uniqueId = $.now();

clickOver.ClickOver = function (selector, options) {
    var self = this;

    //default values
    var isVisible, clickedAway = false;

    var callbackMethod = options.content;
var uniqueDiv = document.createElement("div");
var divId = uniqueDiv.id = ++clickOver.uniqueId;
uniqueDiv.innerHTML = options.loadingContent();

options.trigger = 'manual';
options.animation = false;
options.content = uniqueDiv;

self.onClose = function () {
    $("#" + divId).html(options.loadingContent());
    $(selector).popover('hide')
    isVisible = clickedAway = false;
};
self.onCallback = function (result) {
    $("#" + divId).html(result);
};

$(selector).popover(options);

//events
$(selector).bind("click", function (e) {
    $(selector).filter(function (f) {
        return $(selector)[f] != e.target;
    }).popover('hide');

    $(selector).popover("show");
    callbackMethod(self.onCallback);

    isVisible = !(clickedAway = false);
});

$(document).bind("click", function (e) {
    if (isVisible && clickedAway && $(e.target).parents(".popover").length == 0) {
        self.onClose();
        isVisible = clickedAway = false;
    } else clickedAway = true;
});

}

это мое решение для него.

Ответ 23

Этот подход гарантирует, что вы можете закрыть popover, щелкнув в любом месте страницы. Если вы нажмете на другой кликабельный объект, он скрывает все остальные popovers. Анимация: false требуется другое, вы получите ошибку jquery.remove в консоли.

$('.clickable').popover({
 trigger: 'manual',
 animation: false
 }).click (evt) ->
  $('.clickable').popover('hide')
  evt.stopPropagation()
  $(this).popover('show')

$('html').on 'click', (evt) ->
  $('.clickable').popover('hide')

Ответ 24

Хорошо, это моя первая попытка ответить на что-то в stackoverflow, поэтому здесь ничего не происходит: P

Похоже, что не совсем ясно, что эта функциональность действительно работает из коробки в последнем загрузочном блоке (ну, если вы готовы пойти на компромисс, где пользователь может нажать. Я не уверен, что вам нужно поместите 'click hover' per-se, но на iPad, щелчок работает как переключатель.

Конечный результат: на рабочем столе вы можете навести указатель мыши или щелкнуть (большинство пользователей будет нависнуть). На сенсорном устройстве прикосновение к элементу вызовет его, и прикосновение к нему снова снимет его. Конечно, это небольшой компромисс от вашего первоначального требования, но по крайней мере ваш код теперь более чистый:)

$( "мой-поповер" ). Поповер ({     триггер: 'click hover' });

Ответ 25

Я придумал это: Мой сценарий включал в себя больше popovers на одной странице, и их скрытие просто сделало их невидимыми, и из-за этого щелчок по элементам позади popover не был возможен. Идея состоит в том, чтобы отметить конкретную popover-ссылку как "активную", а затем вы можете просто "переключить" активный popover. Это позволит полностью закрыть 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"

Ответ 26

Взяв код Matt Lockyer, я сделал простую reset, поэтому dom не покрывается элементом в hide.

Мэтт код: http://mattlockyer.com/2013/04/08/close-a-twitter-bootstrap-popover-when-clicking-outside/

Fiddle: http://jsfiddle.net/mrsmith/Wd2qS/

    $('body').on('click', function (e) {
    //hide popover from dom to prevent covering elements
    $('.popover').css('display', 'none');
    //bring popover back if trigger element is clicked
    $('[data-toggle="popover"]').each(function () {
        if ($(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
            $('.popover').css('display', 'block');
        }
    });
    //hide popover with .popover method
    $('[data-toggle="popover"]').each(function () {
        //the 'is' for buttons that trigger popups
        //the 'has' for icons within a button that triggers a popup
        if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
            $(this).popover('hide');
        }
    });
});

Ответ 27

Попробуйте это, это скроется, щелкнув снаружи.

$('body').on('click', function (e) {
    $('[data-toggle="popover"]').each(function () {
    //the 'is' for buttons that trigger popups
    //the 'has' for icons within a button that triggers a popup
    if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
    $(this).popover('hide');
    }
    });
});

Ответ 28

У меня возникали проблемы с решением mattdlockyer, потому что я динамически настраивал ссылки на popover, используя следующий код:

$('body').popover({
        selector : '[rel="popover"]'
});

Поэтому мне пришлось изменить его так. Для меня было много проблем:

$('html').on('click', function (e) {
  $('[data-toggle="popover"]').each(function () {
    //the 'is' for buttons that trigger popups
    //the 'has' for icons within a button that triggers a popup
    if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
        $(this).popover('destroy');
    }
  });
});

Помните, что уничтожение избавляется от элемента, поэтому селекторная часть важна при инициализации popovers.

Ответ 29

Ответ от @guya работает, если у вас нет что-то вроде datepicker или timepicker в popover. Чтобы это исправить, это то, что я сделал.

if (typeof $(e.target).data('original-title') === 'undefined' && 
    !$(e.target).parents().is('.popover.in')) {
        var x = $(this).parents().context;
        if(!$(x).hasClass("datepicker") && !$(x).hasClass("ui-timepicker-wrapper")){
            $('[data-original-title]').popover('hide');
        }
}

Ответ 30

$('html').on('click.popover', function (e) {
    var allpopins = $('.popover.in');
    if (allpopins.has(e.target).length > 0 &&
        !$('.btn', allpopins).is(e.target))
        return;
    // recognise pop-up 
    var id = $(e.target).attr('aria-describedby');
    var popin = $("#" + id);
    //on any button click in entire pop-up hide this pop-ups
    $(popin).on(".btn", function () { popin.remove(); });
    // on any place out of entire popup hide all pop-ups 
    $('.popover.in').not(popin).remove();
});

Это мое лучшее решение для производительности. Приветствия.