it-swarm-es.com

'observar' en 'MutationObserver': el parámetro 1 no es del tipo 'Nodo'

Estoy creando una extensión de Chrome e intentando incluir un pequeño texto junto al botón ENVIAR del cuadro de composición de gMail.

Estoy usando un MutationObserver para saber cuándo aparece la ventana del cuadro de composición. Estoy haciendo esto observando un elemento con la clase no ya que el elemento del cuadro de composición se crea como hijo de este elemento (clase no).

Cuando el usuario hace clic en el botón de composición y aparece la ventana del cuadro de composición, coloco un elemento al lado del botón ENVIAR utilizando el método .after(). El nombre de clase del botón ENVIAR es .gU.Up.

Estos son los nombres de clase reales de gMail y bastante raro también.

A continuación se muestra el código que estoy 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);

El problema es que constantemente recibo el siguiente error:

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

¿Alguien puede ayudar? He intentado bastantes cosas y también he mirado otras respuestas aquí, pero todavía no puedo deshacerme de este error.

Aquí está mi 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" 
    ]
}

PD Ya probé la biblioteca inserttionquery, pero tiene algunas deficiencias. No me permite ser específico en cuanto a los cambios en el elemento específico. Todavía tengo que probar la biblioteca de resumen de mutaciones, pero como utiliza MutationObserver, pensé que el problema persistirá.

Añadido del comentario:
Es cierto que el selector no me está dando un nodo. Lo comprobé en la consola, está dando un objeto. También verifiqué en la consola y está seleccionando el elemento apropiado que deseo que se me observe.

Sin embargo, cuando agrego console.log para el elemento seleccionado, se muestra como no definido. Lo que significa que probablemente tenga razón sobre la ejecución del código antes de que los nodos entren en existencia. ¿Puedes decirme cómo asegurarme de que ocurra el retraso? ¿Funcionará 'setTimeout'? ¿Cómo funciona en el caso de MutationObserver?

12
geet mehar

Como mencioné en un comentario, y Xan declaró una respuesta, el error deja claro que el resultado de document.querySelectorAll(".no")[2] no se evalúa como un Nodo .

De la información que proporcionó en un comentario, queda claro que el problema es que el nodo que desea observar no existe cuando se ejecuta el código. Hay muchas formas de retrasar la ejecución de su código hasta que ese nodo esté disponible. Algunas posibilidades son:

  1. Usando un bucle setTimeout para sondear hasta que detecte que el elemento en el que desea colocar el MutationObserver está disponible:

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

    Esto encontrará el nodo apropiado relativamente poco después de que exista en el DOM. La viabilidad de este método depende de cuánto tiempo después de la inserción del nodo de destino necesite que el observador se coloque en él. Obviamente, puede ajustar la demora entre intentos de sondeo según sus necesidades.

  2. Cree otro MutationObserver para ver un nodo ancestral más alto en el DOM para la inserción del nodo en el que desea colocar su observador principal. Si bien esto encontrará el nodo apropiado inmediatamente cuando se inserta, puede requerir un gran uso de recursos (CPU), dependiendo de qué tan alto en el DOM tenga que observar y cuánta actividad haya con respecto a los cambios del DOM.
13
Makyen

Este error significa que document.querySelectorAll(".no")[2] no es una Node.

Lo más probable es que esto signifique que no existe tal elemento; querySelectorAll siempre devolverá una NodeList, incluso si está vacía; el acceso a miembros no existentes de la lista se realiza correctamente sin un error de tiempo de ejecución, pero devuelve undefined: en este sentido, NodeList actúa como una matriz.

"¡Espera, pero lo hace! ¡Ejecuto este código en la consola y funciona!" puedes exclamar dramáticamente. Eso es porque en el momento en que lo ejecutas, mucho después de que el documento termina de cargarse, esos elementos existen.

Por lo tanto, debe esperar a que se agregue este elemento raíz; probable, con otra MutationObserver para hacer el trabajo.

3
Xan

Intenta usar esto con jQuery.

Si está desarrollando una Extensión de Chrome y obtiene un elemento HTML (Nodo) de la página o DOM en content_script , entonces obtendrá Object y Node será devuelto como propiedad del Object. A continuación, puede hacer que el nodo del objeto pase al método observe(Node,config).

Ejemplo

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