【问题标题】:Bootstrap Popover: Hover/Click and Close on Outside Click, but Revert to Hover ModeBootstrap Popover:悬停/单击并在外部单击时关闭,但恢复为悬停模式
【发布时间】:2019-01-26 20:48:23
【问题描述】:

在下面的 sn-p 中,我有一个支持 Hover 和 Click 模式的 Bootstrap Popover。单击时,窗口保持打开状态,并且应在 (1) 自单击(再次链接)或 (2) 任何外部单击时关闭。

问题:外部点击后,弹出框进入“当前打开”模式。这意味着如果您再次将鼠标悬停在它上面,窗口就会被卡住并且不会消失。应该发生的是,在外部单击之后,当您再次将鼠标悬停在它上面时,您会恢复到原始的悬停和消失模式。此处预期的行为与在内部关闭单击后悬停时相同,这是原始状态。我是不是忘记了什么?

$('#linkPopover').popover({
  trigger: 'hover click', 
  content: 'This is my content', 
  title: 'TITLE'
});

// -----------------
// Just with the above (and no other code), the Hover and Click-Toggle 
// works within the SAME Popover window,
// but now I need to also remove the visible Popover on ANY CLICK OUTSIDE.

// However, although the below works, *after* clicking outside the Popover is in the CLICKED 
// mode i.e. it doesn't hover anymore

$('body').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) {
              // From outside click with the popover open, need to hide
	            $(this).popover('hide');
	        }	    	
	    });  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>

<a id="linkPopover" data-toggle="popover">POPOVER</a>

<br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/>
End of body

【问题讨论】:

    标签: jquery twitter-bootstrap twitter-bootstrap-3


    【解决方案1】:

    此代码可能会对您有所帮助。我更改了您的条件语句以检查用户是否在弹出框触发器之外单击 && 如果弹出框可见,则触发弹出框触发器的 click 事件。

    我之所以想到这样做是因为 @ 987654322@事件是点击触发器本身时发生的事件。

    $(document).ready(function(){
    
    $('#linkPopover').popover({
      trigger: 'hover click',
      content: 'This is my content', 
      title: 'TITLE'
    });
    
    $('body').on('click', function(e) {
        $('[data-toggle="popover"]').each(function () {
            if(!$(this).is(e.target) && ($("#linkPopover").next('div.popover:visible').length)){
            $("#linkPopover").trigger('click');
        }
        });
    });
    
    });
    <script
      src="https://code.jquery.com/jquery-3.3.1.min.js"
      integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
      crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    
    <body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
    
    <a id="linkPopover" data-toggle="popover">POPOVER</a>
    
    <br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/>
    End of body
    </body>

    【讨论】:

    • 不过,这个解决方案存在一个问题。因为您执行trigger('click') 会创建一个无限循环,以防有多个弹出框并且我们捕获所有body.click。至少当我们在弹出窗口上执行hide 时,它并没有传播回body.click。但是现在,想象一下有多个链接。我单击并固定第一个,然后单击并固定第二个。这会创建一个无限循环。实际上,第二个应该关闭第一个。
    • 很好找先生基因,看看我刚刚发布的新答案。希望有帮助
    【解决方案2】:

    当弹出窗口超过 1 个时,由于无限循环,我的第一个答案会产生 Maximum call stack size exceeded 错误(请参阅我的第一个答案和 cmets)。

    为了解决这个问题:每当系统即将执行trigger('click') 时,我在body click 处理程序上使用.off。之后,我重新初始化正文单击处理程序。请参阅下面的示例。

    $(document).ready(function(){
    
    function initializeClick(){
    $('body').on('click', function(e) {
        $('[data-toggle="popover"]').each(function () {
            if(!$(this).is(e.target) && ($(this).next('div.popover:visible').length)){
            $('body').off('click');
            $(this).trigger('click');
            initializeClick();
            }
        });
    });
    }
    
    $('#linkPopover').popover({
      trigger: 'hover click',
      content: 'This is my content', 
      title: 'TITLE'
    });
    
    $('#linkPopover2').popover({
      trigger: 'hover click',
      content: 'This is my content', 
      title: 'TITLE'
    });
    
    $('body').on('click', function(e) {
        $('[data-toggle="popover"]').each(function () {
            if(!$(this).is(e.target) && ($(this).next('div.popover:visible').length)){
            $('body').off('click');
            $(this).trigger('click');
            initializeClick();
            }
        });
    });
    
    });
     <script
          src="https://code.jquery.com/jquery-3.3.1.min.js"
          integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
          crossorigin="anonymous"></script>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    
        <body>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
        <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
    
        <a id="linkPopover" class="btn btn-light" data-toggle="popover">POPOVER</a>
    <a id="linkPopover2" class="btn btn-light" data-toggle="popover">POPOVER2</a>
    
        <br/><br/><br/><br/><br/><br/><br/>
        <br/><br/><br/><br/><br/><br/><br/>
        <br/><br/><br/><br/><br/><br/><br/>
        End of body
        </body>

    【讨论】:

    • 谢谢,赞成,我还发布了我自己的解决方案,我在body.click 中使用了一个自定义标志参数,我定义了如果我们使用该参数调用click,它会忽略主要逻辑。
    【解决方案3】:

    我实际上通过在body.click 中引入自定义标志参数解决了 eminememinem 原始答案中的无限循环(由于trigger('click'))。你可以这样做

         $('body').on('click', function (e, manualClickTriggered) {
    

    我们在自己重新触发的特殊情况下设置标志。如果是这样,我们忽略常规逻辑。

    完整的sn-p:

    $('[id*="linkPopover"]').popover({
      trigger: 'hover click', 
      content: 'This is my content', 
      title: 'TITLE'
    });
    
    // Close any visible popover if clicked outside 
    // The "manualClickTriggered" flag indicates that we initiated the special Click event ourselves in order to turn off the popover, in which case skip the regular logic.
    $('body').on('click', function (e, manualClickTriggered) {
      var linkId = null;
      if (e.target.id.indexOf("linkPopover") != -1) {
        linkId = e.target.id;
      }
    		
      if (manualClickTriggered != true) {
        if (e.target.id.indexOf("linkPopover") == -1) {  // Not coming from any Popover Link (outside click) 
          $('a[id^="linkPopover"][data-toggle="popover"]').each(function () {	    	
            if( !$(this).is(e.target) && ($(this).next('div.popover:visible').length )) {
              $(this).trigger('click', true);
            }
          });
        }
        else // Coming from some Popover link
        {
            $('a[id^="linkPopover"][data-toggle="popover"]').each(function () {
              if ($(this).attr('id') != linkId && $(this).next('div.popover:visible').length) {
                $(this).trigger('click', true);
              }
            });
          }
        }
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
    
    <a id="linkPopover1" data-toggle="popover">POPOVER 1</a><br/>
    <a id="linkPopover2" data-toggle="popover">POPOVER 2</a><br/>
    <a id="linkPopover3" data-toggle="popover">POPOVER 3</a><br/>
    <a id="linkPopover4" data-toggle="popover">POPOVER 4</a><br/>
    
    <br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/>
    End of body

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多