jQuery:在模糊事件之前触发click()事件

140

我有一个输入字段,想要实现自动补全建议。代码如下:

<input type="text" id="myinput">
<div id="myresults"></div>

在输入框的blur()事件中,我想隐藏结果的

$("#myinput").live('blur',function(){
     $("#myresults").hide();
});
当我在输入框中输入内容后,我会向服务器发送请求并获得JSON响应,将其解析为
  • 结构,并将这个
      放入我的#myresults div中。
      当我单击已解析的
    • 元素时,我想将
    • 中的值设置到输入框中,并隐藏#myresults div。
      $("#myresults ul li").live('click',function(){
           $("#myinput").val($(this).html());
           $("#myresults").hide();
      });
      

      一切都很顺利,但是当我点击我的li时,blur()事件会在click()之前触发,并且输入的值无法获得li的html。

      我如何设置click()事件在blur()事件之前触发?


那么为什么要使用模糊函数?当您的需求已经通过点击函数得到满足时。 - Owais Iqbal
这可能不会改变事件触发的顺序,但是如果blur确实在单击li后触发,那么您可能不需要在单击处理程序中执行$(“#myresults”).hide()。看起来发生的情况是$(this).html()返回一个空字符串。您可以记录或警告$(this).html()以确保吗? - veeTrain
@OwaisIqbal 有时候没有结果,有时候用户不想从建议中选择任何东西,有时候用户不想再使用这个输入了,但我必须隐藏未使用的结果。 - Egor Sazanovich
@veeTrain,我的处理程序中有很多操作,我只是将它们最小化以便易于理解我问题的核心。另外,我已经尝试在blur()click()处理程序上在firebug中添加观察点,但是在blur()结束后没有任何操作。 - Egor Sazanovich
看起来你需要排队函数。试着看看这个页面:https://dev59.com/OXNA5IYBdhLWcg3wL6yx。先进先出(FIFO)部分可能与你有关。 - Patriotec
我不确定可能发生了什么,因为您拥有的事件处理程序比您展示的要多。这里有一个 jsfiddle,可以做到您想要的效果;它是否接近您尝试创建的行为?我在失去焦点时调用 show() 来提供点击内容。您能否在那里创建问题? - veeTrain
5个回答

330

解决方案1

监听 mousedown 事件而不是 click 事件。

当你按下鼠标按钮时,mousedownblur 事件会依次发生,但只有在释放按钮时才会触发 click 事件。

解决方案2

你可以在 mousedown 中使用 preventDefault() 来阻止下拉列表窃取焦点。稍微的优势在于当鼠标按钮释放时值将被选择,这是本机选择组件的工作方式。 JSFiddle

$('input').on('focus', function() {
    $('ul').show();
}).on('blur', function() {
    $('ul').hide();
});

$('ul').on('mousedown', function(event) {
    event.preventDefault();
}).on('click', 'li', function() {
    $('input').val(this.textContent).blur();
});

14
解决方案1在我的情况下很有效!修改容易!谢谢 :) - Jon
谢谢 :) 但是您能解释一下为什么监听 mousedown 而不是 click 像魔法一样有效吗? - Mudassir Ali
3
因为mousedown事件在失焦之前发生,而click事件则在其之后发生。 http://jsfiddle.net/f3BKP/ - Alexey Lebedev
@cw24 你说得对,超时会不太可靠。我已经更新了答案,提供了更好的替代方案。 - Alexey Lebedev
5
方案#2非常巧妙,我永远想不出来!谢谢。 - Tobia
显示剩余3条评论

2

我遇到了这个问题,而对于我来说使用mousedown不是一个选项。

我通过在处理函数中使用setTimeout来解决了这个问题。

        elem1.on('blur',function(e) {

            var obj = $(this);

            // Delay to allow click to execute
            setTimeout(function () {
                if (e.type == 'blur') {

                  // Do stuff here

                }
            }, 250);
        });

        elem2.click( function() {
            console.log('Clicked');
        });

2

我刚回答了一个类似的问题:https://dev59.com/0Wox5IYBdhLWcg3wOx_9#46676463

除了mousedown解决方案之外,另一种方法是忽略由于单击特定元素而引起的模糊事件(即,在模糊处理程序中,如果是由于单击特定元素而引起的,则跳过执行)。

$("#myinput").live('blur',function(e){
     if (!e.relatedTarget || !$(e.relatedTarget).is("#myresults ul li")) {
         $("#myresults").hide();
     }
});

在我的情况下,event.relatedTarget返回null,有什么想法为什么会这样? - gaurav5430
好的,这里是答案:https://dev59.com/zVgQ5IYBdhLWcg3wcTeH - gaurav5430

2
$(document).on('blur', "#myinput", hideResult);

$(document).on('mousedown', "#myresults ul li", function(){
     $(document).off('blur', "#myinput", hideResult); //unbind the handler before updating value
     $("#myinput").val($(this).html()).blur(); //make sure it does not have focus anymore
     hideResult(); 
     $(document).on('blur', "#myinput", hideResult);  //rebind the handler if needed
});

function hideResult() {
     $("#myresults").hide();
}

FIDDLE


0

当我点击非按钮元素时,Mousedown解决方案对我无效。因此,这是我在代码中使用模糊功能所做的:

.on("blur",":text,:checkbox,:radio,select",function() {
/*
* el.container 
* container, you want detect click function on.
*/
            var outerDir = el.container.find(':hover').last();
            if (outerDir.length) {
                if ($.inArray(outerDir.prop('tagName'), ["A","SELECT"] ) != -1 || outerDir.prop('type') == 'button' || outerDir.prop('type') == 'submit') {
                    outerDir.click();
                }
                if (outerDir.prop('type') == 'checkbox') {
                    outerDir.change();
                }
                return false;
            }
/*          
* YOUR_BLUR_FUNCTION_HERE;
*/
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接