7

我正在創建一個Chrome擴展並嘗試在gMail撰寫框的SEND按鈕旁包含一個小文本。'MutationObserver'上'觀察':參數1不是'節點'類型

我正在使用MutationObserver來了解組合框窗口何時出現。我通過觀察類no中的元素來完成此操作,因爲組合框元素是作爲此元素的子元素(類no)創建的。

當用戶點擊撰寫按鈕並出現撰寫框窗口時,我使用.after()方法在發送按鈕旁邊放置一個元素。發送按鈕類名稱是.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" 
    ] 
} 

附:我已經嘗試過插入查詢庫,但它有一些缺點。它沒有讓我對具體元素的變化具體說明。我還沒有嘗試突變總結文庫,但由於它使用了MutationObserver,我認爲這個問題會持續存在。

加入評論:
的確,選擇器沒有給我一個節點。我檢查了控制檯,它提供了一個對象。我也檢查了控制檯,並選擇了我想觀察的適當元素。

但是,當我爲所選元素添加console.log時,它顯示爲未定義。這意味着,在代碼執行之前執行代碼可能是正確的。你能告訴我如何確保延遲發生? 'setTimeout'會工作嗎?在MutationObserver的情況下它如何工作?

+2

錯誤清楚地表明,document.querySelectorAll的'結果(「無」)[2]'不計算爲[節點(https://developer.mozilla.org/en-US/docs/Web/API/Node)。您需要查看頁面的結構以確定如何選擇適當的節點。您的代碼可能/可能在您希望在DOM中找到的節點之前執行。如果是這樣,你需要延遲添加觀察者,直到他們存在(許多方法這樣做)。 – Makyen

+0

請將[問題]置於主題上:包括一個重複問題的**完整** [mcve]。通常包括一個* manifest.json *,一些背景*和*內容腳本。尋求調試幫助的問題(「**爲什麼不是這個代碼工作?」)必須包括:►期望的行爲,►特定問題或錯誤*和*►在問題中重現問題所需的最短代碼**本身**。沒有明確問題陳述的問題對其他讀者無益。請參閱:「**如何創建[mcve] **」,[我可以在此處詢問哪些主題?](http://stackoverflow.com/help/on-topic)和[問]。 – Makyen

+0

謝謝@Makyen我已經添加了清單文件。 確實,選擇器沒有給我一個節點,我檢查了控制檯,它給了一個對象。我也檢查了控制檯,並選擇了我想觀察的適當元素。

但是,當我爲所選元素添加'console.log'時,它的未定義。這意味着,在代碼執行之前執行代碼可能是正確的。你能告訴我如何確保延遲發生? 'setTimeout'會工作嗎?在突變觀察者的情況下它是如何工作的? –

回答

5

正如我在評論中提到的,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中較高的祖先節點,以便插入要放置主觀察者的節點。雖然這會在插入時立即找到合適的節點,但這可能會佔用相當多的資源(CPU),具體取決於您需要觀察DOM的高度以及DOM的變化有多少活動。
+0

好吧..我嘗試了第一種和第二種方式,但不是第三種。 1st - 我認爲你的意思是document_end,因爲document_idle是「run_at」的默認狀態,但無論如何。使用'document_end'整個內容腳本沒有得到執行。 2nd - 它工作,但我現在有一個問題,因爲我正在添加一個元素旁邊的發送按鈕,我使用$(「。SendButtonClass」)。後()'。問題是如果我再打開一個組合框,然後'$(「。SendButtonClass」)。after()'被執行兩次,也是第一個組合框。 感謝您的幫助。 –

+0

只是爲了讓您知道: 我想出了另一種解決方案來添加元素旁邊的發送按鈕,而不使用觀察員。 我正在觀看點擊組合按鈕,並添加一個回調以及setTimeout以進行所需的更改。 –

+0

@geetmehar,我不應該包括#1(現在刪除)。我錯過了 - 當默認實際上是「document_idle」時,將默認值記爲'document_end'。因此,這個建議毫無用處。對不起,浪費你的時間。使用'document_end'不應該阻止你的腳本運行,除非有其他的依賴項在其他地方拋出一個錯誤。爲了診斷你所報告的新問題,我需要看到更多的代碼,它確實應該是一個新問題(鏈接到這個問題的上下文。) – Makyen

3

此錯誤表示document.querySelectorAll(".no")[2]不是Node

這很可能意味着沒有這樣的元素; querySelectorAll將始終返回NodeList,即使它是空的;訪問不存在運行時錯誤的列表中不存在的成員成功,但返回undefined:在這個意義上,NodeList就像一個數組。

「等等,但它確實!我在控制檯上運行這個代碼,它的工作原理!」你可能會驚歎不已。這是因爲在文檔加載完成後很長時間執行它時,這些元素就存在了。

所以,你需要等待這個根元素被添加;可能與另一個MutationObserver來完成這項工作。

+0

感謝@Xan幫助我,你對這個問題是正確的,我現在使用Makyen在其他答案中提出的'setTimeout'對它進行了整理。 供參考:我沒有使用另一個突變觀察者,因爲它是資源密集型事件,雖然比突變事件好,但我認爲肯定比setTimeout多。 再次感謝。 –

0

如果你使用jQuery,把這個代碼

$(document).ready(function(){ // your code }); 
相關問題