Javascript jquery单击事件在模糊后丢失

Javascript jquery单击事件在模糊后丢失,javascript,jquery,focus,blur,Javascript,Jquery,Focus,Blur,我有一个textarea字段,我想在它获得焦点时扩展它,在它失去焦点时收缩它。以下是我的测试代码: $(function() { var rows = parseInt( $('textarea[name=details]').attr('rows') ); $('textarea[name=details]').focus(function() { $(this).animate({ rows: rows + 10 }, 250); }).blur(funct

我有一个textarea字段,我想在它获得焦点时扩展它,在它失去焦点时收缩它。以下是我的测试代码:

$(function() {
  var rows = parseInt(
    $('textarea[name=details]').attr('rows')
  );

  $('textarea[name=details]').focus(function() {
    $(this).animate({ rows: rows + 10 }, 250);
  }).blur(function(e) {
    $(this).animate({ rows: rows }, 250);
  });
});
小提琴:

问题是当textarea具有焦点时,用户单击另一个输入元素。 在这种情况下,textarea会重新折叠,但click事件似乎丢失了

我认为正在发生的是,blur()处理程序正在更改页面,以便单击的目标更改位置。由于“模糊”在单击之前运行,因此单击实际上正在发生,但由于目标已移动位置,因此单击不再击中元素。这是在Linux下的Chrome37.0.2062.120上实现的

我这样认为的原因是,如果您在模糊处理程序中注释掉文本区域的大小调整,那么一切都会按预期进行

小提琴:

我在谷歌上搜索了相关问题,并找到了一些关于模糊和点击事件顺序的讨论。通常,解决方案似乎涉及在blur()操作上添加延迟,或者在另一个页面元素上绑定事件以跟踪正在发生的事情

这两种方法都相当脆弱,容易出错。这种行为其实只是一种好的行为,所以如果没有“干净”的方法,我宁愿干脆放弃它

作为参考,延迟方法确实有效,如本小提琴所示:

我理解为什么在单击之前会触发模糊,但我发现令人惊讶的是,单击事件的目标在触发模糊之前没有“设置”。这是预期的行为还是不同浏览器的行为有所不同?

$(窗口)。加载(函数(){
$('textarea.expand').focus(函数(){
$(this).addClass(“扩展”)
$(此)。设置动画({
高度:10em
}, 500);
});
$('textarea.expand').blur(函数(){
$(此)。设置动画({
高度:“1米”
}, 500);
//$(this).removeClass(“扩展”)
});
});
下面是一些文字。它动了吗?
.扩大{
高度:1米;
线高:1米;
宽度:300px;
填充:3倍;
}
.扩大{
位置:绝对位置;
z指数:9;
}
文本区{
调整大小:无;
}

$(窗口)。加载(函数(){
$('textarea.expand').focus(函数(){
$(this).addClass(“扩展”)
$(此)。设置动画({
高度:“10em”
}, 500);
});
$('textarea.expand').blur(函数(){
$(此)。设置动画({
高度:“1米”
}, 500);
//$(this).removeClass(“扩展”)
});
});
下面是一些文字。它动了吗?
.扩大{
高度:1米;
线高:1米;
宽度:300px;
填充:3倍;
}
.扩大{
位置:绝对位置;
z指数:9;
}
文本区{
调整大小:无;
}

引入延迟工程:

$(function() {
  var rows = parseInt(
    $('textarea[name=details]').attr('rows')
  );

  $('textarea[name=details]').focus(function() {
    if (typeof(toDetails) != "undefined") { clearTimeout(toDetails); }
    $(this).animate({ rows: rows + 10 }, 250);
  }).blur(function(e) {
    toDetails = setTimeout(function() { $(this).animate({ rows: rows }, 250); }.bind(this), 250);
  });
});

引入延迟工程:

$(function() {
  var rows = parseInt(
    $('textarea[name=details]').attr('rows')
  );

  $('textarea[name=details]').focus(function() {
    if (typeof(toDetails) != "undefined") { clearTimeout(toDetails); }
    $(this).animate({ rows: rows + 10 }, 250);
  }).blur(function(e) {
    toDetails = setTimeout(function() { $(this).animate({ rows: rows }, 250); }.bind(this), 250);
  });
});

您可以使用设置超时功能:

$('textarea[name=details]').focus(function() {
  $(this).animate({ rows: rows + 10 }, 250);
}).blur(function(e) {
    setTimeout(function(){
        $(this).animate({ rows: rows }, 250);
    }.bind(this),400);

您可以使用设置超时功能:

$('textarea[name=details]').focus(function() {
  $(this).animate({ rows: rows + 10 }, 250);
}).blur(function(e) {
    setTimeout(function(){
        $(this).animate({ rows: rows }, 250);
    }.bind(this),400);

这里有一个解决方案,可以在不使用任何超时的情况下工作。看

HTML:


我相信你认为最初的点击事件没有被触发是正确的,因为目标区域在事件被评估之前已经离开了位置“mousedown”似乎在模糊之前进行评估,因此我们可以使用“mousedown”捕获单击目标信息,然后在“mouseup”上执行事件。目标越大,动画效果越不明显,或者动画速度越慢,也可以解决这个问题。

这里有一个解决方案,可以在不使用任何超时的情况下工作。看

HTML:


我相信你认为最初的点击事件没有被触发是正确的,因为目标区域在事件被评估之前已经离开了位置“mousedown”似乎在模糊之前进行评估,因此我们可以使用“mousedown”捕获单击目标信息,然后在“mouseup”上执行事件。目标越大,动画效果越不明显,或者动画速度越慢,这也解决了这个问题。

这对我来说似乎不太合适。编辑示例fiddle以包含一组链接:至少对我来说,当我在textarea中并单击其中一个链接时,textarea会折叠,但我没有收到任何警报。注释这一行它有效//$(此)。removeClass(“扩展”)嘿,这对我有效:)你明白为什么注释removeClass()吗修复了吗?在我看来,将文本区域的位置设置为绝对位置会使其工作。看看这个精简的测试:这对我在Chrome/Linux上仍然有效。所以,它所做的只是防止其他页面元素在执行展开/折叠时移动。这似乎对我不起作用。编辑示例fiddle以包含一组链接:至少对我来说,当我在textarea中并单击其中一个链接时,textarea会折叠,但我没有收到任何警报。注释这一行它有效//$(此)。removeClass(“扩展”)嘿,这对我有效:)你明白为什么注释removeClass()吗修复了吗?在我看来,将文本区域的位置设置为绝对位置会使其工作。看看这个精简的测试:这对我在Chrome/Linux上仍然有效。所以,它所做的就是防止其他页面元素在执行展开/折叠时移动。谢谢,但我希望找到一种不依赖延迟的解决方案。在问题的最后,我提到我已经确认了延迟方法确实有效,并与一个fiddle示例相联系。我意识到最初我想要一个没有超时的解决方案,但实际上,这似乎是最简单的方法。我已经让它在生产中运行了很长一段时间,用户没有抱怨。谢谢,但我希望找到一个不依赖延迟的解决方案。我在问题的最后提到我已经证实了
$(function() {
    var target = undefined;
    var rows = parseInt(
      $('textarea[name=details]').attr('rows')
    );

    $('textarea[name=details]').focus(function() {
      $(this).animate({ rows: rows + 10 }, 250);
    }).blur(function(e) {
      $(this).animate({ rows: rows }, 250);
    });

    $('.button').mousedown( function (e){
        target = $(e.target).attr('class');
    });
    $(document).mouseup( function (e){
        if (target) {
            alert(target);
            target = undefined;
        }
    });

});