3


1

私のWebアプリケーションでは、親ウィンドウを閉じるたびに子ウィンドウを閉じる必要があります。 「閉じた」とは、新しいウィンドウに移動しただけではなく、ブラウザウィンドウが実際に閉じていることを意味します。

" チャイルドウィンドウを閉じるにはどうすればよいですか?もし親ウィンドウが閉じられたら? "質問は既にありますが、私のものはその拡張です。 その質問に対する答えは、親のアンロードイベントが発生したときに子ウィンドウを閉じるという問題を解決します。 ただしアンロードしてください!= close(IMO);リンクをクリックするだけでアンロードイベントが発生します。

JSには "onclose"イベントがないので、最善の方法は、親がまだ存在するかどうかを確認し、存在しない場合は閉じるために、親のunloadイベントsetTimeoutを使用することです。

var w = window.open( ""、 "Logger"、 "高さ= 480、幅= 640、サイズ変更可能、スクロールバー= yes"); if(w){JSEvents.on(ウィンドウ、 'アンロード'、function(){if(w)

ただし、IE(7)では、親ウィンドウまたは子ウィンドウのunloadイベント中にsetTimeoutを使用できないことを、私はかなり決定的に示しました。 上記の例では、setTimeout無名関数内の `this == w.opener`です。 このテストではアラートが生成されることはありません。

JSEvents.on(window、 'unload'、function(){window.setTimeout(function(){alert( 'HERE');}、500);});

setTimeout`のないまっすぐな alert`は警告を生成します。

私が使用できる親から子にsetTimeoutを設定するためのトリックはありますか?

私が使用できる親が閉じられたことを検出するための他の方法はありますか?

FFの方がはるかに簡単なので、私はこれをIEの下で機能させることに焦点を当てています。

6 Answer


5


_ 私が使用できる親から子にsetTimeoutを設定するためのトリックはありますか? _

あなたはIEで親からのコードでそれをすることはできません。 IEがウィンドウを閉じると、その中のコードから定義したメンバーは削除され、それらのメンバーへの参照(自分の関数を指している子のタイムアウトなど)は未処理のままになります。 使用しているIEのバージョンによっては、何も起こらないか、「解放されたスクリプトからコードを実行できません」というエラーが表示されることがあります。

あなたは子供の中でそれをすることができます。 親は、アンロード時に子にフラグを設定できます(例: w.parentUnloaded = true)子のsetIntervalポーラーはチェックして自分自身を閉じることができます -

if (window.parentUnloaded && (!window.opener || window.opener.closed))

これはIEのバグですか? まあ… 確かに、他のブラウザはアンロードされたスクリプトに対して異なった反応をします。 しかし、ここで起こることになっていることを言う基準はありません。 同じブラウザシリーズ内でも、クロスコンテキストスクリプティングの問題を回避するためにブラウザが更新されると動作が変わります。

このようなことやイベントのタイミングの問題(*)を考慮すると、クロスウィンドウスクリプティングは見かけよりもはるかに正確に実行するのが困難です。 一般的には避けるのが一番です。メインページのdivにあなたの「ポップアップ」を入れることができるのであれば、通常そうするほうが良いです。

:あるウィンドウでイベントが発生し、別のウィンドウのJavaScriptがまだ実行中の間に実行できる場合があります(*) そのため、ウィンドウ「a」はウィンドウ「b」上のメソッドを呼び出し、ウィンドウ「b」内の他のコードがまだ進行中の間にそれを実行することができます。 一度にアクティブな実行スレッドが1つしかないという通常のJavaScriptの仮定の下でそれらが書かれている場合、これはウィンドウ 'b’のスクリプトを劇的に混乱させる可能性があります。 そのため、親に明示的に子を呼び出させるのではなく、子でポーラーを使用することをお勧めします。 将来的には、これらの問題を回避するためにHTML5のpostMessageメソッドを使用する予定です。)

(**:これは絶対に起こらないはずだ、そしてそれは確かに奇妙だが、モーダルダイアログが関係しているかIE IE Javaプラグインのいくつかのバージョンが使用されている時は特に起こる。)

_ アプリケーションを閉じた後、ポップアップウィンドウをそのままにしておくことはできません。丁寧ではありません。 _

失礼が最初の場所でポップアップを開いていたと言う人もいるでしょう。 ;-)

ユーザーがウィンドウを閉じているのか、自分のホームページに戻っているのか、ブックマークにアクセスしているのか、アドレスを入力しているのかに関係なく、親が残ったときに子ウィンドウを閉じることは意味があります。何か。 個人的には、アプリケーションを開始状態に「リセット」しようとしている場合は、リフレッシュ時にも子ウィンドウを失いたいと思うでしょう。

複数の文書があり、親がその間を移動して同じアプリケーションの一部であり、子を閉じてはいけない場合は、自分で問題を解決できます。 :-)しかし、上記の「child window if」のアプローチを採用してopener.locationを傍受し、それがアプリケーション内で終了するかどうかを判断することもできます。 トリックは、オープナーが別のドメインにナビゲートされていた場合、アクセスはセキュリティ例外をスローするので、オープナーの場所もウィンドウを閉じたtry …​ catchブロックでlocationアクセスをラップする必要があります。読めませんでした。

bucabayは書きました(そしてAnthonyに似たようなもの):

_ ウィンドウを更新または閉じると、ブラウザはウィンドウが閉じたと見なします。 子供に関する限りでは、親をリフレッシュするとそのオープナーは消えます。 _

それは非常に賢明で論理的です。 ブラウザはおそらくそのようなドキュメントごとに1つの「ウィンドウ」を持つべきです。 しかし、それを試してください - 彼らはしません。 IE / FF / Op / Saf /では、チャイルドポップアップは、オープナーの更新時に、そのオープナーへのアクセスを保持します(そして、そのオープナーが同じセキュリティコンテキスト内のドキュメントである限り、そのオープナーの内容も保持します) Chr。


2


ポップアップウィンドウ:(これはオープナーが閉じられているかドメインが変更されている場合に機能します)

var int = window.setInterval(function(){//オープナードメインを変更すると、すべてのブラウザでエラーが発生します。 try / catch:try {if(opener)を使ってこのエラーを利用しましょう。 どうして? F Uがその理由です。 var openerRef = window.opener.location.host; } else {//オープナーが閉じられたときにアンケートをロードします。window.location = 'exit-survey.jsp'; catch(err){window.location = 'exit-survey.jsp';}} // //エラーが発生した場合はアンケートをロードします(オープナーがドメインを変更したときにエラーが発生した場合)。 500); )


1


このように開いたウィンドウの中に関数を作成してみました:

window.closeWithParent = function(){if(!window.opener || window.opener.closed){window.close();} ;}}; window.parentClosing = function(){window.setTimeout(window.closeWithParent、500); ;

それからあなたの親ウィンドウから:

JSEvents.on(window、 'unload'、function(){if(w.parentClosing)w.parentClosing();});

よくわかりませんが、ウィンドウ間でウィンドウオブジェクトを操作すると、問題が発生する可能性があります。 また、このようにして、setTimeoutは、アンロードされている親ウィンドウではなく、子ウィンドウのスコープ内で(うまくいけば)呼び出されます(これによりタイムアウトは失われます)。


1


問題は、ブラウザの観点からすると、ウィンドウはドキュメントの内容を表示するために作成された概念です。 そのドキュメントから別のドキュメントに移動すると、そのウィンドウは閉じられ、新しいウィンドウが作成されます。

ブラウザの概念的なウィンドウがブラウザによって所有されている実際のクライアントウィンドウによってホストされていて、そのクライアントウィンドウが後続のドキュメントを表示するために再利用されるという事実は実際にはあなたのビジネスのことではありません。

そのブラウザがどのようにコンテンツを表示するかを選択する方法で、ユーザーがクリックする可能性がある閉じるボタンを持つウィンドウは、ほとんどのブラウザがホスト文書を知る必要があると考える範囲外です。

ですから、これを回避するためにあなたが発明するかもしれないトリックは、もしそれがうまくいったとしても、後のバージョンのブラウザではより厳格なセキュリティによって閉じられるかもしれません。

私のアドバイスはこの要求をやめることだろう。


1


ウィンドウを更新または閉じると、ブラウザはウィンドウが閉じたと見なします。 子供に関する限りでは、親をリフレッシュするとそのオープナーは消えます。

そのため、ウィンドウが更新されたのか、それとも同じドメイン上の別のインスタンスをJavaScriptの参照を使用して開いたのかをテストすることはできません。 (window.openerなど)

ただし、他のウィンドウへの間接参照を作成して、それらをクロスウィンドウのブラウザストレージまたはサーバーストレージに保存することもできます。 ストレージにウィンドウの状態を反映させると、他のウィンドウが参照を持っていなくてもそのウィンドウを監視できるようになります。

あなたはクッキー、または DOM Storageなどを使うことができます。 私はクッキーを使うライブラリを持っています(それはDOMストレージがサポートされていなかった1年前に書かれました - FF2、IE8私は思います)。 例としてそれを見たいのであれば、私はそれをすることができます。

とにかく、あなたができることは、親ウィンドウを表すデータを保持することです。 定期的にそれを更新しておき、子供からそれをポーリングしてください。

クッキーを使った例:

// parent
setInterval(function(){setCookie( 'parent_alive'、new Date())}、1000);
// child
setInterval(function(){if(readCookie( 'parent_alive')<new Date() -  5000)window.close()}、1000)

ここでは、親がCookie「parent_alive」を更新してから5秒後に子が閉じます。 主な問題は、インターネットに接続されているとページが5秒間読み込まれないために、ページが閉じられたと思われることです。 だからそれはバランスの取れた行為です。

セッションCookieを使用する場合、ポーリングはメモリ内に留まるため、ポーリングは非常に効率的です。 しかし、永続的なクッキーを使用している場合は、おそらく吸うディスクを打っているでしょう。


1


子ウィンドウのスコープにスクリプトを追加する正しい方法は、DOMを使用してscriptタグを作成することです。 次のコードは、IEでアンロードしてから1/4秒後に親ウィンドウが開いているかどうかを確認するためのものです。

var w = window.open( ""、 "Logger"、 "高さ= 480、幅= 640、サイズ変更可能、スクロールバー= yes"); if(w){JSEvents.on(ウィンドウ、 'アンロード'、function(){if(w)

この方向に向かって私を指し示す上でみんなの助けをありがとう。 解決策は、 `src`の代わりにテキストコンテンツを含む新しいscriptタグを動的に挿入する方法を考え出すことでした。