【问题标题】:JavaScript FocusOut - get the element that receives focusJavaScript FocusOut - 获取获得焦点的元素
【发布时间】:2014-04-05 10:22:32
【问题描述】:

FocusOut 事件引发时,如何知道哪个元素获得焦点

正确的方法似乎是使用事件的 relatedTarget 属性。但是,这似乎不适用于所有浏览器:

  • 在谷歌浏览器中,它可以工作
  • 在 Firefox 和 Internet Explorer 中,relatedTarget 为空
  • 在 Safari 中,relatedTarget 属性甚至不存在

我找到了一种仅在 IE 中有效的解决方法(使用 document.activeElement),但我想知道是否没有一个已被证明适用于所有主要浏览器的通用解决方案

虽然我可以找到类似的问题和答案,但我还没有找到任何真正适用于所有浏览器的解决方案。

编辑:下面的例子说明了我的意思。

代码:

document.getElementById('text1').addEventListener('focusout', function(e) {
  // At this point, I want to know which element is receiving the focus (i.e. text2)
  console.log(e.relatedTarget); // works in Chrome
  console.log(document.activeElement); // works in IE
  // both do not work in Firefox or Safari
});
<input id="text1" type="text" value="first" />
<input id="text2" type="text" value="second" />

【问题讨论】:

    标签: javascript focusout


    【解决方案1】:

    我对 Firefox 有一个假设和解决方法。 document.activeElement 似乎有效。然后focusout命中,所以它被删除。当 focusin 命中时(或者可能紧随其后),将再次出现一个焦点元素。但是在 out 和 in 之间没有任何焦点,因此没有元素被报告为活动的。

    我的解决方法是一个愚蠢的 setTimeout hack。 setTimeout( function() {console.log(document.activeElement)}, 1); 可靠地让我成为一个活跃的元素。诚然,我只在一台机器上进行了测试,并且花费了 90 秒的时间,但这是迄今为止我发现的最好的。

    【讨论】:

    • 是的,这是一种诡计……但它似乎适用于所有主流浏览器!
    • 据我所知,这只有在元素失去焦点到另一个可以接收击键的元素(例如输入、文本区域)时才有效。对于其他任何事情,document.activeElement == document.body。 developer.mozilla.org/en-US/docs/Web/API/document.activeElement
    【解决方案2】:

    我相信你要找的是document.activeElement

    返回当前获得焦点的元素,即如果用户键入任何键,将获得击键事件的元素。该属性是只读的。

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

    【讨论】:

    • 这似乎合乎逻辑,但在 FocusOut 事件处理程序中,这会在某些浏览器中返回 Body 元素(即使实际焦点从一个输入元素切换到下一个)。
    • 另外,我刚刚注意到您已经尝试过document.activeElement。完全错过了。
    • 嗯,不是真的。我的具体情况是我想知道包含其他元素的 DIV 何时失去焦点。我想使用 DIV 的 FocusOut 事件并检查接收焦点的元素是否是此 DIV 中的另一个元素。但是抛开具体的问题,我只是好奇这样一个简单的问题,有没有跨浏览器的解决方案。
    • 啊...那么也许一个例子会有所帮助。
    • 请注意,这个fiddle 在 Chrome、Firefox、Safari、IE 和 Opera 中始终如一地工作。
    【解决方案3】:

    我在使用 textEditor PrimeFaces 元素时遇到了同样的问题。

    我使用下面的html代码。

    <div contenteditable="true" class="div-focus"> 
        <h:outputText
            styleClass="OutputField" 
            value="#{oController.panelTpl.getComment()}"  
            escape="false"
            />
    </div>    
    <div class="text-editor"> 
        <p:textEditor 
           value="#{oController.panelTpl.txtComment.text}"
           />
    </div>    
    

    TextArea 被定义了两次,因此当显示表单时,用户只能看到第一个

    小部件,而不会看到特定的工具栏。

    当用户点击显示的文本时,focusin() 事件隐藏

    元素并显示包含在
    父级中的 小部件元素。

    为此,我定义了以下 javascript 代码

    function onLoadDialog()
        {
        jQuery(".text-editor").hide();
    
        jQuery(".div-focus").focusin(function()
            {
            $(this).hide();
            $(this).next(".text-editor").show();
            $(this).next(".text-editor").focus();
            });            
    
        jQuery(".text-editor").focusout(function(e)
            {
            if ($(e.relatedTarget).closest(".text-editor").size() == 0)
                {
                $(this).hide();
                $(this).prev(".div-focus").show();
                $(this).prev(".div-focus").text($(this).text());
                }
            });            
        }
    

    onLoadDialog 函数() 在页面加载时被调用,用于隐藏

    元素并显示
    元素。当用户点击
    元素中的文本时,该元素被隐藏并显示以下隐藏元素。
    元素获得焦点。

    focusout() 事件隐藏

    元素并显示
    元素...仅当获得焦点的元素未在
    元素。

    element.focusout() 的问题在于每次包含在主元素中的元素时都会触发它,即使获得焦点的元素是在同一个元素中定义的。

    当您进入房屋时,您可以通过车库或客厅或厨房进入。 当您进入客厅(通过外门)时,您就进入了大楼。 但是当你离开客厅去厨房时,你就呆在家里了!!! 如果你离开客厅去花园里,你就离开了房子(建筑)。

    focusin() 函数实现相同的原理,但不是 focusout() !

    if ($(e.relatedTarget).closest(".text-editor").size() == 0) 在 focusout() 事件中使用的行更正了这个小差异!

    注意:该解决方案并不完美,因为在将文本从 textEditor 小部件复制到 outputText 小部件时,我有一些小问题需要解决!

    【讨论】:

      【解决方案4】:
      //attach a focus out handler
      $("#id").focusOut($El_FocusOut);
      
      //display the id of new element being focused onto
      function $El_FocusOut($eventArgs){
          //firefox specific focusout active element logi
          var activeElement = $eventArgs.originalEvent.explicitOriginalTarget;
          alert($(activeElement).attr("id"))
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-22
        • 2012-04-17
        • 1970-01-01
        • 1970-01-01
        • 2022-01-21
        相关资源
        最近更新 更多