Bem, o "momento mágico" de que você fala é provavelmente quando o DOM do pop-up foi carregado. Ou então pode ser quando tudo (imagens, CSS externo, etc.) tiver sido carregado. Você pode testar isso facilmente adicionando um gráfico muito grande ao pop-up (limpe o cache primeiro!). Se você estava usando um Javascript Framework como jQuery (ou algo semelhante), você poderia usar o evento ready () (ou algo semelhante) para esperar o DOM carregar antes de verificar o deslocamento da janela. O perigo disso é que a detecção do Safari funciona de forma conflitante: o DOM do pop-up nunca estará pronto () no Safari porque ele fornecerá um identificador válido para a janela que você está tentando abrir - se ela realmente abre ou não. (na verdade, acredito que o código de teste pop-up acima não funcionará no Safari.)
Acho que a melhor coisa que você pode fazer é envolver seu teste em um setTimeout () e dar ao pop-up 3-5 segundos para completar o carregamento antes de executar o teste. Não é perfeito, mas deve funcionar pelo menos 95% do tempo.
Aqui está o código que uso para detecção de navegadores cruzados, sem a parte do Chrome.
function _hasPopupBlocker(poppedWindow) {
var result = false;
try {
if (typeof poppedWindow == 'undefined') {
// Safari with popup blocker... leaves the popup window handle undefined
result = true;
}
else if (poppedWindow && poppedWindow.closed) {
// This happens if the user opens and closes the client window...
// Confusing because the handle is still available, but it's in a "closed" state.
// We're not saying that the window is not being blocked, we're just saying
// that the window has been closed before the test could be run.
result = false;
}
else if (poppedWindow && poppedWindow.test) {
// This is the actual test. The client window should be fine.
result = false;
}
else {
// Else we'll assume the window is not OK
result = true;
}
} catch (err) {
//if (console) {
// console.warn("Could not access popup window", err);
//}
}
return result;
}
O que faço é executar este teste do pai e envolvê-lo em um setTimeout (), dando à janela filho 3-5 segundos para carregar. Na janela filha, você precisa adicionar uma função de teste:
teste de funcionamento() {}
O detector do bloqueador de pop-up testa para ver se a função "teste" existe como um membro da janela filho.
ADICIONADO EM 15 DE JUNHO DE 2015:
Acho que a maneira moderna de lidar com isso seria usar window.postMessage () para que a criança notifique o pai de que a janela foi carregada. A abordagem é semelhante (a criança diz aos pais que está carregada), mas os meios de comunicação melhoraram. Consegui fazer este cross-domain desde a criança:
$(window).load(function() {
this.opener.postMessage({'loaded': true}, "*");
this.close();
});
O pai ouve esta mensagem usando:
$(window).on('message', function(event) {
alert(event.originalEvent.data.loaded)
});
Espero que isto ajude.