2014-11-26 10 views
10

A causa di come alcune delle nostre pagine funzionano, JS può essere iniettato nella pagina in qualsiasi momento e talvolta questo JS chiude la finestra corrente. Il problema è che ho bisogno di collegare un listener di eventi al onunload della finestra in modo che un valore possa essere restituito dalla finestra alla pagina padre. Ma poiché lo script di chiusura delle finestre può essere iniettato in qualsiasi momento, non posso associare questo evento all'onload a causa di come funziona, quindi speravo di usare DOMContentLoaded poiché quell'evento si innescherebbe prima che lo script venga iniettato.Collega il listener DOMContentLoaded alla finestra creata dinamicamente

Tuttavia nei miei test, non riesco a ottenere nulla da associare a DOMContentLoaded sulla pagina padre in cui viene creata la nuova finestra.

Ecco un quello che sto attualmente lavorando con: Plunker

Abbiamo solo bisogno di questo per lavorare in Chrome al momento.

Il nostro metodo attuale di fare questo funziona come questo (pseudocodice):

onButtonClick = function(){ 
    win = window.open(...); 
    win.onload = function(){ 
     win.onunload = function(){ 
      //Bind some function that will get the window's "return value" and pass it to the parent page 
      //This will never happen if the window closes itself before the page is done loading 
     }; 
    }; 
}; 

Posso usare DOMContentLoaded per realizzare quello che voglio? In tal caso, come posso collegarlo correttamente alla finestra?

Nota: non è possibile associare l'evento "onunload" direttamente alla finestra una volta creata. Sembra che l'evento "onunload" venga attivato due volte (una volta quando si apre la finestra e quando si chiude). Puoi vedere questo accadendo se usi la funzione "bindOnCreate" nel mio esempio.

risposta

6

se si cambia linea 58 da

w.document.addEventListener('DOMContentLoaded', ...) 

a

w.addEventListener('DOMContentLoaded', ...) 

funziona. Cercherò di spiegare cosa sta succedendo sotto il cofano:

  • Quando la finestra è aperta, inizialmente ha l'URL about:blank. È possibile controllare ciò registrando w.location.toString() nel gestore di eventi onunload (vedere il passaggio successivo).
  • Subito dopo il browser carica l'URL fornito in window.open, attivando così onunload per about:blank(prima volta).
  • La pagina reale con diversi window.document viene caricata nella finestra pop-up, ma i gestori di eventi stanno ancora ascoltando la radice DOM della pagina about:blank perché sono stati aggiunti eventi a window.document, non window; e ora come abbiamo un altro URL caricato, window.document è completamente diverso oggetto di un passo prima.
  • Quando si chiude la finestra, onunload è innescato di nuovo (seconda volta) perché il vostro evento onunload era collegato a finestra.

Se addEventListener per di window pop-up, che riceve gli eventi di tutte window.document -s che saranno caricati all'interno di quella finestra a causa del meccanismo di evento JS bubbling.

Spero che questo risponda alle vostre domande.

+0

Grazie, questo ha risolto il problema e chiarito alcuni di quegli altri problemi che stavo avendo. –

1

In alternativa, è possibile inviare un messaggio dalla finestra secondaria al relativo dispositivo di apertura, anziché consentire a chi apre di gestire l'evento di scaricamento della finestra secondaria. Questo sarà molto più semplice e non dovrai preoccuparti del punto di iniezione. Inoltre puoi sbarazzarti di due volte scaricare evento, come Andrew Dunai ha già dato il motivo di questo problema.

Ecco io do un semplice demo, mostra solo lo scheletro della mia soluzione di messaggistica:

Parent.html

<button id="open">Open Window</button> 
<button id="close">Close Window</button> 
<div></div> 
<script> 
    var child; 

    document.querySelector('#open').addEventListener('click', function() { 
    document.querySelector('div').innerHTML = ''; 
    child = window.open('child.html', 'child', 'width=600,height=600'); 
    }, false); 

    document.querySelector('#close').addEventListener('click', function() { 
    child.close(); 
    }, false); 

    window.addEventListener('message', function(e) { 
    document.querySelector('div').innerHTML = e.data; 
    }, false); 
</script> 

child.html

<input type="text" value="" placeholder="input something"> 
<script> 
    window.addEventListener('beforeunload', function() { 
    var msg = document.querySelector('input').value; 
    window.opener.postMessage(msg, '*'); 
    }, false); 
</script> 

entrambi i casi si chiude la finestra figlio facendo clic sul pulsante di chiusura della propria finestra o sul pulsante in windo genitore w, il valore nell'input del figlio sarà sempre inviato al genitore e presentato.

Questo è l'approccio chiave per uno dei miei progetti collaterali e funziona molto bene.

Problemi correlati