Обнаружение, когда iframe получает или теряет фокус

Каков правильный способ обнаружения, когда iframe получает или теряет фокус (т.е. будет или не будет принимать события клавиатуры)? В Fx4 не работает:

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

Ответ 1

Оказывается, это не реально. Мне пришлось изменить логику моей страницы, чтобы избежать необходимости отслеживания, если в iframe есть фокус.

Ответ 2

Вы можете опросить "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); 

Ответ 3

Я знаю это старый, но у меня также была та же проблема.

i закончил с помощью этого небольшого фрагмента кода:

$(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);
});

Ответ 4

Как проверить, когда был вставлен или выключен элемент iframe, а также состояние при наведении.

Примечание. Я настоятельно рекомендую не выбирать метод опроса и использовать метод, управляемый событиями, такой как этот.


Отказ от ответственности

Невозможно использовать события focus или blur непосредственно в iframe, но вы можете использовать их в window, чтобы обеспечить управляемый событиями метод проверки document.activeElement. Таким образом, вы можете выполнить то, что вы хотите.

Хотя сейчас мы находимся в 2018 году, мой код внедряется в GTM и пытается быть кросс-браузерно-совместимым обратно в IE 11. Это означает, что существует более эффективный код, если вы используете более новые функции ES/ECMAScript.


Настройка

Я собираюсь сделать это на несколько шагов дальше, чтобы показать, что мы также можем получить атрибут iframe src и определить, был ли он отображен.

Код

В идеале вам нужно поместить это в событие готовности документа или, по крайней мере, инкапсулировать его, чтобы переменные не были глобальными [возможно, используйте IIFE]. Я не завернул его в готовый документ, потому что он обрабатывается GTM. Это также может зависеть от того, где вы размещаете это или как вы его загружаете, например, в нижнем колонтитуле.

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

В предварительном просмотре 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);
}

Ответ 5

Решение состоит в том, чтобы ввести 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);

Ответ 6

Вот код для обнаружения, когда 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
    }
}

Ответ 7

Это может работать

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

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

  if (!isClickInsideFrame ) {
    //exec code
  }

});

Ответ 8

Компактная функция, которая принимает обратные вызовы, которые вы хотите запустить, когда 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);
}