web-dev-qa-db-ja.com

動的に作成された<iframe>に<script>を追加すると、親ページでスクリプトが実行されるように見えるのはなぜですか?

JavaScriptを使用して<iframe>を作成し、その<iframe>に<script>要素を追加しようとしています。これを<iframe> dドキュメントのコンテキストで実行します。

残念ながら、何か間違ったことをしているようです-JavaScriptは正常に実行されているように見えますが、<script>のコンテキストは<iframe> dドキュメントではなく親ページです。また、ブラウザがiframe_test.jsを要求すると、Firebugの[Net]タブで301エラーが発生します。成功しました。

これは私が使用しているコードです( http://onespot.wsj.com/static/iframe_test.html のライブデモ):

iframe_test.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>&lt;iframe&gt; test</title>
  </head>
  <body>
    <div id="bucket"></div>
    <script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
    <script type="text/javascript">
      $(document).ready(function() {
        $('#bucket').append('<iframe id="test"></iframe>');
        setTimeout(function() {
          var iframe_body = $('#test').contents().find('body');
          iframe_body.append('<scr' + 'ipt type="text/javascript" src="http://onespot.wsj.com/static/iframe_test.js"></scr' + 'ipt>');
        }, 100);
      });
    </script>
  </body>
</html>

iframe_test.js

$(function() {
  var test = '<p>Shouldn\'t this be inside the &lt;iframe&gt;?</p>';
  $('body').append(test);
});

珍しいと思われることの1つは、iframe_test.jsのコードでも機能することです。 <iframe>自体にはjQueryをロードせず、親ドキュメントにのみロードしました。それは私にとって手がかりのように思えますが、それが何を意味するのかわかりません。

どんなアイデア、提案なども大歓迎です!

45
Bungle

同じ問題を抱えていたので、解決策を見つけるのに何時間もかかりました。 iframeのドキュメントを使用して、スクリプトのオブジェクトを作成するだけです。

var myIframe = document.getElementById("myIframeId");
var script = myIframe.contentWindow.document.createElement("script");
script.type = "text/javascript";
script.src = src;
myIframe.contentWindow.document.body.appendChild(script);

魔法のように機能します!

70
Oleg Grishko

私は元の質問に対する答えを見つけられませんでしたが、(少なくとも私の目的では)さらに良く機能する別のアプローチを見つけました。

これは親ページでjQueryを使用しません(実際にはそこにロードしないほうがよいので、これは良いことです)が、明らかに完全に有効で使用可能な方法でjQueryを<iframe>にロードします。私がしているのは、<iframe>のドキュメントオブジェクトを最初から作成した新しいオブジェクトで上書きすることです。これにより、<iframe>のドキュメントオブジェクトに書き込む<script>要素を文字列に含めることができます。

コード:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>frame</title>
  </head>
  <body>

    <div id="test"></div>

    <script type="text/javascript">
      // create a new <iframe> element
      var iframe = document.createElement('iframe');

      // append the new element to the <div id="bucket"></div>
      var bucket = document.getElementById('test');
      bucket.appendChild(iframe);

      // create a string to use as a new document object
      var val = '<scr' + 'ipt type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></scr' + 'ipt>';
      val += '<scr' + 'ipt type="text/javascript"> $(function() { $("body").append("<h1>It works!</h1>"); }); </scr' + 'ipt>';

      // get a handle on the <iframe>d document (in a cross-browser way)
      var doc = iframe.contentWindow || iframe.contentDocument;
      if (doc.document) {
        doc = doc.document;
      }

      // open, write content to, and close the document
      doc.open();
      doc.write(val);
      doc.close();
    </script>

  </body>
</html>

これが誰かの助けになることを願っています!

16
Bungle

元の質問への答えは簡単です-スクリプトの実行はjqueryによって行われ、jqueryはトップフレームにロードされるため、どこに追加してもスクリプトが実行されます。 jqueryのよりスマートな実装は、間違いなく正しいウィンドウオブジェクトを使用することはできませんが、今のところはそうです。

回避策については、すでに2つの良い答えがあります(1つは自分の答えであっても)。私が追加するかもしれないことは、これらの回避策の1つを使用してjquery.jsをiframeに含めることができ、追加のマークアップを挿入するために一番上のものの代わりにそのjqueryオブジェクトを取得することです...

0
user2107721