AJAX呼び出し後にinnerHTMLによって挿入された<script>を実行する


99

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

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

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

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

divをどのように読み込んでいますか?使用するライブラリによって異なりますが、通常、ajaxのロード後にスクリプトを実行するかどうかを制御できます。
Bill Yang

1
スクリプトを含むdivのコンテンツを含む別の(php)ページをリクエストwindow.onloadするXMTHttpRequestオブジェクトを作成した後。私はこれを単純なJS、ライブラリなし(自分のlol以外)で実行しています
JCOC611

回答:


65

DOMテキストとして挿入されたJavaScriptは実行されません。ただし、動的スクリプトパターンを使用して目的を達成できます。基本的なアイデアは、実行するスクリプトを外部ファイルに移動し、Ajax応答を受け取ったときにスクリプトタグを作成することです。次にsrc、スクリプトタグと出来上がりの属性を設定すると、外部スクリプトが読み込まれて実行されます。

このStackOverflowの他の投稿も参考になります。innerHTMLでスクリプトを挿入できますか?


あなたは()関数をすべてロードされたスクリプトを選択し、evalをすることによって、それらを実行することができます$('#audit-view script').each(function (index, element) { eval(element.innerHTML); })
イェジーGebler

ページに追加されたJavaScriptは絶対に実行する必要があります。(たとえばjsfiddle.net / wnn5fz3m / 1)。問題はなぜそれが時々しないのですか?
NoBugs 2015年

@Choculaスクリプトを別のファイルに移動しましたが、それでもパーシャルからは機能しません。stackoverflow.com/questions/42941856/...
Samra

参考までに(@NoBugsは私に手掛かりを与えます)。私は単純なjavascirpt element.innerHTML = zzzを試してみましたが、うまくいきませんでした。次に、Jquery $(element).html(zzz)を試してみました。
gtryonp

66

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

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

4
私に尋ねると、これは受け入れられたものよりもはるかに良い答えです。これは、ほとんどJavaScriptインジェクションです。
Xedret 2013

これは便利ですが、スクリプト実行されない理由の質問には実際には答えません。たとえば、jsfiddle.net / fkqmcaz7jsfiddle.net/wnn5fz3m/1を参照してください。これは完全に実行されるはずであり、機能しない単純なケースは見つかりません。
NoBugs 2015年

1
@NaoiseGolden OPは文字通りスクリプトの実行について質問しているので、ここでは問題ないと思います。:-)
thedayturns

1
Eval()は強く推奨されていません。-この参照してくださいstackoverflow.com/questions/9107847/...
キングス

15

次のようにAjaxを介してdiv内にスクリプトブロックをロードすると、

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

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

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

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

一部のコンテンツをフェッチした後の成功コールバックとエラーコールバックの使用方法の例:

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

jQueryまたはその他のライブラリを使用したくない場合は、eval()を使用して、DOMテキストとして挿入したスクリプトコードを実行することもできます。


jQueryのコールバックを使用して、新しい<script>内のコードを「実行」するにはどうすればよいですか?
JCOC611、2011年

私は成功コールバックを使用しての例を追加しました:
クリストファーTokar

1
どうもありがとうございます!「myFunction();」一部は、コードから除外していたものでした。
Jason

11

これは、テキスト内のすべてのスクリプトタグを評価するスクリプトです。

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


5

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/


1
非常に古いバージョンのjQueryのバグであったため、これが現在の問題の解決策になる可能性はほとんどありません。
NoBugs 2015年

3

以下は、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

スクリプトタグを必要とする何かを挿入している場合、キャッチされていない構文エラーが発生し、違法なトークンと言う可能性があります。これを回避するには、終了スクリプトタグでスラッシュをエスケープしてください。すなわち;

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

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


0

私はここに同様の投稿をしました、jQueryなしのajaxロードでのaddEventListenerロード

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

そう...

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

次に、ページ2または3についても同じです。


0

これは、ajax .doneから各スクリプトコンテンツでevalを呼び出すことによって私のために働きました:

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

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


0

私の結論は、HTMLはNESTED SCRIPTタグを許可しないということです。JavaScriptタグを含む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>

-3

もう1つのことは、次のようなスクリプトを使用してページをロードすることです。

<div id="content" onmouseover='myFunction();$(this).prop( 'onmouseover', null );'>
<script type="text/javascript">
function myFunction() {
  //do something
}
myFunction();
</script>
</div>

これにより、ページが読み込まれ、スクリプトが実行され、関数が実行されたときにイベントハンドラーが削除されます。これはajaxロードの直後には実行されませんが、ユーザーがdiv要素を入力するのを待っている場合は、これで問題ありません。

PS。jqueryが必要

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.