最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Close all Angular JS Bootstrap popovers with click anywhere on screen? - Stack Overflow

programmeradmin3浏览0评论

I am using the Angular directives for bootstrap.

I have a popover as in their example:

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

It closes when you click on the button again. I'd like to close it -- and any other open popovers -- when the user clicks anywhere.

I don't see a built-in way to do this.

I am using the Angular directives for bootstrap.

I have a popover as in their example:

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

It closes when you click on the button again. I'd like to close it -- and any other open popovers -- when the user clicks anywhere.

I don't see a built-in way to do this.

Share Improve this question asked Apr 7, 2014 at 15:15 SteveSteve 14.9k37 gold badges138 silver badges245 bronze badges
Add a comment  | 

8 Answers 8

Reset to default 9
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();
            }
        }
    }
});

This feature request is being tracked (https://github.com/angular-ui/bootstrap/issues/618). Similar to aet's answer, you can do what is recommended in the feature request as a work-around:

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

(source: vchatterji's comment in feature request mentioned above)

The feature request also has a non-jQuery solution as well as this plnkr: http://plnkr.co/edit/fhsy4V

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

What you say it's a default settings of the popover, but you can control it with the triggers function, by putting blur in the second argument of the trigger like this popover-trigger="{mouseenter:blur}"

One idea is you can change the trigger to use mouse enter and exit, which would ensure that only one popover shows at once. The following is an example of that:

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

You can see this working in this plunker. You can find the entire list of tooltip triggers on the angular bootstrap site (tooltips and popovers have the same trigger options). Best of luck!

Had the same requirement, and this is how we did it: First, we modified bootstrap, in the link function of the tooltip:

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

Then, we run a click handler on the body like so:

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

});

I am using below code for same

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

Thank you Lauren Campregher, this is worked.

Your code is the only one that also runs the state change on the scope.

Only configured so that if you click on the popover, the latter closes.

I've mixed your code, and now also it works if you click inside the popover.

Whether the system, whether done through popover-template,

To make it recognizable pop up done with popover-template, I used classes popover- body and popover-title, corresponding to the header and the body of the popover made with the template, and making sure it is pointing directly at them place in the code:

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

        }
    }
});

Have ever a good day, thank you Lauren, thank you AngularJS, Thank You So Much Stack Family!

Updated:

I updated all adding extra control. The elements within the popover were excluded from the control (for example, a picture inserted into the body of the popover.). Then clicking on the same closed.

I used to solve the command of API Node.contains, integrated in a function that returns true or false.

Now with any element placed inside, run the control, and keeps the popover open if you click inside :

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

        }
    }
});
发布评论

评论列表(0)

  1. 暂无评论