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


186

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

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

有没有一种方法可以获取导致blur事件触发的元素ID (在单击该元素时)在函数内部?怎么样?

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

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

如果在输入元素具有焦点之后立即单击范围,则输入元素将失去其焦点。函数如何知道它是mySpan被单击的?

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

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


我很想知道背后的原因,这是一个有趣的问题-即您为什么要这样做?上下文是什么?
拉胡尔

Rahul和roosteronacid,我更新了这个问题以回应您的评论(PPS)。
Michiel Borkent

1
由于此的信息是有点老了,在这里看到了一个新的答案:stackoverflow.com/questions/7096120/...
乔纳森中号

Answers:


86

嗯...在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" />

警告:这种技术并没有对重点工作的变化所造成的互联通过与键盘领域,并没有在所有的Chrome或Safari工作。使用的一个大问题activeElement(IE除外)是未持续更新,直到之后blur事件已被处理,并在处理过程中可能根本没有有效的价值!通过改变Michiel最终使用的技术,可以缓解这种情况:

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不会将重点放在单击的按钮上(相对于选项卡式)。


1
我一直在寻找类似explicitOriginalTarget的东西。您是怎么发现的?
Kev

3
在FireBug中检查了事件对象。FWIW,该属性是Mozilla特定的,并记录在MDC上:developer.mozilla.org/en/DOM/event.explicitOriginalTarget
Shog9

2
在Windows中的Firefox 3.6和Safari 4.0.3中,这不起作用(或停止工作?)。
Chetan S 2010年

1
@Jonathan:该属性可用,但在blur事件触发时不会更新。我已经详细更新了答案。您是否尝试过在Chrome或Firefox中使用activeElement?它给了你模糊的元素……
Shog9 2011年

1
在FF 31上实际上不起作用:explicitOriginalTarget显示当前模糊目标,在模糊事件中document.activeElement为null。
Adrian Maire 2014年

75

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

EventTarget根据事件的类型,用于识别与Focus事件相关的辅助事件。

对于blur事件

relatedTarget事件目标获得关注。

例:

function 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 { background: orange }
.focused { background: lime }
<p>Blurred elements will become orange.</p>
<p>Focused elements should become lime.</p>
<input /><input /><input />

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


Firefox没有支持,但是有一张票:bugzilla.mozilla.org/show_bug.cgi?
id=687787

3
现在有。看这里
rplaurindo '16

热爱网络社区,现在一切都变得轻松了许多^ _ ^
am05mhz

6
很好的解决方案。不幸的是,如果目标接收焦点不是输入元素,relatedTarget将返回null
Pedro Hoehl Carvalho

5
如果接收焦点元素不是输入元素,则向其添加tabIndex="0"属性,它将起作用
Dany

19

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

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

在FF和IE中均可使用。


9
这在javascript world btw中被认为是不良做法吗?
Michiel Borkent

1
旧帖子,但我有同样的问题。无论如何,这似乎是跨浏览器完成工作的唯一方法。
乔什

这个答案通过解决其他一些问题帮助了我。谢谢迈克尔!
亚历克斯(Alex)2010年

@MichielBorkent这是一个错误的实现,因为它不是事件驱动的。您等待给定的时间,只是希望它足够长。等待的时间越长,您的安全就越安全,但是如果您不需要等待那么长时间,那么您将浪费更多的时间。也许有人正在使用旧的/慢速设备,并且此超时还不够。不幸的是,我在这里是因为这些事件并没有提供确定在FireFox中是否单击iframe所需的信息,但它适用于所有其他浏览器。我现在很想使用这种方法,即使这是一种不好的做法。
CTS_AE

1
这个问题很老,可以追溯到2008年。与此同时,可能有更好的方法。您可以尝试2015年的答案吗?
米歇尔·博尔肯特

16

可以使用文档的mousedown事件代替模糊事件:

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

8

类型FocusEvent实例具有relatedTarget属性,但是,直到FF的47版本为止,具体来说,该属性返回null,因为其中48个已经起作用。

你可以在这里看到更多。


2

我还试图使Autocompleter在单击特定元素并具有有效解决方案时忽略模糊,但仅适用于Firefox,因为explicitOriginalTarget

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。如果是,自动完成程序将不会校准onBlur,否则将调用onBlur。唯一的问题是它仅在Firefox中可用,因为explicitOriginalTarget属性是Mozilla特定的。现在,我试图找到一种不同于使用explicitOriginalTarget的方法。您提到的解决方案要求您手动将onclick行为添加到元素。如果我无法解决explicitOriginalTarget问题,我想我会遵循您的解决方案。


2

您可以在何时以及何时撤消检查的内容吗?那就是如果您记住最后模糊的内容:

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

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

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

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


1

使用这样的东西:

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>

1

我认为这不是可能的,使用IE可以尝试使用window.event.toElement,但不能在Firefox中使用!


不适用于Chrome或Safari。也许无法与更兼容标准的IE新版本一起使用。
robocat

1

该答案所述,您可以检查的值document.activeElementdocument是全局变量,因此您无需做任何魔术操作即可在onBlur处理程序中使用它:

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

1
  • document.activeElement可能是父节点(例如,主体节点,因为它处于从目标切换到另一个的临时阶段),因此它不适用于您的范围
  • ev.explicitOriginalTarget并非总是值

所以最好的方法是使用onclick on body事件间接了解您的节点(event.target)处于模糊状态


1

适用于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版本中评论您的测试。


0

编辑: 这样做的一种怪诞方法是创建一个变量,以跟踪您关心的每个元素的焦点。因此,如果您担心'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'
}" />

这不能回答问题,希望我通过其他示例使它更加清楚
Michiel Borkent

0

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


这几乎是解决方案,但是在onblur事件处理程序中,我已经需要知道单击了哪个项目,因此onblur的超时为我完成了此操作。
Michiel Borkent

0

请记住,使用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">

0

我一直在使用相同的功能,发现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!
fekiri malek's

0

我不喜欢在编码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>

0

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

 event.currentTarget.firstChild.ownerDocument.activeElement

看起来像FF的“ explicitOriginalTarget”。

安托万和J


0

我写了一个替代解决方案,如何使任何元素可聚焦和“模糊”。

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

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

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

演示

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


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


-2

这条路:

<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);
});

编辑:对不起。我看错了问题。


3
如果您知道这不是问题的答案,并且您误读了它,请相应地对其进行更新或删除。
TJ

-2


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

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

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

谢谢
莫妮卡


-2

您可以这样:

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

-2

我在答案中仅看到hack,但是实际上有一个非常易于使用的内置解决方案:基本上,您可以像这样捕获focus元素:

const focusedElement = document.activeElement

https://developer.mozilla.org/zh-CN/docs/Web/API/DocumentOrShadowRoot/activeElement


至少在我的情况下,由于activeElement是主体,因此这不起作用,如果我在下一个渲染/勾选中对其进行了检查,则其设置正确。但是似乎shog9的解决方案是唯一合适的解决方案,因为它可以确保刻度线一直在鸣叫。
Mathijs Segers,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.