[SalesForce] Click outside of popover to hide

I'm trying to do the popover shown on the lightning tutorial: https://www.lightningdesignsystem.com/components/popovers/

I'm new to lightning and I have been looking around on how to hide the popover when a user clicks outside of it but I haven't had much success. Most of the other solutions use jQuery and I don't want to use it. I tried following this solution: How to Close SLDS Dropdown Menu when clicked outside in Lightning Component?

But it doesn't seem to work or I don't know how to apply it properly.

Here is the component and it is embedded into a lightning application that has nothing else but this component:

<aura:component>
<ltng:require styles="{!$Resource.slds214 + '/assets/styles/lightning-design-system-ltng.css'}" />
<span class="star-rating">
    <ui:inputRadio name="stars" text="1" change="{!c.getRating}" /><i></i>
    <ui:inputRadio name="stars" text="2" change="{!c.getRating}" /><i></i>
    <ui:inputRadio name="stars" text="3" change="{!c.getRating}" /><i></i>
    <ui:inputRadio name="stars" text="4" change="{!c.getRating}" /><i></i>
    <ui:inputRadio name="stars" text="5" change="{!c.getRating}" /><i></i>
</span>
<p>Here's some text omg.</p>
The value of your selection is: <ui:outputText class="result" aura:id="rating" value=""></ui:outputText>

<div aura:id="submissionPopover" class="slds-popover slds-nubbin--left-bottom slds-hide" role="dialog" onblur="{!c.hidePopover}">
  <div class="slds-popover__body" >
    <p> lot's of stuff ... </p>
  </div>
</div>

Here is the controller:

({
 getRating : function(cmp, evt) {
    /* previous logic... */
    var myPopover = cmp.find('submissionPopover');
    $A.util.removeClass(myPopover, 'slds-hide');
},

hidePopover : function(cmp, evt) {
    var myPopover = cmp.find('submissionPopover');
    $A.util.toggleClass(myPopover, 'slds-hide');
}
})

It seems that the onBlur event in the div is not firing but the change in the inputRadio is.

Is there a solution to how I can get the popover to disappear? Thanks!

Best Answer

The simplest way I can think of is to set the focus on your popup, then create a method to close the popup when focus is lost. One important thing to note is that writing to the dom is slow, so you need to provide a delay before assigning focus. Here the target is a text input, you will have to update to an appropriate target to focus on within your un-hidden div.

app.cmp

<div aura:id="submissionPopover" class="slds-hide">
  <textarea aura:id="comment" class="slds-textarea" onblur="{!c.hidePopover}" />
</div>

controller.js

({
    getRating : function(cmp, evt, helper) {
      /* previous logic... */
      var myPopover = cmp.find('submissionPopover');
      $A.util.removeClass(myPopover, 'slds-hide');
      setTimeout(function(){helper.setFocus(cmp)}, 300);
    },

    hidePopover : function(cmp, evt) {
        var myPopover = cmp.find('submissionPopover');
        $A.util.toggleClass(myPopover, 'slds-hide');
    }
)}

helper.js

({
    setFocus : function(cmp) {
        cmp.find("comment").getElement().focus();
    }
})

Hope that helps!