【问题标题】:When a 'blur' event occurs, how can I find out which element focus went *to*?当发生“模糊”事件时,我如何找出哪个元素焦点*到*?
【发布时间】:2010-09-12 09:34:13
【问题描述】:

假设我将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,我更新了这个问题作为对你们 cmets(PPS)的反应。
  • 由于此信息有点旧,请参阅此处获取更新的答案:stackoverflow.com/questions/7096120/…

标签: javascript events


【解决方案1】:

编辑: 一个很老套的方法是创建一个变量来跟踪您关心的每个元素的焦点。因此,如果您关心“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'
}" />

【讨论】:

  • 这不能回答问题,希望我通过附加示例更清楚
【解决方案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】:

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

【讨论】:

  • 不适用于 Chrome 或 Safari。可能不适用于兼容更多标准的新版本的 IE。
【解决方案4】:

嗯... 在 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键通过字段引起的焦点变化,并且在所有情况下都不起作用铬或 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 为 null。
【解决方案5】:

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

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

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

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

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

【讨论】:

    【解决方案6】:

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

    【讨论】:

    • 这几乎是解决方案,但在 onblur 事件处理程序中,我已经需要知道点击了什么项目,所以 onblur 的超时为我做了。
    【解决方案7】:

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

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

    适用于 FF 和 IE。

    【讨论】:

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

    如果单击特定元素并有一个有效的解决方案,我还试图让自动完成程序忽略模糊,但由于显式原始目标仅适用于 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 问题,我想我会按照你的解决方案。

    【讨论】:

      【解决方案9】:

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

      【讨论】:

        【解决方案10】:

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

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

        【讨论】:

          【解决方案11】:

          我一直在使用相同的功能,发现 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!
          【解决方案12】:

          使用这样的东西:

          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>
          

          【讨论】:

            【解决方案13】:

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

            【讨论】:

              【解决方案14】:


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

              <input type="text" id="text1" onblur="showMessageOnOnblur(this)">
              
              function showMessageOnOnblur(field){
                  alert($(field).attr("id"));
              }
              

              谢谢
              莫妮卡

              【讨论】:

                【解决方案15】:

                你可以这样:

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

                【讨论】:

                  【解决方案16】:

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

                  用于标识与焦点相关的辅助EventTarget 事件,取决于事件的类型。

                  对于blur 事件,

                  relatedTarget: event target 接收焦点。

                  例子:

                  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 直到版本 48(bug 962251MDN)才支持relatedTarget

                  【讨论】:

                  • 火狐不支持,但是有票:bugzilla.mozilla.org/show_bug.cgi?id=687787
                  • 现在有了。见here
                  • 热爱网络社区,现在一切都变得容易了^_^
                  • 很好的解决方案。不幸的是,如果接收焦点的目标不是输入元素,relatedTarget 将返回 null
                  • 如果接收焦点元素不是输入元素,添加tabIndex="0"属性就可以了
                  【解决方案17】:

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

                   event.currentTarget.firstChild.ownerDocument.activeElement
                  

                  对于 FF,它看起来像“explicitOriginalTarget”。

                  安托万和J

                  【讨论】:

                    【解决方案18】:

                    this answer 中所述,您可以检查document.activeElement 的值。 document 是一个全局变量,所以你不必做任何魔法就可以在你的 onBlur 处理程序中使用它:

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

                    【讨论】:

                      【解决方案19】:

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

                      你可以看到更多here

                      【讨论】:

                        【解决方案20】:

                        我写了一篇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

                        【讨论】:

                          【解决方案21】:
                          • document.activeElement 可能是父节点(例如 body 节点,因为它处于从目标切换到另一个的临时阶段),因此它不适用于您的范围
                          • ev.explicitOriginalTarget 并不总是被重视

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

                          【讨论】:

                            【解决方案22】:

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

                            const focusedElement = document.activeElement
                            

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

                            【讨论】:

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

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

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 2011-09-29
                              • 2013-05-12
                              • 1970-01-01
                              • 2014-04-04
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多