有没有办法在focusOut中使用event.preventDefault?如果没有,为什么?

Kli*_*lik 16 jquery event-handling javascript-events preventdefault

我想阻止focusOut(或blur)事件的默认事件,并将焦点设置为特定的输入字段.

这是我已经尝试过的:

  • 使用event.preventDefault()之初,在函数结束时(用于测试目的,而不是风格)

  • return false; 防止传播

  • 将焦点直接设置回元素中的元素(但我发现焦点仍然会切换,因为焦点开关在函数执行.on()执行.我知道我可以使用setTimeout,但我想避免它并弄清楚心脏这个问题.)

  • 使用blur而不是focusOut

我的代码是这样的:

    _triggerEventHide: function(inst, eventType) {
        inst.$target.on(eventType, function(event) {
            event.preventDefault();
            if (!$.suggestBox.$divCont.hasClass($.suggestBox.mouseOverClassName)) {
                $.suggestBox.$divCont.css({display: 'none'});   //reposition Suggestbox
            } else {
                inst.target.focus(); 
            }
            event.preventDefault();
            return false;
        });
     }
Run Code Online (Sandbox Code Playgroud)

注意,它$target表示jQuery包装的元素并target表示本机DOM元素.

我做了一些研究,已经发现了一些与我的问题相关的文章,但没有一个回答这个问题.

  1. preventDefault对焦点事件不起作用 - 这里给出的答案是使用任何类型的事件操作的替代路径.

  2. 如果没有必要的值,将焦点反射回文本框 - 这里,解决方案是用来setTimeout()将焦点设置回原始元素,这是好的,但我想了解问题的核心,为什么preventDefault()是不在这里工作.

  3. jQuery preventDefault()不起作用 - 我尝试了一些可能的解决方案来自这个线程,比如使用event.stopImmediatePropagation()event.stop(),但一切都没有用.

我感谢任何时候,知识和解决方案(包括尝试)在这件事上的贡献.我真的想学习......

这是一个jsFiddle,向您展示问题...随意玩它并尝试不同的解决方案.

Kli*_*lik 21

经过一些研究后,我发现只有某些事件是"可取消的".

  • 引用自http://help.dottoro.com/ljwolcsp.php

    您可以检查是否可以使用所有浏览器中的cancelable属性取消事件,但在版本9之前的Internet Explorer中除外.虽然Firefox中存在cancelable属性,但无论事件的可取消状态如何,它都始终返回true.无法确定在版本9之前是否可以在Internet Explorer中取消事件.

    请注意,对不可取消事件使用preventDefault方法和returnValue属性不会导致错误.当事件处理程序返回false时,该事件将被取消.您可以使用它而不是preventDefault方法和returnValue属性.参见下面的实施例2.

  • Javascript中的每个事件都有一个可取消的属性,如果可以阻止该事件,则定义为"true";如果无法取消该事件,则定义为"false".参考:http://help.dottoro.com/ljeosnqv.php

  • 从一个示例脚本http://help.dottoro.com/ljeosnqv.php证明这个属性可以发现这里上的jsfiddle(以节省空间).请注意代码中有关Firefox如何为事件对象中的cancelable属性返回true的注释.

一般原则是:

 $('selector').on(eventType, function (event) {
    alert(('cancelable' in event));   //will return true
    alert(event.cancelable);      //will return true if event can be cancelled
                                  //NOTE: Firefox mistakenly always returns true
});
Run Code Online (Sandbox Code Playgroud)
  • 事件具有根据情况发生的预设顺序.例如,如果单击鼠标按钮,则eventTriggers的顺序为:mousedown,mouseup和click.参考:www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-initMouseEvent

  • 引自http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-flow-cancelation

    "可取消事件"是与默认操作相关联的事件,允许在DOM事件流期间取消该操作.在事件流期间的任何阶段,触发的事件侦听器都可以选择取消默认操作或允许默认操作继续.对于浏览器中的超链接,取消操作将导致不激活超链接.并非本规范中定义的所有事件都是可取消的事件.

  • 有时事件序列会使DOM默认操作发生在您要取消的事件之前甚至显示,在这些情况下,您无法取消默认操作,因为它已经发生.也就是说默认操作发生事件发送之前.


我的解决方案

话虽如此,我确实设法找到了解决问题的方法,并且或多或少地解决了这个问题.基本上我有一个eventListener已经有一个focusin元素,我希望这个元素保持焦点.

<div id='display'></div>
$('#idBox').on('focusin', function () {
  $('#div').append('focused');
  //do something
}
Run Code Online (Sandbox Code Playgroud)

最初我点击时尝试使用setTimeout事件,但我发现这不好,因为它再次触发了我的focusin事件.所以我们需要的是在DOM切换焦点的默认操作之前调度的事件.我也发现,有符合这个要求的事件,但只适用于IE浏览器...典型.您的信息是:"onbeforedeactivate",可以取消.但是,由于跨浏览器兼容性很重要,我们不应该使用此eventTrigger.相反,我发现事件mousedown发生在DOM开始其焦点改变行为之前.

所以我们能做的是:

$(document).on('mousedown', function(event) { 
       target = event.target;     // the element clicked on
       myTarget = document.getElementById("idBox");   // the element to keep focus
       if (target !== myTarget) {   
           event.preventDefault();  //prevent default DOM action
           event.stopPropagation();   //stop bubbling
           return false;   // return
       }
});
Run Code Online (Sandbox Code Playgroud)

还有很多其他方法可以解决这个问题.我个人不喜欢将eventListener设置为整个文档,而是为了演示它的用途.


脚注:阅读Javascript中有关事件处理的更多信息的好文章是http://help.dottoro.com/ljtdqwlx.php 我偶然发现了一个惊人的资源.

  • Web标准存在缺陷,使用基于标准的浏览器无法创建高质量和强大的UI. (3认同)
  • 感谢您整理出非常深入的答案! (2认同)