模糊后jquery点击事件丢失

时间:2014-09-28 22:07:54

标签: 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(function(e) {
    $(this).animate({ rows: rows }, 250);
  });
});

小提琴: http://jsfiddle.net/p0t1pzh7/3/

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

相信正在发生的事情,是blur()处理程序正在更改页面,以便点击目标更改位置。由于模糊在点击之前运行,因此实际上发生了点击,但由于目标已移动位置,因此点击不再是点击元素。这是在Linux下的Chrome 37.0.2062.120上。

我认为,如果你在模糊处理程序中注释掉textarea的大小调整,那么一切都按预期工作。

小提琴:http://jsfiddle.net/p0t1pzh7/4/

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

这两种方法都看起来相当脆弱且容易出错。这种行为实际上只是一种精确的行为,所以如果没有“干净”的方式去做,我宁愿放弃它。

作为参考,延迟方法确实有效,正如在这个小提琴中可以看到的那样: http://jsfiddle.net/p0t1pzh7/5/

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

4 个答案:

答案 0 :(得分:2)

您可以使用setTimeout函数:

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

demo

答案 1 :(得分:1)

Try this solution

    $(window).load(function () {
        $('textarea.expand').focus(function () {
            $(this).addClass("expanding")
            $(this).animate({
                height: "10em"
            }, 500);
        });
        $('textarea.expand').blur(function () {
            $(this).animate({
                height: "1em"
            }, 500);
           // $(this).removeClass("expanding")
        });
    });


<table>
    <tr>
        <td>
            <textarea class="expand" rows="1" cols="10"></textarea>
        </td>
    </tr>
    <tr>
        <td>Here is some text just below. Does it move?</td>
    </tr>
</table>


.expand {
    height: 1em;
    line-height: 1em;
    width: 300px;
    padding: 3px;
}
.expanding {
    position: absolute;
    z-index: 9;
}
textarea {
    resize: none;
}

答案 2 :(得分:1)

这是一个不使用任何超时的解决方案。见http://jsfiddle.net/29sw1abb/

HTML:

<textarea name="details" rows="5"></textarea>

<p>
  <a href="#" class="button">click me</a>
</p>

JS

$(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;
        }
    });

});

我相信你是正确的假设原始点击事件没有被触发,因为目标区域在评估事件之前移出位置。 'mousedown'似乎在模糊之前进行评估,因此我们可以使用'mousedown'捕获点击目标信息,然后在'mouseup'上操作事件。拥有更大的目标,更少戏剧性的动画和更慢的动画也解决了这个问题。

答案 3 :(得分:0)

介绍延迟有效:

$(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);
  });
});
相关问题