确定焦点何时出现在元素外部

Determining when focus occurs outside an element

本文关键字:元素 外部 何时出 焦点      更新时间:2023-09-26

我想看看以下是否可能:

  • 由于性能原因,在不使用文档级全局选择器(如$(document)$(body)$(window)等)的情况下确定焦点是否出现在元素外部
  • 如果没有全局选择器是不可能实现的,请用一个可证明的理由来解释自己。重要的是,我要理解为什么用今天的最新技术无法做到这一点
  • 奖励回合:确定任务的最高效(计算时间)选择器/事件处理程序/插件

我的实现由一个非常简单的HTML导航栏组成,如下面的代码段所示。我在每个<a>标签之间进行本机键盘导航。第一个列表元素是标题,包含可见的锚点,第二个元素

<ul class="test">
  <li>
    <a href="#">Title</a>
  </li>
  <li>
    <ul>
      <li>
        <a href="#">Some link</a>
      </li>
      <li>
        <a href="#">Some link</a>
      </li>
      <li>
        <a href="#">Some link</a>
      </li>
      <li>
        <a href="#">Some link</a>
      </li>
    </ul>
  </li>
</ul>

这个导航栏的目标很简单:

  1. 本机键盘选项卡或shift+选项卡从一个锚点转到另一个锚点
  2. 在关注内部锚点元素时显示下拉菜单
  3. 当不关注任何内部锚点元素时,隐藏下拉菜单

我有1和2,但3是棘手的,因为上面列出的要求。我知道使用全局选择器可以很容易地完成这项工作,但这项挑战是要弄清楚并理解是否可以用其他方式完成。

$(document).ready(function() {
    dropdownMenu = $(".test > ul");
    dropdownMenu.hide();
    $(".test").focusin(function() {
        if (dropdownMenu.is(":hidden")) {
          dropdownMenu.show();
        }
    });
    // Some selector for some event here to handle the focus/clicks outside the $(".test") element
});

重要:我认为event.stopPropagation();,如CSS技巧-停止事件传播的危险中所解释的,在这个问题的范围内是一种危险的技术,但是,如果使用所述技术导致最有效的方法,那么我将欢迎它。

我不确定我是否百分之百地回答了这个问题,但我想我明白了。

您可以使用focusin事件将event.targetclosest一起使用。

$(document).on('focusin', function (event) {
  var $target = $(event.target);
  if (!$target.closest('.bar').length) {
    console.log('You focused outside of .bar!');
  }
});

这是一把小提琴:https://jsfiddle.net/crswll/qk14r7c7/2/

在没有全局选择器的情况下,这里的一个选项是短暂延迟关闭操作:

  var isVisible = false;
  $(".test").focusin(function() {
    if (dropdownMenu.is(":hidden")) {
      dropdownMenu.show();
    }
    isFocused = true;
  });
  $(".test").focusout(function() {
    isFocused = false;
    setTimeout(function() {
      if (!isFocused && dropdownMenu.is(":visible")) {
        dropdownMenu.hide();
      }
    }, 100);
  });

这有点麻烦,但可以保护您在切换时不会出现错误关闭。看见https://jsfiddle.net/d5fa5o8q/4/