Je viens de découvrir que window.opener
n'est pas disponible dans une fenêtre ouverte via window.open
si la nouvelle URL est interdomaine, dans IE. Comment détecter l'ouvre-fenêtre dans IE
Cela se produira si la fenêtre démarre dans mon domaine, la quitte, puis revient à mon domaine. J'essaie d'avoir une inscription sociale (facebook, google, etc.) dans la fenêtre contextuelle. Une fois terminé, il devrait fermer la nouvelle fenêtre et rediriger l'ouvreur.
Je sais que Soundcloud réussit, mais je ne sais pas comment. Je vois l'URL passer de la leur à Facebook, puis je ferme.
Après avoir redirigé vers mon site depuis un tiers, je lance ceci:
var data = {
type : 'complete',
destination : '<?= $destination; ?>'
};
if ( window.opener ) {
window.opener.postMessage( JSON.stringify( data ), '*' );
window.close();
}
else {
alert( "Unable to find window" );
}
Il alerte dans IE, même si la fenêtre était à l'origine mon domaine, qui a ensuite été redirigé vers FB, puis redirigé vers moi. Je pensais que depuis l'ouverture de mon site et la redirection immédiate depuis PHP cela peut être un problème. Cependant, même lorsque j'ai ouvert mon site, window.location.href = 'facebookssite.com'
il se plaignait encore à son retour.
[~ # ~] note [~ # ~]
Les inscriptions sociales ne fonctionnent pas pour google, FB, etc. dans un iframe
. Je pense qu'ils les interdisent pour des raisons de sécurité.
Faites-le dans l'autre sens. Suivez l'état de la fenêtre contextuelle enfant à partir de la fenêtre principale (ouvre) et vous pouvez facilement savoir quand la fenêtre enfant a été redirigée vers votre domaine, afin que vous puissiez "lui parler" à nouveau. Mais ne fermez pas la fenêtre enfant par elle-même. Laissez la fenêtre d'ouverture obtenir le résultat de la fenêtre enfant, puis fermez-la.
Par exemple, main.html:
<!DOCTYPE html>
<head>
<title>main</title>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<script>
window.addEventListener("message", function(ev) {
if (ev.data.message === "deliverResult") {
alert("result: " + ev.data.result);
ev.source.close();
}
});
function Go() {
var child = window.open("child.html", "_blank", "height=200,width=200");
var leftDomain = false;
var interval = setInterval(function() {
try {
if (child.document.domain === document.domain)
{
if (leftDomain && child.document.readyState === "complete")
{
// we're here when the child window returned to our domain
clearInterval(interval);
alert("returned: " + child.document.URL);
child.postMessage({ message: "requestResult" }, "*");
}
}
else {
// this code should never be reached,
// as the x-site security check throws
// but just in case
leftDomain = true;
}
}
catch(e) {
// we're here when the child window has been navigated away or closed
if (child.closed) {
clearInterval(interval);
alert("closed");
return;
}
// navigated to another domain
leftDomain = true;
}
}, 500);
}
</script>
</head>
<body>
<button onclick="Go()">Go</button>
</body>
child.html:
<!DOCTYPE html>
<head>
<title>child</title>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<script>
window.addEventListener("message", function(ev) {
if (ev.data.message === "requestResult") {
// ev.source is the opener
ev.source.postMessage({ message: "deliverResult", result: true }, "*");
}
});
</script>
</head>
<body>
<a href="http://www.example.com">Go to example.com</a>
Then click the browser Back button when ready.
</body>
Testé avec IE10.
Pour des raisons de sécurité, window.opener
est supprimé lors de la redirection vers un autre domaine. Le navigateur ne prend pas la peine de restaurer le window.opener
à votre retour. Dans votre cas, vous pouvez essayer:
1) Faites votre authentification dans un iframe si possible au lieu d'utiliser la redirection.
2) Dans votre cas, je vois que vous devez publier les données dans la fenêtre parent. Vous pouvez essayer ceci à la place:
Dans votre fenêtre ouverte, stockez simplement votre data
et fermez normalement.
var data = {
type : 'complete',
destination : '<?= $destination; ?>'
};
window.hasData = true;
window.data = data;
window.close();
Votre fenêtre parente a accès à votre fenêtre ouverte et peut gérer son événement close
:
openedWindow.beforeunload = function (){
//here you could access this.data or openedWindow.data because you're on the same domain
if (this.hasData){
}
//Reason we have this check is because the beforeunload event fires whenever the user leaves your page for any reason including close, submit, clicking a link, ...
}
3) Une solution de contournement: utilisez une minuterie dans votre page parent pour vérifier la propriété closed
de la openedWindow
setInterval(function(){
if (openedWindow.closed){
}
},1000);
4) Une autre solution utilisant localStorage car vous êtes sur le même domaine. Votre page parent peut écouter l'événement
window.addEventListener("storage", function(event){
}, true);
Votre code openWindow:
var data = {
type : 'complete',
destination : '<?= $destination; ?>'
};
if (localStorage){
localStorage.setItem(JSON.stringify(data));
}
window.close();
Utilisez localStorage ou IndexedDB pour communiquer entre des fenêtres qui affichent des documents du même domaine mais qui n'ont pas de référence les uns aux autres.
Ayez simplement une minuterie à grande vitesse pour vérifier les données, enregistrer une autre donnée pour accuser réception et l'autre fenêtre peut la trouver et la fermer.
En bref - vous utilisez localStorage pour passer des commandes et pouvez même avoir une bibliothèque pour ce faire et supprimer les commandes une fois qu'elles sont exécutées et publier les valeurs de retour.