2016-10-30 5 views
0

У меня есть привязки ключевых событий для клавиш со стрелками на веб-странице. Эти привязки отлично работают по мере загрузки страницы, но внезапно перестают работать, когда реклама Google AdSense на странице загружается. Это не происходит на каждой странице/загрузке объявлений, но примерно на половину из них.Javascript Keybindings «Прервано» или «Ломать фокус страницы» после загрузки рекламы в Chrome

Если это произойдет, если я нажимаю клавиши со стрелками несколько раз во время загрузки страницы, связанное событие будет успешно срабатывать до тех пор, пока не появится объявление, после чего событие перестанет работать, а действие по умолчанию клавиши (прокрутка страницы) начнется когда я продолжаю нажимать клавишу. Это странно, так как я отключил действие по умолчанию на этом клавише с помощью:

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; 
    } 
}; 

Если я затем нажмите в любом месте на теле страницы, ключевые привязки начнут работать снова.

Я предполагаю, что, возможно, когда объявление закончит загрузку (что находится после остальной части страницы), оно вызывает какое-то прерывание, которое «крадет фокус» со страницы (но, видимо, не окно, так как прокрутка по-прежнему бывает?).

Фактические привязки клавиш выполняются с помощью мышеловки, хотя это, похоже, не имеет ничего общего с проблемой, и я столкнулся с этой проблемой только в Google Chrome. Я не получаю такое поведение в Firefox. Если я включу AdBlock в Chrome, проблема не возникнет, показывая, что это реклама, инициирующая это «прерывание».

Есть ли что-то очевидное, что я не знаю, что может полностью прерывать привязки клавиш таким образом, сохраняя при этом ключи для прокрутки страницы до тех пор, пока пользователь не нажмет на тело снова? Есть ли способ предотвратить рекламу от нарушения интерактивности пользователя со страницей таким образом?

+0

Вы можете попробовать что-то вроде 'adsLoader.addEventListener (AdsLoadedEvent.ADS_LOADED, функция() {если (document.activeElement) {document.activeElement.blur();}}, ложь);' попытаться вернуться сосредоточиться на теле. [(adsLoaderEvent docs)] (https://support.google.com/adsense/answer/1705827?hl=ru) – amdouglas

ответ

0

Одно из предложений заключалось в том, чтобы зафиксировать событие ADS_LOADED AdSense, но оно доступно только при использовании SDK Google IMA в видео.

Решение, которое я придумал, состояло в том, чтобы прослушивать все события размытия, а когда фокус был украден из тела документа рекламой, верните фокус на окно. Это работает только тогда, когда 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; 
     } 
    } 
});