Detecting when an iframe gets or loses focus

前端 未结 9 1268
我寻月下人不归
我寻月下人不归 2020-12-31 06:24

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:



        
相关标签:
9条回答
  • 2020-12-31 06:43

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

    function checkFocus() {
      if(document.activeElement == document.getElementsByTagName("iframe")[0]) {
        console.log('iframe has focus');
      } else {
        console.log('iframe not focused');
      }
    }
    
    window.setInterval(checkFocus, 1000); 
    
    0 讨论(0)
  • 2020-12-31 06:43

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

    /* 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);
    }
    
    0 讨论(0)
  • 2020-12-31 06:47

    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);
    });
    
    0 讨论(0)
  • 2020-12-31 06:48

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

    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 focus or blur events directly on an iframe but you can use them on the window to provide an event driven method of checking the document.activeElement. Thus you can accomplish what you're after.

    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.


    Setup

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

    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.

    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.

    // 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);
    }
    
    0 讨论(0)
  • 2020-12-31 06:53

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

    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);
    
    0 讨论(0)
  • 2020-12-31 06:53

    This might work

    document.addEventListener('click', function(event) {
      var frame= document.getElementById("yourFrameID");
    
      var isClickInsideFrame = frame.contains(event.target);
    
      if (!isClickInsideFrame ) {
        //exec code
      }
    
    });
    
    0 讨论(0)
提交回复
热议问题