코드 기술을 실행하기 전에 페이지가로드되기를 기다리는 사용자 스크립트?


80

Greasemonkey 사용자 스크립트를 작성 중이며 표시하려는 div 카운트를 반환하므로 페이지가 완전히로드되면 특정 코드가 실행되기를 원합니다.

문제는이 특정 페이지가 모든 것이로드되기 전에 때때로 약간의 시간이 걸린다는 것입니다.

나는 시도, 문서 $(function() { });$(window).load(function(){ });래퍼. 그러나 내가 그것들을 잘못 적용 할 수도 있지만 아무도 나를 위해 일하지 않는 것 같습니다.

내가 할 수있는 최선의 방법은 setTimeout(function() { }, 600);작동 하는 a 를 사용하는 것 입니다. 항상 신뢰할 수있는 것은 아닙니다.

페이지로드가 완료 될 때 특정 코드가 실행되도록하기 위해 Greasemonkey에서 사용하는 가장 좋은 기술은 무엇입니까?


3
(function init(){var counter = document.getElementById('id-of-element');if (counter) { /* do something with counter element */ } else { setTimeout(init, 0);}})();요소의 존재를 지속적으로 폴링 하는 데 사용할 수 있습니다 . 이것이 가장 일반적인 솔루션입니다.
Rob W

2
Greasemonkey의 사촌 인 Tampermonkey와 Scriptish 는 사용할 수있는 @run-at값을 포함 document-idle하여 더 많은 값을 지원 context-menu합니다. Greasemonkey는 아직 문서화되지 않았지만 지원추가하고있는 것으로 보입니다 document-idle.
Mr. Llama 2015

나를 위해 일한 @RobW, 감사합니다.
zx81

답변:


71

Greasemonkey (일반적으로)에는 jQuery가 없습니다. 따라서 일반적인 접근 방식은

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

사용자 스크립트 내부


16
jQuery 추가는 @require http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js현재 스크립트에 추가 하는 것만 큼 ​​쉽습니다 . 나는 항상 사용하기 때문에 템플릿 스크립트에 넣었습니다. 또한 this.$ = this.jQuery = jQuery.noConflict(true);일반적인 충돌을 피하십시오.
m3nda

jQuery에 대한 종속성 추가
sleblanc

2
사람들이 왜 모든 것에 jquery를 추가하고 싶어하는지 잘 모르겠습니다.
Wyatt8740

61

이것은 일반적인 문제이며, AJAX가 그 이후에 일을 변경할 수 있고 변경하기 때문에 페이지로드를 기다리는 것만으로는 충분하지 않습니다.

이러한 상황에 대한 표준 (ish) 강력한 유틸리티가 있습니다. 이것의waitForKeyElements() 유틸리티 .

다음과 같이 사용하십시오.

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

보다 구체적인 예를 보려면 타겟 페이지의 정확한 세부 정보를 제공하세요.


대상 페이지에 이미 JQuery가있는 경우 어떻게됩니까? 페이지에 JQuery를로드하면 원래 코드가 손상되지만 GM 스크립트는 JQuery가 실행되기 전에 실행됩니다. 내 시나리오의 특정 페이지는 JQuery 1.7.2를 실행하는 backpack.tf입니다.
Jack

4
@Jack, 스크립트에서 jQuery를 사용하면 페이지에로드되지 않으며 @grant GM_addStyle표시된대로 를 사용할 때 아무것도 손상되지 않습니다 . 그것이 거기에있는 이유입니다.
Brock Adams

코드를 한 번만 실행 true하려면 세 번째 인수로 전달해야합니다.waitForKeyElements
Starwarswii

41

Greasemonkey 3.6 (2015 년 11 월 20 일)부터 메타 데이터 키 @run-at는 새 값을 지원합니다 document-idle. 간단히 Greasemonkey 스크립트의 메타 데이터 블록에 넣으십시오.

// @run-at      document-idle

문서는 다음과 같이 설명합니다 :

스크립트는 페이지와 모든 리소스 (이미지, 스타일 시트 등)가로드되고 페이지 스크립트가 실행 된 후에 실행됩니다.


7
경고. Greasemonkey는 Chrome / Tampermonkey와는 다르게 구현 한 것으로 보입니다. 따라서 스크립트는 브라우저에서 동일하게 작동하지 않을 수 있습니다. waitForKeyElements또는 같은 것을 사용하는 것이 여전히 더 강력합니다 MutationObserver.
Brock Adams

21

Brock의 대답 은 좋지만 더 현대적이고 우아한 AJAX 문제에 대한 또 다른 솔루션을 제공하고 싶습니다. 그의 스크립트는 또한 setInterval()주기적으로 (300ms) 확인 하는 데 사용되기 때문에 즉시 응답 할 수 없습니다.

즉시 응답해야하는 경우을 사용 MutationObserver()하여 DOM 변경을 수신하고 요소가 생성되는 즉시 응답 할 수 있습니다.

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

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

비록 이후 check()모든 DOM 변경시 발생하기 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});

13

내 스크립트를 래핑하는 $(window).load(function(){ })데 실패하지 않았습니다.

페이지가 끝났을 수도 있지만 여전히 일부 ajax 콘텐츠가로드되고 있습니다.

이 경우 Brock Adams 의 멋진 코드 가 도움이 될 수 있습니다.
https://gist.github.com/raw/2625891/waitForKeyElements.js

나는 일반적으로 포스트 백에 나타나는 요소를 모니터링하는 데 사용합니다 .

다음과 같이 사용하십시오. waitForKeyElements("elementtowaitfor", functiontocall)


6

노드 값을 가져 오거나 스타일을 변경하는 것과 같은 노드를 조작하려면이 함수를 사용하여 이러한 노드를 기다릴 수 있습니다.

const waitFor = (...selectors) => new Promise(resolve => {
    const delay = 500
    const f = () => {
        const elements = selectors.map(selector => document.querySelector(selector))
        if (elements.every(element => element != null)) {
            resolve(elements)
        } else {
            setTimeout(f, delay)
        }
    }
    f()
})

그런 다음 사용 promise.then

// scripts don't manipulate nodes
waitFor('video', 'div.sbg', 'div.bbg').then(([video, loading, videoPanel])=>{
    console.log(video, loading, videoPanel)
    // scripts may manipulate these nodes
})

또는 사용 async&await

//this semicolon is needed if none at end of previous line
;(async () => {
    // scripts don't manipulate nodes
    const [video, loading, videoPanel] = await waitFor('video','div.sbg','div.bbg')
    console.log(video, loading, video)
    // scripts may manipulate these nodes
})()

다음은 icourse163_enhance 의 예 입니다.


2

XHR이 웹 페이지에서로드를 완료했는지 감지하기 위해 일부 기능을 트리거합니다. 나는에서이 얻을 내가 크롬에서 콘솔에서 "XHR 완성로드"메시지 저장소에 자바 스크립트를 어떻게 사용합니까? 그리고 그것은 진짜 작동합니다.

    //This overwrites every XHR object's open method with a new function that adds load and error listeners to the XHR request. When the request completes or errors out, the functions have access to the method and url variables that were used with the open method.
    //You can do something more useful with method and url than simply passing them into console.log if you wish.
    ///programming/43282885/how-do-i-use-javascript-to-store-xhr-finished-loading-messages-in-the-console
    (function() {
        var origOpen = XMLHttpRequest.prototype.open;
        XMLHttpRequest.prototype.open = function(method, url) {
            this.addEventListener('load', function() {
                console.log('XHR finished loading', method, url);
                display();
            });

            this.addEventListener('error', function() {
                console.log('XHR errored out', method, url);
            });
            origOpen.apply(this, arguments);
        };
    })();
    function display(){
        //codes to do something;
    }

그러나 페이지에 XHR이 많으면 특정 XHR을 필터링하는 방법을 모릅니다.

또 다른 방법은 waitForKeyElements ()입니다. https://gist.github.com/BrockA/2625891
Greasemonkey 사용을위한 샘플이 있습니다. 같은 페이지에서 Greasemonkey 스크립트를 여러 번 실행 하시겠습니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.