17

我想阻止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;
        });
     }

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

我已经进行了一些研究,并且已经找到了一些与我的问题相关的文章,但没有一篇文章回答了这个确切的问题。

  1. preventDefault 不适用于焦点事件——在这里,给出的答案是使用任何类型的事件操作的替代途径。

  2. 如果没有必需的值,则将焦点返回文本框上的焦点–在这里,解决方案是使用setTimeout()将焦点设置回原始元素,这没关系,但我想了解问题的核心,为什么preventDefault()是不在这里工作。

  3. jQuery preventDefault() 不起作用——我从这个线程尝试了一些可能的解决方案,例如使用event.stopImmediatePropagation()and event.stop(),但都是徒劳的。

我感谢在此问题上贡献的任何时间、知识和解决方案(包括尝试)。我真的很想学习……</p>

这是一个向您展示问题的 jsFiddle ……请随意使用它并尝试不同的解决方案。

4

4 回答 4

22

经过更多研究后,我发现只有某些事件是“可取消的”。

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

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

    请注意,在不可取消的事件上使用 preventDefault 方法和 returnValue 属性不会导致错误。当事件处理程序返回 false 时,该事件将被取消。您可以使用它来代替 preventDefault 方法和 returnValue 属性。请参见下面的示例 2。

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

  • 可以在 jsFiddle 上找到来自 http://help.dottoro.com/ljeosnqv.php 的演示此属性示例脚本(以节省空间)。请注意代码中关于 Firefox 如何始终为事件对象中的可取消属性返回 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
});
  • 根据情况,事件具有预设的发生顺序。例如,如果单击鼠标按钮,则 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,我希望这个元素保持焦点。

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

最初,当我单击关闭时,我尝试使用 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
       }
});

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


脚注:了解更多关于 Javascript 事件处理的好文章是http://help.dottoro.com/ljtdqwlx.php 我偶然发现的一个了不起的资源。

于 2013-01-31T06:52:34.927 回答
1

我们知道这是导致问题的点击功能。所以在像chrome这样的普通资源管理器中,你可以检测mousedown事件,然后阻止默认。

但这在 ie 中不起作用,但我们可以使用 beforedeactivate 事件来代替http://msdn.microsoft.com/en-us/library/windows/apps/jj569321.aspx。它可以在焦点发生变化时被检测到。所以只是阻止它。

代码会是这样的:

       $inp.on('blur', function(){

            self.hide();
        });

        isIE && $inp.on('beforedeactivate', function(evt){
            mousedown && evt.preventDefault();
        });

        $holder.on('mousedown', function(evt){
            evt.preventDefault();
            mousedown = 1;
        });
于 2014-07-22T10:04:15.717 回答
0

我试图在 contenteditable 元素中实现这种行为。我想在单击将焦点从 contenteditable 元素上移开的外部按钮时将光标保持在原位。

作为解决方案,我拦截了 focusout 事件并恢复了原始选择。打字稿中的示例:

editable_element.addEventListener('focusout',(e)=> {
    if(e.relatedTarget && e.relatedTarget.tagName=="BUTTON") 
    {
        let sel : any = App.SR.getSelection();
        let range : any = sel.getRangeAt(0);
        sel.removeAllRanges();
        sel.addRange(range);
    }
});
于 2020-08-28T22:18:47.807 回答
-1
inst.$target.on("blur", function() {
     if (!$.suggestBox.$divCont.hasClass($.suggestBox.mouseOverClassName)) {
        $.suggestBox.$divCont.css({'display': 'none'});   //reposition Suggestbox
        return true;
        } 
      inst.target.focus();
      return false;
         });

需要查看您的html。我认为您的称呼不正确 EX:

$.suggestBox我想应该是$(".suggestBox"),但我不能不看你的htnl就知道

于 2013-01-30T21:22:04.313 回答