編集:私のChromeブラウザに問題があり、スクリプトとの競合が発生したため、完全な再インストールにより、問題の原因が何であっても排除されました。原因を突き止めた場合、それを含めます。ここに。
EDIT2:2017年にこれを読んでいる人に、私がこれを忘れていないことと、前回の編集以降、この問題が発生したことがないことを知らせたいだけです。
EDIT3:それは2019年であり、今のところ私はこの問題を二度と経験していません。
私は単純なChrome userscriptポートである拡張機能を作成する方法を学習しています。このスクリプトは、run at
をdocument-start
に設定してTampermonkeyで完全に動作します最初からキャッチする必要があるイベントはすべてキャプチャされます。
ただし、Chrome拡張機能で同じ設定を設定すると、同じ実行設定がTampermonkeyの設定よりも速いため、最初の関数が失敗する原因となることがわかりました:(Uncaught TypeError: Cannot call method 'appendChild' of null.
) 0.010秒後まで存在しないhead
セクションにスクリプト要素を追加します。
これまでの私の汚い解決策は、タイマーを10に設定してsetInterval
関数を使用してdocument.head
が存在するかどうかを確認し、条件がtrueの場合にコードを続行することでした。
setInterval
に頼らずに、またはWebページのコンテキストでユーザースクリプトを実行しているように見えるTampermonkeyのgrant none
オプションを複製せずに、これを正しく動作させる方法はありますか?
以下は私のmanifest.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
イベントに行き詰まります。事前に感謝します提供されるヘルプ。
編集:私はすでに返信の提案を試しました:異なるrun at
ポイントを使用し、DOMContentLoaded
を使用してdocument.documentElement
に追加します。 1と2はスクリプトが初期のイベントを見逃す原因となり、3はdocument.head
に追加しようとしたときと同じTypeErrorを返します。
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);
}
コンソールにTypeError: Cannot call method 'appendChild' of null
が表示されます
manifest.json
で実行されるChrome拡張機能コンテンツスクリプト(document_start
から実行)、doの前に起動 document.readyState
ドク が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);
otherDOM要素を追加または変更する場合は、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"
リスナー内でコードをラップして"document_idle"
を引き続き使用できます。これにより、DOMの読み込みと解析が完全に完了したときにコードが実行されます。次に例を示します。
document.addEventListener("DOMContentLoaded", function() {
// Run your code here...
});