【问题标题】:How to determine where focus went?如何确定焦点在哪里?
【发布时间】:2011-10-29 02:17:00
【问题描述】:

这个问题之前here问过,不过几年前,当时还没有跨平台的解决方案(除了setTimeout这个解决方案,真的不太好用)。

我想做onblur="foo(parm);" 并让foo 能够确定现在哪个元素具有焦点。

我正在使用常规的 javascript;请不要使用 jQuery。

现在有可能吗?

【问题讨论】:

  • 嗯,它在 jQuery 中是可行的,这意味着它在 Javascript 中是可行的。不过我不知道,好问题。 +1
  • 嗯。你可以在答案中发布 jQuery,也许我可以从那开始工作吗?
  • @Daniel:是的,我在帖子中提到过,但当时的答案不是跨平台的。
  • setTimeout 没有什么不方便的。这是最好的解决方案,也是唯一真正有效的解决方案。所有其他都失败了,因为触发模糊事件时的“活动元素”还不是被点击或标签到的那个:它只会在另一个事件之后接收焦点,当模糊事件的处理完成时!

标签: javascript html focus onblur


【解决方案1】:

在 jQuery 中,应 OP 的要求:

$(':input').blur(function() {
    $focusedElement = $(':input:focus');
    //Do stuff with $focusedElement
}

【讨论】:

  • 谢谢,Rikudo。这是一个起点。有人对如何将其转移到常规 javascript 有想法吗?
  • @Daniel:在 cmets 中,我要求以此作为起点。很酷。
  • 您最好使用 jQuery 或其他一些 JavaScript 库,因为好的库可以跨多个浏览器运行。
  • @DwB:是的,但是这里接受的activeElement 解决方案也是跨平台的,所以这是一种合法的方式。如果有兴趣,请参阅:help.dottoro.com/ljmiswgp.php
【解决方案2】:

你可以试试这样的:

function whereDidYouGo() {
    var all = document.getElementsByTagName('*');

        for (var i = 0; i < all.length; i++)
            if (all[i] === all[i].ownerDocument.activeElement)
                return all[i];
}

编辑:

function whereDidYouGo() { return document.activeElement; }

【讨论】:

  • 嗯。有趣的。在activeElement 上做一些阅读。难道我不能做到elementWithFocus=document.activeElement; 吗?
  • @JonathanM: 哈哈,是的,我刚刚抓住了 jQuery 的 :focus 过滤器
  • 是的,我想是的。这似乎表明了这一点:help.dottoro.com/external/examples/ljmiswgp/activeElement_1.htm
  • 优秀。非常感谢。你和 Rikudo 之间的良好团队合作。 :) 给他点赞。 :D
  • @WolfgangAdamec -- 显然不是。在某些浏览器中,如果我不使用 setTimeout,我会返回 body。在 IE8 中,不需要超时。在 FF 18.0.1 中,需要 setTimeout 。在 Chrome 中,看起来锚点没有获得焦点。 jsfiddle-ige
【解决方案3】:

有趣的问题。问题的核心是——“焦点”事件何时触发,在模糊事件之前还是之后?如果它在 blur 事件之前触发,问题就很简单了,因为您可以将当前焦点存储在您的 blur 事件可以访问的变量中。

但是,至少在 Chrome 13 中,模糊事件似乎发生在焦点事件之前。一种可能的解决方案。

给定以下 HTML:

<input id="foo" value='foo' />
<input id="bar" value='bar' />

然后你可以:

var currentFocus;
var pendingBlur;

var foo = document.getElementById('foo');
foo.addEventListener('focus', function(){ 
    currentFocus = foo;
    if(pendingBlur !== undefined){
        pendingBlur();
        pendingBlur = undefined;
    }
});
foo.addEventListener('blur', function(){
    pendingBlur = function(){
        console.log('new focus:', currentFocus);
    };
});

var bar= document.getElementById('bar');
bar.addEventListener('focus', function(){ 
   currentFocus = bar;
   if(pendingBlur !== undefined){
        pendingBlur();
        pendingBlur = undefined;
   }
});
bar.addEventListener('blur', function(){
    pendingBlur = function(){
        console.log('new focus:', currentFocus);
    };
});

基本上,我只是不使用模糊回调,因此在我们知道哪个元素被聚焦后调用焦点事件很方便。

这是 JSFiddle 上的 working example

编辑:此解决方案存在以下问题:如果您通过单击 other 而不是另一个表单元素来模糊表单,则模糊事件永远不会触发(因为我们等待焦点事件)。我能想到的唯一解决方法是使用计时器来检查是否定义了pendingBlur,如果是,则调用它。此时您不再需要焦点事件来调用模糊回调......

【讨论】:

  • 谢谢,马特。我必须在午饭后消化这个。 :)
  • +1 用于考虑 blur()focus() 的时间安排并在 chrome 上进行测试。但是,处理blur()focus() 之间的滞后的更好方法可能是使用setTimeout()onblur 调用的函数。
  • @Jonathan M,是的,我倾向于使用超时。鉴于您在问题中的要求,我只是避免了它:)
  • 很抱歉让你失望了。我不一定反对使用 setTimeout(),只是涉及它的解决方案。该解决方案需要为每个onclick 设置一个变量...非常混乱。非常感谢您的帮助。
【解决方案4】:

2020 年:所有主要浏览器(桌面和移动)都支持FocusEvent.relatedTarget

【讨论】:

    【解决方案5】:

    event.relatedTarget 找不到新聚焦的元素(在我的例子中是 div 类型),但只有 null 被返回。

    在元素上附加属性tabindex="0"后,现在它可以工作了。

    <div id="myDiv">myDiv</div>
    console.log(e.relatedTarget) // null
    
    <div id="myDiv" tabindex="0"> tabindexed div </div>
    console.log(e.relatedTarget) // <div id="myDiv" tabindex="0">
    

    tabindex 是一个使用键盘上的 Tab 键使元素可聚焦的属性。我想这主要是为了网络可访问性。

    而且我猜你不需要设置tabindex 属性,只要可以通过 Tab 键访问焦点元素(例如aselect.. 等等)

    【讨论】:

      猜你喜欢
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-03
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多