0

Я ищу способ получить целенаправленный ввод любой страницы с целью ее обновления.Идентифицировать истинный активный элемент в иерархии кадров

У меня есть скрипт контента, который получает значение и проверяет, является ли activeElement <input>.

Задача заключается в том, что активный элемент основного документа является iframe. Я могу установить all_frames: true в манифест, который найдет любой активный <input>, но я хочу только установить значение activeElement активного iframe.

В настоящее время я решаю это, разрешив дочернему контенту (-ам) контента blur() все активные элементы, кроме текущего (прикрепление обработчика к focusin), но решение, которое не изменяет состояние документа, было бы лучше imho.

Можно ли отправить сообщение только основному документу, и если этот активный элемент является iframe, получите этот frameId (и повторите попытку)?

Я не контролирую веб-страницы.

ответ

0

Внесите новый скрипт контента, который проверяет полную иерархию кадров, включая междоменные кадры.

Основное содержание сценария запрашивает страницу фон/событие, если это необходимо:

if (document.activeElement.matches('input') && window == parent) { 
    console.log('Input', document.activeElement); 
    document.activeElement.value += ' gotcha!'; 
} else { 
    chrome.runtime.sendMessage({action: 'modifyInput'}); 
} 

background/event page скрипт выполняет дополнительный контент сценария во всех кадрах:

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse)) { 
    if (msg.action == 'modifyInput') { 
     chrome.tabs.executeScript(sender.tab && sender.tab.id, { 
      file: 'modify-input.js', 
      allFrames: true, 
      matchAboutBlank: true, 
      runAt: 'document_end', 
     }); 
    } 
}); 

изменения-вход. js, IIFE используется, чтобы убедиться, что сбор мусора удаляет впрыскиваемый материал.

;(function() { 
if (isInputActive()) { 
    if (window == parent) { 
     foundTheInput(); 
    } else { 
     askParent(); 
    } 
} else if (isFrameActive()) { 
    window.addEventListener('message', function onMessage(e) { 
     if (!e.data || e.data.id != chrome.runtime.id) 
      return; 
     switch (e.data.action) { 
     // request from a child frame 
     case 'checkme': 
      if (window == parent) { 
       confirmChild(e.source); 
       window.removeEventListener('message', onMessage); 
      } else { 
       askParent(); 
      } 
      break; 
     // response from a parent 
     case 'confirmed': 
      window.removeEventListener('message', onMessage); 
      if (isInputActive()) { 
       foundTheInput(); 
      } else if (isFrameActive()) { 
       confirmChild(e.source); 
      } 
      break; 
     } 
    }); 
} 

function isInputActive() { 
    return document.activeElement.matches('input'); 
} 

function isFrameActive() { 
    return document.activeElement.matches('frame, iframe'); 
} 

function askParent() { 
    parent.postMessage({id: chrome.runtime.id, action: 'checkme'}, '*'); 
} 

function confirmChild(childWindow) { 
    console.log('Frame', document.activeElement); 
    childWindow.postMessage({id: chrome.runtime.id, action: 'confirmed': true}, '*'); 
} 

function foundTheInput() { 
    console.log('Input', document.activeElement); 
    document.activeElement.value += ' gotcha!'; 
} 
})(); 

Я не тестировал это, но ранее использовал аналогичный код.

+0

Интересное решение .. Нужно также иметь слушателя в isInputActive case: Если '' 'B''' является подкадром' '' A''', и мы ищем элемент input-activeElement в B. B не будет слушателя с кодом, как было предложено. Это значит, что мне тоже нужно отклонить сообщения (чтобы очистить слушателей). – ttyridal

+0

и A - главное окно. Довольно запутанный, но получить работу - И я не нашел лучшего способа => принял – ttyridal

Смежные вопросы