【问题标题】:How do I detect when a div has lost focus?如何检测 div 何时失去焦点?
【发布时间】:2023-03-24 02:23:02
【问题描述】:

鉴于以下标记,我想检测编辑器何时失去焦点:

<div class="editor">
    <input type="text"/>
    <input type="text"/>
</div>
<div class="editor">
    <input type="text"/>
    <input type="text"/>
</div>
<button>GO</button>

编辑:当用户在输入元素中切换并且每个编辑器 div 失去焦点(意味着他们在 div 之外切换)时,将加载类添加到失去焦点的 div。

这点 jquery 是我期望的,但它什么也没做:

$(".editor")
.blur(function(){
    $(this).addClass("loading");
});

这似乎有效,直到您添加控制台日志并意识到它会在输入的每个焦点输出时触发。

$('div.editor input').focus( function() {
    $(this).parent()
        .addClass("focused")
        .focusout(function() {
            console.log('focusout');
            $(this).removeClass("focused")
                   .addClass("loading");        
        });
});

Here is a jsfiddle 我一直在处理的测试用例。我知道我在这里遗漏了一些基本的东西。哪位大神可以解惑一下?

编辑:在下面的一些 cmets 之后,我几乎可以按照我想要的方式工作。现在的问题是检测焦点何时更改到编辑器 div 之外的某个地方。这是我当前的实现:

function loadData() {
    console.log('loading data for editor ' + $(this).attr('id'));
    var $editor = $(this).removeClass('loaded')
        .addClass('loading');

    $.post('/echo/json/', {
        delay: 2
    })
        .done(function () {
        $editor.removeClass('loading')
            .addClass('loaded');
    });
}

$('div.editor input').on('focusin', function () {
    console.log('focus changed');
    $editor = $(this).closest('.editor');
    console.log('current editor is ' + $editor.attr('id'));
    if (!$editor.hasClass('focused')) {
        console.log('switched editors');

        $('.editor.focused')
            .removeClass('focused')
            .each(loadData);

        $editor.addClass('focused');
    }
})

有点复杂,并且使用类来表示状态。我还添加了下一点复杂性,即当编辑器失去焦点时进行异步调用。 Here a my jsfiddle 我目前的工作。

【问题讨论】:

  • 虽然这个问题是关于检测焦点丢失的,但它比链接的问题要具体得多。
  • 你应该使用捕获而不是冒泡,并防止在 div 上传播,你得到了我相信的所有子事件,让我试试。
  • 是的,因为就像文档中所说:当元素或其中的任何元素失去焦点时,将焦点事件发送到元素。这与 blur 事件不同,它支持检测对后代元素失去焦点(换句话说,它支持事件冒泡)。
  • 你不能使用blur,因为div不是form的一部分。

标签: javascript jquery


【解决方案1】:

如果您希望将输入对的进入和退出视为组合成一个控件,则需要查看元素获得焦点是否为在同一个editor。您可以使用 0 的 setTimeout 将检查延迟一个周期(等待所有当前任务完成)。

$('div.editor input').focusout(function () {
    var $editor = $(this).closest('.editor');
    // wait for the new element to be focused
    setTimeout(function () {
        // See if the new focused element is in the editor
        if ($.contains($editor[0], document.activeElement)) {
            $editor.addClass("focused").removeClass("loading");
        }
        else
        {
            $editor.removeClass("focused").addClass("loading");
        }
    }, 1);
});

JSFiddle:http://jsfiddle.net/TrueBlueAussie/8s8ayv52/18/

要完成拼图(获得初始绿色状态),您还需要捕获 focusin 事件并查看它是否来自同一编辑器(保存之前关注的全局元素等)。

旁注:我最近不得不编写一个 jQuery 插件来为元素组完成所有这些工作。它会生成自定义 groupfocus 和 groupblur 事件,以使其余代码更易于使用。

更新 1:http://jsfiddle.net/TrueBlueAussie/0y2dvxpf/4/

根据您的新示例,您可以反复捕捉 focusin 而不会造成损坏,因此根本不需要跟踪先前的焦点。使用我之前的 setTimeout 示例可以解决您在 div 外部单击时遇到的问题。

$('div.editor input').focusin(function(){
    var $editor = $(this).closest('.editor');
    $editor.addClass("focused").removeClass("loading");

}).focusout(function () {
    var $editor = $(this).closest('.editor');
    // wait for the new element to be focused
    setTimeout(function () {
        // See if the new focused element is in the editor
        if (!$.contains($editor[0], document.activeElement)) {
            $editor.removeClass("focused").each(loadData);
        }
    }, 0);
});

【讨论】:

  • 嗯,这更接近我的目标。让我把它弄乱一些,看看我能不能让它变得可行。谢谢。
  • 好的,我越来越接近我所追求的了。这是我的最新代码,它可以按预期工作,直到您尝试单击编辑器 div 之外的某个位置。 jsfiddle.net/0y2dvxpf​
  • 非常好的解决方案。享受您接受的正确答案。并感谢您的帮助。
【解决方案2】:

这对我有用:

$(".editor").on("focusout", function() {
    var $this = $(this);
    setTimeout(function() {
        $this.toggleClass("loading", !($this.find(":focus").length));        
    }, 0);
});

例子:

http://jsfiddle.net/Meligy/Lxm6720k/

【讨论】:

    【解决方案3】:

    我认为你可以做到这一点。这是我做的一个例子。看看这个: http://jsfiddle.net/igoralves1/j9soL21x/

    $( "#divTest" ).focusout(function() {
    alert("focusout");
    });
    

    【讨论】:

    • 好吧,问题很明确:“如何检测 div 何时失去焦点?”我就是这么做的。
    • 刚刚尝试了您的 JSFiddle。我看到了问题。他们想知道您何时完全离开 div。此版本报告它已离开即使您单击同一 div 中的另一个输入。那不是他们想要的。您可能需要修改此答案以符合要求:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 2011-07-07
    • 2011-09-16
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    相关资源
    最近更新 更多