ある時点でlocation.href
を変更するサイトのGreasemonkeyスクリプトを書いています。
window.addEventListener
がページ上で変更されたときに、(window.location.href
または類似のものを介して)イベントを取得するにはどうすればよいですか?また、新しい/変更されたURLを指すドキュメントのDOMへのアクセスも必要です。
私はタイムアウトとポーリングを含む他のソリューションを見てきましたが、可能であればそれを避けたいです。
アクティブな履歴エントリが変更されると、popstateイベントが発生します。 [...] popstateイベントは、戻るボタンのクリック(またはJavaScriptのhistory.back()の呼び出し)などのブラウザーアクションを実行することによってのみトリガーされます。
したがって、history.pushState()
を使用しているときにpopstate
イベントをリッスンし、popstate
イベントを送信するだけで、href
変更に対してアクションを実行できます。
window.addEventListener('popstate', listener);
const pushUrl = (href) => {
history.pushState({}, '', href);
window.dispatchEvent(new Event('popstate'));
};
ポーリングを避けることはできません。hrefを変更するイベントはありません。
とにかく、船外に出ない限り、インターバルの使用は非常に軽いです。 50msごとにhrefを確認しても、心配していればパフォーマンスに大きな影響はありません。
拡張機能「任意のメディアを取得」でこのスクリプトを使用し、正常に動作します(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>
ただし、スクリプトが原因であるか、誰かがクリックしたかどうかにかかわらず、ページから離れるたびにevereが発生することに注意してくださいリンク。あなたの本当の課題は、発生するイベントのさまざまな理由を検出することです。 (これがロジックにとって重要な場合)
Jqueryを通じて、試してみてください
$(window).on('beforeunload', function () {
//your code goes here on location change
});
javascriptを使用して:
window.addEventListener("beforeunload", function (event) {
//your code goes here on location change
});
参照ドキュメント: https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
location.href
を変更するには2つの方法があります。ページをリロードするlocation.href = "y.html"
を記述するか、ページをリロードしない履歴APIを使用できます。最近、最初の実験をたくさんしました。
子ウィンドウを開いて、親ウィンドウから子ページのロードをキャプチャする場合、ブラウザごとに動作が大きく異なります。唯一一般的なのは、古いドキュメントを削除して新しいドキュメントを追加することです。したがって、たとえば、readystatechangeやloadイベントハンドラーを古いドキュメントに追加しても効果はありません。ほとんどのブラウザは、ウィンドウオブジェクトからイベントハンドラも削除します。唯一の例外はFirefoxです。 Karmaランナーを使用するChromeおよびFirefoxでは、unload + next tick
を使用すると、読み込み中のreadyStateで新しいドキュメントをキャプチャできます。そのため、たとえば、ロードイベントハンドラーまたはreadystatechangeイベントハンドラーを追加したり、ブラウザーが新しいURIでページをロードしていることをログに記録したりできます。手動テストによるChrome(おそらくGreaseMonkeyも)およびOpera、PhantomJS、IE10、IE11では、読み込み中の状態で新しいドキュメントをキャプチャできません。これらのブラウザでは、unload + next tick
はページのloadイベントが発生する数百ミリ秒後にコールバックを呼び出します。遅延は通常100〜300ミリ秒ですが、opera simetimeは次のティックで750ミリ秒の遅延を生じます。これは恐ろしいことです。したがって、すべてのブラウザーで一貫した結果が必要な場合は、loadイベントの後に必要な処理を行いますが、その前に場所が上書きされないという保証はありません。
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";
Firefoxでのみスクリプトを実行する場合は、簡略化されたバージョンを使用して、ドキュメントを読み込み状態でキャプチャできるため、たとえば、読み込まれたページのスクリプトは、URIの変更を記録するまで移動できません。
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";
URIのハッシュ部分を変更する、または履歴APIを使用する単一ページアプリケーションについて話している場合は、ウィンドウのhashchange
およびpopstate
イベントをそれぞれ使用できます。これらは、同じページにとどまるまで履歴を前後に移動してもキャプチャできます。ドキュメントはそれらによって変更されず、ページは実際にはリロードされません。