2012-10-15 15 views
38

Piszę o usercriptie Greasemonkey i chcę, aby określony kod był wykonywany po całkowitym zakończeniu ładowania strony, ponieważ zwraca ona liczbę div, którą chcę wyświetlić.Greasemonkey - poczekaj na załadowanie strony przed wykonaniem technik kodu

Problem polega na tym, że ta strona czasami zajmuje trochę czasu, zanim wszystko się załaduje.

Próbowałem, dokumentów $(function() { }); i $(window).load(function(){ }); owijki. Jednak żadna nie wydaje się działać dla mnie, chociaż mógłbym niewłaściwie je zastosować.

Najlepsze co mogę zrobić, to użyć setTimeout(function() { }, 600);, który działa, ale nie zawsze jest niezawodny.

Jaką technikę najlepiej zastosować w Greasemonkey, aby zapewnić, że określony kod zostanie wykonany po zakończeniu ładowania strony?

+1

Można użyć '(function init() {var licznik = document.getElementById ('id-of-elementu'); if (licznik) {/ * zrobić coś z elementem licznika * /} else {setTimeout (init, 0);}})(); 'aby nieustannie odpytywać o istnienie elementu. To najbardziej ogólne rozwiązanie. –

+0

kuzyni Greasemonkey, w Tampermonkey Scriptish, wsparcia i więcej [ '@-at' uruchomić] (https://tampermonkey.net/documentation.php#_run_at) wartości, które zawierają' dokumentu idle' i 'menu' kontekstowe, które mogą być użytkowania. Wygląda również na to, że Greasemonkey jest [dodając wsparcie] (https://github.com/greasemonkey/greasemonkey/issues/2109) dla "bezczynności dokumentu", chociaż nie zostało to jeszcze udokumentowane. –

Odpowiedz

42

Greasemonkey (zwykle) nie ma jQuery. Tak więc wspólne podejście jest użycie

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

wewnątrz userscript

+8

Dodaj jQuery jest tak proste, jak dodać '@require \t http: // ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js' do bieżącego skryptu. Umieściłem je również w szablonie, bo zawsze używam. Należy również umieścić 'this. $ = This.jQuery = jQuery.noConflict (true);' aby uniknąć typowych konfliktów. – erm3nda

+0

Dodawanie zależności od jQuery gdy – sleblanc

9

owijając moje skrypty w $(window).load(function(){ }) nie powiodło się dla mnie.

Być może Twoja strona została zakończona, ale wciąż jest załadowana zawartość ajax.

jeśli tak jest, to ładny kawałek kodu z Brock Adams może pomóc:
https://gist.github.com/raw/2625891/waitForKeyElements.js

Zwykle używam go do monitorowania elementów, które pojawia się na odświeżenie.

wykorzystanie go tak: waitForKeyElements("elementtowaitfor", functiontocall)

31

Jest to powszechny problem i, jak pan powiedział, czekając na stronie obciążenia nie wystarczy - ponieważ AJAX i nie może zmienić ten stan rzeczy długo po tym.

Istnieje standardowe (ish) niezawodne narzędzie do takich sytuacji. To jest the waitForKeyElements() utility.

Używaj go tak:

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

Daj dokładne szczegóły na stronie docelowej na bardziej konkretnym przykładzie.

+0

Co jeśli strona docelowa ma już JQuery? Ładowanie JQuery na stronie łamie oryginalny kod, ale mój skrypt GM działa przed uruchomieniem JQuery. Określoną stroną dla mojego scenariusza jest plecak.tf, na którym działa JQuery 1.7.2. – Jack

+4

@Jack, Użycie jQuery w skrypcie nie powoduje wczytania go na stronę ani złamania czegokolwiek podczas korzystania z '@grant GM_addStyle', jak pokazano. Po to tam jest. –

10

Od Greasemonkey 3.6 (20 listopada 2015 r.) Klucz metadanych @run-at obsługuje nową wartość document-idle. Wystarczy umieścić to w bloku metadanych swojego skryptów Greasemonkey:

// @run-at  document-idle 

documentation opisuje go następująco:

skrypt zostanie uruchomiony po stronie i wszystkich zasobów (obrazy, arkusze stylów, itp .) są ładowane, a skrypty strony zostały uruchomione.

+3

Ostrzeżenie. Wydaje się, że Greasemonkey wdrożył to inaczej niż zrobił to Chrome/Tampermonkey. Skrypty mogą więc nie działać tak samo w różnych przeglądarkach. Wciąż bardziej niezawodne jest użycie czegoś takiego jak 'waitForKeyElements' lub' MutationObserver'. –

0

Brock's answer jest dobry, ale chciałbym zaoferować inne rozwiązanie problemu AJAX, dla kompletności. Ponieważ jego skrypt używa również setInterval() do okresowego sprawdzania (300 ms), nie może natychmiast reagować.

Jeśli trzeba natychmiast reagować, można użyć MutationObserver() do nasłuchiwania zmian DOM i odpowiedzieć na nie najszybciej jak to element jest tworzony

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

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

choć od check() pożarów na każdej zmianie DOM, może to być powolnym, jeśli DOM zmienia się bardzo często lub twój stan zajmuje dużo czasu, aby ocenić.

Kolejny przypadek użycia jest, jeśli nie szukasz konkretnego elementu, ale czekają na stronę, aby zatrzymać się zmienia. Możesz połączyć to z setTimeout(), aby również na to poczekać.

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 
} 

Ta metoda jest na tyle uniwersalna, że ​​można nasłuchiwać zmian atrybutów i tekstu. Wystarczy ustawić attributes i characterData do true w opcjach

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