it-swarm.com.de

'observ' bei 'MutationObserver': Parameter 1 ist nicht vom Typ 'Node'

Ich erstelle eine Chrome-Erweiterung und versuche, neben der SEND-Schaltfläche der gMail-Erstellungsbox einen kleinen Text einzufügen.

Ich verwende einen MutationObserver, um zu wissen, wann das Fenster zum Erstellen einer Box angezeigt wird. Ich mache dies, indem ich ein Element mit der Klasse no beobachte, da das Compose-Box-Element als untergeordnetes Element dieses Elements (Klasse no) erstellt wird.

Wenn der Benutzer auf die Zusammenstellungsschaltfläche klickt und das Fenster "Zusammenstellungsbox" angezeigt wird, platziere ich ein Element neben der SENDEN-Schaltfläche mit der .after()-Methode. Der Klassenname der SEND-Schaltfläche lautet .gU.Up.

Dies sind die echten Klassennamen von gMail und auch ziemlich komisch.

Unten ist der Code, den ich verwende:

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

Das Problem ist, dass ich ständig folgenden Fehler bekomme:

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

Kann jemand helfen? Ich habe einige Dinge ausprobiert und auch andere Antworten hier angeschaut, kann diesen Fehler aber immer noch nicht beseitigen.

Hier ist meine manifest.json datei:

{
    "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" 
    ]
}

P.S. Ich habe bereits die Einfügungsabfragebibliothek ausprobiert, sie hat jedoch einige Mängel. Ich kann mich nicht genau auf die Änderungen in dem spezifischen Element beziehen. Ich habe die Mutationsummary-Bibliothek noch nicht ausprobiert, aber da sie MutationObserver verwendet, dachte ich, dass das Problem bestehen bleibt.

Hinzugefügt von Kommentar:
Es stimmt, dass der Selektor mir keinen Knoten gibt. Ich habe in der Konsole nachgesehen, es gibt ein Objekt. Ich habe auch die Konsole eingecheckt und sie wählt das entsprechende Element aus, das ich beobachten möchte. 

Wenn ich jedoch console.log für das ausgewählte Element hinzufüge, wird es als undefiniert angezeigt. Das heißt, Sie haben wahrscheinlich Recht, wenn Code ausgeführt wird, bevor Knoten entstehen. Können Sie mir sagen, wie Sie sicherstellen können, dass die Verzögerung auftritt? funktioniert 'setTimeout'? Wie funktioniert das bei MutationObserver?

12
geet mehar

Wie ich in einem Kommentar erwähnt habe und Xan eine Antwort angegeben hat, macht der Fehler klar, dass das Ergebnis von document.querySelectorAll(".no")[2] nicht zu einem Node ausgewertet wird. 

Aus den Informationen, die Sie in einem Kommentar angegeben haben, ist klar, dass das Problem darin besteht, dass der Knoten, den Sie beobachten möchten, nicht vorhanden ist, wenn Ihr Code ausgeführt wird. Es gibt viele Möglichkeiten, die Ausführung Ihres Codes so lange zu verzögern, bis dieser Knoten verfügbar ist. Einige Möglichkeiten sind:

  1. Verwenden Sie eine setTimeout-Schleife zum Abfragen, bis Sie feststellen, dass das Element, auf dem Sie den MutationObserver ablegen möchten, verfügbar ist:

    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();
    

    Dadurch wird der entsprechende Knoten relativ kurz nachdem er im DOM existiert, gefunden. Die Durchführbarkeit dieser Methode hängt davon ab, wie lange nach dem Einfügen des Zielknotens der Beobachter darauf platziert werden muss. Natürlich können Sie die Verzögerung zwischen den Abrufversuchen an Ihre Bedürfnisse anpassen.

  2. Erstellen Sie einen weiteren MutationObserver, um einen Vorfahrknoten zu überwachen, der höher im DOM liegt, um den Knoten einzufügen, auf dem Sie Ihren primären Beobachter platzieren möchten. Dies wird zwar beim Einfügen des entsprechenden Knotens sofort gefunden, kann jedoch sehr ressourcenintensiv (CPU) sein, abhängig davon, wie hoch der DOM ist, den Sie beachten müssen und wie viel Aktivität in Bezug auf DOM-Änderungen vorhanden ist.
13
Makyen

Dieser Fehler bedeutet, dass document.querySelectorAll(".no")[2] keine Node ist.

Dies bedeutet höchstwahrscheinlich, dass es kein solches Element gibt. querySelectorAll gibt immer eine NodeList zurück, auch wenn sie leer ist; Der Zugriff auf nicht vorhandene Mitglieder der Liste ist ohne Laufzeitfehler erfolgreich, gibt jedoch undefined zurück: In diesem Sinne verhält sich NodeList wie ein Array.

"Warten Sie, aber es tut! Ich führe diesen Code in der Konsole aus und es funktioniert!" Sie können dramatisch ausrufen. Das liegt daran, dass diese Elemente zum Zeitpunkt der Ausführung des Dokuments vorhanden sind, lange nachdem das Laden des Dokuments abgeschlossen ist.

Sie müssen also warten, bis dieses Wurzelelement hinzugefügt wird. wahrscheinlich mit einer anderen MutationObserver, die den Job erledigt.

3
Xan

Versuchen Sie, dies mit jQuery zu verwenden.

Wenn Sie eine Chrome-Erweiterung entwickeln und ein HTML-Element (Node) von der Seite oder DOM im content_script erhalten, erhalten Sie Object und Node werden als Eigenschaft des Objekts zurückgegeben. Dann können Sie Node vom Object erhalten, um an die observe(Node,config)-Methode zu übergeben.

Beispiel

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.
1
Code Me