web-dev-qa-db-fra.com

Exécution de <script> dans <div> récupéré par AJAX

Il y a un div appelé "Contenu":

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

Il devrait être rempli avec les données d'un fichier PHP, par AJAX, y compris une balise <script>. Cependant, le script à l'intérieur de cette balise n'est pas en cours d'exécution.

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

JavaScript inséré sous forme de texte DOM ne sera pas exécuté. Cependant, vous pouvez utiliser le modèle de script dynamic pour atteindre votre objectif. L'idée de base est de déplacer le script que vous souhaitez exécuter dans un fichier externe et de créer une balise de script lorsque vous obtenez votre réponse Ajax. Vous définissez ensuite l'attribut src de votre balise de script et le tour est joué, il charge et exécute le script externe.

Cet autre article de StackOverflow peut également vous être utile: Des scripts peuvent-ils être insérés avec innerHTML? .

60
Chocula

J'ai utilisé ce code, il fonctionne bien

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

Si vous chargez un bloc de script dans votre div via Ajax comme ceci:

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

... il met simplement à jour le DOM de votre page, myFunction () n'est pas nécessairement appelé. 

Vous pouvez utiliser une méthode de rappel Ajax telle que celle de la méthode ajax () de jQuery pour définir les tâches à exécuter à la fin de la demande. 

Ce que vous faites est différent du chargement d’une page avec JavaScript inclus dès le départ (qui est exécuté).

Voici un exemple d'utilisation du rappel de succès et du rappel d'erreur après l'extraction de contenu:

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

Un autre moyen rapide et dangereux consiste à utiliser eval () pour exécuter tout code de script que vous avez inséré en tant que texte DOM si vous ne souhaitez pas utiliser jQuery ou une autre bibliothèque.

12
Christopher Tokar

Voici le script qui évaluera toutes les balises de script dans le texte.

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);
  }
}

Appelez simplement cette fonction après avoir reçu votre code HTML du serveur. Soyez averti: utiliser eval peut être dangereux.

Démo: http://plnkr.co/edit/LA7OPkRfAtgOhwcAnLrl?p=preview

8
Evgenii

Cela "fonctionne" pour moi avec jQuery, à condition que vous n'essayiez pas d'ajouter un sous-ensemble du code HTML renvoyé par XHR au document. (Voir ce rapport de bogue montrant le problème avec jQuery.)

Voici un exemple montrant qu'il fonctionne:

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

Voici l'équivalent de ce qui précède: http://jsfiddle.net/2CTLH/

4
Phrogz

Si vous injectez quelque chose qui nécessite la balise script, vous pouvez obtenir une erreur de syntaxe uncaught et dire un jeton illégal . Pour éviter cela, veillez à échapper les barres obliques dans vos balises de script de fermeture. c'est à dire;

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

Il en va de même pour les balises de fermeture, telles que les balises de formulaire.

2
TommyRay

Voici une fonction que vous pouvez utiliser pour analyser les réponses AJAX, en particulier si vous utilisez minifiedjs et souhaitez exécuter le code JavaScript renvoyé ou si vous souhaitez simplement analyser les scripts sans les ajouter au DOM, il gère également les erreurs d'exception. J'ai utilisé ce code dans la bibliothèque php4sack et c'est utile en dehors de la bibliothèque.

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
Andre Van Zuydam

Ma conclusion est que HTML n'autorise pas les balises NESTED SCRIPT. Si vous utilisez du javascript pour injecter du code HTML incluant des balises de script, cela ne fonctionnera pas, car le javascript est également associé à une balise de script. Vous pouvez le tester avec le code suivant et vous constaterez qu'il ne fonctionnera pas. Le cas d'utilisation est que vous appelez un service avec AJAX ou similaire, vous obtenez du code HTML et vous souhaitez l'injecter directement dans le DOM HTML. Si le code HTML injecté contient des balises SCRIPT, cela ne fonctionnera pas. 

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

J'ai eu un post similaire ici, addEventListener charge sur ajax load SANS jQuery

La façon dont j'ai résolu le problème était d'insérer des appels à des fonctions dans ma fonction stateChange. La page que j'avais configurée était composée de 3 boutons permettant de charger 3 pages différentes dans la zone contentArea. Comme je devais savoir quel bouton était enfoncé pour charger la page 1, 2 ou 3, je pouvais facilement utiliser les instructions if/else pour déterminer quelle page était en cours de chargement et quelle fonction exécuter. Ce que j’essayais de faire, c’était d’enregistrer différents écouteurs de boutons qui ne fonctionneraient que lorsque la page spécifique était chargée à cause des ID d’élément.

alors...

si (page1 est en cours de chargement, pageload = 1) exécuter la fonction registerListeners1

alors la même chose pour la page 2 ou 3.

0
Richard Chase

Cela a fonctionné pour moi en appelant eval sur chaque contenu de script depuis ajax .done:

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

Note: Je n'ai pas écrit les paramètres dans $ .ajax que vous devez ajuster selon votre ajax.

0
shivgre