-
Notifications
You must be signed in to change notification settings - Fork 6.7k
hide tooltips and popovers when a user clicks away #4419
Conversation
This needs to be opt-in behind a feature - there are some cases where developers explicitly want to programmatically close it. |
In addition, this needs unit tests as well. |
Is the feature to programmatically close Popovers and Tooltips already implemented? What are the relevant commits for that? I can add an attribute for toggling this feature. Any preference as to what that attribute/directive should be called? Also, what are you guys using for unit tests? I might not know how to do that, but I can look into adding them if you point me in the right direction. |
Oh, I'm sorry, you're talking about the isOpen property, aren't you? |
Not just that - the programmatic triggers for hiding/showing |
Using |
Should I just make this another trigger? var triggerMap = {
'mouseenter': 'mouseleave',
'click': 'click',
+ 'clickaway': 'clickaway',
'focus': 'blur',
'none': ''
}; |
That could work, and logic should be added for the binding and unbinding of event listeners depending on if it matches the string |
Something like that? b00a550 |
Yep, that works - just needs unit tests now :) . Also for simplicity, you can do |
I just noticed that in |
Sure |
I made some updates, including unbinding toggleTooltipBind in unregisterTriggers, added a unit test, and updated the readme. |
// hide tooltips/popovers when click away | ||
function bodyHideTooltipBind(e) { | ||
var target_elem = angular.element(e.target); | ||
if (e.target != element[0] && !target_elem.hasClass('popover') && !target_elem.hasClass('popover-inner') && !target_elem.hasClass('popover-title') && !target_elem.hasClass('popover-content') && !target_elem.hasClass('tooltip') && !target_elem.hasClass('tooltip-inner')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain the specific classes you're targeting here with the check? This seems a bit fragile to me.
Or better, can you explain what is being accomplished by the check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check makes sure the user is not clicking on a popover or tooltip itself, allowing the user to select text in the popover or tooltip. Otherwise, if you clicked on anything that wasn't the popover or tooltip element/link, it would close the popover. These classes are part of bootstrap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A better check out be to iterate over all of the elements in the stacked map and compare directly with each element - I am wary about tying it too heavily with a hardcoded class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree with that. I hadn't thought much about it. I'll make the change when I have some time again - hopefully tomorrow.
I implemented this feature using a slightly different approach. Rather than rely on the body click exclusively, I also watch for a focus event which will handle tabbing out of the popover. The approach I use for adding the event handlers to the body are:
With the useCapture enabled, I can simply use 'contains' to see if the triggering element is a child of the popover element like so:
|
Clicks bubble up to body, so we're not just handling when the body is clicked - we're handling when anything is clicked. Listening for click on the body and ignoring it when the click is on the link or the tooltip/popover is the best way I can think of, because it allows users to click the popover, and select text. Also, is .contains part of jqlite? |
Also, this feature is specifically for "clicking away". I'm not sure it makes sense to hide the popover when a key is pressed, even tab to move focus. |
contains is native DOM api |
Oh, ok. That's good to know. Let me think about this some more, and later today I'll make an update that I hope will satisfy you. Thanks for your continued feedback! |
Can we merge this into the library? |
Question, how will this work with multiple angular apps on 1 page? Will one app close all other popovers from the other app? |
No, it should not affect popovers in other apps on the page. On Mon, Oct 19, 2015, 5:06 AM Ash Belmokadem [email protected]
|
@SystemDisc Question: Does this also work for the above workflow, like when you open a popover will it close the already opened popover? Or will it require more logic to get this to work? |
Should be fine - there is a |
It would keep popovers open when you click on another popover. It closes It would be easy to change the functionality so that only one On Wed, Oct 21, 2015, 2:52 PM alanirudh [email protected] wrote:
|
Thanks for the quick response. The reason I have asked about it is because if we have multiple rows with popover menu opening on left or the right. Then previously opened popover will be covered by the newly opened popover. It's nice that it doesn't close the popover when we click with in the popover though. We have something called autoclose in dropdown module which closes any opened dropdown when opening new dropdown. So, to be consistent with outsideClick action of dropdown we can have this behavior which closes when we click outside. |
Good point. I'll make the behavior of popover's outsideClick consistent On Wed, Oct 21, 2015, 3:42 PM alanirudh [email protected] wrote:
|
I'll try to get to it this weekend. |
tooltip/popover It will behave the way @alanirudh's gif illustrates above. |
@wesleycho This PR no longer needs to be squashed, and I think it works the way everyone wanted it to. |
close: hide | ||
close: hide, | ||
triggerElement: element, | ||
element: null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need the 'triggerElement' and 'element' to be in the modal stack since you are no longer ignoring close events from other tooltip elements?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we don't, but I figured it might be useful in the future. I can remove it. Let me know if I should.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My philosophy is don't add it unless it's needed. It just adds unnecessary overhead to the openedTooltips collection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RobJacobs Pushing now
outsideClick will open a tooltip/popover on click and close that tooltip/popover when a click happens that is not targeting a tooltip/popover trigger element or a tooltip/popover itself
@wesleycho I've addressed some concerns @RobJacobs brought up. Let me know if you guys need anything else before merging. |
Can you clean up the eslint errors? |
Actually, did the cleanup - thanks for sticking with this PR & putting in the good work @SystemDisc! |
@wesleycho, please, can you make a release for bower version that includes this update? It will be awesome. |
The fix (and repos) will be available when we release 1.0. We don't have a date for this release yet but want to get it out before the end of the year. We still have some things we need to finish. In the meantime, please feel free to pull down the latest code and do an |
Hello, I am also interested in this feature. I installed the npm version: npm install angular-ui-bootstrap and linked the ui-bootstrap-tpls.js (which was not in the disc folder). I could't get the popover open providing the popover-trigger="outsideClick" option. Could you please provide some plunker with the example usage of this feature? |
@h6784rfg6 currently this is not released - if one wants to use this feature, one has to consume |
This solves issue #1055 and helps with similar issues (#618, #590, #749, #751)
Let me know if this is something that's desired and if an option needs to be added for toggling this behavior.