kutombawewe.net

'osserva' su 'MutationObserver': il parametro 1 non è di tipo 'Node'

Sto creando un'estensione di Chrome e sto provando a includere un piccolo testo accanto al pulsante INVIO della casella di composizione di gMail.

Sto usando un MutationObserver per sapere quando appare la finestra di compose box. Lo faccio osservando un elemento con classe no poiché l'elemento box di composizione viene creato come figlio di questo elemento (class no).

Quando l'utente fa clic sul pulsante di composizione e viene visualizzata la finestra di composizione, quindi posiziono un elemento accanto al pulsante INVIA utilizzando il metodo .after(). Il nome della classe del pulsante INVIO è .gU.Up.

Questi sono i veri nomi di classe di gMail e anche abbastanza strani.

Di seguito è riportato il codice che sto usando:

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

Il problema è che ottengo costantemente l'errore seguente:

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

Qualcuno può aiutare? Ho provato diverse cose e ho anche guardato altre risposte qui, ma non riesco ancora a liberarmi di questo errore.

Ecco il mio manifest.json file:

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

Post scriptum Ho già provato la libreria insertionquery, ma presenta alcune lacune. Non mi consente di essere specifico riguardo ai cambiamenti nell'elemento specifico. Devo ancora provare la libreria mutationsummary, ma visto che usa MutationObserver, ho capito che il problema persisterà.

Aggiunto dal commento:
È vero che il selettore non mi sta dando un nodo. Ho controllato la console, sta dando un oggetto. Ho anche controllato la console e sta selezionando l'elemento appropriato che voglio osservare. 

Tuttavia, quando aggiungo console.log per l'elemento selezionato, viene visualizzato come non definito. Il che significa che probabilmente hai ragione sull'esecuzione del codice prima che i nodi entrino in esistenza. Puoi dirmi come assicurarmi che il ritardo si verifichi? funzionerà 'setTimeout'? Come funziona in caso di MutationObserver?

12
geet mehar

Come ho menzionato in un commento, e Xan ha dichiarato una risposta, l'errore chiarisce che il risultato di document.querySelectorAll(".no")[2] non viene valutato su Node

Dalle informazioni fornite in un commento, è chiaro che il problema è che il nodo che desideri osservare non esiste quando il tuo codice viene eseguito. Esistono molti modi per ritardare l'esecuzione del codice finché tale nodo non è disponibile. Alcune possibilità sono:

  1. Utilizzare un ciclo setTimeout per eseguire il polling fino a quando non si rileva che l'elemento su cui si desidera mettere MutationObserver è disponibile:

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

    Questo troverà il nodo appropriato relativamente poco dopo che esiste nel DOM. La validità di questo metodo dipende da quanto tempo dopo l'inserimento del nodo di destinazione è necessario che l'osservatore sia posizionato su di esso. Ovviamente, è possibile regolare il ritardo tra i tentativi di polling in base alle proprie esigenze.

  2. Creare un altro MutationObserver per guardare un nodo antenato più in alto nel DOM per l'inserimento del nodo su cui si desidera posizionare l'osservatore principale. Mentre questo troverà il nodo appropriato immediatamente quando viene inserito, potrebbe essere piuttosto intensivo per le risorse (CPU), a seconda di quanto in alto nel DOM si deve osservare e quanta attività ci sia rispetto alle modifiche del DOM.
13
Makyen

Questo errore significa che document.querySelectorAll(".no")[2] non è un Node.

Molto probabilmente questo significa che non esiste un tale elemento; querySelectorAll restituirà sempre un NodeList, anche se è vuoto; l'accesso a membri inesistenti della lista ha esito positivo senza un errore di runtime, ma restituisce undefined: in questo senso, NodeList si comporta come un array.

"Aspetta, ma funziona! Eseguo questo codice nella console e funziona!" puoi esclamare drammaticamente. Questo perché nel momento in cui viene eseguito, molto tempo dopo il completamento del caricamento del documento, questi elementi esistono.

Quindi, è necessario attendere che questo elemento root venga aggiunto; probabilmente, con un altro MutationObserver per fare il lavoro.

3
Xan

Prova a usare questo con jQuery.

Se stai sviluppando un'estensione di Chrome e ottieni un elemento HTML (nodo) dalla pagina o DOM in content_script , otterrai Object e il nodo verrà restituito come proprietà dell'oggetto. È quindi possibile ottenere il nodo dall'oggetto per passare al metodo observe(Node,config).

Esempio

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