如何检测div何时失去焦点? [英] How do I detect when a div has lost focus?

查看:297
本文介绍了如何检测div何时失去焦点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Given the following markup, I want to detect when an editor has lost focus:

<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。

As the user tabs through the input elements and as each editor div loses focus (meaning they tabbed outside the div) add the loading class to the div that lost focus.

这个jquery是我期望的工作,但它什么都不做:

This bit of jquery is what I expected to work, but it does nothing:

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

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

This seems to work, until you add the console log and realize it is triggering on every focusout of the inputs.

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

这是我测试用例的一个jsfiddle ,我一直在努力。我知道我在这里缺少一些基本的东西。有人可以启发我吗?

Here is a jsfiddle of my test case that I have been working on. I know I am missing something fundamental here. Can some one enlighten me?

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

After some of the comments below, I have this almost working the way I want it. The problem now is detecting when focus changes to somewhere outside an editor div. Here is my current implementation:

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');
    }
})

有点复杂,并且使用类进行状态。我还添加了下一个复杂性,即在编辑失去焦点时进行异步调用。 这是我当前工作的一部分。

A bit more complicated, and using classes for state. I have also added in the next bit of complexity which is to make an async call out when an editor loses focus. Here a my jsfiddle of my current work.

推荐答案

如果您希望将输入对的输入和退出视为组合成单个控件,则需要查看元素获得焦点位于相同的编辑器中。你可以这样做,使用 setTimeout 为0,将检查延迟一个周期(等待所有当前任务完成)。

If you wish to treat entry and exit of the pairs of inputs as if they were combined into a single control, you need to see if the element gaining focus is in the same editor. You can do this be delaying the check by one cycle using a setTimeout of 0 (which waits until all current tasks have completed).

$('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/

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

完成拼图(获得初始绿色状态) )你还需要捕获 focusin 事件,看看它是否来自来自相同的编辑器(保存以前的焦点元素)全球等)。

To complete the puzzle (get your initial green state) you will also need to also catch the focusin event and see if it is coming from the same editor or not (save the previous focused element in a global etc).

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

Side note: I recently had to write a jQuery plugin that did all this for groups of elements. It generates custom groupfocus and groupblur events to make the rest of the code easier to work with.

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

Update 1: http://jsfiddle.net/TrueBlueAussie/0y2dvxpf/4/

根据您的新示例,您可以反复捕捉 focusin 而不会造成任何损害,所以追踪以前的焦点是没有必要的。使用我之前的setTimeout示例解决了在div之外单击时遇到的问题。

Based on your new example, you can catch the focusin repeatedly without damage, so tracking the previous focus is not necessary after all. Using my previous setTimeout example resolves the problem you have with clicking outside the divs.

$('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何时失去焦点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆