简体   繁体   English

jQuery单击事件丢失后模糊

[英]jquery click event lost after blur

I have a textarea field that I would like to have expand when it gains focus, and to contract back when it loses focus. 我有一个textarea字段,我希望在获得焦点时可以扩展,而在失去焦点时可以收缩。 Here is my test code: 这是我的测试代码:

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

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

The problem is when the textarea has focus, and the user clicks on another input element. 问题是当文本区域具有焦点时,用户单击了另一个输入元素。 The textarea collapses back in this case, but the click event appears to be lost. 在这种情况下,文本区域会折叠起来,但是单击事件似乎丢失了。

What I believe is happening, is the blur() handler is changing the page such that the target of the click changes position. 相信正在发生的事情是blur()处理程序正在更改页面,从而使单击目标更改位置。 Since blur runs before click, the click is in fact happening, but because the target has moved position, the click is no longer hitting an element. 由于模糊发生在单击之前,因此实际上发生了单击,但是由于目标已移动位置,因此单击不再击中某个元素。 This is on Chrome 37.0.2062.120 under Linux. 这是在Linux下的Chrome 37.0.2062.120上。

The reason I think that, is if you comment out the resizing of the textarea in the blur handler, everything works as intended. 我认为的原因是,如果您在模糊处理程序中注释掉textarea的大小调整,一切都会按预期进行。

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

I've googled and searched SO for related issues and did find several discussions on the ordering of the blur and click events. 我已经在Google上搜索并搜索了相关问题,并且确实找到了一些有关模糊和单击事件顺序的讨论。 Generally, solutions seemed to involve either adding a delay on the blur() action, or binding events on the other page element to keep track of what is occurring. 通常,解决方案似乎涉及在blur()操作上添加延迟,或者在另一个页面元素上绑定事件以跟踪正在发生的事情。

Both of those approaches seen rather fragile and error-prone. 这两种方法都相当脆弱且容易出错。 This behavior is really just a nicety, so if there's no "clean" way to do it, I'd rather just drop it altogether. 这种行为实际上只是一个很好的选择,因此,如果没有“干净”的方法,我宁愿完全放弃它。

For reference, the delay approach does work, as can be seen in this fiddle: http://jsfiddle.net/p0t1pzh7/5/ 作为参考,可以使用延迟方法,如下面的小提琴所示: http : //jsfiddle.net/p0t1pzh7/5/

And I understand why blur is triggered before click, but found it surprising that the target of the click event isn't "set" prior to blur being triggered. 而且我了解了为什么在点击之前触发了模糊,但是令人惊讶的是,点击事件的目标没有在触发模糊之前“设置”。 Is that expected behavior or does this vary between browsers? 这是预期的行为,还是在浏览器之间有所不同?

You may use setTimeout function: 您可以使用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 演示

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

Here is a solution that works without using any timeouts. 这是一种无需使用任何超时即可工作的解决方案。 See http://jsfiddle.net/29sw1abb/ 参见http://jsfiddle.net/29sw1abb/

HTML: HTML:

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

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

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

});

I beleive you are correct in assuming the original click event is not firing because the target area moves out of position before the event can be evaluated. 我相信您是对的,假设原始点击事件没有触发,因为目标区域在评估事件之前就移开了位置。 'mousedown' seems to evaluate before the blur so we can capture the click target info with 'mousedown' and then action the event on 'mouseup'. 'mousedown'似乎在模糊之前进行评估,因此我们可以使用'mousedown'捕获点击目标信息,然后对'mouseup'进行操作。 Having larger targets, less dramatic animation and or slower animation also solves this issue. 具有较大的目标,较不生动的动画和较慢的动画也可以解决此问题。

Introducing a delay works: 引入延迟的工作原理:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM