2012-10-15 12 views
38

Sto scrivendo un codice utente Greasemonkey e voglio che un codice specifico venga eseguito quando la pagina completa completamente il caricamento, poiché restituisce un conteggio div che voglio visualizzare.Greasemonkey - attendi che la pagina venga caricata prima di eseguire le tecniche di codice

Il problema è che questa pagina in particolare richiede un po 'prima di caricare tutto.

Ho provato, documento $(function() { }); e wrapper $(window).load(function(){ });. Tuttavia, nessuno sembra funzionare per me, anche se potrei applicarli male.

La cosa migliore che posso fare è usare un setTimeout(function() { }, 600); che funziona, anche se non sempre affidabile.

Qual è la tecnica migliore da utilizzare in Greasemonkey per garantire che il codice specifico venga eseguito al termine del caricamento della pagina?

+1

Si potrebbe utilizzare '(funzione init() {var counter = document.getElementById ('id-di-elemento'); if (contatore) {/ * fare qualcosa con l'elemento contatore * /} else {setTimeout (init, 0);}})(); 'per eseguire continuamente il polling dell'esistenza dell'elemento. Questa è la soluzione più generica. –

+0

I cugini di Greasemonkey, Tampermonkey e Scriptish, supportano più ['@ run-at'] (https://tampermonkey.net/documentation.php#_run_at) valori che includono' document-idle' e 'context-menu' che possono essere d'uso. Sembra inoltre che Greasemonkey stia [aggiungendo supporto] (https://github.com/greasemonkey/greasemonkey/issues/2109) per 'document-idle' sebbene non sia stato ancora documentato. –

risposta

42

Greasemonkey (in genere) non ha jQuery. Quindi l'approccio comune è quello di utilizzare

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

all'interno del vostro userscript

+8

Aggiungi jQuery è semplice come aggiungere '@require \t http: // ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js' al tuo script corrente. Li ho inseriti nello script del modello anche perchè lo uso sempre. Metti anche 'this. $ = This.jQuery = jQuery.noConflict (true);' per evitare conflitti tipici. – erm3nda

+0

Aggiunta di dipendenze su jQuery quando – sleblanc

9

avvolgendo i miei script in $(window).load(function(){ }) mai fallito per me.

forse la tua pagina è finita, ma c'è ancora del contenuto di ajax in fase di caricamento.

se questo è il caso, questo bel pezzo di codice da Brock Adams può aiutare:
https://gist.github.com/raw/2625891/waitForKeyElements.js

io di solito uso per monitorare per gli elementi che appaiono su postback.

uso in questo modo: waitForKeyElements("elementtowaitfor", functiontocall)

31

Questo è un problema comune e, come hai detto, in attesa del caricamento della pagina non è sufficiente - poiché AJAX può e deve cambiare le cose molto tempo dopo.

Esiste un'utilità standard (ish) robusta per queste situazioni. È the waitForKeyElements() utility.

Utilizzare in questo modo:

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

fornire dettagli esatti della vostra pagina di destinazione per un esempio più specifico.

+0

Cosa succede se la pagina di destinazione contiene già JQuery? Il caricamento di JQuery nella pagina interrompe il codice originale, ma il mio script GM viene eseguito prima dell'esecuzione di JQuery. La pagina specifica per il mio scenario è backpack.tf, che esegue JQuery 1.7.2. – Jack

+4

@Jack, L'uso di jQuery nello script non lo carica nella pagina, né si interrompe nulla quando si utilizza '@grant GM_addStyle' come mostrato. Ecco a cosa serve. –

10

A partire da Greasemonkey 3.6 (20 novembre 2015) la chiave dei metadati @run-at supporta il nuovo valore document-idle. In poche parole questo nel blocco di metadati dello script Greasemonkey:

// @run-at  document-idle 

Il documentation descrive come segue:

lo script verrà eseguito dopo che la pagina e tutte le risorse (immagini, fogli di stile, ecc .) sono caricati e gli script di pagina sono stati eseguiti.

+3

Avviso. Greasemonkey sembra averlo implementato diversamente da Chrome/Tampermonkey. Quindi gli script potrebbero non funzionare allo stesso modo su tutti i browser. È ancora più robusto usare qualcosa come "waitForKeyElements" o "MutationObserver". –

0

Brock's answer è buono, ma mi piacerebbe offrire un'altra soluzione al problema AJAX, per completezza. Poiché il suo script usa anche setInterval() per controllare periodicamente (300 ms), non può rispondere istantaneamente.

Se è necessario rispondere immediatamente, è possibile utilizzare MutationObserver() per ascoltare le modifiche DOM e rispondere ad essi, non appena l'elemento viene creato

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

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

Anche se dal check() incendi su ogni singola modifica DOM, questo può essere lento se il DOM cambia molto spesso o la tua condizione richiede molto tempo per essere valutata.

Un altro caso d'uso è se non stai cercando alcun elemento specifico, ma stai solo aspettando che la pagina smetta di cambiare. È possibile combinare questo con setTimeout() per attendere anche quello.

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 
} 

Questo metodo è così versatile, è possibile ascoltare anche le modifiche di attributi e di testo. Basta impostare attributes e characterData a true nelle opzioni

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