Javascript 检测 iframe 何时获得或失去焦点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5456239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:16:23  来源:igfitidea点击:

Detecting when an iframe gets or loses focus

javascripthtmldomdom-events

提问by CAFxX

What's the correct way of detecting when an iframe gets or loses focus (i.e. will or will not receive keyboard events)? The following is not working in Fx4:

检测 iframe 何时获得或失去焦点(即会或不会接收键盘事件)的正确方法是什么?以下在 Fx4 中不起作用:

var iframe = /* my iframe */;
iframe.addEventListener("focus", function() { /* never gets called */ }, false);

采纳答案by CAFxX

Turns out it's not really possible. I had to change the logic of my page to avoid the need of tracking if the iframe has focus.

事实证明这是不可能的。如果 iframe 具有焦点,我不得不更改页面的逻辑以避免需要跟踪。

回答by Ryan

You can poll "document.activeElement" to determine if it matches the iframe. Polling isn't ideal, but it works:

您可以轮询“document.activeElement”以确定它是否与 iframe 匹配。轮询并不理想,但它有效:

function checkFocus() {
  if(document.activeElement == document.getElementsByTagName("iframe")[0]) {
    console.log('iframe has focus');
  } else {
    console.log('iframe not focused');
  }
}

window.setInterval(checkFocus, 1000); 

回答by EliorCohen

i know it's old, but i also had the same problem.

我知道它很旧,但我也遇到了同样的问题。

i ended up using this little pice of code:

我最终使用了这段代码:

$(document).on('focusout', function(){
       setTimeout(function(){
       // using the 'setTimout' to let the event pass the run loop
       if (document.activeElement instanceof HTMLIFrameElement) {
             // Do your logic here..
        }
    },0);
});

回答by CTS_AE

How to check when an iframe has been clicked in or out of as well as hover-state.

如何检查 iframe 何时被点击进入或退出以及悬停状态。

Note: I would highly recommend you don't choose a polling method and go with an event driven method such as this.

注意:我强烈建议您不要选择轮询方法,而是使用诸如此类的事件驱动方法。



Disclaimer

免责声明

It is not possible to use the focusor blurevents directly on an iframe but you can use them on the windowto provide an event driven method of checking the document.activeElement. Thus you can accomplish what you're after.

无法直接在 iframe 上使用focusblur事件,但您可以在 上使用它们window来提供事件驱动的方法来检查document.activeElement. 这样你就可以完成你所追求的。

Although we're now in 2018, my code is being implemented in GTM and tries to be cross browser compatible back to IE 11. This means there's more efficient code if you're utilizing newer ES/ECMAScript features.

虽然我们现在是 2018 年,但我的代码正在 GTM 中实现,并尝试跨浏览器兼容回到 IE 11。这意味着如果您使用更新的 ES/ECMAScript 功能,会有更高效的代码。



Setup

设置

I'm going to take this a few steps further to show that we can also get the iframe's srcattribute as well as determine if it's being hovered.

我将更进一步说明我们还可以获取 iframe 的src属性并确定它是否被悬停。

Code

代码

You would ideally need to put this in a document ready event, or at least encapsulate it so that the variables aren't global [maybe use an IIFE]. I did not wrap it in a document ready because it's handled by GTM. It may also depend where you place this or how you're loading it such as in the footer.

理想情况下,您需要将其放在文档就绪事件中,或者至少将其封装,以便变量不是全局变量 [也许使用 IIFE]。我没有将它包装在准备好的文档中,因为它是由 GTM 处理的。这也可能取决于您将其放置在哪里或如何加载它,例如在页脚中。

https://jsfiddle.net/9285tbsm/9/

https://jsfiddle.net/9285tbsm/9/

I have noticed in the JSFiddle preview that it's already an iframe, sometimes you have to focus it first before events start to capture. Other issues can be that your browser window isn't yet focused either.

我在 JSFiddle 预览中注意到它已经是一个 iframe,有时你必须在事件开始捕获之前先聚焦它。其他问题可能是您的浏览器窗口还没有聚焦。

// Helpers

var iframeClickedLast;

function eventFromIframe(event) {
  var el = event.target;
  return el && el.tagName && el.tagName.toLowerCase() == 'iframe';
}

function getIframeSrc(event) {
  var el = event.target;
  return eventFromIframe(event) ? el.getAttribute('src') : '';
}

// Events

function windowBlurred(e) {
  var el = document.activeElement;
  if (el.tagName.toLowerCase() == 'iframe') {
    console.log('Blurred: iframe CLICKED ON', 'SRC:', el.getAttribute('src'), e);
    iframeClickedLast = true;
  } 
  else {
    console.log('Blurred', e);
  }
}

function windowFocussed(e) {
  if (iframeClickedLast) {
    var el = document.activeElement;
    iframeClickedLast = false;
    console.log('Focussed: iframe CLICKED OFF', 'SRC:', el.getAttribute('src'), e);
  } 
  else {
    console.log('Focussed', e);
  }
}

function iframeMouseOver(e) {
  console.log('Mouse Over', 'SRC:', getIframeSrc(e), e);
}

function iframeMouseOut(e) {
  console.log('Mouse Out', 'SRC:', getIframeSrc(e), e);
}

// Attach Events

window.addEventListener('focus', windowFocussed, true);  
window.addEventListener('blur', windowBlurred, true);

var iframes = document.getElementsByTagName("iframe");
for (var i = 0; i < iframes.length; i++) {
  iframes[i].addEventListener('mouseover', iframeMouseOver, true);
  iframes[i].addEventListener('mouseout', iframeMouseOut, true);
}

回答by Adam Jagosz

A compact function that accepts callbacks you want to run when iframe gets or loses focus.

当 iframe 获得或失去焦点时,接受要运行的回调的紧凑函数。

/* eslint-disable no-unused-vars */
export default function watchIframeFocus(onFocus, onBlur) {
  let iframeClickedLast;

  function windowBlurred(e) {
    const el = document.activeElement;
    if (el.tagName.toLowerCase() == 'iframe') {
      iframeClickedLast = true;
      onFocus();
    } 
  }
  function windowFocussed(e) {
    if (iframeClickedLast) {
      iframeClickedLast = false;
      onBlur();
    } 
  }
  window.addEventListener('focus', windowFocussed, true);  
  window.addEventListener('blur', windowBlurred, true);
}

回答by Brian Norman

This solution is working for me on both mobile and desktop:

此解决方案适用于移动设备和桌面设备:

;(function pollForIframe() {
  var myIframe = document.querySelector('#my_iframe');
  if (!myIframe) return setTimeout(pollForIframe, 50);

  window.addEventListener('blur', function () {
    if (document.activeElement == myIframe) {
      console.log('myIframe clicked!');
    }
  });
})();

回答by Sindar

The solution is to inject a javascript event on the parent page like this :

解决方案是在父页面上注入一个 javascript 事件,如下所示:

var script = document.createElement('script');
script.type = 'text/javascript';

script.innerHTML = 
"document.addEventListener('click', function()" + 
"{ if(document.getElementById('iframe')) {" +
    // What you want
"}});"; 

head.appendChild(script);

回答by Sheo Dayal Singh

Here is the code to Detecting when an iframe gets or loses focus

这是检测 iframe 何时获得或失去焦点的代码

 // This code can be used to verify Iframe gets focus/loses.

      function CheckFocus(){

       if (document.activeElement.id == $(':focus').context.activeElement.id) {
                // here do something
            }
     else{
      //do something
    }
}

回答by Justine Lance T. Mojal

This might work

这可能有效

document.addEventListener('click', function(event) {
  var frame= document.getElementById("yourFrameID");

  var isClickInsideFrame = frame.contains(event.target);

  if (!isClickInsideFrame ) {
    //exec code
  }

});