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

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

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

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

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

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



답변

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

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

사용자 스크립트 내부


답변

이것은 일반적인 문제이며, 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
}

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


답변

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

// @run-at      document-idle

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

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


답변

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


답변

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

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

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

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

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


답변

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

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 의 예 입니다.


답변

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 스크립트를 여러 번 실행 하시겠습니까?