-
Notifications
You must be signed in to change notification settings - Fork 47k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
relatedTarget in blur event in Firefox returns null always #2011
Comments
cc @syranide our resident event export these days |
Haha, I believe I've seen some code in there that's meant to fix this, I'll have a look tomorrow and see what's going on. @leoasis I'm curious what you need this for. |
Basically I'm trying to show some contextual elements whenever I'm focused in a component. So I have an onBlur handler at the root of my component and use the relatedTarget (which in a blur event is the element where i'm going TO) and check wether that element is inside the root one or not to figure out if I'm actually leaving the component or not. I worked it around right now by checking the same but with clicks, attaching the handler in the document object and doing the same check. It works, but only for clicks (pressing tab won't work for example). |
@leoasis That sounds like something you could/should solve with |
Actually I want to show/hide things when focused, not when I'm hovering. Think about a contextual dropdown menu for example. |
@leoasis So |
That's actually what I used, the thing is that |
@leoasis |
@syranide I think that won't work in this case, since I don't want to handle the blur events in the children, I am handling the event in the top element inside the component, so I want to have the events propagated to that one. |
Yep, your choice, but AFAIK, the React-way would be to handle it in the children and propagate a callback through props instead. Anyway, I'm going to have a look at fixing this either way. |
Thanks for taking a look at it! Anyway, I think I'm still not clear in what I need to do, and I don't think the React way is to traverse the entire children adding blur and focus handles to just see if i'm blurring out of the component or not. To be clear, this is a simplified version of what I'm trying to do, in a fiddle: http://jsfiddle.net/leoasis/VkebS/569/ Notice that I want to be able to select the , and also I want it to disappear when I click or tab outside, for example in the other input or anywhere else |
@zpao @leoasis OK, so I imagine it could be solved by simply keeping track of the last focused element, but I suspect that it's more fragile in practice than you would expect, so it would probably not be a great fix. It also doesn't really fit with how React is meant to be used...
|
Follow-up to the previous, I haven't tested it yet, but I imagine |
If I'm not wrong, focusin and focusout events are not supported in Firefox yet: https://developer.mozilla.org/en-US/docs/Web/Events/focusin |
Hmm, it says listening to |
Ran into this recently too... hacked around it using nativeEvent.explicitOriginalTarget (FF only) if e.relatedTarget is null, though it feels pretty fragile. Would it make sense to normalize relatedTarget across browsers? |
@nbergseng I'm interested in knowing how We ran into this problem today as well, and hacked around it using |
@nbergseng I'm pretty sure the correct solution is to use |
@ezequiel They kind of are, |
i don't use react but i came across this issue while searching for what to do about the missing function blurHandler(e) {
var relatedTarget = e.relatedTarget ||
e.explicitOriginalTarget ||
document.activeElement; // IE11
if (!relatedTarget || !e.currentTarget.contains(relatedTarget) && !element.contains(relatedTarget)) {
// blur is moving to an element outside of the tree under currentTarget
}
} maybe that will help someone. |
One way we got around this issue was to stop the mouse down event being fired for the component that is listening to the blur event, e.g.: handleBlur: function() {
if (!event.relatedTarget) {
this.handleHide();
}
},
handleMouseDown: function(event) { event.preventDefault(); },
render: function() {
<div onBlur={this.handleBlur} onMouseDown={this.handleMouseDown} tabIndex="-1">...</div>
} This seems to work fine in all browsers though it'd be nice to get |
@emecell won't that stop clicks being generated for elements inside that div? |
Thanks @neonstalwart, it will prove useful for me. My use case is a form consisting of two fields, if I click or tab between them I don't want anything special to happen, but the moment both of those fields become unfocused ( |
Some of the facts and guesses in this bug are incorrect, so this issue probably isn't going to get fixed when everyone is looking at the wrong thing to fix. (Primarily the suggestion that onfocusout is a fix). Firstly people here are correct that Firefox's lacks
Next, the jQuery mimics You can see this in this test. When the button loses focus Which brings me to React. React delegates all its events. This means that when you use As a result |
@neonstalwart Be aware that you probably don't want to use |
Just spent ~2h on that before realising what was happening, that's a shame Firefox doesn't have it. |
Thanks I'll keep that in mind when I try on IE |
Looking at your comment without being half asleep like yesterday, it's much better than explicitOriginalTarget! Cheers! |
Just don't forget that React's synthetic events purge themselves when the event is over. So any event property you want, will need to be copied to a local variable to use it in the callback. |
@dantman |
It's a shame this bug hasn't been resolved yet. I recently implemented behavior for a search bar using My use-case was telling an event not to cause a component to be unmounted, so that component's onClick handler would have a chance to run. I circumvented this by using a timeout inside of the first event-handler so the other component would not be unmounted until its onClick handler had a chance to run. This solution works with negligible side-effects. However, it's far from elegant. It would be great to have this be compatible with Firefox and Chrome. Bonus points if it ends up working on IE (maybe it already does?). |
relatedTarget works with IE11 and focusout - not blur. |
you can prob get what you want simply by doing a |
I am adding the event listener manually and using:
|
Edit: Still don't have a solution for Safari. |
This issue appears to be resolved in 15.6 with Firefox 55.0.3. https://jsfiddle.net/60ten3bw/ |
Actually for documentation purposes in case someone stumbles back here this has been fixed in Firefox since Firefox 48 and I don't think it really depends on React version I am not sure whether it was fixed on Safari or not yet |
For Safari I use a simple solution: don't use a button element or if you need button you must insert into button tag an element like 'div' with 'tabindex="0"' and fire events on it. |
We're changing React to use |
Notice that there is another difference that was not mentioned in #6410: the blur event fires when the element has lost focus, while focusout happens just before the focus loss. |
Basically that, the relatedTarget is returning null all the time, when in Chrome it is returning the correct value if clicking on an actual element (will return null if clicking outside the document, which is ok).
This is something that Firefox is doing natively, so there should be some "patch" in that case to make it cross browser as a syntethic event.
Here is an example: http://jsfiddle.net/leoasis/kb3gN/4476/ Click the first input and then the second, and you'll see in the console: a) the relatedTarget if in Chrome, or b) null if in Firefox.
The text was updated successfully, but these errors were encountered: