• 締切済み

postMessageによるiframeの書き換え

iframeに表示している自身のブログを作成・修正するスクリプトを考えていますがうまくいきません。 「contentWindowで取得した変数の属性は読み取り専用なので、変数を操作するにはpostMessageを使う必要がある」といった記事があったので、自分なりにスクリプトを書いてみました。以下が、そのサンプルです。 親のparentから子のiframeに変数var1をpostMessageで送り、子側で変数var1を使ってoutputの内容を書き換えています。 しかし、これだとcontentWindowで変数を取得・操作を行なった場合と何ら変わらない結果になってしまいます。 つまりiframe.htmlを直接ブラウザで開いて表示しても、outputの表示内容が書き換わっていません。 どこに誤りがあるのでしょうか。 それとも「読み取り専用」に関する私の理解が間違っているのでしょうか。 <html lang="ja"> <head> <meta charset="UTF-8" /> <title>parent</title> </head> <body> <iframe id="iframe" src="iframe.html"></iframe></br> 天気<input type="text" id="var1" value=""> <input type="button" id="build" onclick="send()" value="データ送付"> <script type="text/javascript"> function send(){ var win = document.getElementById("iframe").contentWindow; win.postMessage(document.getElementById("var1").value, '*'); } </script> </body> </html> <html lang="ja"> <head> <meta charset="UTF-8" /> <title>iframe</title> </head> <body> <p>タイトル</p> <div id="output"></div> <div id="var1"></div> <script type="text/javascript"> window.addEventListener('load', function(){ var var1 = "晴れ"; build(var1); }); function onMessage(e) { var var1 = e.data; build(var1); } window.addEventListener("message", onMessage, false); function build(var1) { var output = "きょうは" + var1 + "です。"; document.getElementById("output").innerHTML = output; } </script> </body> </html>

みんなの回答

回答No.3

>これをテンポラリーなものではなくhtmlとして書き換えられないかということです。 やっぱりそういう事をやりたいんですよね? 物理ファイルを書き換えたいって事でしょ? それなら、仮想空間で動いている言語は、書き換えができるのは 仮想空間だけなので、元のファイルは変わらないし 変わってはいけないですよ。(危なすぎますので) むしろPHPなどを覚える方が良いかと思います。 1.PHPが独自の設定ファイルを読み出す   →送り出す。 2.PHPで独自の設定ファイルを書き換えるように作る   →書き換える。 こうすれば、次のリロードで書き変わった物が読み出されることと。 その都度サーバー側を書き換えているので、本当に 書き変わります。 JavaScriptの場合は、 「サーバーが送り出す」→「受信したブラウザが表示してるだけ」 の流れなので、受信したブラウザには、「サーバー」はないので 書き換えることに意味がないので(リロードで消えますから) 自分だけ、書き変わればそれでいいなら、クッキーという手も ありますが、これは他の人には影響しないですが。 聞いている限りはPHPなどの「サーバーサイド言語」を 何か取り入れた方が、確実に早そうに感じます。

natsu0508
質問者

お礼

私もPHPなどサーバーサイドでの処理について少し調べてみましたがやはり大変そうですね。 取りあえずなるべく簡単にできる方法がないかを考えているところです。 編集が終わったらスクリプトで書き換え部分をalert出力するようにして、コピペでiframe用のhtmlに貼り付ける方法なら出来そうです。 <table>~</table>間、<boby>~</body>間、何なら<html>~</html>間全部をalertで書き出してもいいと思います。 私のFirefox環境であればalert出力が途中で切れることもなく、テキストのコピーも問題なくできそうです。 あと、FirefoxだとiframeとのやりとりでcontentWindowを使用してもローカルファイルエラーが起きません。 この件に関しては自分の環境でできれば何だっていいので、リモートで可能なこの方法で進めたいと思います。 スマートではありませんが、取りあえずブログを立ち上げることを優先することにします。

回答No.2

>この場を借りてお礼申し上げます。 あ~覚えてないや^^ 私の方って、基本「覚えない」ことを強みとしてる部分もあり^^ スキル的な物も、必要になってから調べればいいや~ 程度だったりするもので^^ それで~今回のiframeのやつですが、やれる方法あるはずです。 ただ、忘れた^^以前やったことがあるんですよね。 実は^^ 少なくとも、iframeのエレメントそのものをJSで作って 追加していってフレームが作れるなら、 いじれるはずなのでね。。 逆に別のURL作るより安全なはずでして 明日?暇だったらやってみますわ^^ (あはは、適当でごめんね)

natsu0508
質問者

お礼

ご回答ありがとうございます。 子frameに書き出したい内容をサンプルにして整理してみました。 変数var1~var3とその変数を用いて作成した記事outputとなります。 親からはその変数を操作して記事の作成や修正を行ないます。 これをテンポラリーなものではなくhtmlとして書き換えられないかということです。 <html lang="ja"> <head> <meta charset="UTF-8" /> <title>parent</title> </head> <body> <iframe id="iframe" src="iframe.html"></iframe></br> 天気<input type="text" id="var1" value=""> 気温<input type="text" id="var2" value=""> 湿度<input type="text" id="var3" value=""> <input type="button" id="build" onclick="build()" value="書き込み"> <script type="text/javascript"> //初期読み込み時 window.addEventListener('load', function(){ //iframe内のvar1(初期値)の取得 var doc = document.getElementById("iframe").contentWindow; var var1 = doc.document.getElementById("var1").innerHTML; var var2 = doc.document.getElementById("var2").innerHTML; var var3 = doc.document.getElementById("var3").innerHTML; //input値として格納 document.getElementById("var1").value = var1; document.getElementById("var2").value = var2; document.getElementById("var3").value = var3; //記事の作成、表示 build(); }); //書き込みボタンが押された時 function build(){ //input値の取得 var var1 = document.getElementById("var1").value; var var2 = document.getElementById("var2").value; var var3 = document.getElementById("var3").value; // iframe要素の呼び出し var doc = document.getElementById("iframe").contentWindow; // 変数の引き渡し doc.document.getElementById("var1").innerHTML = var1; doc.document.getElementById("var2").innerHTML = var2; doc.document.getElementById("var3").innerHTML = var3; //記事の作成 var output = "きょうは" + var1 + " 気温" + var2 + "℃ 湿度" + var3 + "%です。"; //記事の表示 var doc = document.getElementById("iframe").contentWindow; doc.document.getElementById("var1").innerHTML = var1; doc.document.getElementById("output").innerHTML = output; } </script> </body> </html> <html lang="ja"> <head> <meta charset="UTF-8" /> <title>iframe</title> </head> <body> <p>タイトル</p> <div id="var1"></div> <div id="var2"></div> <div id="var3"></div> <div id="output"></div> </body> <script> var arr = [ ["var1", "晴れ"], ["var2", 20], ["var3", 40], ]; </script> </html>

回答No.1

実際にやってみましたが書き変わってましたよ。 ブラウザの中だけでは。 もしかして元々のファイルを書き換えたい?って 意味だとしたら、それは、JavaScriptがやる事じゃないですよ。 iframeというタグの内容として ← これに iframe.htmlを読み出して張り付けてるだけで、 iframe.htmlを張ってるわけじゃないので、元が変わることはないですから。 例えば、 src=abc.php のような動的な物だったり src=abc.shtml サーバーサイドインクルードありのHTML これだったら、書き換える方法をブラウザが知ることはできない。 (知る必要もないので) って事なので。

natsu0508
質問者

お礼

ありがとうございます。 私も調べてみましたが、JavaScriptでファイル自体の書き換えをやるのは難しそうですね。 別件になりますが、質問「input値をボタンでoutput表示する方法」に関しては、ご提案いただいたクエリーを用いた書き換え(reloadではない)でうまくいきました。 苦労しましたが勉強になりました。ただ、ご指摘のようにこれはイレギュラーな方法なので、カレンダー自体のスクリプトをきちんとfunction()で括られる形に変更してreloadが不要になるようにして問題回避しました。この場を借りてお礼申し上げます。

natsu0508
質問者

補足

こちらが、contentWindowで変数を取得・操作を行なった場合のサンプルです。 この方法だと変数の属性が読み取り専用になる?ということだったので、postMessageを使用するように書き換えた次第です。 しかし、結局のところそれによって何が変わったのかは不明です。 (むしろスクリプトとしてはこちらの方がすっきりしているように思います。) いずれにしても、iframe.htmlをjavascriptで書き換えることは無理なようですね。 ただ、iframe用のhtmlをサーバーに送り込むには作成したファイルを個々に書き出す必要があります。 どのような方法が可能でしょうか。 <html lang="ja"> <head> <meta charset="UTF-8" /> <title>parent</title> </head> <body> <iframe id="iframe" src="iframe.html"></iframe></br> 天気<input type="text" id="var1" value=""> <input type="button" id="build" onclick="build()" value="書き込み"> <script type="text/javascript"> window.addEventListener('load', function(){ var doc = document.getElementById("iframe").contentWindow; var var1 = doc.document.getElementById("var1").innerHTML; document.getElementById("var1").value = var1; build(); }); function build(){ var var1 = document.getElementById("var1").value; var output = "きょうは" + var1 + "です。"; var doc = document.getElementById("iframe").contentWindow; doc.document.getElementById("var1").innerHTML = var1; doc.document.getElementById("output").innerHTML = output; } </script> </body> </html> <html lang="ja"> <head> <meta charset="UTF-8" /> <title>iframe</title> </head> <body> <p>タイトル</p> <div id="output"></div> <div id="var1">晴れ</div> </body> </html>

関連するQ&A