J'ai un script qui insère du contenu dans un élément en utilisant innerHTML
.
Le contenu pourrait par exemple être:
<script type="text/javascript">alert('test');</script>
<strong>test</strong>
Le problème est que le code à l'intérieur de la <script>
balise n'est pas exécuté. Je l'ai googlé un peu mais il n'y avait pas de solutions apparentes. Si j'ai inséré le contenu à l'aide de jQuery, $(element).append(content);
les parties du script ont eval
été injectées dans le DOM.
Quelqu'un a-t-il un extrait de code qui exécute tous les <script>
éléments? Le code jQuery était un peu complexe, donc je ne pouvais pas vraiment comprendre comment cela était fait.
Modifier :
En jetant un œil dans le code jQuery, j'ai réussi à comprendre comment jQuery le fait, ce qui a abouti au code suivant:
Demo:
<div id="element"></div>
<script type="text/javascript">
function insertAndExecute(id, text)
{
domelement = document.getElementById(id);
domelement.innerHTML = text;
var scripts = [];
ret = domelement.childNodes;
for ( var i = 0; ret[i]; i++ ) {
if ( scripts && nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
}
}
for(script in scripts)
{
evalScript(scripts[script]);
}
}
function nodeName( elem, name ) {
return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
}
function evalScript( elem ) {
data = ( elem.text || elem.textContent || elem.innerHTML || "" );
var head = document.getElementsByTagName("head")[0] || document.documentElement,
script = document.createElement("script");
script.type = "text/javascript";
script.appendChild( document.createTextNode( data ) );
head.insertBefore( script, head.firstChild );
head.removeChild( script );
if ( elem.parentNode ) {
elem.parentNode.removeChild( elem );
}
}
insertAndExecute("element", "<scri"+"pt type='text/javascript'>document.write('This text should appear as well.')</scr"+"ipt><strong>this text should also be inserted.</strong>");
</script>
javascript
dom
eval
innerhtml
Phidah
la source
la source
function testFunction(){ alert('test'); }
au code inséré dans innerHTML, et que j'essaye de l'appeler, cela indique que la fonction n'est pas définie.Réponses:
Le script de l'OP ne fonctionne pas dans IE 7. Avec l'aide de SO, voici un script qui fait:
la source
$(parent).html(code)
- voir ma réponse ci-dessous.if (nodeName(child, "script" ) && (!child.type || child.type.toLowerCase() === "text/javascript")) { scripts.push(child); } else { exec_body_scripts(child); }
elem.src
et définir de manière conditionnelle lasrc
propriété de l'élément de script créé au lieu de définir son contenu textuel.eval
astuce globale au lieu de créer un<script>
élément et de l'insérer dans le<head>
? Ils exécutent tous les deux du code JS sans exposer la fermeture actuelle.@phidah ... Voici une solution très intéressante à votre problème: http://24ways.org/2005/have-your-dom-and-script-it-too
Donc, cela ressemblerait à ceci à la place:
<img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" />
la source
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" onload="alert('test');">
si vous souhaitez empêcher une requête http inutile.style="display:none;
) pour masquer l'icône d'image cassée<style>
c'est mieux que<img>
, car il ne fait pas de demande de réseauVoici un script plus court et plus efficace qui fonctionne également pour les scripts avec la
src
propriété:Remarque: bien que cela
eval
puisse causer une faille de sécurité s'il n'est pas utilisé correctement, c'est beaucoup plus rapide que de créer une balise de script à la volée.la source
eval
été conçu pour blesser les utilisateurs. Toute exécution de script dynamique est un risque et c'est pourquoi CSP l'appelle'unsafe-eval'
parce que c'est le cas. Vous nuit également à la sécurité de vos sites si vous l'utilisez dans une bibliothèque car ils ne peuvent pas le désactiver.src
propriété seront téléchargés de manière asynchrone et exécutés comme arrivés. La commande n'est pas conservée. Les scripts en ligne seront également exécutés dans le désordre, de manière synchrone avant les scripts asynchrones.Vous ne devez pas utiliser la propriété innerHTML mais plutôt la méthode appendChild du Node: un nœud dans une arborescence de documents [HTML DOM]. De cette façon, vous pourrez appeler ultérieurement votre code injecté.
Assurez-vous que vous comprenez que ce
node.innerHTML
n'est pas la même chose quenode.appendChild
. Vous voudrez peut-être passer un peu de temps sur la référence du client Javascript pour plus de détails et le DOM. J'espère que ce qui suit vous aidera ...L'injection d'échantillon fonctionne:
Cordialement,
la source
try this, look how clever I am
réponses. Mérite un UV, il a le mien.var _in = document.getElementById(inject);
, Je pense.Version ES6 simplifiée de la réponse de @ joshcomley avec un exemple.
Pas de JQuery, pas de bibliothèque, pas d'évaluation, pas de changement DOM, juste du Javascript pur.
http://plnkr.co/edit/MMegiu?p=preview
Usage
la source
setInnerHtml
passetInnerHTML
setInnerHTML
mais il est appelé àsetInnerHtml
partir de larunB
fonction. Par conséquent, l'exemple ne fonctionne pasEssayez cet extrait:
la source
Cela fonctionne dans Chrome dans mon projet
la source
Une solution sans utiliser "eval":
Cela clone essentiellement la balise de script, puis remplace la balise de script bloquée par la balise nouvellement générée, permettant ainsi l'exécution.
la source
scriptNode.innerHTML = code
n'a pas fonctionné pour IE. La seule chose à faire est de remplacer parscriptNode.text = code
et cela fonctionne bienla source
Il est plus facile d'utiliser jquery
$(parent).html(code)
au lieu deparent.innerHTML = code
:Cela fonctionne également avec les scripts qui utilisent
document.write
et les scripts chargés via l'src
attribut. Malheureusement, même cela ne fonctionne pas avec les scripts Google AdSense.la source
Faites simplement:
la source
Vous pouvez jeter un œil à ce post . Le code pourrait ressembler à ceci:
la source
Grâce au script de Larry, qui fonctionnait parfaitement bien dans IE10, voici ce que j'ai utilisé:
la source
Prolongement de Larry. Je l'ai fait rechercher récursivement tout le bloc et les nœuds enfants.
Le script appellera désormais également des scripts externes spécifiés avec le paramètre src. Les scripts sont ajoutés à l'en-tête au lieu d'être insérés et placés dans l'ordre dans lequel ils sont trouvés. Les scripts de commande sont donc spécifiquement préservés. Et chaque script est exécuté de manière synchrone, de la même manière que le navigateur gère le chargement initial du DOM. Donc, si vous avez un bloc de script qui appelle jQuery depuis un CDN et que le nœud de script suivant utilise jQuery ... Pas de problème! Oh et j'ai étiqueté les scripts ajoutés avec un identifiant sérialisé basé sur ce que vous avez défini dans le paramètre de balise afin que vous puissiez trouver ce qui a été ajouté par ce script.
la source
Essayez ceci, cela fonctionne pour moi sur Chrome, Safari et Firefox:
Une chose à noter cependant, c'est que le script imbriqué div suivant ne fonctionnera PAS:
Pour qu'un script s'exécute, il doit être créé en tant que nœud puis ajouté en tant qu'enfant. Vous pouvez même ajouter un script à l'intérieur d'un div précédemment injecté et il s'exécutera (j'ai déjà rencontré cela lorsque j'essayais de faire fonctionner le code du serveur publicitaire):
la source
Expansion de la réponse de Lambder
Vous pouvez utiliser une image base64 pour créer et charger votre script
Ou si vous en avez un,
Iframe
vous pouvez l'utiliser à la placela source
J'avais besoin de quelque chose de similaire, mais j'avais besoin que le script reste ou soit recréé au même endroit que le script d'origine, car mon script cible l'emplacement de la balise de script dans le DOM pour créer / cibler des éléments. J'ai également rendu le script récursif pour m'assurer qu'il fonctionne également s'il est inférieur à plus d'un niveau.
REMARQUE: j'utilise
const
ici, si vous avez un navigateur plus ancien, utilisez simplementvar
.la source
Fait cette nouvelle fonction d'aide dans TypeScript, peut-être que quelqu'un l'appréciera. Si vous supprimez la déclaration de type du paramètre de script, il ne s'agira que de JS.
la source
Essayez la fonction eval ().
Ceci est un exemple réel d'un projet que je développe. Merci à ce post
la source
Voici ma solution dans un projet récent.
la source