Javascript 键绑定 "Interrupted" 或 "Lose Page Focus" 在 Chrome 中加载广告后
Javascript Keybindings "Interrupted" or "Lose Page Focus" After Advertisement Loads in Chrome
我有网页上箭头键的键事件绑定。这些绑定在页面加载时完美运行,但在加载页面上的 Google AdSense 广告时突然停止工作。并非每次 page/ad 加载都会发生这种情况,但大约有一半会发生这种情况。
发生这种情况时,如果我在页面加载期间重复按箭头键,绑定事件将成功触发,直到广告出现,此时事件停止工作,键的默认操作(滚动页面)开始当我一直按下键时发生。这很奇怪,因为我通过以下方式禁用了这些键的默认操作:
window.onkeydown = function(e) {
// Spacebar, all four arrow keys
if (e.keyCode == 32 || e.keyCode == 37 || e.keyCode == 38 || e.keyCode == 39 ||
e.keyCode == 40) {
e.preventDefault();
return false;
}
};
如果我随后单击页面正文中的任意位置,键绑定将再次开始工作。
我猜也许当广告完成加载时(在页面的其余部分之后),它会导致页面 "steals focus" 的某种中断(但显然不是 window 因为滚动仍然发生?)。
实际的键绑定是使用 Mousetrap 完成的,尽管这似乎与问题无关,而且我只在 Google Chrome 中遇到过这个问题。我在 Firefox 中没有这种行为。如果我在 Chrome 上启用 AdBlock,则不会出现此问题,进一步表明它是触发此 "interruption."
的广告
有什么明显的我没有意识到的可以通过这种方式完全中断键绑定,同时仍然允许键滚动页面直到用户再次点击正文吗?有什么方法可以防止广告以这种方式干扰用户与页面的交互吗?
一个建议是捕获 AdSense ADS_LOADED 事件,但这似乎只有在视频中使用 Google IMA SDK 时才可用。
我想出的解决方案是侦听所有模糊事件,当广告从文档正文中窃取焦点时,return 将焦点转移到 window。这仅在 window.focus() 被超时包装时有效,这是我目前不理解的。
isDescendant() 函数取自 this answer。
function isDescendant(child, parent) {
/*
Test if child is contained within parent regardless of how many levels deep
*/
var node = child.parentNode;
while (node != null) {
if (node == parent) {
return true;
}
node = node.parentNode;
}
return false;
}
window.addEventListener('blur', function() {
var ads = document.getElementsByClassName('ad');
var n = ads.length;
for (i=0; i<n; i++) {
if (isDescendant(document.activeElement, ads[i])) {
// This only works if wrapped in a timeout (why?)
window.setTimeout(function () {
window.focus();
}, 0);
break;
}
}
});
我有网页上箭头键的键事件绑定。这些绑定在页面加载时完美运行,但在加载页面上的 Google AdSense 广告时突然停止工作。并非每次 page/ad 加载都会发生这种情况,但大约有一半会发生这种情况。
发生这种情况时,如果我在页面加载期间重复按箭头键,绑定事件将成功触发,直到广告出现,此时事件停止工作,键的默认操作(滚动页面)开始当我一直按下键时发生。这很奇怪,因为我通过以下方式禁用了这些键的默认操作:
window.onkeydown = function(e) {
// Spacebar, all four arrow keys
if (e.keyCode == 32 || e.keyCode == 37 || e.keyCode == 38 || e.keyCode == 39 ||
e.keyCode == 40) {
e.preventDefault();
return false;
}
};
如果我随后单击页面正文中的任意位置,键绑定将再次开始工作。
我猜也许当广告完成加载时(在页面的其余部分之后),它会导致页面 "steals focus" 的某种中断(但显然不是 window 因为滚动仍然发生?)。
实际的键绑定是使用 Mousetrap 完成的,尽管这似乎与问题无关,而且我只在 Google Chrome 中遇到过这个问题。我在 Firefox 中没有这种行为。如果我在 Chrome 上启用 AdBlock,则不会出现此问题,进一步表明它是触发此 "interruption."
的广告有什么明显的我没有意识到的可以通过这种方式完全中断键绑定,同时仍然允许键滚动页面直到用户再次点击正文吗?有什么方法可以防止广告以这种方式干扰用户与页面的交互吗?
一个建议是捕获 AdSense ADS_LOADED 事件,但这似乎只有在视频中使用 Google IMA SDK 时才可用。
我想出的解决方案是侦听所有模糊事件,当广告从文档正文中窃取焦点时,return 将焦点转移到 window。这仅在 window.focus() 被超时包装时有效,这是我目前不理解的。
isDescendant() 函数取自 this answer。
function isDescendant(child, parent) {
/*
Test if child is contained within parent regardless of how many levels deep
*/
var node = child.parentNode;
while (node != null) {
if (node == parent) {
return true;
}
node = node.parentNode;
}
return false;
}
window.addEventListener('blur', function() {
var ads = document.getElementsByClassName('ad');
var n = ads.length;
for (i=0; i<n; i++) {
if (isDescendant(document.activeElement, ads[i])) {
// This only works if wrapped in a timeout (why?)
window.setTimeout(function () {
window.focus();
}, 0);
break;
}
}
});