web-dev-qa-db-ja.com

外部をクリックしてTwitter Bootstrap Popoverを閉じるには?

モーダルと同じようにポップオーバーを消すことができますか。ユーザーがそれらの外側のどこかをクリックしたときにそれらを閉じますか?

残念ながら、ポップオーバーの代わりに実際のモーダルを使用することはできません。モーダルはposition:fixedを意味するため、ポップオーバーではなくなります。 :(

272
Ante Vrli

更新:もう少し堅牢な解決策: 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生成ポップオーバーの場合'[data-original-title]'の代わりに'[data-toggle="popover"]'を使用する

警告:上記の解決策では、複数のポップオーバーを一度に開くことができます。

一度に1ポップオーバーしてください:

更新:ブートストラップ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');
        }
    });
});

これは、既に開いていてクリックされていない、またはそれらのリンクがクリックされていないポップオーバーを閉じる処理を行います。


更新:ブートストラップ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
        }

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

ポップオーバー以外の場所をクリックすると、すべてのポップオーバーが閉じます。

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

最も単純で最も安全なバージョンは、あらゆるブートストラップバージョンで動作します。

デモ: http://jsfiddle.net/guya/24mmM /

デモ2:Popoverコンテンツ内をクリックしても見逃さない http://jsfiddle.net/guya/fjZja/

デモ3:複数ポップオーバー: http://jsfiddle.net/guya/6YCjW/


この行を呼び出すだけですべてのポップオーバーが解除されます。

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

このコードで外側をクリックするとき、すべてのポップオーバーを閉じます。

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

上のスニペットはボディにクリックイベントを添付します。ユーザーがポップオーバーをクリックすると、通常どおりに動作します。ユーザーがポップオーバーではない何かをクリックすると、それはすべてのポップオーバーを閉じます。

これは、うまくいかない他の例とは対照的に、Javascriptで開始されるポップオーバーでもうまくいきます。 (デモを見てください)

ポップオーバーコンテンツ内をクリックしたときに却下したくない場合は、次のコードを使用してください(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');
  }
});
36
guya

ブートストラップ2.3.2では、トリガを 'focus'に設定することができ、それはただ動作します:

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

これは基本的にそれほど複雑ではありませんが、グリッチを回避するために行うべきチェックがいくつかあります。

デモ(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');
});
18
Sherbrow

高得点の考えられる解決策はどれも私のために正しく機能しませんでした。最初にポップオーバーを開いたり閉じたり(他の要素をクリックして)したときにバグが発生しますが、2回クリックするまでは再び開きません。 1つではなくリンクを起動します。

だから私はそれを少し修正しました:

$(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');
        }
    });
})
15
Anton Sergeyev

その方法を示すためにjsfiddleを作成しました。

http://jsfiddle.net/3yHTH/

ボタンをクリックするとポップオーバーを表示し、ボタンの外側をクリックするとポップオーバーを非表示にするという考え方です。

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

http://getbootstrap.com/javascript/#popovers によると、

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

ユーザーが次にクリックしたときにポップオーバーを閉じるには、フォーカストリガーを使用します。

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

これは here の前に尋ねられています。私がしたのと同じ答えがまだ当てはまります。

私は同様の必要性を持っていて、これを発見しました - BootstrapX - clickover と呼ばれる、Lee CarmichaelによるTwitter Bootstrap Popoverの非常に小さな拡張。彼はまたいくつかの使用例を持っています ここ 。基本的には、ポップオーバーをインタラクティブなコンポーネントに変更し、ページの別の場所をクリックするかポップオーバー内の閉じるボタンをクリックすると閉じます。これにより、同時に複数のポップオーバーを開くことや、他の多数のNice機能を使用することもできます。

3
Miika L.

承認された解決策を修正しました。私が経験したことは、いくつかのポップオーバーが隠された後、それらは再び現れるために二度クリックされなければならないということでした。これは、Popover( 'hide')が既に非表示のPopoverで呼び出されていないようにするためです。

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

この属性を要素とともに追加するだけです。

data-trigger="focus"
3
siraj k

これはパーティーに遅れる...しかし私はそれを共有しようと思った。私はポップオーバーが大好きですが、組み込み機能はほとんどありません。私はポップオーバーになりたいすべてのものであるブートストラップ拡張子.bubble()を書きました。却下する4つの方法外側をクリックしてリンクを切り替え、Xをクリックしてエスケープキーを押します。

自動的に配置されるので、ページからはみ出すことはありません。

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

これは無礼な自己宣伝ではありません...私は私の人生の中で何度も他の人のコードをつかみました、私は私自身の努力を申し出たいと思いました。それに旋風を与え、それがあなたのために働くかどうかを確認してください。

3
Itumac

2回目のポップオーバーを表示するときにこのソリューションは厄介な2回目のクリックを取り除きます

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

セレクタの委譲を使用してポップオーバーを作成した場合、 'hide'メソッドは機能しません。代わりに '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

2

DOMからポップアップを削除するためにイベントバブリングを使うこともできます。少し汚れていますが、うまくいきます。

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

あなたのHTMLでは、Popoverを閉じるべきPopover内のコンテンツに.popover-closeクラスを追加してください。

2
Hendrik

@mattdlockyerのソリューションに問題があることがわかりました(このソリューションに感謝します)。このようにpopoverコンストラクタにselectorプロパティを使うと...

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

... BS3用に提案された解決策は機能しません。代わりに、$(this)に対してローカルな2番目のpopoverインスタンスを作成します。これを防ぐための解決策は次のとおりです。

$(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's where the magic happens
            if (bsPopover) bsPopover.hide();
        }
    });
});

すでに述べたように、$(this).popover('hide');は委任リスナーのために2番目のインスタンスを作成します。提供されたソリューションは、すでにインスタンス化されているポップオーバーを隠すだけです。

時間を節約することができればと思います。

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

ブートストラップ はこれをネイティブにサポートします

JS Bin Demo

次のクリックで却下するには特定のマークアップが必要です

適切なクロスブラウザおよびクロスプラットフォーム動作を実現するには、<a>タグ、not<button>タグを使用し、さらにrole="button"およびtabindex属性を含める必要があります。

2
Tanner Perrien

3.3.6でテストされ、2回目のクリックで大丈夫です

        $('[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');
                }
            });
        });
1
Sungwook Ji

新しいポップオーバーが表示される前に、他のアクティブなポップオーバーを削除するだけです(ブートストラップ3)。

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

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

私は以前の答えの多くを試してみました、本当に私には何の効果もありませんが、この解決策はしました:

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

ボタンではなくアンカータグを使用し、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>
1
Ahmed El Damasy

この解決策はうまくいきます:

$("body")   .on('click'     ,'[data-toggle="popover"]', function(e) { 
    e.stopPropagation();
});

$("body")   .on('click'     ,'.popover' , function(e) { 
     e.stopPropagation();
});

$("body")   .on('click'  , function(e) {
        $('[data-toggle="popover"]').popover('hide');
});
1
L N

わかりましたこれは実際にstackoverflowで何かに答えるという私の最初の試みなので、ここでは何もしません:P

最新のブートストラップでこの機能が実際に動作しているかどうかは明らかではないようです(ただし、妥協したい場合は、ユーザーはクリックできます。あなたがそれ自体に「クリックホバー」を置かなければならないかどうかはわかりませんが、iPadでは、クリックはトグルとして機能します。

その結果、デスクトップではホバーまたはクリックできます(ほとんどのユーザーがホバーします)。タッチデバイスでは、要素に触れるとそれが上がり、もう一度触れると下がります。もちろん、これは元の要件からのわずかな妥協ですが、少なくともコードはよりクリーンになりました:)

$( "。my-popover")。popover({trigger: 'クリックホバー'});

0
Ivan Portugal

Matt Lockyerのコードを取って、私は単純なリセットをしたので、domはhideの要素で覆われません。

マットのコード: http://mattlockyer.com/2013/04/08/close-a-Twitter-bootstrap-popover-when-clicking-outside/

フィドル: 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');
        }
    });
});
0
user14174

デモ: 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;
});

}

これは私の解決策です。

0
Oğuzhan Topçu

承認された回答の最新の更新に問題があります。いくつかのツールチップを有効にしてポップオーバーを開いてからツールチップを含む要素をクリックすると、ツールチップのテキストがポップオーバーとして表示されます。

これを防ぐには、単に追加するだけです。

 if ($(this).data('bs.popover')) {

ifステートメント内(または&&と連結したものをifステートメントに追加する)

// only show one popover at the time and hide on clicking outside
$(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) {
            if ($(this).data('bs.popover')) {
                (($(this).popover('hide').data('bs.popover') || {}).inState || {}).click = false  // fix for BS 3.3.6
            }
        }
    });
});
0
Niklas Hantke

これを試してください、これは外側をクリックすることで隠れます。

$('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');
    }
    });
});
0
Rakesh Vadnal

私はこの問題に対する良い簡単な解決策を見つけました。こうすることで、必要なときにだけイベントリスナをアクティブにすることができます。さらに、ポップアップを解除するイベントが同時に発生しているため、ポップオーバーが表示されないという問題もありません。

ポップオーバーをHTMLに追加します

   <input id="popoverId" type="text" data-toggle="popover" data-trigger="manual" data-content="Popover content">

好きなときにポップオーバーを表示します。

$('#popoverId').popover('show');

このリスナーをJavascriptに追加してください。このリスナーはポップオーバーが表示されるとすぐに起動し、ユーザーがページの本文の任意の場所をクリックしたときにポップオーバーを非表示にしてポップオーバーが再び表示されるまでイベントリスナーを削除します。

$('#popoverId').on('shown.bs.popover', function () {
    $('body').click(function () {
        $('#popoverId').popover('hide');
        $('body').off();
    });
});
0
jakobinn

私はこれを思いつきました:私のシナリオは同じページの上にもっとポップオーバーを含んでいました、そしてそれらを隠すことはそれらを単に見えなくしたので、ポップオーバーの後ろの項目をクリックすることは不可能でした。アイデアは特定のpopover-linkを 'active'としてマークすることです、そしてあなたは単にあなたが単にアクティブ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"
0
Adi Nistor
$(document).on('click', function(e) {
  $('[data-toggle="popover"]').each(function() {
    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
    }

  });
});
0
Pradeep

私のようにAngularを使用している場合に備えて、Angularディレクティブを追加するためのものです。

app.directive('popover', ['$document', function($document) {
    return {
        restrict: 'EA',
        link: function(scope, elem, attrs) {
            $(document).ready(function() {
                $('[data-toggle="popover"]').popover();
            });

            elem.bind('click', function(e) {
                $('#notification').popover('toggle');
            })

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

HTMLコード:

<a popover tabindex="0" role="button"
   id="notification"
   data-toggle="popover" data-trigger="manual"
   data-container="body" data-placement="bottom"
   data-content="This is a popover">
   Popover button
</a>

ブートストラップによれば、それはdata-trigger='click focus'を使うのと同じくらい簡単であるべきです:

ポップオーバーのトリガー方法 - クリック|ホバーフォーカス|マニュアル。複数のトリガーを渡すことができます。スペースで区切ります。 manualを他のトリガーと組み合わせることはできません。

しかし、クリックとフォーカスを一緒に使用しても、未知の理由で私にはうまくいきません。代わりに手動で切り替える必要があります。

0
swang

ポップオーバーに日付ピッカーやタイムピッカーのようなものがない限り、@ guyaからの答えは有効です。これを修正するために、これが私がしたことです。

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

このようなコードを使って動的にポップオーバーリンクを設定していたので、私はmattdlockyerのソリューションに問題がありました。

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

Destroyは要素を取り除くので、セレクタ部分はpopoverを初期化する上で重要です。

0
bryanjj

次のクリックでポップオーバーを閉じるには、この要素をhtml要素に追加するだけです。

data-trigger="focus"

https://getbootstrap.com/docs/3.3/javascript/#popovers からの参照

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

これが私の最高のパフォーマンスソリューションです。乾杯。

0
Jozef Kemenik

この方法では、ページ上の任意の場所をクリックしてポップオーバーを閉じることができます。クリック可能な別のエンティティをクリックすると、他のポップオーバーはすべて非表示になります。アニメーション: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')
0
Arijit Lahiri