代码之家  ›  专栏  ›  技术社区  ›  Michiel Borkent

当一个“模糊”事件发生时,我如何才能找出哪个元素焦点*到*?

  •  153
  • Michiel Borkent  · 技术社区  · 16 年前

    假设我附上 blur 像这样的HTML输入框的函数:

    <input id="myInput" onblur="function() { ... }"></input>
    

    是否有方法获取导致 模糊 要在函数内部激发的事件(单击的元素)?怎么用?

    例如,假设我有这样一个跨度:

    <span id="mySpan">Hello World</span>
    

    如果在输入元素有焦点后单击范围,输入元素将失去焦点。函数如何知道它是 mySpan 点击了吗?

    PS:如果跨度的onclick事件发生在输入元素的onblur事件之前,那么我的问题就会得到解决,因为我可以设置一些状态值,指示特定元素已被单击。

    PPS:这个问题的背景是我想在外部(从可点击元素)触发一个Ajax自动完成器控件来显示它的建议,而不会因为 模糊 输入元素上的事件。所以我想登记 模糊 函数,如果单击了一个特定元素,则忽略模糊事件。

    23 回复  |  直到 6 年前
        1
  •  79
  •   Community CDub    8 年前

    隐马尔可夫模型。。。在火狐中,你可以使用 explicitOriginalTarget 以拉出单击的元素。我期待 toElement 对ie也一样,但似乎不起作用…但是,可以从文档中提取新焦点元素:

    function showBlur(ev)
    {
       var target = ev.explicitOriginalTarget||document.activeElement;
       document.getElementById("focused").value = 
          target ? target.id||target.tagName||target : '';
    }
    
    ...
    
    <button id="btn1" onblur="showBlur(event)">Button 1</button>
    <button id="btn2" onblur="showBlur(event)">Button 2</button>
    <button id="btn3" onblur="showBlur(event)">Button 3</button>
    <input id="focused" type="text" disabled="disabled" />
    

    Caveat: 这种技术可以 因工作引起的焦点变化 制表 通过键盘字段,在Chrome或Safari中根本不工作。使用中的大问题 activeElement (IE中除外)是否在 之后 这个 blur 事件已被处理,处理过程中可能根本没有有效值!这可以通过改变 the technique Michiel ended up using :

    function showBlur(ev)
    {
      // Use timeout to delay examination of activeElement until after blur/focus 
      // events have been processed.
      setTimeout(function()
      {
        var target = document.activeElement;
        document.getElementById("focused").value = 
          target ? target.id||target.tagName||target : '';
      }, 1);
    }
    

    这应该适用于大多数现代浏览器(在chrome、ie和firefox中测试),但需要注意的是chrome不会将焦点放在 喀喀 (与选项卡式到)。

        2
  •  57
  •   Oriol    9 年前

    2015答 据: UI Events ,您可以使用 relatedTarget 事件属性:

    用于标识辅助 EventTarget 与焦点相关 事件,取决于事件类型。

    为了 blur 事件,

    相关目标 : event target 接收焦点。

    例子:

    function blurListener(event) {
      event.target.className = 'blurred';
      if(event.relatedTarget)
        event.relatedTarget.className = 'focused';
    }
    [].forEach.call(document.querySelectorAll('input'), function(el) {
      el.addEventListener('blur', blurListener, false);
    });
    .blurred { background: orange }
    .focused { background: lime }
    <p>Blurred elements will become orange.</p>
    <p>Focused elements should become lime.</p>
    <input /><input /><input />

    注意:火狐不支持 相关目标 直到48版( bug 962251 , MDN )

        3
  •  18
  •   Michiel Borkent    16 年前

    我最终在onblur事件上解决了这个问题(多亏了一个不是stackoverflow的朋友的建议):

    <input id="myInput" onblur="setTimeout(function() {alert(clickSrc);},200);"></input>
    <span onclick="clickSrc='mySpan';" id="mySpan">Hello World</span>
    

    在FF和IE中都有效。

        4
  •  16
  •   Evgeny Shmanev    15 年前

    可以使用文档的mousedown事件而不是blur:

    $(document).mousedown(function(){
      if ($(event.target).attr("id") == "mySpan") {
        // some process
      }
    });
    
        5
  •  4
  •   rplaurindo    7 年前

    类型 FocusEvent 实例有 relatedTarget 但是,在FF的47版之前,特别是,这个属性返回空值,从48开始就可以了。

    你可以看到更多 here .

        6
  •  2
  •   matte    16 年前

    我也试图让自动完成器忽略模糊,如果一个特定的元素被点击,并有一个有效的解决方案,但由于明确的目标只有火狐。

    Autocompleter.Base.prototype.onBlur = Autocompleter.Base.prototype.onBlur.wrap( 
            function(origfunc, ev) {
                if ($(this.options.ignoreBlurEventElement)) {
                    var newTargetElement = (ev.explicitOriginalTarget.nodeType == 3 ? ev.explicitOriginalTarget.parentNode : ev.explicitOriginalTarget);
                    if (!newTargetElement.descendantOf($(this.options.ignoreBlurEventElement))) {
                        return origfunc(ev);
                    }
                }
            }
        );
    

    此代码包装autocompleter的默认onblur方法,并检查是否设置了ignoreblureventElement参数。如果已设置,则每次检查单击的元素是否为IgnoreBlureVenteElement。如果是,自动完成器不会校准模糊,否则它会调用模糊。唯一的问题是,它只在Firefox中工作,因为explicitoriginalTarget属性是特定于Mozilla的。现在,我试图找到一种不同的方法,而不是使用明确的目标。您提到的解决方案要求您手动向元素添加onclick行为。如果我不能解决明确的目标问题,我想我会遵循你的解决方案。

        7
  •  2
  •   bmb    10 年前

    你能把你正在检查的内容和时间颠倒过来吗?如果你记得最后模糊的东西:

    <input id="myInput" onblur="lastBlurred=this;"></input>
    

    然后在onclick for your span中,用两个对象调用函数():

    <span id="mySpan" onClick="function(lastBlurred, this);">Hello World</span>
    

    然后,函数可以决定是否触发ajax.autocompleter控件。函数具有单击的对象 模糊的物体。onblur已经发生了,所以它不会使建议消失。

        8
  •  1
  •   Benoit Garret    13 年前

    使用类似的方法:

    var myVar = null;
    

    然后在你的功能里面:

    myVar = fldID;
    

    然后:

    setTimeout(setFocus,1000)
    

    然后:

    function setFocus(){ document.getElementById(fldID).focus(); }
    

    最终代码:

    <html>
    <head>
        <script type="text/javascript">
            function somefunction(){
                var myVar = null;
    
                myVar = document.getElementById('myInput');
    
                if(myVar.value=='')
                    setTimeout(setFocusOnJobTitle,1000);
                else
                    myVar.value='Success';
            }
            function setFocusOnJobTitle(){
                document.getElementById('myInput').focus();
            }
        </script>
    </head>
    <body>
    <label id="jobTitleId" for="myInput">Job Title</label>
    <input id="myInput" onblur="somefunction();"></input>
    </body>
    </html>
    
        9
  •  1
  •   T J    10 年前

    我想这是不可能的, 用IE你可以试着用 window.event.toElement 但是它不适用于火狐!

        10
  •  1
  •   Community CDub    8 年前

    如在 this answer ,您可以检查 document.activeElement . document 是一个全局变量,因此不必在onblur处理程序中使用它:

    function myOnBlur(e) {
      if(document.activeElement ===
           document.getElementById('elementToCheckForFocus')) {
        // Focus went where we expected!
        // ...
      }
    }
    
        11
  •  1
  •   user6228847    8 年前
    • document.activeelement可以是父节点(例如body节点,因为它处于从目标到另一个目标的临时阶段切换),因此它不适用于您的作用域
    • ev.explicitoriginalTarget并不总是被重视

    因此,最好的方法是使用onclick-on-body事件来间接理解您的节点(event.target)处于模糊状态。

        12
  •  0
  •   brock.holum    16 年前

    编辑: 一个简单的方法是创建一个变量来跟踪你关心的每一个元素的焦点。因此,如果您关心“myinput”失去焦点,请将变量设置为focus。

    <script type="text/javascript">
       var lastFocusedElement;
    </script>
    <input id="myInput" onFocus="lastFocusedElement=this;" />
    

    原始答案: 您可以将“this”传递给函数。

    <input id="myInput" onblur="function(this){
       var theId = this.id; // will be 'myInput'
    }" />
    
        13
  •  0
  •   stalepretzel    16 年前

    我建议使用全局变量blurfrom和blurto。然后,配置您关心的所有元素,当它们失去焦点时,将它们在DOM中的位置分配给变量blurfrom。另外,对它们进行配置,以便获得焦点将变量blurto设置为 他们的 在DOM中的位置。然后,您可以一起使用另一个函数来分析BlurFrom和Blurto数据。

        14
  •  0
  •       16 年前

    请记住,对于文本输入到文本输入跳转,带expliciginaltarget的解决方案不起作用。

    尝试用以下文本输入替换按钮,您将看到不同之处:

    <input id="btn1" onblur="showBlur(event)" value="text1">
    <input id="btn2" onblur="showBlur(event)" value="text2">
    <input id="btn3" onblur="showBlur(event)" value="text3">
    
        15
  •  0
  •   EricDuWeb    14 年前

    我一直在使用相同的功能,发现FF、IE、Chrome和Opera能够提供事件的源元素。我还没有测试过Safari,但我想它可能有类似的东西。

    $('#Form').keyup(function (e) {
        var ctrl = null;
        if (e.originalEvent.explicitOriginalTarget) { // FF
            ctrl = e.originalEvent.explicitOriginalTarget;
        }
        else if (e.originalEvent.srcElement) { // IE, Chrome and Opera
            ctrl = e.originalEvent.srcElement;
        }
        //...
    });
    
        16
  •  0
  •   Sunil D.    13 年前

    我不喜欢在编写JavaScript时使用超时,所以我会用与MichielBorkent相反的方式来实现它。(没有尝试代码隐藏,但您应该了解这个想法)。

    <input id="myInput" onblur="blured = this.id;"></input>
    <span onfocus = "sortOfCallback(this.id)" id="mySpan">Hello World</span>
    

    在头脑里,就像那样

    <head>
        <script type="text/javascript">
            function sortOfCallback(id){
                bluredElement = document.getElementById(blured);
                // Do whatever you want on the blured element with the id of the focus element
    
    
            }
    
        </script>
    </head>
    
        17
  •  0
  •   Madbean    9 年前

    你可以用以下方法修复IE:

     event.currentTarget.firstChild.ownerDocument.activeElement
    

    它看起来像是FF的“explicitinginaltarget”。

    安托万与J

        18
  •  0
  •   Serhii Matrunchyk    8 年前

    我写了一篇文章 alternative solution 如何使任何元素可聚焦和“蓝色”。

    它是基于使元素 contentEditable 并以可视方式隐藏它并禁用编辑模式本身:

    el.addEventListener("keydown", function(e) {
      e.preventDefault();
      e.stopPropagation();
    });
    
    el.addEventListener("blur", cbBlur);
    el.contentEditable = true;
    

    DEMO

    注意:在Chrome、Firefox和Safari(OS X)中测试。对IE不确定。


    相关:我正在寻找VueJS的解决方案,因此对于那些对如何使用Vue Focusable指令实现此类功能感兴趣/好奇的人,请 take a look .

        19
  •  0
  •   LuisEduardox    7 年前

    适用于Google Chrome V66.x、Mozilla V59.x和Microsoft Edge…使用jquery的解决方案。

    我在Internet Explorer 9中测试,但不受支持。

    $("#YourElement").blur(function(e){
         var InputTarget =  $(e.relatedTarget).attr("id"); // GET ID Element
         console.log(InputTarget);
         if(target == "YourId") { // If you want validate or make a action to specfic element
              ... // your code
         }
    });
    

    在其他Internet Explorer版本中评论您的测试。

        20
  •  0
  •   xpy    6 年前

    我只看到答案中有黑客,但实际上有一个内置的解决方案非常容易使用: 基本上,您可以像这样捕获焦点元素:

    const focusedElement = document.activeElement
    

    https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement

        21
  •  -2
  •   Armin Ronacher    16 年前

    这种方式:

    <script type="text/javascript">
        function yourFunction(element) {
            alert(element);
        }
    </script>
    <input id="myinput" onblur="yourFunction(this)">
    

    或者,如果您通过javascript(本例中的jquery)附加侦听器:

    var input = $('#myinput').blur(function() {
        alert(this);
    });
    

    编辑 对不起。我误解了这个问题。

        22
  •  -2
  •   Monika Sharma    12 年前


    我认为很容易通过jquery传递引起“this”中onblur事件的字段的引用。
    例如

    <input type="text" id="text1" onblur="showMessageOnOnblur(this)">
    
    function showMessageOnOnblur(field){
        alert($(field).attr("id"));
    }
    

    谢谢
    莫妮卡

        23
  •  -2
  •   Shikekaka Yamiryuukido    10 年前

    你可以这样做:

    <script type="text/javascript">
    function myFunction(thisElement) 
    {
        document.getElementByName(thisElement)[0];
    }
    </script>
    <input type="text" name="txtInput1" onBlur="myFunction(this.name)"/>