• 締切済み

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

  • innerHTMLに代入したインラインフレームのDIVの値の取得について

    下記のソースは「読み込み」ボタンを押した時にあらかじめ用意してた<div id="box">にインラインフレームを代入し、「値取得」ボタンを押したら、'sample.html'内のdivの値「keisan」をアラートで表示する記述です。このソース内容を、ボタンのイベントで「keisan」の値を取得するのではなく、<body>のonLoadでページを開いた瞬間にアラートが 出るようにしたいのですが、お分かりになる方はいらっしゃいますでしょうか? わかりにくい説明ですみません。どうかよろしくお願いします。 <html> <head></head> <body> <div id="box"></div> <input type="button" value="読み込み" onClick="Details.changeURL('sample.html')" /> <input type="button" value="値取得" onClick="Details.showMessage('keisan')" /> </body> <script type="text/javascript"> <!-- var Details = (function(){ var handle = document.getElementById('box'); var buffer = null; return { changeURL: function(url){ handle.innerHTML = "<iframe src=\""+url+"\" id=\"ifr\"></iframe>"; }, showMessage: function(id){ buffer = document.getElementById('ifr').contentWindow.document; alert(buffer.getElementById(id).innerHTML); } } })(); //--> </script> </html>

  • 引数のある関数をhtml読み込み後に実行

    次のhtmlとスクリプトでresultのような結果を得たいのですが、スクリプトがheadにあるとエラーが出てしまいます。 body直前にスクリプトを置けば動作はするのですが、head内で動作させるにはどうしたら良いのでしょうか? [html] <div id="here"></div> [JavaScript] function ins( id ) { var output = document.createElement( 'span' ); output.className = 'ins'; output.innerHTML = '<p>content</p>'; var element = document.getElementById( id ); element.appendChild( output ); } ins( 'here' ); [result] <div id="here"> <span> <p>content</p> </span> </div> よろしければどなたかアドバイスを頂けると助かります。 よろしくお願い致します。

  • 横スクロールのiframeをスムース移動させたい。

    webサイトの横スクロールのインラインフレームをスムーススクロールにしようとしています。 Javascript初心者です。 色々調べたのですが、うまくできず、力を貸していただけたらと思います。 http://okwave.jp/qa/q6244820.html こちらの質問のようにスムーススクロールを使った移動を横スクロールで使いたいと考えています。 上記のサイトを参考に組んだコードが下記です。 <!-- 親html --> <div> <a href="#a" onclick="return document.getElementById('inline').contentWindow.ps2.scroller(this);">A</a> </div> <div> <a href="#b" onclick="return document.getElementById('inline').contentWindow.ps2.scroller(this);">B</a> </div> <div> <a href="#c" onclick="return document.getElementById('inline').contentWindow.ps2.scroller(this);">C</a> </div> <div> <a href="#d" onclick="return document.getElementById('inline').contentWindow.ps2.scroller(this);">D</a> </div> <div> <a href="#e" onclick="return document.getElementById('inline').contentWindow.ps2.scroller(this);">E</a> </div> <div> <a href="#f" onclick="return document.getElementById('inline').contentWindow.ps2.scroller(this);" >F</a> </div> <iframe id="inline" src="フレーム内html" name="inline"> </iframe> <!-- フレーム内html --> <head> <script type="text/javascript" src="/ps2.js"></script> </head> <body> <div> <a id="a" name="a"> A </a> <a id="b" name="b"> B </a> <a id="c" name="c"> C </a> <a id="d" name="d"> D </a> <a id="e" name="e"> E </a> <a id="f" name="f"> F </a> </div> </body> しっかり理解していなくて恐縮なのですが読み込んでいるJavaScriptは横スクロールには対応していないのでしょうか? 文章の欠陥もしくはJavaScriptの応用の仕方、もしくは別のこうした使用に対応できる他のJavaScript等ありましたら教えて下さい。 どうぞ宜しくお願い致します。

  • IFRAMEのscrollingを常にnoにしたい

    iframeを使ってBBSをscrolling="no"で表示したいのですが、 src="パスワード.cgi"から自動でbbs.cgiになったときにスクロール表示してしまいます。 iframe内で表示先が変更された場合でもスクロール表示しないようにできるのでしょうか?もしできるのであれば教えていただきたいのですが… 掲示板をiframe と言うことで、某ホームページをを参考にスクロールが表示さ れないようにしてみました。 が以下のようにパスワードを入力後に表示するiframe はスクロールを表示して しまいます。 <script type="text/javascript"> <!-- function LoadFrame(frid) { var IFR = document.getElementById(frid); IFR.style.height = (IFR.contentWindow)? IFR.contentWindow.document.body.scrollHeight: document.frames[frid].document.body.scrollHeight; } //--> </script> <iframe src="member/gate.cgi" name="coach" onload="LoadFrame(this.id)" id= "Ifr" width=497 frameborder="0" scrolling="no"></iframe> 試行錯誤しながらなんとかやってる超初心者です。よろしくお願いします。

  • 引数を持つコールバック関数をonloadで複数実行

    下記のような内容で、指定したidを持つ要素に新しい内容を追加したいのですが、この内容だとcontent2のidを持つdiv要素にしか内容が追加されません。 そこで、対象となるidを持つ要素をいくつ追加しても反映されるようにしたいのですが、これを実現するにはどうしたら良いでしょうか? アドバイス等、何かしらお力添えを頂ければ幸いです。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Title</title> <script type="text/javascript"> // </body>直前には置きたくない // 指定したidを持つ要素に新たな内容を追加する関数 function ins( id ) { var output = document.createElement( 'span' ); output.innerHTML = '<p>content</p>'; // 追加する内容はhtmlやjavascriptなど必要に応じて変化する var element = document.getElementById( id ); element.appendChild( output ); } window.onload = function() { ins( 'content1' ); } window.onload = function() { ins( 'content2' ); } </script> </head> <body> <div id="content1"></div> <!-- window.onloadではins( 'content2' );に上書きされてしまう --> <div id="content2"></div> <!-- <div id="content3"></div> <div id="content4"></div> ... いくつ追加しても対応出来るようにしたい --> </body> </html>

  • 親ページから子ページ内の操作をする iframe

    インラインフレームを用いたサンプルを作っています。 親から子へ指示を送ったら、子がそれに応じるというものです。 ローカル環境でエラーを出さずに実現するには postMessageで、どんなコードになりますか? 【親ページ】parent.html <body style="background:bisque"> <div>parent.html 親ページです.</div> <pre> 【テーマ】親ページから子ページ内の操作をする <条件> ・ローカル環境 ・親子とも同じ場所 ・親の指示で子が応じる </pre> <iframe id="iframe2" width="500" height="160" src="./child.html"> </iframe> <div>親からの指示内容</div> <div><button onclick="func1()">書き換え1</button> 「囲まれています」を「囲まれました」に書き換える</div> <div><button onclick="func2()">書き換え2</button> 「-----」を「親から伝言あり」に書き換える</div> <script> //子に指示する関数 function func1(){ } function func2(){ } </script> </body> 【子ページ】child.html <body style="background:#eee"> <div>child.html 子ページです.</div> <p> <span id="test">ここは「id属性がtest」のspan要素に囲まれています。</span> <div id="result">output:<span>-----</span></div> </p> <script> //子が応じる関数 </script> </body>

  • jsでプルダウンで選択したものがうまく表示されない

    以下のhtml文があります。 <!DOCTYPE html> <html> <head> <title></title> <script language="javascript" type="text/javascript"> function onButtonClick() { var val = document.forms.form1.textBox1.value; var target = document.getElementById("output"); if (val == "Penguin") { target.innerHTML = "合っています。"; } else { target.innerHTML = "間違っています。"; } } </script> </head> <body> <form action="" id="form1"> <div>"Penguin"と入力してください。</div> <input id="textBox1" type="text" value="" /> <input type="button" value="Exec" onclick="onButtonClick();" /> </form> <div id="output"></div> </body> </html> Penguinと入力すると合っていますと表示が出ます。 これを、プルダウン方式にしました。 <!DOCTYPE html> <html> <head> <title></title> <script language="javascript" type="text/javascript"> function selectboxChange() { var val1 = document.forms.form1.Select1.value1; var target = document.getElementById("output"); if (val1 == "要素1") { target.innerHTML = "合っています。"; } else { target.innerHTML = "間違っています。"; } } </script> </head> <body> <form name="form1" action=""> <select id="Select1" onchange="selectboxChange();"> <option>---</option> <option value1 == "要素1">要素1</option> <option>要素2</option> <option>要素3</option> <option>要素4</option> <option>要素5</option> </select> </form> <div id="output"></div> </body> </body> </html> これにすれば、要素1を選択すれば、会っていますと表示されるのですが、されません。 どうしたら改善されますか。

  • iframe内をリロードできますか?

    たとえば <HTML> <head> <script language="javascript"> <!-- function a1reload(){ "iframe内をリロードする文章" } //--> </script> </head> <body> <iframe src="a1.html" id="a1iframe"><br> <a href="javascript: a1reload()">ここをクリック</a> </body> </HTML> こんな感じでiframe内をリロードできないでしょうか? お願いします。

  • designMode=on のときのキーイベント処理

    HTMLエディタを使ったWEBアプリケーションを作っているのですが、 designMode=onにしてインナーフレームを編集可能にしたとき、 Mozillaの場合、キーイベントが反応せず困っております。(IEでは動きます) どなたか、ご存知のかたは教えてください。 よろしくお願いします。 OS : WindowsXP ブラウザ:firefox 2.0.0.4 ・ソース <html> <head> <script type="text/javascript"> var doc=null; function init(){ var doc = document.getElementById("testFrame").contentWindow.document; doc.designMode = "on"; doc.onkeydown = test; } function test(){ alert("OK"); } </script> </head> <body onload='init();'> <iframe id="testFrame" width="500px" height="500px" ></iframe> </body> </html>

  • IFRAMEで高さを自動調整したい

    IFRAMEを使っているのですが、PCを起動して最初にページを開いたときだけ、正しい高さに設定できなくて困っています。 「更新」をクリックするとそれ以降はうまく動くのですが... IE(6)の症状で、FireFoxではPC起動直後でも問題なく動きます。 <iframe src="http://aaaaa.php?mode=abc" onload="LoadFrame(this.id)" id="Ifr-a" width="700" marginwidth="0" marginheight="0" scrolling="no" frameborder="0"></iframe> javaScript側は、 function LoadFrame(frid) { var IFR = document.getElementById(frid); IFR.height = (IFR.contentWindow)? IFR.contentWindow.document.body.scrollHeight: document.frames[frid].document.body.scrollHeight; } PCを起動した直後の1回目だけうまく表示されません。 IFR.height<1のようなので、処理結果は0になってるようです。 よろしくお願いいたします。

    • ベストアンサー
    • HTML

専門家に質問してみよう