Javascript 如果它的任何一个孩子获得焦点,则防止触发模糊事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12092261/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:05:16  来源:igfitidea点击:

Prevent firing the blur event if any one of its children receives focus

javascriptjqueryknockout.jsonblur

提问by Thwaitesy

I have a div on a page that shows some info about a particular category (Image, Name etc).

我在页面上有一个 div,显示有关特定类别(图像、名称等)的一些信息。

When I click on the edit image it puts the category into edit mode which allows me to update the name. As you can see from the image below it shows that "Soup" is currently in edit mode, the others are in normal view mode. This all works as expected with the cancel / save buttons doing everything right. (I tried adding an image but wouldn't let me, need more love)

当我单击编辑图像时,它会将类别置于编辑模式,从而允许我更新名称。从下图中可以看出,“Soup”当前处于编辑模式,其他处于正常查看模式。这一切都按预期工作,取消/保存按钮一切正常。(我尝试添加图像但不会让我,需要更多的爱)

Howeveronce in edit mode if I click anywhere else on the page (Outside of the div) the expected result would be that the soup category would go back to view mode. Upon an event firing of some sort, this should also allow me to ask if they wanted to save changes.

但是,一旦进入编辑模式,如果我单击页面上的任何其他地方(div 之外),预期结果将是汤类别将返回查看模式。在某种事件触发时,这也应该允许我询问他们是否想要保存更改。

So what I then decided to do is create an blur event on the "soups" parent div. This works as expected if I click anywhere on the page, however if I click on the inner element of the div it also causes the parents blur event to be fired, thus causing the category to go back to view mode.

所以我然后决定做的是在“汤”父 div 上创建一个模糊事件。如果我点击页面上的任何地方,这会按预期工作,但是如果我点击 div 的内部元素,它也会导致父模糊事件被触发,从而导致类别返回查看模式。

So, is there a way to prevent the parent div from firing the blur event if any one of its children receive focus?

那么,如果父 div 中的任何一个获得焦点,是否有办法防止父 div 触发模糊事件?

<div tabindex="-1" onblur="alert('outer')">
    <input type="text" value="Soup" />
</div>

I just wrote the code without a compiler so not sure if that even works but with that hopefully you get the idea.

我只是在没有编译器的情况下编写了代码,所以不确定它是否有效,但希望你能明白。

I'm using Knockout.js to update the GUI on the fly but that shouldn't effect this answer I wouldn't have thought.

我正在使用 Knockout.js 即时更新 GUI,但这不会影响我没想到的这个答案。

回答by jbabey

I've had to tackle this problem before. I am not sure if it is the best solution, but it is what I ended up using.

我以前不得不解决这个问题。我不确定这是否是最好的解决方案,但这是我最终使用的。

Since the click event fires after the blur, there is no (cross-browser, reliable) way to tell what element is gaining focus.

由于单击事件在模糊之后触发,因此没有(跨浏览器、可靠的)方法来判断哪个元素获得焦点。

Mousedown, however, fires before blur. This means that you can set some flag in the mousedown of your children elements, and interrogate that flag in the blur of your parent.

然而,Mousedown 会在模糊之前触发。这意味着您可以在子元素的 mousedown 中设置一些标志,并在父元素的模糊中询问该标志。

Working example: http://jsfiddle.net/L5Cts/

工作示例:http: //jsfiddle.net/L5Cts/

Note that you will also have to handle keydown(and check for tab/shift-tab) if you want to also catch blurs caused by the keyboard.

请注意,keydown如果您还想捕捉由键盘引起的模糊,您还必须处理(并检查 tab/shift-tab)。

回答by Rob Allsopp

I don't think there is any guarantee mousedownwill happen before the focus events in all browsers, so a better way to handle this might be to use evt.relatedTarget. For the focusinevent, the eventTargetproperty is a reference to the element that is currently losingfocus. You can check if that element is a descendant of the parent, and if its not, you know focus is entering the parent from the outside. For the focusoutevent, relatedTargetis a reference to the element that is currently receivingfocus. Use the same logic to determine if focus is fully leaving the parent:

我不认为mousedown在所有浏览器中的焦点事件之前会发生任何保证,因此处理此问题的更好方法可能是使用evt.relatedTarget. 对于focusin事件,该eventTarget属性是对当前失去焦点的元素的引用。您可以检查该元素是否是父元素的后代,如果不是,则您知道焦点正在从外部进入父元素。对于focusout事件,relatedTarget是对当前接收焦点的元素的引用。使用相同的逻辑来确定焦点是否完全离开父级:

const parent = document.getElementById('parent');

parent.addEventListener('focusin', e => {
    const enteringParent = !parent.contains(e.relatedTarget);

    if (enteringParent) {
        // do things in response to focus on any child of the parent or the parent itself
    }
});

parent.addEventListener('focusout', e => {
    const leavingParent = !parent.contains(e.relatedTarget);

    if (leavingParent) {
        // do things in response to fully leaving the parent element and all of its children
    }
});

回答by Yahel Yechieli

I faced the same issue. This what worked for me.

我遇到了同样的问题。这对我有用。

 handleBlur(event) {
    // if the blur was because of outside focus
    // currentTarget is the parent element, relatedTarget is the clicked element
    if (!event.currentTarget.contains(event.relatedTarget)) {
        .....
    }
}

Enjoy :)

享受 :)