2012-10-15 69 views
38

我正在寫一個Greasemonkey的userscript之前加載,並且希望特定的代碼執行時,頁面完全加載完畢,因爲它返回一個div計數我想顯示。的Greasemonkey - 等待頁面被執行代碼技術

問題是,這個特定頁面一切加載之前有時需要一點。

我試過了,文檔$(function() { });$(window).load(function(){ });包裝。然而,似乎沒有人爲我工作,雖然我可能會錯誤地應用它們。

盡我所能做的就是用setTimeout(function() { }, 600);它的工作原理,但並不總是可靠的。

最新最好的技術,在Greasemonkey的使用,以確保特定的代碼,當頁面加載完畢後會執行?

+1

你可以使用'(函數的init(){VAR計數器=的document.getElementById() '元素ID-的 - ';如果(計數器){/ *做其他元素* /} else {setTimeout(init,0);}})();'連續查詢元素的存在。這是最通用的解決方案。 –

+0

Greasemonkey的表兄弟Tampermonkey和Scriptish支持更多['@ run-at'](https://tampermonkey.net/documentation.php#_run_at)值,其中包括'document-idle'和'context-menu',可能是使用。它似乎也是Greasemonkey [添加支持](https://github.com/greasemonkey/greasemonkey/issues/2109)用於'document-idle',儘管它尚未被記錄。 –

回答

42

的Greasemonkey(通常)沒有jQuery的。因此,常用的方法是使用

window.addEventListener('load', function() { 
    // your code here 
}, false); 

您userscript

+8

添加jQuery非常簡單,只需將'@require \t http:// ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js'添加到當前腳本。我把它們放到模板腳本中,因爲我總是使用它。還要把'this。$ = this.jQuery = jQuery.noConflict(true);'以避免典型的衝突。 – erm3nda

+0

當 – sleblanc

9

裏面$(window).load(function(){ })從來沒有爲我包裝我的腳本。

也許你的頁面已經完成,但仍然有一些ajax內容被加載。

,如果是這樣的話,從Brock Adams這個漂亮的代碼都可以幫助您:
https://gist.github.com/raw/2625891/waitForKeyElements.js

我通常用它來監視上回發出現的元素。

使用這樣的:waitForKeyElements("elementtowaitfor", functiontocall)

31

這是一個常見的問題,正如你所說,等待頁面加載是不夠的 - 因爲AJAX能夠和長後,它改變的東西。

沒有爲這些情況標準(ISH)健壯效用。這是the waitForKeyElements() utility

使用它,像這樣:

// ==UserScript== 
// @name  _Wait for delayed or AJAX page load 
// @include http://YOUR_SERVER.COM/YOUR_PATH/* 
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js 
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js 
// @grant GM_addStyle 
// ==/UserScript== 
/*- The @grant directive is needed to work around a major design 
    change introduced in GM 1.0. 
    It restores the sandbox. 
*/ 

waitForKeyElements ("YOUR_jQUERY_SELECTOR", actionFunction); 

function actionFunction (jNode) { 
    //-- DO WHAT YOU WANT TO THE TARGETED ELEMENTS HERE. 
    jNode.css ("background", "yellow"); // example 
} 

給你的目標頁面的具體細節進行更具體的例子。

+0

在jQuery上添加依賴項如果目標頁面上已經有JQuery,該怎麼辦?在頁面上加載JQuery會破壞原始代碼,但是我的GM腳本在JQuery運行之前運行。 我的場景的特定頁面是backpack.tf,它運行JQuery 1.7.2。 – Jack

+4

@Jack,在腳本中使用jQuery不會將其加載到頁面中,也不會在使用'@grant GM_addStyle'時出現任何內容,如圖所示。這就是它的目的。 –

10

自Greasemonkey 3.6(2015年11月20日)起,元數據密鑰@run-at支持新值document-idle。 簡單地說這在你的Greasemonkey腳本的元數據塊:

// @run-at  document-idle 

documentation其描述如下:

腳本的網頁,所有資源後,將運行(圖片,樣式表等)被加載並且頁面腳本已經運行。

+3

警告。 Greasemonkey似乎已經實現了不同於Chrome/Tampermonkey的做法。所以在不同的瀏覽器上,腳本可能不一樣。使用'waitForKeyElements'或'MutationObserver'這樣的函數更健壯。 –

0

Brock's answer很好,但爲了完整性,我想提供另一種AJAX問題的解決方案。由於他的腳本也使用setInterval()定期檢查(300毫秒),因此無法立即響應。

如果你需要立即作出反應,你可以使用MutationObserver(),因爲在每一個DOM的變化,這可能check()火災偵聽DOM的變化,對他們儘快元素創建

迴應
(new MutationObserver(check)).observe(document, {childList: true, subtree: true}); 

function check(changes, observer) { 
    if(document.querySelector('#mySelector')) { 
     observer.disconnect(); 
     // code 
    } 
} 

雖然如果DOM經常變化或者您的狀況需要很長時間才能評估,則速度會變慢。

另一個用例是,如果您不想查找任何特定元素,而只是等待頁面停止更改。你可以將它與setTimeout()結合起來等待。

var observer = new MutationObserver(resetTimer); 
var timer = setTimeout(action, 3000, observer); // wait for the page to stay still for 3 seconds 
observer.observe(document, {childList: true, subtree: true}); 

function resetTimer(changes, observer) { 
    clearTimeout(timer); 
    timer = setTimeout(action, 3000, observer); 
} 

function action(o) { 
    o.disconnect(); 
    // code 
} 

這種方法是如此多才多藝,你可以聽的屬性和文本也會改變。只需在選項中設置attributescharacterDatatrue

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