J'écris un script Greasemonkey pour un site qui modifie à un moment donné location.href
.
Comment puis-je obtenir un événement (via window.addEventListener
ou quelque chose de similaire) quand window.location.href
changements sur une page? J'ai également besoin d'accéder au DOM du document pointant sur l'URL nouvelle/modifiée.
J'ai déjà vu d'autres solutions qui impliquent des délais d'attente et des scrutations, mais j'aimerais éviter cela si possible.
L'événement popstate est déclenché lorsque l'entrée d'historique active est modifiée. [...] L'événement popstate est uniquement déclenché par une action du navigateur, telle qu'un clic sur le bouton Précédent (ou l'appel de history.back () en JavaScript).
Donc, écouter popstate
événement et envoyer un événement popstate
lorsque vous utilisez history.pushState()
devrait suffire à agir sur href
change:
window.addEventListener('popstate', listener);
const pushUrl = (href) => {
history.pushState({}, '', href);
window.dispatchEvent(new Event('popstate'));
};
Vous ne pouvez pas éviter les scrutations, il n'y a pas d'événement pour changer href.
De toute façon, utiliser des intervalles est assez léger si vous n'allez pas trop loin. Vérifier le href toutes les 50 ms ou plus n'aura aucun effet significatif sur les performances si cela vous inquiète.
J'utilise ce script dans mon extension "Grab Any Media" et je fonctionne bien (comme 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);
};
Vous pouvez utiliser un événement onhashchange
par défaut.
Et peut être utilisé comme ceci:
function locationHashChanged( e ) {
console.log( location.hash );
console.log( e.oldURL, e.newURL );
if ( location.hash === "#pageX" ) {
pageX();
}
}
window.onhashchange = locationHashChanged;
Si le navigateur ne supporte pas oldURL
et newURL
, vous pouvez le lier comme ceci:
//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;
} );
} () );
Avez-vous essayé beforeUnload? Cet événement se déclenche immédiatement avant que la page ne réponde à une demande de navigation, ce qui devrait inclure la modification du 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>
Attention, cependant, votre événement sera déclenché ( à chaque fois que vous naviguez en dehors de la page, que ce soit à cause du script, ou quelqu'un qui clique sur un lien. Votre véritable défi consiste à détecter les différentes raisons du déclenchement de l’événement. (Si cela est important pour votre logique)
Avec Jquery , essayez juste
$(window).on('beforeunload', function () {
//your code goes here on location change
});
En utilisant javascript :
window.addEventListener("beforeunload", function (event) {
//your code goes here on location change
});
Voir le document: https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
Eh bien, il y a 2 façons de changer le location.href
. Soit vous pouvez écrire location.href = "y.html"
, qui recharge la page ou peut utiliser l’API d’historique qui ne recharge pas la page. J'ai expérimenté le premier beaucoup récemment.
Si vous ouvrez une fenêtre enfant et capturez le chargement de la page enfant à partir de la fenêtre parente, les différents navigateurs se comportent très différemment. La seule chose courante est qu'ils suppriment l'ancien document et en ajoutent un nouveau. Par exemple, l'ajout de readystatechange ou le chargement de gestionnaires d'événements dans l'ancien document n'a aucun effet. La plupart des navigateurs suppriment également les gestionnaires d’événements de l’objet window, la seule exception étant Firefox. Dans Chrome avec Karma runner et dans Firefox, vous pouvez capturer le nouveau document dans le chargement de readyState si vous utilisez unload + next tick
. Vous pouvez donc ajouter, par exemple, un gestionnaire d’événements load ou un gestionnaire d’événements readystatechange, ou simplement indiquer que le navigateur charge une page avec un nouvel URI. Dans Chrome avec test manuel (probablement aussi avec GreaseMonkey)) et dans Opera, PhantomJS, IE10, IE11, vous ne pouvez pas capturer le nouveau document à l'état de chargement. Dans ces navigateurs, le unload + next tick
appelle le rappel quelques centaines de ms plus tard que l'événement de chargement de la page. Le délai est généralement de 100 à 300 ms, mais opera simetime génère un délai de 750 ms pour le prochain tick, ce qui est effrayant. Si vous voulez un résultat cohérent dans tous les navigateurs, faites ce que vous voulez. vouloir après l'événement de chargement, mais rien ne garantit que l'emplacement ne sera pas remplacé avant.
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";
Si vous exécutez votre script uniquement dans Firefox, vous pouvez utiliser une version simplifiée et capturer le document dans un état de chargement. Ainsi, par exemple, un script de la page chargée ne peut pas quitter sans vous enregistrer la modification de l'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";
Si nous parlons d'applications d'une page qui changent la partie de hachage de l'URI ou utilisent l'API d'historique, vous pouvez utiliser respectivement les événements hashchange
et popstate
de la fenêtre. Ceux-ci peuvent capturer même si vous avancez dans l’historique jusqu’à ce que vous restiez sur la même page. Le document ne change pas par ceux-ci et la page n'est pas vraiment rechargée.