Je souhaite ajouter un extrait de code JavaScript dans un iFrame existant de la page à l'aide de jQuery. J'ai le code suivant...
Code:
content = "<script>" + js_code + "</script>";
$('#iframe_id').contents().find('body').append(content);
Mais d'une certaine manière, cela ne fonctionne pas. J'ai vérifié certaines des réponses existantes/associées, et il semble que jQuery ne reconnaisse pas tout à fait les balises de script en tant que ... balises de script. L'iFrame se trouve dans le même domaine/le même port/le même hôte. Il n'y a donc aucun problème de script intersite, etc. Comment puis-je résoudre ce problème?
Le problème est que l’analyseur HTML devient confus si votre script contient la balise de script de fermeture (</script>
) et ferme la balise de script prématurément.
La solution est d'échapper au /
dans "<\/script>"
. Cela fonctionne parce que les chaînes en JavaScript (et certaines autres langues), toutes les séquences d'échappement invalides sont simplement ignorées, donc "\l"
est traité en tant que "l"
et "\/"
en tant que "/"
. L'analyseur HTML, cependant, n'utilise pas de barre oblique inversée pour les échapper, de sorte qu'il ne soit pas confus (crédits de https://stackoverflow.com/users/405681/keaukraine ).
var scriptTag = "<script>alert(1)<\/script>";
$("#iframe").contents().find("body").append(scriptTag);
Solution originale
Casser cette balise de fermeture afin de ne pas gâcher l'analyseur HTML. Les autres solutions de cette page fonctionnent car elles n'ont jamais la chaîne </script>
dans leur code
var scriptTag = "<script>alert(1)<";
scriptTag += "/script>";
console.log(scriptTag);
$("#iframe").contents().find("body").append(scriptTag);
function putScriptInIframes(script, scriptId) {
var $iframes = $('iframe');
$iframes.each(function () {
var thisDoc = this.contentWindow.document;
if ( ! thisDoc.getElementById(scriptID)) {
var scriptObj = thisDoc.createElement("script");
scriptObj.type = "text/javascript";
scriptObj.id = scriptId;
scriptObj.innerHTML = script;
thisDoc.body.appendChild(scriptObj);
}
});
}
C'était la façon la plus simple de le faire fonctionner.
var script = "alert('hello world');";
$('#iframe').contents().find('body').append($('<script>').html(script))
fonctionne dans Fiddle
Vous devez vous échapper du /script
.
Faites comme google analytics par exemple
$("#iframe").contents().find("body").append(decodeURI("**%3Cscript%3E** alert(2) **%3C/script%3E**"));
remplace les script
et /script
par ces échappés
J'espère que ça aide.
Étant donné que l’iframe s’exécute à sa propre window
, vous devrez également injecter l’importation du fichier jquery.js.
<script type="text/javascript" src="/jquery/jquery-ui-1.9.1.custom.js"></script>
EDIT: J'ai donc joué un peu plus avec ça et voici ce que j'ai trouvé.
HTML
<iframe id="frame"></iframe>
JS
$("#frame").attr(
"src", "data:text/html;charset=utf-8," +
"<html>" +
"<style>.red {color: red}</style>" +
"<div class=\"test\">Test</test>" +
"<script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js\"><" + "/script>" +
"<script>$(function(){ $(\".test\").addClass(\"red\")});<" + "/script>" +
"</html>"
);
Cela fonctionne, voir ici http://jsfiddle.net/WsCxj/ .
Donc, il y a plusieurs points:
Je passe tout le contenu en une seule chaîne. Vous devez préfixer data:text/html;charset=utf-8,
et ensuite vous pouvez définir votre chaîne en tant que src de l'iframe.
J'ajoute le fichier jquery.js avec un chemin absolu} - Cela semble être important, sans doute parce que le cadre n'a pas de chemin par lui-même car son contenu est généré dynamiquement.
Je divise la balise de fin de script comme suit: <" + "/script>
car au moins firefox tente de terminer le script à ce stade. L’approche plus propre consisterait probablement à avoir le fichier js sous forme de fichier totalement séparé.
Vous n'avez pas besoin d'ajouter un script de balise pour exécuter JavaScript, vous pouvez créer une fonction et appliquer le contexte iframe ...
en utilisant eval
function initFrame (code){
eval (code);
}
initFrame.apply ($('#iframe').contents(),[js_code]);
Sans eval
var initFrame = new Function(js_code);
initFrame.apply ($('#iframe').contents(),[]);
Je ne peux pas commenter votre dernier message, car je suis nouveau ici et je n’ai pas assez de réputation, mais comme je l’ai dit dans mon message, le problème se trouvait dans/script.
Donc, y échapper (comme Google le fait par exemple) est peut-être la meilleure option ...
Eh bien, la bonne nouvelle est que le problème est résolu;)
Cordialement