web-dev-qa-db-ja.com

'MutationObserver'の 'observe':パラメーター1はタイプ 'Node'ではありません

Chrome拡張機能を作成し、gMail作成ボックスの[送信]ボタンの横に小さなテキストを含めようとしています。

MutationObserverを使用して、作成ボックスウィンドウがいつ表示されるかを確認しています。構成ボックス要素はこの要素(クラスno)の子として作成されるため、クラスnoを持つ要素を観察することでこれを行っています。

ユーザーが作成ボタンをクリックして、作成ボックスウィンドウが表示されたら、.after()メソッドを使用してSENDボタンの横に要素を配置します。 SENDボタンのクラス名は.gU.Upです。

これらはgMailの実際のクラス名で、かなり奇妙です。

以下は私が使用しているコードです:

var composeObserver = new MutationObserver(function(mutations){ 
    mutations.forEach(function(mutation){
        mutation.addedNodes.forEach(function(node){
            $(".gU.Up").after("<td> <div> Hi </div> </td>");
        });
    });
});

var composeBox = document.querySelectorAll(".no")[2];
var config = {childList: true};
composeObserver.observe(composeBox,config);

問題は、次のエラーが常に発生することです。

Uncaught TypeError: Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'

誰でも助けることができますか?私は非常に多くのことを試し、他の回答もここで見ましたが、それでもこのエラーを取り除くことはできません。

ここに私のmanifest.jsonファイルがあります:

{
    "manifest_version": 2,
    "name": "Gmail Extension",
    "version": "1.0",

    "browser_action": {
        "default_icon": "icon19.png",   
        "default_title": "Sales Analytics Sellulose"    
    },

    "background": {
        "scripts": ["eventPage.js"],
        "persistent": false
    },

    "content_scripts": [
    {
        "matches": ["https://mail.google.com/*"],
        "js": ["jquery-3.1.1.js", "insQ.min.js", "gmail_cs.js"]
    }
],

    "web_accessible_resources":[
        "compose_icon.png",
        "sellulosebar_icon.png" 
    ]
}

追伸私はすでにinsertqueryライブラリを試しましたが、いくつかの欠点があります。特定の要素の変更について具体的に説明することはできません。私はまだmutationsummaryライブラリを試していませんが、MutationObserverを使用しているため、この問題が続くと考えました。

コメントから追加:
セレクターからノードが提供されないのは事実です。コンソールでチェックインしましたが、オブジェクトを提供しています。また、コンソールでチェックインし、観察したい適切な要素を選択しています。

ただし、選択した要素にconsole.logを追加すると、未定義として表示されます。つまり、おそらく、ノードが存在する前にコードを実行するのは正しいでしょう。遅延が発生することを確認する方法を教えてもらえますか? 「setTimeout」は機能しますか? MutationObserverの場合、どのように機能しますか?

17
geet mehar

コメントで述べたように、Xanが答えを述べたように、このエラーにより、document.querySelectorAll(".no")[2]の結果が Node に評価されないことが明らかになります。

コメントで提供された情報から、問題は、コードの実行時に、観察したいノードが存在しないということです。そのノードが使用可能になるまでコードの実行を遅らせる方法はたくさんあります。いくつかの可能性は次のとおりです。

  1. SetTimeoutループを使用して、 MutationObserver を配置する要素が使用可能であることを検出するまでポーリングします。

    function addObserverIfDesiredNodeAvailable() {
        var composeBox = document.querySelectorAll(".no")[2];
        if(!composeBox) {
            //The node we need does not exist yet.
            //Wait 500ms and try again
            window.setTimeout(addObserverIfDesiredNodeAvailable,500);
            return;
        }
        var config = {childList: true};
        composeObserver.observe(composeBox,config);
    }
    addObserverIfDesiredNodeAvailable();
    

    これにより、適切なノードがDOMに存在してから比較的すぐに見つかります。このメソッドの実行可能性は、ターゲットノードの挿入後、オブザーバーを配置する必要がある時間に依存します。明らかに、ニーズに基づいてポーリング試行間の遅延を調整できます。

  2. 別のMutationObserverを作成して、プライマリオブザーバを配置するノードの挿入について、DOMの上位にある祖先ノードを監視します。これは、挿入されるとすぐに適切なノードを検出しますが、監視する必要があるDOMの高さと、DOMの変更に関するアクティビティの量によっては、かなりのリソース(CPU)を消費する場合があります。
15
Makyen

これをjQueryで使用してみてください。

Chrome拡張を開発していて、ページまたはHTMLエレメント(ノード)を content_script で取得している場合、オブジェクトを取得し、Nodeが返されますオブジェクトのプロパティとして。次に、オブジェクトからNodeを取得して、observe(Node,config)メソッドに渡すことができます。

var node = $("#elementId");  //this is wrong because if you logged this in the console you will get Object

var node = $("#elementId")[0];  //This gives the first property of the Object returned, and this is correct because if you logged this in the console you will get the Node element for which you want to detect changes in the DOM.
7
Code Me

このエラーは、document.querySelectorAll(".no")[2]Nodeではないことを意味します。

ほとんどの場合、これはそのような要素がないことを意味します。 querySelectorAllは、空であっても常にNodeListを返します。リストの存在しないメンバーへのアクセスは実行時エラーなしで成功しますが、undefinedを返します。この意味で、NodeListは配列のように機能します。

「待ってください、でもできます!このコードをコンソールで実行すると動作します!」あなたは劇的に叫ぶかもしれません。それは、ドキュメントをロードし終えてからずっと経ってから、それらの要素が存在するからです。

そのため、このルート要素が追加されるのを待つ必要があります。おそらく、別のMutationObserverでジョブを実行します。

4
Xan