137 votes

Le script utilisateur doit attendre le chargement de la page avant d'exécuter le code technique ?

J'écris un utilisateur Greasemonkey script, et je veux que le code spécifique s'exécute lorsque la page finit complètement de se charger, car il renvoie un compte div que je veux afficher.

Le problème est que cette page particulière prend parfois un peu de temps avant que tout ne se charge.

J'ai essayé, document $(function() { }); y $(window).load(function(){ }); enveloppes. Cependant, aucun d'entre eux ne semble fonctionner pour moi, même si je les applique peut-être mal.

Le mieux que je puisse faire est d'utiliser un setTimeout(function() { }, 600); qui fonctionne, même si elle n'est pas toujours fiable.

Quelle est la meilleure technique à utiliser dans Greasemonkey pour s'assurer que le code spécifique sera exécuté à la fin du chargement de la page ?

115voto

devnull69 Points 6702

Greasemonkey ne dispose (généralement) pas de jQuery. L'approche commune consiste donc à utiliser

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

dans votre script utilisateur

81voto

Brock Adams Points 36841

C'est un problème courant et, comme vous l'avez dit, il ne suffit pas d'attendre le chargement de la page, car AJAX peut modifier les choses bien après.

Il existe un utilitaire standard (ou presque) robuste pour ces situations. Il s'agit de le site waitForKeyElements() utilitaire .

Utilisez-le comme ça :

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

Donnez les détails exacts de votre page cible pour un exemple plus spécifique.

69voto

goweon Points 584

La réponse de Brock c'est bien, mais j'aimerais proposer une autre solution au problème AJAX qui est plus moderne et plus élégante.

Puisque son script, comme la plupart des autres, utilise aussi setInterval() pour vérifier périodiquement (300ms), il ne peut pas répondre instantanément et il y a toujours un délai. D'autres solutions utilisent les événements onload, qui se déclenchent souvent plus tôt que prévu sur les pages dynamiques.

Vous pouvez utiliser MutationObserver() pour écouter les changements du DOM et y répondre dès que l'élément est créé

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

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

Bien que depuis check() se déclenche à chaque changement du DOM, ce qui peut être lent si le DOM change très souvent ou si votre condition prend beaucoup de temps à être évaluée, donc au lieu d'observer document Dans le cas de l'utilisation d'un DOM, on essaie de limiter la portée en observant un sous-arbre DOM aussi petit que possible.

Cette méthode est très générale et peut être appliquée à de nombreuses situations. Pour répondre plusieurs fois, il suffit de ne pas déconnecter l'observateur lorsqu'il est déclenché.

Un autre cas d'utilisation est que si vous ne recherchez pas un élément spécifique, mais attendez simplement que la page cesse de changer, vous pouvez combiner cela avec une minuterie.

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});

// reset timer every time something changes
function resetTimer(changes, observer) {
    clearTimeout(timer);
    timer = setTimeout(action, 3000, observer);
}

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

Cette méthode est si polyvalente que vous pouvez également écouter les changements d'attributs et de texte. Il suffit de définir attributes y characterData a true dans les options

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

61voto

Leviathan Points 1620

À partir de Greasemonkey 3.6 (20 novembre 2015), la clé de métadonnées @run-at supporte la nouvelle valeur document-idle . Il suffit de mettre ceci dans le bloc de métadonnées de votre script Greasemonkey :

// @run-at      document-idle

El documentation le décrit comme suit :

Le script sera exécuté après le chargement de la page et de toutes les ressources (images, feuilles de style, etc.) et l'exécution des script de la page.

16voto

RASG Points 2768

En enveloppant mes scripts dans des $(window).load(function(){ }) n'a jamais échoué pour moi.

peut-être que votre page est terminée, mais il y a encore du contenu ajax en cours de chargement.

si c'est le cas, ce joli morceau de code de Brock Adams peut vous aider :
https://gist.github.com/raw/2625891/waitForKeyElements.js

Je l'utilise généralement pour surveiller les éléments qui apparaissent sur le site. postback .

Utilisez-le comme ceci : waitForKeyElements("elementtowaitfor", functiontocall)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X