ChatGPT解决这个技术问题 Extra ChatGPT

当发生“模糊”事件时,我如何找出哪个元素焦点*到*?

假设我将 blur 函数附加到 HTML 输入框,如下所示:

<input id="myInput" onblur="function() { ... }"></input>

有没有办法在函数内部获取导致 blur 事件触发的元素的 ID(被点击的元素)?如何?

例如,假设我有这样的跨度:

<span id="mySpan">Hello World</span>

如果我在输入元素获得焦点后立即单击跨度,则输入元素将失去焦点。函数如何知道点击的是 mySpan

PS:如果 span 的 onclick 事件发生在 input 元素的 onblur 事件之前,我的问题将得到解决,因为我可以设置一些状态值来指示特定元素已被单击。

PPS:这个问题的背景是我想在外部(从可点击元素)触发一个 AJAX 自动完成器控件以显示其建议,而不会因为输入元素上的 blur 事件而立即消失建议。因此,如果单击了某个特定元素,我想检查 blur 函数,如果是,则忽略模糊事件。

这是一个有趣的问题,我很乐意看到背后的推理——即你为什么要这样做?上下文是什么?
Rahul 和 roosteronacid,我更新了这个问题作为对您的评论(PPS)的回应。
由于此信息有点旧,请参阅此处以获取更新的答案:stackoverflow.com/questions/7096120/…

O
Oriol

2015回答:根据UI Events,可以使用事件的relatedTarget属性:

用于标识与 Focus 事件相关的辅助 EventTarget,具体取决于事件的类型。

对于 blur 个事件,

relatedTarget:事件目标接收焦点。

例子:

函数 blurListener(event) { event.target.className = 'blurred'; if(event.relatedTarget) event.relatedTarget.className = 'focused'; } [].forEach.call(document.querySelectorAll('input'), function(el) { el.addEventListener('blur', blurListener, false); }); .blurred { 背景:橙色 } .focused { 背景:石灰 }

模糊的元素会变成橙色。

焦点元素应该变成石灰。

注意 Firefox 直到版本 48(bug 962251MDN)才支持 relatedTarget


Firefox 没有支持,但有一张票:bugzilla.mozilla.org/show_bug.cgi?id=687787
现在它有了。请参阅here
喜欢网络社区,现在一切都变得容易了^_^
很好的解决方案。不幸的是,如果接收焦点的目标不是输入元素,relatedTarget 将返回 null
如果接收焦点元素不是输入元素,则为其添加 tabIndex="0" 属性,它将起作用
C
Community

嗯... 在 Firefox 中,您可以使用 explicitOriginalTarget 拉出被点击的元素。我希望 toElement 对 IE 做同样的事情,但它似乎不起作用......但是,您可以从文档中提取新聚焦的元素:

function showBlur(ev)
{
   var target = ev.explicitOriginalTarget||document.activeElement;
   document.getElementById("focused").value = 
      target ? target.id||target.tagName||target : '';
}

...

<button id="btn1" onblur="showBlur(event)">Button 1</button>
<button id="btn2" onblur="showBlur(event)">Button 2</button>
<button id="btn3" onblur="showBlur(event)">Button 3</button>
<input id="focused" type="text" disabled="disabled" />

警告:此技术适用于使用键盘tab键通过字段引起的焦点变化,并且在 Chrome 或 Safari 中根本不起作用.使用 activeElement(在 IE 中除外)的最大问题是它直到 blur 事件被处理后才会持续更新,并且在处理过程中可能根本没有有效值!这可以通过 the technique Michiel ended up using 的变化来缓解:

function showBlur(ev)
{
  // Use timeout to delay examination of activeElement until after blur/focus 
  // events have been processed.
  setTimeout(function()
  {
    var target = document.activeElement;
    document.getElementById("focused").value = 
      target ? target.id||target.tagName||target : '';
  }, 1);
}

这应该适用于大多数现代浏览器(在 Chrome、IE 和 Firefox 中测试),但需要注意的是,Chrome 不会将焦点放在被点击的按钮上(与标签页相比)。


我一直在寻找像explicitOriginalTarget 这样的东西。你是怎么发现的?
检查 FireBug 中的事件对象。 FWIW,该属性是 Mozilla 特定的,并记录在 MDC:developer.mozilla.org/en/DOM/event.explicitOriginalTarget
这在 Windows 的 Firefox 3.6 和 Safari 4.0.3 中不起作用(或停止工作?)。
@Jonathan:该属性可用,但在 blur 事件触发时未更新。我已经用详细信息更新了答案。您是否尝试过在 Chrome 或 Firefox 中为此使用 activeElement?它让你的元素被模糊......
实际上不适用于 FF 31:explicitOriginalTarget 显示当前的模糊目标,document.activeElement 在模糊事件中为空。
M
Michiel Borkent

我最终通过 onblur 事件超时解决了它(感谢不是 StackOverflow 的朋友的建议):

<input id="myInput" onblur="setTimeout(function() {alert(clickSrc);},200);"></input>
<span onclick="clickSrc='mySpan';" id="mySpan">Hello World</span>

适用于 FF 和 IE。


顺便说一句,这在javascript世界中被认为是不好的做法吗?
旧帖子,但我有同样的问题。无论如何,这似乎是唯一可以跨浏览器完成工作的事情。
这个答案通过解决其他一些问题帮助了我的 TON……谢谢迈克尔!
@MichielBorkent 这是一个糟糕的实现,因为它不是事件驱动的。你等待给定的时间,只是希望它已经足够长了。你等待的时间越长,你就越安全,但如果你不需要等待那么久,你就会浪费更多的时间。也许有人在一个非常旧/慢的设备上,这个超时是不够的。不幸的是,我在这里是因为事件没有为我提供确定是否在 FireFox 中单击 iframe 所需的信息,但它适用于所有其他浏览器。即使这是不好的做法,我现在也很想使用这种方法。
这个问题很老了,可以追溯到2008年。同时可能有更好的方法。你能试试2015年的答案吗?
E
Evgeny Shmanev

可以使用文档的 mousedown 事件而不是模糊:

$(document).mousedown(function(){
  if ($(event.target).attr("id") == "mySpan") {
    // some process
  }
});

r
rplaurindo

FocusEvent 类型的实例具有 relatedTarget 属性,但是,直到 FF 的版本 47,具体来说,此属性返回 null,它已经从 48 开始工作。

您可以看到更多here


L
LuisEduardox

适用于 Google Chrome v66.x、Mozilla v59.x 和 Microsoft Edge... 使用 jQuery 的解决方案。

我在 Internet Explorer 9 中测试但不支持。

$("#YourElement").blur(function(e){
     var InputTarget =  $(e.relatedTarget).attr("id"); // GET ID Element
     console.log(InputTarget);
     if(target == "YourId") { // If you want validate or make a action to specfic element
          ... // your code
     }
});

在其他 Internet Explorer 版本中评论您的测试。


m
matte

如果单击特定元素并有一个有效的解决方案,我还试图让 Autocompleter 忽略模糊,但由于 explicitOriginalTarget 仅适用于 Firefox

Autocompleter.Base.prototype.onBlur = Autocompleter.Base.prototype.onBlur.wrap( 
        function(origfunc, ev) {
            if ($(this.options.ignoreBlurEventElement)) {
                var newTargetElement = (ev.explicitOriginalTarget.nodeType == 3 ? ev.explicitOriginalTarget.parentNode : ev.explicitOriginalTarget);
                if (!newTargetElement.descendantOf($(this.options.ignoreBlurEventElement))) {
                    return origfunc(ev);
                }
            }
        }
    );

此代码包装了 Autocompleter 的默认 onBlur 方法,并检查是否设置了 ignoreBlurEventElement 参数。如果已设置,则每次检查单击的元素是否为 ignoreBlurEventElement。如果是,Autocompleter 不会调用 onBlur,否则它会调用 onBlur。唯一的问题是它只适用于 Firefox,因为 explicitOriginalTarget 属性是 Mozilla 特定的。现在我试图找到一种不同于使用explicitOriginalTarget 的方法。您提到的解决方案要求您手动将 onclick 行为添加到元素。如果我无法解决explicitOriginalTarget 问题,我想我会遵循您的解决方案。


b
bmb

你能扭转你正在检查的内容和时间吗?也就是说,如果您还记得最后模糊的内容:

<input id="myInput" onblur="lastBlurred=this;"></input>

然后在您的跨度的 onClick 中,使用两个对象调用 function() :

<span id="mySpan" onClick="function(lastBlurred, this);">Hello World</span>

然后,您的函数可以决定是否触发 Ajax.AutoCompleter 控件。该函数具有单击对象和模糊对象。 onBlur 已经发生,所以它不会使建议消失。


B
Benoit Garret

使用这样的东西:

var myVar = null;

然后在你的函数里面:

myVar = fldID;

接着:

setTimeout(setFocus,1000)

接着:

function setFocus(){ document.getElementById(fldID).focus(); }

最终代码:

<html>
<head>
    <script type="text/javascript">
        function somefunction(){
            var myVar = null;

            myVar = document.getElementById('myInput');

            if(myVar.value=='')
                setTimeout(setFocusOnJobTitle,1000);
            else
                myVar.value='Success';
        }
        function setFocusOnJobTitle(){
            document.getElementById('myInput').focus();
        }
    </script>
</head>
<body>
<label id="jobTitleId" for="myInput">Job Title</label>
<input id="myInput" onblur="somefunction();"></input>
</body>
</html>

T
T J

我认为这是不可能的,使用 IE 你可以尝试使用 window.event.toElement,但它不适用于 firefox!


不适用于 Chrome 或 Safari。也许不适用于更多标准兼容的新版本的 IE。
M
Madbean

您可以使用以下方法修复 IE:

 event.currentTarget.firstChild.ownerDocument.activeElement

它看起来像 FF 的“explicitOriginalTarget”。

安托万和 J


C
Community

this answer 中所述,您可以检查 document.activeElement 的值。 document 是一个全局变量,因此您无需做任何魔术即可在 onBlur 处理程序中使用它:

function myOnBlur(e) {
  if(document.activeElement ===
       document.getElementById('elementToCheckForFocus')) {
    // Focus went where we expected!
    // ...
  }
}

佚名

document.activeElement 可能是父节点(例如 body 节点,因为它处于从目标切换到另一个目标的临时阶段),因此它不适用于您的范围

ev.explicitOriginalTarget 并不总是被重视

所以最好的方法是使用 onclick 对 body 事件间接理解你的 node(event.target) 是模糊的


b
brock.holum

编辑:一个hacky方法是创建一个变量来跟踪您关心的每个元素的焦点。因此,如果您关心“myInput”失去焦点,请在焦点上为其设置一个变量。

<script type="text/javascript">
   var lastFocusedElement;
</script>
<input id="myInput" onFocus="lastFocusedElement=this;" />

原始答案:您可以将“this”传递给函数。

<input id="myInput" onblur="function(this){
   var theId = this.id; // will be 'myInput'
}" />

这不能回答问题,希望我通过附加示例更清楚
s
stalepretzel

我建议使用全局变量 blurfrom 和 blurto。然后,配置您关心的所有元素,以在它们失去焦点时将它们在 DOM 中的位置分配给变量 blurfrom。此外,配置它们以便获得焦点将变量 blurto 设置为它们在 DOM 中的位置。然后,您可以完全使用另一个函数来分析 blurfrom 和 blurto 数据。


这几乎是解决方案,但在 onblur 事件处理程序中,我已经需要知道点击了哪些项目,所以 onblur 的超时为我做了。
佚名

请记住,使用explicitOriginalTarget 的解决方案不适用于文本输入到文本输入的跳转。

尝试用以下文本输入替换按钮,您将看到不同之处:

<input id="btn1" onblur="showBlur(event)" value="text1">
<input id="btn2" onblur="showBlur(event)" value="text2">
<input id="btn3" onblur="showBlur(event)" value="text3">

E
EricDuWeb

我一直在使用相同的功能,发现 FF、IE、Chrome 和 Opera 能够提供事件的源元素。我没有测试过 Safari,但我猜它可能有类似的东西。

$('#Form').keyup(function (e) {
    var ctrl = null;
    if (e.originalEvent.explicitOriginalTarget) { // FF
        ctrl = e.originalEvent.explicitOriginalTarget;
    }
    else if (e.originalEvent.srcElement) { // IE, Chrome and Opera
        ctrl = e.originalEvent.srcElement;
    }
    //...
});

这很好用,为什么要投票?只需删除 originalEvent!
S
Sunil D.

我不喜欢在编写 javascript 时使用超时,所以我会以 Michiel Borkent 的相反方式来做。 (没有尝试后面的代码,但你应该明白)。

<input id="myInput" onblur="blured = this.id;"></input>
<span onfocus = "sortOfCallback(this.id)" id="mySpan">Hello World</span>

在头上是这样的

<head>
    <script type="text/javascript">
        function sortOfCallback(id){
            bluredElement = document.getElementById(blured);
            // Do whatever you want on the blured element with the id of the focus element


        }

    </script>
</head>

S
Serhii Matrunchyk

我写了一篇 alternative solution 如何使任何元素具有焦点和“模糊性”。

它基于将元素设为 contentEditable 并在视觉上隐藏它并禁用编辑模式本身:

el.addEventListener("keydown", function(e) {
  e.preventDefault();
  e.stopPropagation();
});

el.addEventListener("blur", cbBlur);
el.contentEditable = true;

DEMO

注意:在 Chrome、Firefox 和 Safari (OS X) 中测试。不确定IE。

相关:我正在寻找 VueJs 的解决方案,因此对于那些对如何使用 Vue Focusable 指令实现此类功能感兴趣/好奇的人,请take a look


x
xpy

我在答案中只看到了黑客,但实际上有一个非常易于使用的内置解决方案:基本上你可以像这样捕获焦点元素:

const focusedElement = document.activeElement

https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement


至少在我的情况下,这不起作用,因为 activeElement 是主体,如果我在下一次渲染/勾选时检查它,它设置正确。但似乎 shog9 的解决方案是唯一合适的解决方案,因为它确保滴答声一直在滴答作响。
A
Armin Ronacher

这边走:

<script type="text/javascript">
    function yourFunction(element) {
        alert(element);
    }
</script>
<input id="myinput" onblur="yourFunction(this)">

或者,如果您通过 JavaScript(本例中为 jQuery)附加侦听器:

var input = $('#myinput').blur(function() {
    alert(this);
});

编辑:对不起。我误读了这个问题。


如果您知道这不是问题的答案并且您误读了它,请相应地更新或删除它。
M
Monika Sharma

我认为它很容易通过 jquery 通过传递导致“this”中的 onblur 事件的字段的引用来实现。例如

<input type="text" id="text1" onblur="showMessageOnOnblur(this)">

function showMessageOnOnblur(field){
    alert($(field).attr("id"));
}

谢谢莫妮卡


S
Shikekaka Yamiryuukido

你可以这样:

<script type="text/javascript">
function myFunction(thisElement) 
{
    document.getElementByName(thisElement)[0];
}
</script>
<input type="text" name="txtInput1" onBlur="myFunction(this.name)"/>