Ответ 1
Оказывается, это не реально. Мне пришлось изменить логику моей страницы, чтобы избежать необходимости отслеживания, если в iframe есть фокус.
Каков правильный способ обнаружения, когда iframe получает или теряет фокус (т.е. будет или не будет принимать события клавиатуры)? В Fx4 не работает:
var iframe = /* my iframe */;
iframe.addEventListener("focus", function() { /* never gets called */ }, false);
Оказывается, это не реально. Мне пришлось изменить логику моей страницы, чтобы избежать необходимости отслеживания, если в iframe есть фокус.
Вы можете опросить "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);
Я знаю это старый, но у меня также была та же проблема.
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);
});
Примечание. Я настоятельно рекомендую не выбирать метод опроса и использовать метод, управляемый событиями, такой как этот.
Невозможно использовать события 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);
}
Решение состоит в том, чтобы ввести 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);
Вот код для обнаружения, когда 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
}
}
Это может работать
document.addEventListener('click', function(event) {
var frame= document.getElementById("yourFrameID");
var isClickInsideFrame = frame.contains(event.target);
if (!isClickInsideFrame ) {
//exec code
}
});
Компактная функция, которая принимает обратные вызовы, которые вы хотите запустить, когда 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);
}