ti-enxame.com

'observe' em 'MutationObserver': o O parâmetro 1 não é do tipo 'Node'

Estou criando uma extensão do Chrome e tentando incluir um pequeno texto ao lado do botão SEND da caixa de composição do gMail.

Eu estou usando um MutationObserver para saber quando a janela da caixa de composição aparece. Eu estou fazendo isso observando um elemento com a classe no, pois o elemento da caixa de composição é criado como filho desse elemento (classe no).

Quando o usuário clica no botão de composição e a janela da caixa de composição é exibida, eu coloco um elemento ao lado do botão ENVIAR usando o método .after(). O nome da classe do botão ENVIAR é .gU.Up.

Estes são os nomes reais de classe do gMail e bastante estranhos também.

Abaixo está o código que estou 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);

O problema é que eu constantemente recebo o seguinte erro:

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

Alguém pode ajudar? Eu tentei algumas coisas e também olhei para outras respostas aqui, mas ainda sou incapaz de me livrar desse erro.

Aqui está meu 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" 
    ]
}

P.S. Eu já tentei a biblioteca de inserção, mas tem algumas deficiências. Não me deixa ser específico quanto às mudanças no elemento específico. Ainda estou para tentar a biblioteca mutationsummary, mas desde que ele usa o MutationObserver, percebi que o problema persistirá.

Adicionado do comentário:
É verdade que o seletor não está me dando um nó. Eu verifiquei no console, está dando um objeto. Eu também verifiquei no console e está selecionando o elemento apropriado que eu quero ser observado. 

No entanto, quando eu adiciono console.log para o elemento selecionado, ele é mostrado como indefinido. O que significa que você provavelmente está certo sobre a execução de código antes da criação dos nós. Você pode me dizer como garantir que o atraso aconteça? o trabalho de 'setTimeout'? Como funciona no caso do MutationObserver?

12
geet mehar

Como mencionei em um comentário, e Xan afirmou uma resposta, o erro deixa claro que o resultado de document.querySelectorAll(".no")[2] não é avaliado como um Node

A partir das informações fornecidas em um comentário, fica claro que o problema é que o nó que você deseja observar não existe quando seu código é executado. Há muitas maneiras de atrasar a execução do seu código até que esse nó esteja disponível. Algumas possibilidades são:

  1. Usando um loop setTimeout para pesquisar até detectar que o elemento no qual você deseja colocar o MutationObserver está disponível:

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

    Isto irá encontrar o nó apropriado relativamente pouco depois de existir no DOM. A viabilidade desse método depende de quanto tempo após a inserção do nó de destino você precisa que o observador seja colocado nele. Obviamente, você pode ajustar o atraso entre as tentativas de pesquisa com base nas suas necessidades.

  2. Crie outro MutationObserver para observar um nó ancestral mais alto no DOM para a inserção do nó no qual você deseja colocar seu observador principal. Enquanto isso vai encontrar o nó apropriado imediatamente quando ele é inserido, pode ser bastante recurso (CPU) intensivo, dependendo de quão alto no DOM você tem que observar e quanta atividade existe com relação às alterações do DOM.
13
Makyen

Este erro significa que document.querySelectorAll(".no")[2] não é um Node.

Muito provavelmente isso significa que não existe tal elemento; querySelectorAll sempre retornará um NodeList, mesmo que esteja vazio; acessar membros inexistentes da lista é bem-sucedido sem um erro de tempo de execução, mas retorna undefined: nesse sentido, NodeList age como uma matriz.

"Espere, mas funciona! Eu corro este código no console e funciona!" você pode exclamar dramaticamente. Isso porque, no momento em que você o executa, muito depois de o documento terminar de carregar, esses elementos existem.

Então, você precisa esperar que este elemento raiz seja adicionado; provavelmente, com outro MutationObserver para fazer o trabalho.

3
Xan

Tente usar isso com jQuery.

Se você estiver desenvolvendo uma extensão do Google Chrome e estiver obtendo o elemento HTML (nó) da página ou DOM no content_script , você receberá Object e Node será retornado como propriedade do objeto. Você pode então obter o nó do objeto para passar para o método observe(Node,config).

Exemplo

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