Program Club

window.location.href 변경시 이벤트

proclub 2020. 12. 11. 18:59
반응형

window.location.href 변경시 이벤트


어느 시점에서 수정하는 사이트에 대한 Greasemonkey 스크립트를 작성 중 location.href입니다.

페이지 window.addEventListenerwindow.location.href변경 될 때 어떻게 이벤트를받을 수 있습니까 ( 또는 이와 유사한 것을 통해 ) ? 또한 새 / 수정 된 URL을 가리키는 문서의 DOM에 액세스해야합니다.

시간 초과 및 폴링과 관련된 다른 솔루션을 보았지만 가능하면 피하고 싶습니다.


popstate 이벤트 :

popstate 이벤트는 활성 히스토리 항목이 변경 될 때 시작됩니다. [...] popstate 이벤트는 뒤로 버튼을 클릭하거나 JavaScript에서 history.back ()을 호출하는 것과 같은 브라우저 작업을 수행해야만 트리거됩니다.

따라서 popstate이벤트를 수신하고 popstate사용할 때 이벤트를 보내는 history.pushState()것만으로도 href변경 조치를 취할 수 있습니다.

window.addEventListener('popstate', listener);

const pushUrl = (href) => {
  history.pushState({}, '', href);
  window.dispatchEvent(new Event('popstate'));
};

폴링을 피할 수 없으며 href 변경에 대한 이벤트가 없습니다.

배 밖으로 나가지 않으면 간격을 사용하는 것은 어쨌든 매우 가볍습니다. 50ms 정도마다 href를 확인하는 것이 걱정된다면 성능에 큰 영향을 미치지 않습니다.


내 확장 프로그램 "Grab Any Media"에서이 스크립트를 사용하고 잘 작동합니다 ( 예 : youtube case )

var oldHref = document.location.href;

window.onload = function() {

    var
         bodyList = document.querySelector("body")

        ,observer = new MutationObserver(function(mutations) {

            mutations.forEach(function(mutation) {

                if (oldHref != document.location.href) {

                    oldHref = document.location.href;

                    /* Changed ! your code here */

                }

            });

        });

    var config = {
        childList: true,
        subtree: true
    };

    observer.observe(bodyList, config);

};

onhashchange사용할 수 있는 기본 이벤트가 있습니다.

여기에 문서화

다음과 같이 사용할 수 있습니다.

function locationHashChanged( e ) {
    console.log( location.hash );
    console.log( e.oldURL, e.newURL );
    if ( location.hash === "#pageX" ) {
        pageX();
    }
}

window.onhashchange = locationHashChanged;

브라우저가 지원하지 않는 경우 oldURL그리고 newURL당신은 이런 식으로 바인딩 할 수 있습니다 :

//let this snippet run before your hashChange event binding code
if( !window.HashChangeEvent )( function() {
    let lastURL = document.URL;
    window.addEventListener( "hashchange", function( event ) {
        Object.defineProperty( event, "oldURL", { enumerable: true, configurable: true, value: lastURL } );
        Object.defineProperty( event, "newURL", { enumerable: true, configurable: true, value: document.URL } );
        lastURL = document.URL;
    } );
} () );

전에 시도해 보셨습니까? 이 이벤트는 페이지가 탐색 요청에 응답하기 직전에 발생하며 여기에는 href의 수정이 포함되어야합니다.

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
    <HTML>
    <HEAD>
    <TITLE></TITLE>
    <META NAME="Generator" CONTENT="TextPad 4.6">
    <META NAME="Author" CONTENT="?">
    <META NAME="Keywords" CONTENT="?">
    <META NAME="Description" CONTENT="?">
    </HEAD>

         <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
            <script type="text/javascript">
            $(document).ready(function(){
                $(window).unload(
                        function(event) {
                            alert("navigating");
                        }
                );
                $("#theButton").click(
                    function(event){
                        alert("Starting navigation");
                        window.location.href = "http://www.bbc.co.uk";
                    }
                );

            });
            </script>


    <BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">

        <button id="theButton">Click to navigate</button>

        <a href="http://www.google.co.uk"> Google</a>
    </BODY>
    </HTML>

Beware, however, that your event will fire whenever you navigate away from the page, whether this is because of the script, or somebody clicking on a link. Your real challenge, is detecting the different reasons for the event being fired. (If this is important to your logic)


Through Jquery, just try

$(window).on('beforeunload', function () {
    //your code goes here on location change 
});

By using javascript:

window.addEventListener("beforeunload", function (event) {
   //your code goes here on location change 
});

Refer Document : https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload


Well there is 2 ways to change the location.href. Either you can write location.href = "y.html", which reloads the page or can use the history API which does not reload the page. I experimented with the first a lot recently.

If you open a child window and capture the load of the child page from the parent window, then different browsers behave very differently. The only thing that is common, that they remove the old document and add a new one, so for example adding readystatechange or load event handlers to the old document does not have any effect. Most of the browsers remove the event handlers from the window object too, the only exception is Firefox. In Chrome with Karma runner and in Firefox you can capture the new document in the loading readyState if you use unload + next tick. So you can add for example a load event handler or a readystatechange event handler or just log that the browser is loading a page with a new URI. In Chrome with manual testing (probably GreaseMonkey too) and in Opera, PhantomJS, IE10, IE11 you cannot capture the new document in the loading state. In those browsers the unload + next tick calls the callback a few hundred msecs later than the load event of the page fires. The delay is typically 100 to 300 msecs, but opera simetime makes a 750 msec delay for next tick, which is scary. So if you want a consistent result in all browsers, then you do what you want to after the load event, but there is no guarantee the location won't be overridden before that.

var uuid = "win." + Math.random();
var timeOrigin = new Date();
var win = window.open("about:blank", uuid, "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes");


var callBacks = [];
var uglyHax = function (){
    var done = function (){
        uglyHax();
        callBacks.forEach(function (cb){
            cb();
        });
    };
    win.addEventListener("unload", function unloadListener(){
        win.removeEventListener("unload", unloadListener); // Firefox remembers, other browsers don't
        setTimeout(function (){
            // IE10, IE11, Opera, PhantomJS, Chrome has a complete new document at this point
            // Chrome on Karma, Firefox has a loading new document at this point
            win.document.readyState; // IE10 and IE11 sometimes fails if I don't access it twice, idk. how or why
            if (win.document.readyState === "complete")
                done();
            else
                win.addEventListener("load", function (){
                    setTimeout(done, 0);
                });
        }, 0);
    });
};
uglyHax();


callBacks.push(function (){
    console.log("cb", win.location.href, win.document.readyState);
    if (win.location.href !== "http://localhost:4444/y.html")
        win.location.href = "http://localhost:4444/y.html";
    else
        console.log("done");
});
win.location.href = "http://localhost:4444/x.html";

If you run your script only in Firefox, then you can use a simplified version and capture the document in a loading state, so for example a script on the loaded page cannot navigate away before you log the URI change:

var uuid = "win." + Math.random();
var timeOrigin = new Date();
var win = window.open("about:blank", uuid, "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes");


var callBacks = [];
win.addEventListener("unload", function unloadListener(){
    setTimeout(function (){
        callBacks.forEach(function (cb){
            cb();
        });
    }, 0);
});


callBacks.push(function (){
    console.log("cb", win.location.href, win.document.readyState);
    // be aware that the page is in loading readyState, 
    // so if you rewrite the location here, the actual page will be never loaded, just the new one
    if (win.location.href !== "http://localhost:4444/y.html")
        win.location.href = "http://localhost:4444/y.html";
    else
        console.log("done");
});
win.location.href = "http://localhost:4444/x.html";

If we are talking about single page applications which change the hash part of the URI, or use the history API, then you can use the hashchange and the popstate events of the window respectively. Those can capture even if you move in history back and forward until you stay on the same page. The document does not changes by those and the page is not really reloaded.

참고URL : https://stackoverflow.com/questions/3522090/event-when-window-location-href-changes

반응형