2012-10-15 28 views
38

Tôi đang viết một người dùng Greasemonkey và muốn mã cụ thể thực thi khi trang hoàn tất tải, vì nó trả về số div tôi muốn hiển thị.Greasemonkey - đợi trang tải trước khi thực hiện các kỹ thuật mã

Vấn đề là, trang cụ thể này đôi khi mất một chút trước khi mọi thứ tải.

Tôi đã thử, tài liệu $(function() { });$(window).load(function(){ }); trình bao bọc. Tuy nhiên, dường như không có gì làm việc cho tôi, mặc dù tôi có thể áp dụng chúng sai.

Điều tốt nhất tôi có thể làm là sử dụng setTimeout(function() { }, 600); hoạt động, mặc dù không phải lúc nào cũng đáng tin cậy.

Whats kỹ thuật tốt nhất để sử dụng trong Greasemonkey để đảm bảo mã cụ thể sẽ thực thi khi trang kết thúc tải?

+1

Bạn có thể sử dụng '(hàm init() {var counter = document.getElementById ('id-of-yếu tố'); if (bộ đếm) {/ * làm một cái gì đó với phần tử truy cập * /} else {setTimeout (init, 0);}})(); 'để thăm dò liên tục cho sự tồn tại của phần tử. Đó là giải pháp chung nhất. –

+0

Anh em họ của Greasemonkey, Tampermonkey và Scriptish, hỗ trợ nhiều giá trị ['@ run-at'] (https://tampermonkey.net/documentation.php#_run_at) bao gồm' document-idle' và 'context-menu' có thể là sử dụng. Nó cũng xuất hiện rằng Greasemonkey là [thêm hỗ trợ] (https://github.com/greasemonkey/greasemonkey/issues/2109) cho 'tài liệu-idle' mặc dù nó đã không được tài liệu như được nêu ra. –

Trả lời

42

Greasemonkey (thường) không có jQuery. Vì vậy, phương pháp phổ biến là sử dụng

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

bên UserScript bạn

+8

Thêm jQuery dễ dàng như thêm '@require \t http: // ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js' vào tập lệnh hiện tại của bạn. Tôi đã đặt chúng vào kịch bản mẫu quá cuz tôi sử dụng luôn. Cũng đặt 'this. $ = This.jQuery = jQuery.noConflict (true);' để tránh xung đột điển hình. – erm3nda

+0

Thêm phụ thuộc vào jQuery khi – sleblanc

9

gói kịch bản của tôi trong $(window).load(function(){ }) không bao giờ thất bại cho tôi.

có thể trang của bạn đã hoàn tất, nhưng vẫn còn một số nội dung ajax đang được tải.

nếu đó là trường hợp, mảnh đẹp mã này từ Brock Adams có thể giúp bạn:
https://gist.github.com/raw/2625891/waitForKeyElements.js

tôi thường sử dụng nó để theo dõi cho các yếu tố xuất hiện trên postback.

sử dụng nó như thế này: waitForKeyElements("elementtowaitfor", functiontocall)

31

Đây là một vấn đề phổ biến và, như bạn đã nói, chờ đợi tải trang là không đủ - kể từ AJAX có thể và không thay đổi mọi thứ lâu sau đó.

Có một tiện ích mạnh mẽ chuẩn (ish) cho những tình huống này. Đó là the waitForKeyElements() utility.

Sử dụng nó như vậy:

// ==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 
} 

Nêu chi tiết chính xác của trang mục tiêu của bạn cho một ví dụ cụ thể hơn.

+0

Điều gì xảy ra nếu trang đích đã có JQuery trên đó? Tải JQuery trên trang ngắt mã gốc, nhưng tập lệnh GM của tôi chạy trước khi JQuery chạy. Trang cụ thể cho kịch bản của tôi là backpack.tf, đang chạy JQuery 1.7.2. – Jack

+4

@Jack, Sử dụng jQuery trong tập lệnh không tải nó vào trang, cũng như không phá vỡ bất cứ điều gì khi bạn sử dụng '@grant GM_addStyle' như được hiển thị. Đó là những gì nó có cho. –

10

Kể từ Greasemonkey 3.6 (ngày 20 tháng 11 năm 2015) khóa siêu dữ liệu @run-at hỗ trợ giá trị mới document-idle. một cách đơn giản này trong khối siêu dữ liệu của Greasemonkey script của bạn:

// @run-at  document-idle 

Các documentation mô tả nó như sau:

Các kịch bản sẽ chạy sau trang và mọi nguồn lực (hình ảnh, style sheets, vv .) được tải và các tập lệnh trang đã chạy.

+3

Cảnh báo. Greasemonkey dường như đã thực hiện điều này khác với Chrome/Tampermonkey đã làm. Vì vậy, tập lệnh có thể không hoạt động giống nhau trên các trình duyệt. Nó vẫn còn mạnh mẽ hơn để sử dụng một cái gì đó như 'waitForKeyElements' hoặc' MutationObserver'. –

0

Brock's answer là tốt, nhưng tôi muốn cung cấp giải pháp khác cho vấn đề AJAX, để hoàn chỉnh. Kể từ khi kịch bản của ông cũng sử dụng setInterval() để kiểm tra định kỳ (300ms), nó không thể trả lời ngay lập tức.

Nếu bạn cần phải đáp ứng ngay lập tức, bạn có thể sử dụng MutationObserver() để lắng nghe những thay đổi DOM và trả lời họ càng sớm càng yếu tố được tạo ra

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

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

Mặc dù kể từ check() cháy trên tất cả các thay đổi DOM duy nhất, điều này có thể chậm nếu DOM thay đổi rất thường xuyên hoặc tình trạng của bạn mất nhiều thời gian để đánh giá.

Trường hợp sử dụng khác là nếu bạn không tìm kiếm bất kỳ thành phần cụ thể nào, nhưng chỉ cần đợi trang ngừng thay đổi. Bạn có thể kết hợp điều này với setTimeout() để chờ điều đó.

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 
} 

Phương pháp này rất linh hoạt, bạn cũng có thể nghe các thay đổi về thuộc tính và văn bản. Chỉ cần thiết lập attributescharacterData để true trong các tùy chọn

observer.observe(document, {childList: true, attributes: true, characterData: true, subtree: true}); 
Các vấn đề liên quan