22

I want to add a JavaScript snippet into an existing iFrame in the page using jQuery. I have the following code...

Code:

content = "<script>" + js_code + "</script>";

$('#iframe_id').contents().find('body').append(content);

But somehow this is not working. I checked some of the existing/related answers, and it seems jQuery does not quite recognize the script tags as...script tags. The iFrame is in the same domain/same port/same host, so there is no issue about cross-site scripting etc. How can I fix this?

8
  • Please post ALL relevant code. Commented Aug 21, 2013 at 23:59
  • Yes...the content iFrame belongs to me, basically the same domain Commented Aug 22, 2013 at 0:01
  • @Gandalf Is the snippet embedded within markup (<script>...</script>) or in an separate .js file? Commented Aug 22, 2013 at 0:36
  • this snippet will be inside (script) tags only... Commented Aug 22, 2013 at 5:31
  • interesting.. what about to try this: frames[0].window.$ = frames[0].window.jQuery = window.$; Commented Sep 1, 2013 at 4:18

8 Answers 8

31

The problem is that the HTML parser gets confused if your script contains the closing script tag in it (</script>) and it closes the script tag prematurely.

The solution is to escape the / in "<\/script>". This works because strings in JavaScript, (and some other languages), any invalid escape sequences are just ignored, so "\l" is treated as "l", and "\/" is treated as "/". The HTML parser, however, doesn't use a backslash to escape them so it doesn't get confused (credits to https://stackoverflow.com/users/405681/keaukraine).

var scriptTag = "<script>alert(1)<\/script>";
$("#iframe").contents().find("body").append(scriptTag);

Original solution

Break up that closing tag so you don't mess up the HTML parser. The other solutions on this page work because they never have the string </script> in their code (jsfiddle):

var scriptTag = "<script>alert(1)<";
scriptTag +=  "/script>";
console.log(scriptTag);
$("#iframe").contents().find("body").append(scriptTag);

Or (jsfiddle):

var scriptTag = "<script>alert(1)<"+"/script>";
$("#iframe").contents().find("body").append(scriptTag);
Sign up to request clarification or add additional context in comments.

3 Comments

Just escape slash: var scriptTag = "<script>alert(1)<\/script>"; - jsfiddle.net/tLHn5
@keaukraine That's an awesome technique, never seen it before since there's no need to escape forward slashes. I'm wondering if that behavior is specified though.
escaping the slash worked perfectly. I put my script tags straight into the src with no issues
8
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);
        }
    });
}

This was the simplest way I could make it work.

Comments

5
var script = "alert('hello world');";
$('#iframe').contents().find('body').append($('<script>').html(script))

works in Fiddle

9 Comments

Care to explain what the difference is? I see it works, but don't understand why
I believe the difference is the same as the difference between the text() method and the html() method in jQuery. if you are appending a string, it might not be evaluated as html
then it must have to do with the script tags specifically.
@JuanMendes It's not entirely clear why the original didn't work, but guessing the snippet is in a <script> element, where mentioning </script> would close the element rather than keep as a String value. This avoids mentioning it.
@JonathanLonowski That's correct, I added an answer explaining it as you typed this comment.
|
4

You need to escape the /script. It apears.

Do like google analitcs for instance

 $("#iframe").contents().find("body").append(decodeURI("**%3Cscript%3E** alert(2)  **%3C/script%3E**")); 

replace the script and /script with this escaped ones

Hope it helps.

3 Comments

This works, but it still doesn't make sense in my mind, please add an explanation
well.. i suppose that jQuery is doing some kind of validation with scripts.
It's not jquery, I found the problem, posting an answer
2

As the iframe runs as it's own window, you will have to also inject the import of the jquery.js file.

<script type="text/javascript" src="/jquery/jquery-ui-1.9.1.custom.js"></script>

EDIT: So I played with this a bit more and here is what I came up with.

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

This works, see here http://jsfiddle.net/WsCxj/.

So there are several points:

  1. I am passing the entire content as one string. You have to prepend data:text/html;charset=utf-8, and then you can set your string as src of the iframe.

  2. I am adding the jquery.js file with an absolute path - This seems to be important, presumably because the frame has no path by itself as it's content is dynamically generated.

  3. I split the script end tag like this <" + "/script> because at least firefox tries to end the actual script at this point. The cleaner approach would probably be to have the js as totally separate file.

5 Comments

Hmm... Did you try building the entire content as one string and then setting it as the src attribute of the iframe?
l="<script"+" src"+"=\"code.jquery.com/jquery-1.9.1.js\">"+"<"+"/"+"script>"; $('#iframe_id').contents().find('body').append(l);
@Gandalf see edits, that works. You can probably take this and make it also work using your jQuery approach, but usually string building HTML is anyways faster that doing it in jQuery.
In IE9, the iframe says "The webpage cannot be displayed" error. Any reason?
IE might need a little special treatment, check this thread: stackoverflow.com/questions/16504816/…
1

You don't need add a tag script to execute javascript, you can do a function and apply iframe context...

using eval

function initFrame (code){

    eval (code);

}

initFrame.apply ($('#iframe').contents(),[js_code]);

Without eval

var initFrame = new Function(js_code);


initFrame.apply ($('#iframe').contents(),[]);

4 Comments

Using new Function is essentially the same as an eval. Running functions in the context of another frame can be problematic and hard to debug since the global object is different in both contexts...
eval can't receive a return statment, and function cannot resolve a value like (5), eval and new Function are different.
Yes they are slightly different, but in your case it doesn't matter at all. new Function still does an eval under the hood. Therefore, avoiding eval for new Function is not any better. eval may not allow a return statement, but it returns the value of the last expression evaled.
This seems to work if the content of js_code is core JavaScript. What if the content of js_code is a jQuery snippet. This does not seem to work then. Any suggestions?
-1

This worked for me, paste following code in the page which is in an iframe, not the parent page:

window.myFunction = function(args) {
   alert("script from iframe");
}

And now add following code to call above function:

var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);

Comments

-2

How about setting ajax refresh with js interval function to take any data stored in file/session etc. ?

It's surely not the most lightweight mode and it involves a tiny bit php, but can do the work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.