• ベストアンサー

親ページから子ページ内の操作をする 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>

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

  • ベストアンサー
回答No.9

完全ローカルの場合にはオリジンがないので、 if (event.origin == "http://localhost"){ この判定を外すか、 if (event.origin == null){ にしてください。 とりあえず、この質問なかなか!楽しめたので、こちらからも ありがと!って気持ちですよ! また、 <条件> ・ローカル環境 ・親子とも同じ場所 ・親の指示で子が応じる この部分を、要件定義と言いますが、これをはっきり書いている事 がとても素晴らしい! 実際に仕事をするとき、これが曖昧で大きな損失になってる 会社も多いほどなので、これらがあることはとても 良い事なんです!。 また、次回!熱い(w)質問待ってます! 変なニュアンスですが、どうでもいい質問にどうでもいい回答して 質問者がめんどくさくなってBAつけて30Pもらえるより こういう、難易度がちゃんとある(???)質問に まっすぐ向き合うほうが私も楽しめてうれしいです! また次回どこかで! では!

retorofan
質問者

お礼

AsarKingChangさん 私のは switch()文で作りました。 お陰様で、 新しい知見を得ることが出来ました。 どうもありがとうございました。 m(_ _)m

その他の回答 (8)

回答No.8

この行はいらないので削除でいいですよ。 //送信元のドメインをチェックすることが推奨されています console.log( 'message is : '+ event.data ); ミニ解説! function abc() って書くと 実は、それがwindow空間でメソッドを作ったことになってるだけなので。 window["abc"]()で、呼べるんです。 なので、event.dataにそのまま関数名を入れて、それをコールしてます。 感覚的に、関数を別のフレームから呼んでる風に見えて 見やすいでしょう。なお、関数があるか?を 知りたいなら、window[ 関数名 ]があるか?で判定できます。 後は、それを親から名前で呼び出すだけでいい! おかげで、見ての通り1行しかない(笑) もしも、複雑なパラメーターを入れたいな~ってときは、 メッセージをJSONにして { api:"func1", para1:123, para2:123 } みたいに、オブジェクト化したものをJSONでテキスト化 それを子供が、テキストからオブジェクトに戻して、 該当するAPIを呼び出せばOKです。 ってことで、全部解決かな?

retorofan
質問者

お礼

AsarKingChangさん あなたのコンセプトを理解しました。 child.html function func1(){ test.innerHTML = test.innerHTML.replace(/囲まれています/, "囲まれました"); } function func2(){ result.innerHTML = result.innerHTML.replace(/-----/, "親から伝言あり"); } 以上で条件が満たされました。 深く感謝申し上げます。

回答No.7

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(){ document.getElementById("iframe2").contentWindow.postMessage('func1','*' ); } function func2(){ document.getElementById("iframe2").contentWindow.postMessage('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> //子が応じる関数 window.addEventListener('message', function (event) { //送信元のドメインをチェックすることが推奨されています if (event.origin == "http://localhost"){ console.log( 'message is : '+ event.data ); window[event.data](); } }); function func1(){ let e=document.getElementById("koko"); let out=e.innerHTML; out = out.replace('りんご', 'Apple'); out = out.replace('みかん', 'Orange'); e.innerHTML=out; } function func2(){ let e=document.getElementById("koko"); let out=e.innerHTML; out = out.replace('あっぷる', 'アップル'); out = out.replace('おれんじ', 'オレンジ'); e.innerHTML=out; } </script> <div id="koko"> りんご・りんご・ あっぷる・あっぷる・ みかん・みかん・ おれんじ・おれんじ・ </div> </body> -- これがやりたかった?って事かな??

回答No.6

もしかして、、、 https://developer.mozilla.org/ja/docs/Web/API/Window/postMessage これを使いたい?って意味だった?? なんか、これの事を言ってる気がしてきた^^

回答No.5

>実は当方、ポストメッセージの送受信で >実現出来ております。 やっぱそうでしょ? CORSを無効にしないと動かないはずなんです。 先ほど無効にする方法などは、書いておきました。 また、XAMPPなどでPCに簡易サーバーを立てる方法も。 なれれば、簡易サーバーを立てる方が、効率がいいですよ。 こちらでも、その上でこのようなサンプルは作っているので。 なので、ソース自体は動くものなんですが。 CORSがある限りは、検証できないのが正常なんです。 localhostにはオリジンがないので。 こうなって当然でして。 上に書いた対処法で、再度実験を!

回答No.4

ソース見てわかるとは思いますが、 外部のフレーム内のエレメントを入手出来てしまっているという サンプルなので、このエレメントに子エレメントを 動的に作り出して結合(DOM構築)すれば 子フレーム側のHTML構造すらも追加削除可能ですので、 興味があれば、実験してみてください。 では!さらばじゃ~ (この程度なら、およそ作業時間10分くらいで、できますので、  必要ならまた、お声を~)

retorofan
質問者

補足

早速ためしてみたところ、 次のようなエラーが出ました。 parent.html:30 Uncaught DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame. at getFrameDocument (

回答No.3

--- 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> /* 指定のFrameIDをDocumentに変換 */ function getFrameDocument(name) { let e=document.getElementById(name); let d=e.contentDocument || e.contentWindow.document; return d; } //子に指示する関数 function func1(){ /* フレームのid="iframe2"を取得 */ let f=getFrameDocument("iframe2"); /* フレーム側のid="koko"を取得 */ let e=f.getElementById("koko"); /* innerHTMLは直接書き換えるべきではないので、ローカル変数に移し替える */ let out=e.innerHTML; out = out.replace('りんご', 'Apple'); out = out.replace('みかん', 'Orange'); e.innerHTML=out; } function func2(){ /* フレームのid="iframe2"を取得 */ let f=getFrameDocument("iframe2"); /* フレーム側のid="koko"を取得 */ let e=f.getElementById("koko"); /* innerHTMLは直接書き換えるべきではないので、ローカル変数に移し替える */ let out=e.innerHTML; out = out.replace('あっぷる', 'アップル'); out = out.replace('おれんじ', 'オレンジ'); e.innerHTML=out; } </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> <div id="koko"> りんご・りんご・ あっぷる・あっぷる・ みかん・みかん・ おれんじ・おれんじ・ </div> </body> --- 見ての通り、子供にはJSはありません。 親のみで子供を自由に書き換えられますので。 「囲まれています」を「囲まれました」に書き換える 「-----」を「親から伝言あり」に書き換える こうはなってませんが、ソース見ればわかる通り、 簡単に対応できますね。 なお、CORSがない環境で動作することを前提としており 同一サーバーまたはCORSを無効にしている環境 限定です。(こちらでは動作確認は取りました)

回答No.2

ということであれば、 CORSがない環境を今現在使えている?という 前提でサンプルを書いてもいいですが。 それでもOKですか? (というのは、本来は動かないはずなので、  動かないぞ!って文句言われても困るので^^) おまけ!  ちなみ、子にはJSいらないですよ。  【親ページ】parent.html  子供から見たら確かにparentですが、  これ自体を表示するわけなので、parentじゃないです。  このファイル名だと「このファイルの親」って  意味なので、ちょっと意味が違いますけど。  とりあえず、動作だけなら、aでもbでもいいので^^  どっちでもいい事ですが。

回答No.1

実際に、やってみたら、 https://www.tekizai.net/entry/javascript_iframe_var#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%A0%E3%81%A8%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%AA%E3%82%8B こちらで紹介されている、 「ローカルファイルだとエラーになる」となりました。 対処法としては、CORSを外す https://qiita.com/t_katsumura/items/3f2a401ff6e2076acb26 自分のPCに、ローカルのサーバーを立てる。 XAMPPなど https://www.apachefriends.org/jp/index.html が必要になりそうですね。 どういうことかというと、ローカルファイルには、 オリジンが存在しないので、別の同じローカルファイルだが、 比較相手のオリジンが存在しないので、同じと判断できない! 結果、エラーになったということになります。 なのでCORSをクリアしてもらえれば、 追加でサンプルを作ることは、できますが。 今のままでは実行できる場所がないというのが 回答になります。 (こちらで私がサーバーで動くものを作っても、  質問者さんが試せないため)

retorofan
質問者

お礼

AsarKingChangさん ご協力くださいまして、とても感謝しています。 実は当方、ポストメッセージの送受信で 実現出来ております。 ただ、他のコードでできるかどうか、 知者のオチカラを拝見させて頂きたいと 思っております。 以上、よろしくお願いいたします。

関連するQ&A

  • iframeの中から親ページをスムーズスクロール

    タイトルどおり、iframeの中から親ページをスムーズスクロールしたいと考えています。 ヘッダに <script> $(function() { var topBtn = $('#toTop'); topBtn.click(function () { parent.$('body,html').animate({ scrollTop: 0 }, 500); return false; }); }); </script> 親ページには高さ3000ピクセルのiframeを作って、そこに読み込んでいる子ページ最下部に <div id="gotoTop"><a href="#top_page"><img src="_image/btn_top.jpg" alt="トップに戻る" /></a></div> と記述しています。 この状態で親ページをスムーズスクロールさせることができません。 事情があって、親ページ側にはスクリプトやタグを追加することができません。 親も子もおなじドメインにあります。 ["parent" $('body,html') animate]などのキーワードで検索した記事を参考に parent.$('body,html').animate を window.parent.$("body").animate や $('html, body', window.parent.document).animate に書き換えてみてもうまくいきませんでした。 どうかアドバイスをお願いいたします。

  • 単独で開かれたiframeを親ページに表示したい

    ブログ記事(blog1.html、blog2.html、blog3.html)を親ページ(index.html)のiframeとして表示しています。 親ページを開いた際には、デフォルトで最も新しいブログblog3.htmlが表示されるようになっています。 ブログ記事が単独で開かれた場合には、 if (window == window.parent) { location.href = "./index.html"; により自動的に親ページに導くようにしていますが、その際に開かれたブログ記事を表示したいと思います。 当たり前ですが、現在はblog3が開かれてしまいます。 どのようにしたらいいでしょうか。 以下、現在確認中のサンプルスクリプトです。 ■親ページ■ <html lang="ja"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> <p>index.html</p> <iframe src="./blog3.html" frameborder="2" width="300" height="100"></iframe> <div id="result"></div> </body> </html> ■ブログ1■ <html lang="ja"> <head> <meta charset="UTF-8"> <title>blog1</title> </head> <body> <p>blog1.html</p> <script> // 単独で開かれている場合 if (window == window.parent) { location.href = "./index.html"; // iframeで開かれている場合 } else { } </script> </body> </html> ■ブログ3■ <html lang="ja"> <head> <meta charset="UTF-8"> <title>blog3</title> </head> <body> <p>blog3.html</p> <script> // 単独で開かれている場合 if (window == window.parent) { location.href = "./index.html"; // iframeで開かれている場合 } else { } </script> </body> </html>

  • 子ページから親ページのものを実行したい

    <body> <p> <input type="button" id="sample1" value="サンプル1" /> <input type="button" id="sample2" value="サンプル2" /> </p> </div> <script src="js/jquery.min.js"></script> <script src="js/jquery.backstretch.min.js"></script> <script> $.backstretch("sample01.jpg", {speed: 500}); $("#sample1").click(function() { $.backstretch("sample01.jpg"); }); $("#sample2").click(function() { $.backstretch("sample02.jpg"); }); </script> </body> --------------------- 上の記述ですが jqueryで背景が切り替わるサンプルをいただいてきました。 これに子ページを読ませました。 子ページ側に <p> <input type="button" id="sample1" value="サンプル1" /> <input type="button" id="sample2" value="サンプル2" /> </p> このボタンを貼りつけて、 親ページの背景を切り替えたいのですが、 子ページにはどのように記述すればよいのでしょうか。 どなたかお教えいただけませんでしょうか 何卒宜しくお願い致します

  • 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>

  • iframe子ページから親ページへのアクション

    iframe内(子ページ)の<input>をクリックすると、 親ページのアクションとして<a href="#wrap">●●●</a>の 「●●●」を押したときと同じアクションをしてほしいのです。。 <input type="submit" onclick="(function(){ window.parent.※※※※※(); }());" /> ↑みたいな感じで実現できるのでしょうか?(T_T)

    • ベストアンサー
    • HTML
  • iframe内から親ページに文字列追加

    サイト内でiframeを使っているのですが、iframe内のファイルを読み込んだとき、もしくはiframe内のリンクをクリックしたときに大元の親ページに文字列(リンク)を追加したいと考えています。 ・階層イメージ ([ ]内は内容)    index(親)[iframe(メイン)]          ↓      main(メイン) [iframe(子)(子へのリンクがある)]          ↓        child(子)[内容] 現在このようになっています。 childを読み込んだときか、mainの子へのリンクをクリックしたときにindexのほうに文字列(リンク)を追加したいのですが、どなたか方法をご存じの方はいらっしゃらないでしょうか? 当方はあまりHTMLには詳しいとは言えませんので、できれば具体的なタグなどで解説していただければありがたいです。 よろしくお願いします。

    • ベストアンサー
    • HTML
  • JavaScript 手作業から解放されたいのです

    今、インラインフレームにデータを読み込んで作表するサンプルを作成中です。 インラインフレームには select() メソッドが使えないために 手作業でテキストエリアに copy&pasteしている状態です。 この手作業から解放されたいのですが、どういうコードでできますか? スキルある方のお力添えをお待ちしております。 【親ページ】parent.html <body> <div>parent.html 親ページです.</div> <style> body { background: lavender; } .wrap { list-style-type: none; display: flex; width: 640px; padding: 1.5em; background: lightgreen; border-radius: 10px; } form > div { margin-top: 1em; font-weight: bold; } label { display: block; } pre b { color: red; } #iframe3 { width: 300px; height: 160px; background: #eee; } #textArea { margin-left: 10px; width: 300px; height: 160px; } </style> <pre> 【テーマ】子ページ内のデータで作表する <条件> ・子ページの情報で親ページに作表する ・ローカル環境(当然 Ajax(XMLHttpRequest)は対象外、new FileReader不使用) ・ファイルは、親子とも同じ場所 ・現在は、<b>読込ファイル選択 ▶ IFRAMEをCTRL+C ▶ TEXTAREAでCTRL+V ▶ 作表ボタン押下 ▶ 作表</b>  理想は、手作業を省略して、<b>読込ファイル選択 ▶ 作表</b> </pre> <ul class="wrap"> <li>(1)[IFRAME](理想は非表示に) <iframe id="iframe3" src="./20230515-child.tsv" title="子ページ"> </iframe> </li> <li> (2)[TEXTAREA](理想は非表示に) <textarea id="textArea" placeholder="貼付場所"></textarea> </li> </ul> <form name="form1"> <div>読込データファイルの選択</div> <label><input name="cbox" type="radio" value="0" checked> 1.TSVファイル (タブ区切り .tsv)</label> <label><input name="cbox" type="radio" value="1"> 2.HTMLファイル</label> </form> <p> <button id="button1">作表</button> <table id="listTable"></table> </p> <script> (function () { //エレメント const iframe = document.getElementById('iframe3'); const table = document.getElementById('listTable'); const textArea = document.getElementById('textArea'); const button1 = document.getElementById('button1'); //読み込みファイルの選択 document.form1.onchange = function(event) { let n = event.target.value; iframe.src = "./child." + ["tsv","html"][n]; } //作表処理 button1.onclick = function (){ // 値を全選択してコピー (※使用不可能) // iframe.select(); // var result = document.execCommand("copy"); //------------------------------------------------------------- // 整形 文字データの配列化 作表 // (略) //------------------------------------------------------------- }; })(); </script> </body> 【子ページ1】child.tsv 番号 名称 半径 衛星個数 1 水星 2,439 0 2 金星 6,051 0 3 地球 6,378 1 4 火星 3,396 2 5 木星 71,492 95 6 土星 60,268 104 7 天王星 25,559 27 8 海王星 24,764 14 9 冥王星 1,188 5 【子ページ2】child.html <pre> 番号 名称 半径 衛星個数 1 水星 2,439 0 2 金星 6,051 0 3 地球 6,378 1 4 火星 3,396 2 5 木星 71,492 95 6 土星 60,268 104 7 天王星 25,559 27 8 海王星 24,764 14 9 冥王星 1,188 5 </pre>

  • iframe内からjQueryで指定したい

    jQueryのparentで親要素のIDを収得したいのですが、iframe内から、 読み込み元のHTMLを.parent()で追っていくと、取得できません。 jQuery("div#main iframe").contents().find('body').click(function(){ var hoge = jQuery(this).parent().parent().attr("id"); alert(hoge); }); .parent()では読み込み元のHTMLをまでいけないようなんですが、jQueryでは取得できないのでしょうか。 他にiframeから親を取得する記述があるのでしょうか。 アドバイスいただけると助かります。 拙い説明で恐縮ですが、どうぞよろしくお願いします。 こちら↓の板が閉鎖されるのを知らずにポストしていまい、 http://www.tagindex.com/cgi-lib/q4bbs/patio.cgi 解決の見込みがなさそうですで、改めてこちらでお尋ねしています。 ややマルチ気味で恐縮ですが、ご容赦ください。

  • 渡された引数をインラインフレーム名として使うには

    現在、以下のような関数を使って 任意のインラインフレーム内の任意ID部分のHTMLを改変するスクリプトを作っています。 <script>  function func(framename,id) {   parent.framename.document.getElementById(id).innerHTML='';  } </script> <body>  <a href=# onclick="func('Frame1','ID1')">Frame1のID1を改変</a>  <iframe name="Frame1" src="javascript:document.write('<div id=ID1><p>ID1</p></div>')"></iframe> </body> つまり、インラインフレームの name と div要素の id を引数として関数に渡しているのですが、 上記のように書くと「parent.framename.document は Null またはオブジェクトではありません」とエラーが出てしまいます。 id の方はエラーなく処理できるようなのですが、 引数として渡した文字列を「フレーム名」として処理するにはどうすればよいのでしょうか? ご回答よろしくお願い致します。

  • iframeの中でページ内リンクはできますか?

    iframeを使って下記のようなつくりでHTMLを組んでみましたが、Chromeでリンクに飛ぶことができません。((1)をクリックすると(2)の位置に飛んでほしい) = A.html = <html> <body> <iframe src="B.html" scrolling="no" frameborder="0" width="750" height="2000"></iframe> </body> </html> = B.html = <html> <body> <a href="#CCC"><img src="xxx.jpg" /></a>…(1)   ・   ・   ・ <a href="C.html" name="CCC">あいうえお </a>…(2) </body> </html> ざっくりと書いてしまいましたが、親HTML(ここでいうA.html)では指示をせず、あくまでiframe中の子HTML(ここでいうB.html)の中でページ内リンクをしたいと思っています。 ちなみにiframeを使っていますが、ブラウザ上の見え方としては、A.htmlに1ページで組んでいるかのような形にしたいと思っています。 ネットでいろいろ調べてみましたがよくわからず、記述が悪いのか、Chromeではうまくいかないのか、悩んでおります。(Sarfari等、うまくいったブラウザもあるのですが…) よい方法がございましたら教えてください。 宜しくお願いします。

専門家に質問してみよう