Расширение Chrome, установленное на "run at ""document start", работает слишком быстро?
EDIT: что-то было не так с моим браузером Chrome и создание конфликта с моим скриптом, полная переустановка устранена независимо от источника проблемы. Если мне случится узнать, что вызвало это, я включу его сюда.
EDIT2: просто, чтобы кто-нибудь, читающий это в 2017 году, знал, что я этого не забыл, и у меня никогда не было этой проблемы с момента моего предыдущего редактирования.
я учился, как создать простое расширение Chrome, которое является порт юзерскрипта. Скрипт отлично работает с Tampermonkey с настройкой run at
to document-start
, все необходимые события, которые должны быть пойманы с самого начала все захвачены.
однако, когда я установил те же настройки в расширении Chrome, я обнаружил, что тот же параметр работает быстрее, чем Tampermonkey, что приводит к сбою первой функции: (Uncaught TypeError: Cannot call method 'appendChild' of null.
), поскольку он пытается добавить элемент сценария к head
раздел, который не существует до 0.010 s позже.
мое грязное решение до сих пор было использовать setInterval
функция с таймером, установленным на 10, чтобы проверить, если document.head
существует, а затем продолжить работу с кодом, если условие истинно.
есть ли способ, которым я могу сделать эту работу правильно, не прибегая к setInterval
или, может быть, повторить Tampermonkey в grant none
опция, которая, как представляется, запускает userscript в контексте веб-страницы?
ниже приведен мой манифест.формат JSON файл:
{
"manifest_version": 2,
"content_scripts": [ {
"js": [ "simpleuserscript.user.js" ],
"matches": [ "https://www.google.com/*"],
"run_at": "document_start"
} ],
"converted_from_user_script": true,
"description": "Chrome extension",
"name": "Testing",
"version": "1"
}
всего этого можно было бы избежать, если бы Chrome принял afterscriptexecute
событие, но пока это не произойдет, я застрял с load
событие. Заранее благодарю за любую помощь.
EDIT: я уже пробовал предложения в ответах: используя другой run at
точка, используя DOMContentLoaded
и добавить document.documentElement
. Все были неудачными, потому что: 1 и 2 заставляют скрипт пропускать ранние события, а 3 возвращает тот же TypeError, что и при попытке добавить в document.head
.
скрипт должен быть вставлен/бег, когда document.readyState = loading
или же он пропустит ранние необходимые события, но не так рано, чтобы быть неспособным добавить Чайлдса к любому documentElement
или head
пример кода внутри simpleuserscript.user.js
:
var script = document.createElement("script");
script.textContent = "console.log('success')";
if(document.head) {
document.head.appendChild(script);
} else if(document.documentElement) {
document.documentElement.appendChild(script);
}
2 ответов
расширение для Chrome сценарии (запускается с manifest.json
), которые выполняются в document_start
, do огонь до document.readyState
Doc достиг interactive
-- это самое раннее, что вы хотите начать возиться с большинством элементов страницы.
тем не менее, вы можете ввести большинство <script>
узлы сразу, если вы хотите. Только не document.head
или document.body
потому что они еще не существует.
Добавить в documentElement
вместо. Для пример:
var s = document.createElement ("script");
s.src = "http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js";
s.async = false;
document.documentElement.appendChild (s);
или
var s = document.createElement ("script");
s.src = chrome.extension.getURL ("MyPwnCode.js");
s.async = false;
document.documentElement.appendChild (s);
если вы добавляете или изменяете другое элементы DOM, в скрипте, работающем на document_start
подождите, пока DOMContentLoaded
событие вот так:
document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
function fireContentLoadedEvent () {
console.log ("DOMContentLoaded");
// PUT YOUR CODE HERE.
//document.body.textContent = "Changed this!";
}
ваша проблема в том, что при использовании "run_at": "document_start"
, единственным элементом, который предоставляется для существования в DOM, является <html>
элемент. Если вы хотите избежать ошибок относительно загрузки страницы, например, при попытке доступа к элементу, который еще не создан, вам придется либо:
сделайте свой скрипт работать на
"document_idle"
или"document_end"
. Хотя"document_end"
все еще не предоставляет вам, что все элементы и ресурсы страницы были полностью загружены (но DOM уже был синтаксический анализ), то"document_idle"
ключевое слово даст вам уверенность в том, что DOM был проанализирован, и все элементы и ресурсы были правильно загружены до запуска скрипта.-
или, вместо этого, вы можете продолжать использовать
"document_start"
упаковка кода внутри"DOMContentLoaded"
прослушиватель, который заставит его работать, когда DOM полностью закончит загрузку и синтаксический анализ, аналогично"document_idle"
. Вот пример:document.addEventListener("DOMContentLoaded", function() { // Run your code here... });