web-dev-qa-db-ja.com

AJAXによって取得された<div>内の<script>の実行

「コンテンツ」というdivがあります。

<div id="content"></div>

PHPファイルからのデータで、AJAXによって<script>タグを含めて入力する必要があります。ただし、このタグ内のスクリプトは実行されていません。

<div id="content"><!-- After AJAX loads the stuff that goes here -->
   <script type="text/javascript">
     //code
   </script>
   <!-- More stuff that DOES work here -->
</div>
91
JCOC611

DOMテキストとして挿入されたJavaScriptは実行されません。ただし、 動的スクリプトパターン を使用して目標を達成できます。基本的な考え方は、実行するスクリプトを外部ファイルに移動し、Ajax応答を取得したときにスクリプトタグを作成することです。次に、スクリプトタグのsrc属性を設定し、外部スクリプトをロードして実行します。

この他のStackOverflowの投稿も役立つ場合があります: innerHTMLでスクリプトを挿入できますか?

61
Chocula

私はこのコードを使用しました、それはうまく機能しています

var arr = MyDiv.getElementsByTagName('script')
for (var n = 0; n < arr.length; n++)
    eval(arr[n].innerHTML)//run script inside div
57
Firas Nizam

次のようにAjaxを介してdiv内にスクリプトブロックを読み込む場合:

<div id="content">
    <script type="text/javascript">
    function myFunction() {
      //do something
    }
    myFunction();
    </script>
</div>

...ページのDOMを更新するだけで、myFunction()は必ずしも呼び出されません。

JQueryの ajax() メソッドのようなAjaxコールバックメソッドを使用して、リクエストが終了したときに実行するものを定義できます。

あなたがしていることは、get-go(実行されます)からJavaScriptが含まれているページをロードすることとは異なります。

いくつかのコンテンツを取得した後に成功コールバックとエラーコールバックを使用する方法の例:

  $.ajax({
    type: 'GET',
    url: 'response.php',
    timeout: 2000,
    success: function(data) {
      $("#content").html(data);
      myFunction();
    },
    error: function (XMLHttpRequest, textStatus, errorThrown) {
      alert("error retrieving content");
    }

もう1つの手っ取り早い方法は、jQueryまたは他のライブラリを使用したくない場合に eval() を使用して、DOMテキストとして挿入したスクリプトコードを実行することです。

13

テキスト内のすべてのスクリプトタグを評価するスクリプトを次に示します。

function evalJSFromHtml(html) {
  var newElement = document.createElement('div');
  newElement.innerHTML = html;

  var scripts = newElement.getElementsByTagName("script");
  for (var i = 0; i < scripts.length; ++i) {
    var script = scripts[i];
    eval(script.innerHTML);
  }
}

サーバーからHTMLを受け取った後にこの関数を呼び出すだけです。警告:evalを使用すると危険です。

デモ: http://plnkr.co/edit/LA7OPkRfAtgOhwcAnLrl?p=preview

8
Evgenii

XHRから返されたHTMLのサブセットをドキュメントに追加しようとしない限り、これはjQueryを使用して「機能します」。 ( このバグレポート jQueryの問題を示すを参照してください。)

動作を示す例を次に示します。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html lang="en"> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <title>test_1.4</title> 
    <script type="text/javascript" charset="utf-8" src="jquery.1.4.2.js"></script> 
    <script type="text/javascript" charset="utf-8"> 
        var snippet = "<div><span id='a'>JS did not run<\/span><script type='text/javascript'>" +
        "$('#a').html('Hooray! JS ran!');" +
        "<\/script><\/div>";
        $(function(){
            $('#replaceable').replaceWith($(snippet));
        });
    </script> 
</head> 
<body> 
    <div id="replaceable">I'm going away.</div> 
</body> 
</html>

これは上記と同等です: http://jsfiddle.net/2CTLH/

4
Phrogz

スクリプトタグを必要とするものを注入している場合、キャッチされていない構文エラーと不正なトークンが表示される場合があります。これを回避するには、必ず終了スクリプトタグのスラッシュをエスケープしてください。すなわち;

var output += '<\/script>';

フォームタグなどの終了タグについても同様です。

2
TommyRay

AJAX応答を解析するために使用できる関数は次のとおりです。特にminifiedjsを使用して返されたJavascriptを実行する場合、またはDOMに追加せずにスクリプトを解析する場合、例外エラーを次のように処理します。まあ。私はこのコードをphp4sackライブラリーで使用しましたが、ライブラリーの外部で役立ちます。

function parseScript(_source) {
    var source = _source;
    var scripts = new Array();

    // Strip out tags
    while(source.toLowerCase().indexOf("<script") > -1 || source.toLowerCase().indexOf("</script") > -1) {
        var s = source.toLowerCase().indexOf("<script");
        var s_e = source.indexOf(">", s);
        var e = source.toLowerCase().indexOf("</script", s);
        var e_e = source.indexOf(">", e);

        // Add to scripts array
        scripts.Push(source.substring(s_e+1, e));
        // Strip from source
        source = source.substring(0, s) + source.substring(e_e+1);
    }

    // Loop through every script collected and eval it
    for(var i=0; i<scripts.length; i++) {
        try {
          if (scripts[i] != '')
          {         
            try  {          //IE
                  execScript(scripts[i]);   
      }
      catch(ex)           //Firefox
      {
        window.eval(scripts[i]);
      }   

            }  
        }
        catch(e) {
            // do what you want here when a script fails
         // window.alert('Script failed to run - '+scripts[i]);
          if (e instanceof SyntaxError) console.log (e.message+' - '+scripts[i]);
                    }
    }
// Return the cleaned source
    return source;
 }
2

私の結論は、HTMLはネストされたスクリプトタグを許可しないということです。内部にスクリプトタグを含むHTMLコードを挿入するためにJavaScriptを使用している場合、JavaScriptはスクリプトタグにも挿入されるため機能しません。次のコードでテストできますが、動作しません。ユースケースは、AJAXまたは同様のサービスを呼び出している場合、HTMLを取得していて、HTML DOMに直接挿入したい場合です。挿入されたHTMLコードの内部にSCRIPTタグがある場合、機能しません。

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"></head><body></body><script>document.getElementsByTagName("body")[0].innerHTML = "<script>console.log('hi there')</script>\n<div>hello world</div>\n"</script></html>
0
Antonio Martin

ここでも似たような投稿がありました jqueryなしのajaxロードでのaddEventListenerロード

どのように解決したかは、stateChange関数内に関数の呼び出しを挿入することでした。私が設定したページは、3つの異なるページをcontentAreaにロードする3つのボタンでした。ページ1、2、または3をロードするためにどのボタンが押されているかを知る必要があるため、if/elseステートメントを使用して、どのページがロードされ、次にどの機能を実行するかを簡単に判断できます。私がやろうとしていたことは、要素IDのために特定のページがロードされたときにのみ動作する異なるボタンリスナーを登録することでした。

そう...

(page1がロードされている場合、pageload = 1)関数registerListeners1を実行します

ページ2または3でも同じです。

0
Richard Chase

これは、ajax .doneの各スクリプトコンテンツでevalを呼び出すことで機能しました。

$.ajax({}).done(function (data) {      
    $('div#content script').each(function (index, element) { eval(element.innerHTML); 
})  

注:$ .ajaxには、ajaxに応じて調整する必要があるパラメーターを記述しませんでした。

0
shivgre