如何检测div何时失去焦点?

时间:2014-10-10 16:17:42

标签: javascript jquery

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

<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我一直在研究的测试用例。我知道我在这里缺少一些基本的东西。有人可以启发我吗?

编辑:在下面的一些评论之后,我几乎按照我想要的方式工作。现在的问题是检测焦点何时更改到编辑器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我目前的工作。

3 个答案:

答案 0 :(得分:6)

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

$('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插件,为元素组完成所有这些操作。它会生成自定义groupfocusgroupblur个事件,以使其余代码更易于使用。

更新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);
});

答案 1 :(得分:1)

这对我有用:

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

示例:

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

答案 2 :(得分:-1)

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

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