• ベストアンサー

window.openでフレームページを開いたときのフレーム名Object生成について

いつもお世話になります。 今回、別の方の疑問に答えるためにフレームページの検証を重ねるうちに変な現象に行き当たってしまいました。 下記のようなJavaScriptを組み込んだページで、スクリプト内の関数から「sFramePageURL」で指定される 「frame01」及び「frame02」から構成されるフレームページを開いた際、新窓内のフレームにおけるObjectの 生成状況がブラウザによって異なります。 このリストの場合は「frame02」を監視しています。 「新しい窓を開いてFrame確認」のボタンを押すと、多少の時間差はあるのですが  IE 8  FireFox 3.0.10  Opera 9.63  Netscape 7.1 はObjectが生成されます。 ところが Safari 3.1.1 GoogleChrome 2.0.172.31 に関してはチェック回数や時間間隔をどう増やしてみてもいっこうに生成されません。 処理終了後に「新しい窓のFrame確認」ボタンで確認するとしっかりとObjectが確認できるのですが・・・ この差異は仕様によるものでしょうか単なるバグでしょうか? また、これをSafari及びChromeで回避する(同一プロセス内でObject生成できる)手法などございましたらご教授お願いいたします。 ********************************************************* 作成した実験用ページ:ここから <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <title>TEST</title> </head> <SCRIPT Language="JavaScript"> <!-- var FrameContent_TEST; var sFramePageURL = 'http://www.hogehoge.jp/test/FramePage.html'; var sWinName = 'TestPage'; function fShowFramePage(){ FrameContent_TEST = window.open(sFramePageURL,sWinName,'width=800,height=700,scrollbars=1'); FrameContent_TEST.focus(); // *********************************** alert(typeof(FrameContent_TEST.frame02)); alert(typeof(FrameContent_TEST.frame02)); alert(typeof(FrameContent_TEST.frame02)); // *********************************** return true; } function fConfirmFramePage(){ // *********************************** alert(typeof(FrameContent_TEST.frame02)); // *********************************** return true; } //--> </SCRIPT> <body> <br> 試験フレーム1【ページ開く】<input type="button" value="新しい窓を開いてFrame確認" name="B1" onClick="fShowFramePage();"><br> 試験フレーム2【フレームチェック】<input type="button" value="新しい窓のFrame確認" name="B2" onClick="fConfirmFramePage();"><br> <br><br> </body> </html> ********************************************************* 作成した実験用ページ:ここまで

質問者が選んだベストアンサー

  • ベストアンサー
  • atse
  • ベストアンサー率83% (36/43)
回答No.6

#1&#4です スクリプト書いたほうが早そうなので書いておきます。 whileのチェックをsetTimeoutにしただけです。 safariでもchromeでもframe02を確認できました。 function fShowFramePage(){ FrameContent_TEST = window.open(sFramePageURL,sWinName,'width=800,height=700,scrollbars=1'); FrameContent_TEST.focus(); CheckFrame(FrameContent_TEST); } function CheckFrame(w){ if(typeof(w.frame02) != 'undefined') alert(typeof(w.frame02)+"を確認しました"); else setTimeout(function(){CheckFrame(w)}, 1000); } フレーム表示のhtmlは下記だけです。 <html> <head> <title>-</title> </head> <frameset rows="50%,*"> <frame src="hoge.html" name="frame01"> <frame src="hoge.html" name="frame02"> </frameset> </html>

ralf124c
質問者

お礼

検証に時間がかかってしまい申し訳ありませんでした。 処理といいリストの美しさといいみごとな回答です。 本当にありがとうございました。 処理を見ると監視部分を関数化している以外はほぼ同じことをやっていたのに不思議でしょうがありません。これからじっくりと相違点を追跡して原因部分を探って生きたいと思います。

すると、全ての回答が全文表示されます。

その他の回答 (5)

  • think49
  • ベストアンサー率59% (285/482)
回答No.5

#2,3です。 #2,3はページ読み込みに時間がかかると期待通りに動作しませんね…。失礼しました。 ** 代替案 ** DOMでdisplay:none;なiframeを生成してcontentwindowから取得することはできるので、オブジェクトはiframeで取得してwindow.openは別に発行する手はあります。 ただし、window.openとiframeで2重アクセスしてしまいます。 掲示板/JavaScript質問板/子ページをロード時に編集したい - TAG index Webサイト http://www.tagindex.com/cgi-lib/q4bbs/patio.cgi?mode=view&no=2172 上記URLでは参照先(B.html) のonloadで参照元(A.html)の関数を呼び出すのが良い、という結論ですが参照先が自サイト内でないと使えないので、参照先(B.html) を自サイト内のHTMLにして、 B.htmlではURLパラメータで渡された外部URLをiframeで生成すれば、アクセスは一回に抑えられます。 いずれもスマートではないですし、一長一短なのでどれが正解ということはないと思います。 参考程度に受け取ってください。

ralf124c
質問者

お礼

ご回答、ありがとうございます。 かなり手の込んだソースを拝見させていただきました。 頭の固くなった年寄りには読むのに少々時間がかかりました。 DOMとイベント処理を駆使して新窓を開くやり方は目に鱗がおちる思いで、こういうアプローチの仕方もあったのかとたいへん勉強になりました。 開けた窓のリソースをチェックするやり方から、根本的に窓の開け方を変えてチェックするというアプローチを行ってみます。 たいへん参考になりました。

ralf124c
質問者

補足

朝、就業前にあわてて書いたので今見たら文がおかしいですね。 「目から鱗が落ちる」の間違いでした。目に鱗がおちたら痛いですよね。 訂正してお詫びいたします。

すると、全ての回答が全文表示されます。
  • atse
  • ベストアンサー率83% (36/43)
回答No.4

#1です > while(typeof(FrameContent_TEST.frame02) != 'undefined'); typeof(FrameContent_TEST.frame02)が'undefined'ではなければ実効し続ける、です。 つまり、while開始時点でundefinedだとすぐ抜けてしまいます。 逆に、while開始時点でobjectとして確認できると、永久ループになってしまいます。 while(typeof(FrameContent_TEST.frame02) == 'undefined'); こうすれば、'undefined'であればループし続け、'object'であればwhileを抜けます。 そこまで細かい間隔で調べる必要がなければ、setTimeoutやsetIntervalあたりを使い、間隔を少しあけながら確認するのが無難かと思います。 fConfirmFramePage()でframe02を確認できるブラウザであれば、成功すると思いますよ。

ralf124c
質問者

お礼

すみません。 ご指摘ありがとうございます。 いろいろと実験していて「==」でブラウザがウンともスンとも言わなくなってタスクマネージャで何とか落とすことが出来た後に、間違って上げた場合の用心にロジックを逆にしておいた方を貼り付けてしまいました。 このほかにも「FrameContent_TEST.closed」などをループで確認しながらチェックしたりしていました。 でもやっぱり、「Safari」と「GoogleChrome」だけは何十分待っても・・・ orz 状態です。

すると、全ての回答が全文表示されます。
  • think49
  • ベストアンサー率59% (285/482)
回答No.3

#2に補足。 Chromeでも onload を実行できるようです。 function init(){ var test = document.getElementById('Test'); test.onclick = function(){ var url = 'http://www.google.co.jp/search?q=window.open+focus'; // window.open(url,'_blank','width=800,height=700,scrollbars=1').focus(); var win = window.open(url,'_blank','width=800,height=700,scrollbars=1'); win.onload = function(){ this.focus(); }; } } # win.onload.focus(); はChromeでは動きませんね。Fxでは動くのですけど。

すると、全ての回答が全文表示されます。
  • think49
  • ベストアンサー率59% (285/482)
回答No.2

これでどうでしょう? Fx3.0.1.1, GoogleChrome2.0.172.31 で動作OKを確認しました。 ------- <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'> <html lang='ja' xml:lang='ja' xmlns='http://www.w3.org/1999/xhtml'> <head> <meta http-equiv='content-type' content='text/html; charset=utf-8' /> <meta http-equiv='content-style-type' content='text/css' /> <meta http-equiv='content-script-type' content='text/javascript' /> <title>TEST</title> <script type="text/javascript"> (function(){ function init(){ var test = document.getElementById('Test'); test.onclick = function(){ var url = 'http://www.google.co.jp/search?q=window.open+focus'; window.open(url,'_blank','width=800,height=700,scrollbars=1').focus(); } } if(typeof window.addEventListener == 'function'){ window.addEventListener('load', init, false); } else if(typeof window.attachEvent == 'object'){ window.attachEvent('onload', init); } })(); </script> </head> <body> <input id='Test' type="button" value="アクティブなウインドウで開く"> </body> </html> -------

すると、全ての回答が全文表示されます。
  • atse
  • ベストアンサー率83% (36/43)
回答No.1

メインのスクリプトの処理推移は、開いたウィンドウと非同期です。 要するに、window.openの次行以降、alert等を処理する際、開いたウィンドウのロード完了を待たずに実行されるということです。 よって、バグではなく仕様上の動作として、新しいウィンドウがframe02を定義する前にメインのほうでalertを行ってしまっているのでしょう。 --------------------------------- firefox3あたりなら、FrameContent_TESTのonloadにalert処理を入れればよいのですが、こちらで調べたsafariでは新しく開いたウィンドウには効かないようです。(onloadは存在するが実行されない) 解決には至りませんが、この辺りが何かの糸口になるのではないでしょうか。 ちなみにfirefoxにおいても「クロスドメインではない」が前提です。

ralf124c
質問者

お礼

早速の回答ありがとうございます。 > メインのスクリプトの処理推移は、開いたウィンドウと非同期です。 問題の核心をひとことで言い表わしていただいて感謝いたします。 > よって、バグではなく仕様上の動作として、新しいウィンドウがframe02を定義する前にメインのほうでalertを行ってしまっているのでしょう。 こちらに関しては実験で使っているPCの個体差にもよるのですが、IEとNetscapeはOpenの直後でもObjectが確認できました。 のこりのものも、  while(typeof(FrameContent_TEST.frame02) != 'undefined'); や、タイマー処理で時間をずらしながら「FrameContent_TEST.frame02」の状況を監視することで、Object生成をその関数処理内で確認することが出来ました。 確かに、非同期によるタイミングの問題であれば、そのように監視やWAITをかけることでObject(フレーム)の存在が確認できるはずなのですが、SafariとChromeに関しては、最悪「監視の永久ループ」に入ってしまうしまつです。 いつまで待っても生成されません。 これが取得できないことで生じる問題点として「スクリプト処理内で別窓フレームのTARGETを特定することが出来ないこと」です。 無料のブラウザに文句を言ってもしょうがないのですが、よくあるJSの差ということでしょうか。 > ちなみにfirefoxにおいても「クロスドメインではない」が前提です。 セキュリティの基本を思い出させていただき感謝です。 window.openという古典的な関数で、自スクリプトからTARGET指定で生成される子プロセスに関してブロックがかかるなら「そりゃないんじゃない」と思ってしまいます。 また、セキュリティの事情云々であれば、当該JSの処理終了後に別の処理からはObject取得が可能なのが中途半端な実装を証明しているように感じてしまいます(担当者が違う可能性があるかも)。 とにかく、いろいろとありがとうございます。 あつかましいお願いですが、何かまたヒントなどございいましたらよろしくお願いいたします。

すると、全ての回答が全文表示されます。

関連するQ&A