2013-07-27 50 views
9

我正在創建Google Chrome擴展程序,並且需要檢測頁面標題何時更改。該頁面的標題會在Twitter中更改:(num) Twitter(請參閱下面的屏幕截圖) - 發佈新推文時,數字會增加。例如:如何使用擴展程序檢測Google Chrome中的頁面標題更改?

enter image description here

我試圖發現那是我其中一個標籤加載的URL的標題的變化和播放蜂鳴聲,每當有區別。此檢查將在重複的時間間隔內完成,我認爲可以使用setTimeOut()函數完成。

我創建了一個manifest.json如下:

{ 
    "manifest_version": 2, 

    "name": "Detect Page Title Changes", 
    "description": "Blah", 
    "version": "1.0", 

    "browser_action": { 
    "default_icon": "icon.png", 
    "default_popup": "background.html" 
    }, 
    "permissions": [ 
    "tabs" 
    ] 
} 

不過,我茫然不知休息。我已經通過文檔搜索12並嘗試類似堆棧溢出線程的解決方案,如this one我但找不到符合我的要求的任何內容。

你有什麼建議嗎?請儘可能包含一個示例。

+0

如果您正在投票,您是否需要事件?你不能只存儲最後一個標籤標題,並將其與當前的比較? – nrabinowitz

+0

我認爲使用事件(如果有的話)是個好主意。但是,如果沒有一個,你的想法也可以使用。 –

+0

我對倒計時感到困惑;如果他/她認爲這是一個無用的和/或不正確的迴應,那麼我可以改善它:) –

回答

16

相反的意見主張一定的方法更好,讓我更有建設性,並以展示添加回答的​​我合寫我自己,並解釋你可能會遇到的一些陷阱成。 代碼片段是指與Twitter不同的服務,但目標相同。事實上,此代碼的目標是報告未讀郵件的確切數量,因此您的郵件可能會更簡單。

我的方法是基於an answer這裏SO,和而不是被輪詢驅動(檢查以固定間隔條件)是事件驅動(在狀態通知的電勢變化)。

優點包括立即檢測到變化(否則在下一次輪詢之前不會檢測到),並且在條件沒有改變時不浪費輪詢資源。無可否認,第二個論點在這裏幾乎不適用,但第一個論點依然存在。


架構一目瞭然:

  1. 注入內容腳本到相關頁面。

  2. 分析標題的初始狀態,通過sendMessage報告到背景頁面。

  3. 註冊標題更改事件的處理程序。

  4. 每當事件觸發且處理程序被調用時,分析標題的新狀態,通過sendMessage報告到背景頁面。


已經步驟1具有疑難雜症到它。普通內容腳本注入機制在清單中定義內容腳本時,會在導航到與URL匹配的頁面時將其注入到頁面中。

"content_scripts": [ 
    { 
    "matches": [ 
     "*://theoldreader.com/*" 
    ], 
    "js": ["observer.js"], 
    "run_at": "document_idle" 
    } 
] 

這工作得很好,直到你的擴展重新加載。這可能會在開發中發生,因爲您正在應用所做的更改,或者在部署實例中進行自動更新。然後會發生什麼情況是內容腳本而不是重新注入現有的打開頁面(直到導航發生,如重新加載)。因此,如果你依賴於基於清單注射,你也應該考慮包括程序注入到已經打開的標籤時擴展初始化:

function startupInject() { 
    chrome.tabs.query(
    {url: "*://theoldreader.com/*"}, 
    function (tabs) { 
     for (var i in tabs) { 
     chrome.tabs.executeScript(tabs[i].id, {file: "observer.js"}); 
     } 
    } 
); 
} 

在另一端,是活躍在延長的時間內容的腳本實例重新加載沒有終止,但是是孤立的:任何sendMessage或類似的請求將失敗。正是因此,建議嘗試與父擴展交流時,經常檢查異常,並自終止(刪除處理),如果失敗的話:

try { 
    chrome.runtime.sendMessage({'count' : count}); 
} catch(e) { // Happens when parent extension is no longer available or was reloaded 
    console.warn("Could not communicate with parent extension, deregistering observer"); 
    observer.disconnect(); 
} 

第2步也有一個疑難雜症到它,但它取決於您正在觀看的服務的具體情況。內容腳本範圍內的某些頁面不會顯示未讀項目的數量,但這並不意味着沒有新消息。

在觀察Web服務的工作方式之後,我得出結論,如果標題在沒有導航的情況下更改爲某些內容,則可以安全地假設新值是正確的,但對於初始標題「不應該新項目」應該被忽略爲不可靠。

因此,分析代碼佔它是否初始讀數或處理的更新:

function notify(title, changed) { 
    // ... 
    var match = /^\((\d+)\)/.exec(title); 
    var match_zero = /^The Old Reader$/.exec(title); 

    if (match && match[1]) { 
    count = match[1]; 
    } else if (match_zero && changed) { 
    count = 0; 
    } 
    // else, consider that we don't know the count 
    //... 
} 

這就是所謂的與最初的標題和在步驟2中changed = false


步驟3 & 4是主要回答「如何監視標題的變化」(在事件驅動方式)。

var target = document.querySelector('head > title'); 

var observer = new window.MutationObserver(
    function(mutations) { 
    mutations.forEach(
     function(mutation){ 
     notify(mutation.target.textContent, true); 
     } 
    ); 
    } 
); 

observer.observe(target, { subtree: true, characterData: true, childList: true }); 

對於具體爲何的observer.observe某些選項被設置,看到original answer

注意notify調用與changed = true,從「(1)老讀者」到「老讀者」那麼回事沒有導航被認爲是零個未讀郵件「真」的變化。

+0

@AmalMurali'observer.js'幾乎可以,因爲它只是修改網址和標題匹配模式以適合您的網絡服務。現在忘了關於'storage.js'以及選項頁如何工作,將它們刪除,並且可以丟棄大部分處理除''以外的內容的背景代碼('background.js'和'functions.js') onMessage'。剩下的 - 你需要實現自己的邏輯來處理報告計數,並調整'manifest.json'。這是一個起點,祝你好運。 – Xan

+1

不錯的答案,一個建議:使用前綴「window.MutationObserver」。您只需要添加'window.MutationObserver = window.MutationObserver || window.WebKitMutationObserver;'如果您想要支持Chrome 26或更低版本,但考慮到[Chrome網上應用店現在拒絕在Chrome 30或更早版本中安裝擴展程序]( https://code.google.com/p/chromium/issues/detail?id=377278),你只需使用前置API就可以。 –

+0

@RobW很好的接收。事實上,我注意到了它,並將其固定在了代碼庫中,然後在這裏忘記更新。 – Xan

7

研究Chrome的標籤API後,它看起來並不像什麼脫穎而出,直接幫助你。但是,您應該能夠將事件偵聽器附加到您感興趣的選項卡的標題節點.DOMSubtreeModified突變事件適用於Chrome,並且在正常的html文檔中進行快速測試證明對我很有用 - 應該與擴展內部沒有區別。

var title = document.getElementsByTagName('title')[0]; 

if (title) { 
    title.addEventListener('DOMSubtreeModified', function (e) { 
     // title changed 
    }, false); 
} 

+1

這是一個古老的答案;此後,'DOMSubtreeModified'事件被視爲棄用。 – Xan

5

chrome.tabs.onUpdated.addListener在你的背景腳本:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { 
    console.log(changeInfo); 
}); 

changeInfo是一個對象,它包括標題的變化,例如在這裏:

Screenshot of changeInfo object in console

然後可以在對象上進行過濾,這樣,如果changeInfo包括標題變化的作用只發生。對於額外的操作,例如通過頁面內容/操作響應頁面標題更改,可以在滿足任何條件後,從監聽器內部向內容腳本發送消息。

+2

這是迄今爲止最好的答案。非常低估。 –

+0

解決了我的問題 –

相關問題