单击屏幕上的任意位置关闭所有 Angular JS Bootstrap 弹出窗口?

Posted

技术标签:

【中文标题】单击屏幕上的任意位置关闭所有 Angular JS Bootstrap 弹出窗口?【英文标题】:Close all Angular JS Bootstrap popovers with click anywhere on screen? 【发布时间】:2014-05-19 22:26:50 【问题描述】:

我正在使用 Angular 指令进行引导。

我有一个弹出框,就像他们的例子一样:

<button popover="Hello, World!" popover-title="Title" class="btn btn-default ng-scope">Dynamic Popover</button>

当您再次单击该按钮时它会关闭。当用户点击任何地方时,我想关闭它 - 以及任何其他打开的弹出窗口。

我没有看到执行此操作的内置方法。

【问题讨论】:

【参考方案1】:
angular.element(document.body).bind('click', function (e) 
    var popups = document.querySelectorAll('.popover');
    if(popups) 
        for(var i=0; i<popups.length; i++) 
            var popup = popups[i];
            var popupElement = angular.element(popup);

            if(popupElement[0].previousSibling!=e.target)
                popupElement.scope().$parent.isOpen=false;
                popupElement.remove();
            
        
    
);

【讨论】:

我能找到的最佳答案 我想做的一件事是扩展跳过条件:if (popupElement[0].previousSibling != e.target &amp;&amp; popupElement[0].previousSibling != e.target.parentElement) 效果很好,但请确保您没有popover-append-to-body="true",否则将无法使用。【参考方案2】:

正在跟踪此功能请求 (https://github.com/angular-ui/bootstrap/issues/618)。与 aet 的回答类似,您可以按照功能请求中的建议作为解决方法:

$('body').on('click', function (e) 
   $('*[popover]').each(function () 
        //Only do this for all popovers other than the current one that cause this event
        if (!($(this).is(e.target) || $(this).has(e.target).length > 0) 
             && $(this).siblings('.popover').length !== 0 
             && $(this).siblings('.popover').has(e.target).length === 0)                  
        
             //Remove the popover element from the DOM          
             $(this).siblings('.popover').remove();
             //Set the state of the popover in the scope to reflect this          
             angular.element(this).scope().tt_isOpen = false;
        
    );
);

(来源:vchatterji 在上述功能请求中的评论)

功能请求也有非jQuery解决方案以及这个plnkr:http://plnkr.co/edit/fhsy4V

【讨论】:

【参考方案3】:
        angular.element(document.body).bind('click', function (e) 
            var popups = document.querySelectorAll('.popover');
            if (popups) 
                for (var i = 0; i < popups.length; i++) 
                    var popup = popups[i];
                    var popupElement = angular.element(popup);
                    console.log(2);
                    if (popupElement[0].previousSibling != e.target) 
                        popupElement.scope().$parent.isOpen = false;
                        popupElement.scope().$parent.$apply();
                    
                
            
        );

【讨论】:

对 Lauren Campreghers 答案的小改进,无需删除元素,(重新打开弹出框时会产生错误),只需刷新弹出框父范围( popupElement.scope().$parent.$apply ();)【参考方案4】:

你所说的是弹出框的默认设置,但你可以使用 triggers 函数来控制它,方法是像这样popover-trigger="mouseenter:blur" 将 blur 放在触发器的第二个参数中

【讨论】:

【参考方案5】:

一个想法是您可以更改触发器以使用鼠标进入和退出,这将确保一次只显示一个弹出窗口。下面是一个例子:

<button popover="I appeared on mouse enter!"
        popover-trigger="mouseenter" class="btn btn-default"
        popover-placement="bottom" >Hello World</button>

你可以看到这个工作in this plunker。您可以在angular bootstrap site 上找到工具提示触发器的完整列表(工具提示和弹出框具有相同的触发器选项)。祝你好运!

【讨论】:

【参考方案6】:

有同样的要求,我们就是这样做的: 首先,我们修改bootstrap,在tooltip的链接功能中:

if (prefix === "popover") 
    element.addClass('popover-link');

然后,我们像这样在 body 上运行一个点击处理程序:

$('body').on('click', function(e) 
    var clickedOutside = true;
    // popover-link comes from our modified ui-bootstrap-tpls
    $('.popover-link').each(function() 
        if ($(this).is(e.target) || $(this).has(e.target).length) 
            clickedOutside = false;
            return false;
        
    );
    if ($('.popover').has(e.target).length) 
        clickedOutside = false;
    
    if (clickedOutside) 
        $('.popover').prev().click();
    

);

【讨论】:

为了避免编辑引导程序,只需将 $('.popover-link') 选择器替换为 $('[popover-trigger="click"]')【参考方案7】:

我正在使用下面的代码

    angular.element(document.body).popover(
        selector: '[rel=popover]',
        trigger: "click"
    ).on("show.bs.popover", function(e)
        angular.element("[rel=popover]").not(e.target).popover("destroy");
         angular.element(".popover").remove();
    );

【讨论】:

【参考方案8】:

谢谢 Lauren Campregher,这行得通。

您的代码是唯一在作用域上运行状态更改的代码。

仅配置为如果您单击弹出框,后者会关闭。

我已经混合了你的代码,现在如果你在弹出框内点击它也可以工作。

是否系统,是否通过popover-template完成,

为了让 popover-template 的弹出框可识别,我使用了 popover-body 和 popover-title 类,对应于使用模板制作的弹出框的标题和主体,并确保它直接指向它们放在代码中:

angular.element(document.body).bind('click', function (e) 
    var popups = document.querySelectorAll('.popover');
    if(popups) 
        for(var i=0; i<popups.length; i++) 
            var popup = popups[i];
            var popupElement = angular.element(popup);        

            var content;
            var arrow;
            if(popupElement.next()) 
              //The following is the content child in the popovers first sibling
              // For the classic popover with Angularjs Ui Bootstrap
              content = popupElement[0].querySelector('.popover-content');


              // For the templating popover (popover-template attrib) with Angularjs Ui Bootstrap              
              bodytempl = popupElement[0].querySelector('.popover-body');
              headertempl= popupElement[0].querySelector('.popover-title');


              //The following is the arrow child in the popovers first sibling
              // For both cases.
              arrow = popupElement[0].querySelector('.arrow');              
            



            if(popupElement[0].previousSibling!=e.target && e.target != content && e.target != arrow && e.target != bodytempl && e.target != headertempl)
                popupElement.scope().$parent.isOpen=false;
                popupElement.remove();
            

        
    
);

祝你有美好的一天,感谢 Lauren,感谢 AngularJS,感谢 Stack Family!

更新:

我更新了所有添加额外的控件。 弹出框内的元素已从控件中排除(例如,插入弹出框主体的图片。)。然后点击同样关闭。

我曾经解决API Node.contains的命令,集成在一个返回true或false的函数中。

现在将任何元素放入其中,运行控件,如果单击内部,则保持弹出框打开:

// function for checkparent with Node.contains
function check(parentNode, childNode)  if('contains' in parentNode)       return parentNode.contains(childNode);     else       return parentNode.compareDocumentPosition(childNode) % 16;  

angular.element(document.body).bind('click', function (e) 
    var popups = document.querySelectorAll('.popover');
    if(popups) 
        for(var i=0; i<popups.length; i++) 
            var popup = popups[i];
            var popupElement = angular.element(popup);        

            var content;
            var arrow;
            if(popupElement.next()) 
              //The following is the content child in the popovers first sibling
              // For the classic popover with Angularjs Ui Bootstrap
              content = popupElement[0].querySelector('.popover-content');


              // For the templating popover (popover-template attrib) with Angularjs Ui Bootstrap              
              bodytempl = popupElement[0].querySelector('.popover-body');
              headertempl= popupElement[0].querySelector('.popover-title');


              //The following is the arrow child in the popovers first sibling
              // For both cases.
              arrow = popupElement[0].querySelector('.arrow');              
            

        var checkel= check(content,e.target);

            if(popupElement[0].previousSibling!=e.target && e.target != content && e.target != arrow && e.target != bodytempl && e.target != headertempl&& checkel == false)
                popupElement.scope().$parent.isOpen=false;
                popupElement.remove();
            

        
    
);

【讨论】:

以上是关于单击屏幕上的任意位置关闭所有 Angular JS Bootstrap 弹出窗口?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过单击菜单外部来关闭移动菜单

通过使用纯Javascript单击页面上的任意位置来关闭元素

当我们单击带有打印窗口的屏幕中的任意位置时,引导模式背景不会消失

当用户点击屏幕上的任意位置时调用函数

单击外部编辑器时,Angular js Summernote 下拉菜单未关闭

如何在单击窗口的任何位置关闭通知