Gagik
Gagik

Reputation: 96

Problems with custom JavaScript code being run in iFrame

So I am making a JS playground like JSFiddle. While adding the JavaScript functionality and calling different functions, it seems like the code is running from the page document root and not the iframe one.

$(document).ready(function()
{
    var result = $("#result"); 

    htmlVal = htmlEditor.getValue();
    cssVal = cssEditor.getValue();
    jsVal = jsEditor.getValue();

    iframe = $("<iframe></iframe>");

    result.append(iframe);

    var iframeDoc = $(iframe.get(0).contentDocument) //iframe.contents();
    bodyFrame = iframeDoc.find("body");
    headFrame = iframeDoc.find("head");
    cssFiddle = headFrame.append("<style id='cssEdit'>"  + settings.JS + "\n" +  cssVal + "</style>").children("#cssEdit");
    jsFiddle = bodyFrame.append("<script id='jsEdit'>" + settings.JS + "\n" + jsVal + "</script>").children("#jsEdit");

    $("#update").click(updateResult);

    //setInterval(updateResult, 100);
});

function updateResult()
{
    htmlVal = htmlEditor.getValue();
    cssVal = cssEditor.getValue();
    jsVal = jsEditor.getValue();

    if(htmlVal.split("</body>").length == 2)
    {
        var bodyText = htmlVal.split("<body>")[1].split("</body>")[0];
        bodyFrame.html(bodyText);
        jsFiddle = bodyFrame.append("<script id='jsEdit'>" + settings.JS + "\n" + jsVal + "</script>").children("#jsEdit");
    }
    if(htmlVal.split("</head>").length == 2)
    {
        var headText = htmlVal.split("<head>")[1].split("</head>")[0];
        headFrame.html(headText);
        css = headFrame.append("<style id='cssEdit'>" + settings.JS + "\n" + cssVal + "</style>").children("#cssEdit");
    } else
    {
        bodyFrame.html(htmlVal);
        js = bodyFrame.append("<script id='jsEdit'>" + settings.JS + "\n" + jsVal + "</script>").children("#jsEdit");
    }

    jsFiddle.html(settings.JS + "\n" + jsVal);
    cssFiddle.html(settings.CSS + "\n" + cssVal);
}

Example

Upvotes: 0

Views: 217

Answers (2)

Gagik
Gagik

Reputation: 96

This answer really helped.

So the reason of the code being executed in global namespace is because of jQuery. Calling bodyFrame.append('script'), runs document.createElement('script'), meaning the code will run in document, not in iframeDoc in my case. So we need to use pure javascript.

    jsFiddle = doc.createElement("script");
    jsFiddle.setAttribute("type", "text/javascript");
    jsFiddle.textContent = "console.log(document.body)";

    bodyFrame[0].appendChild(jsFiddle);

Upvotes: 1

winhowes
winhowes

Reputation: 8065

To access an iframe's document do this:

var iframeDoc = $(iframe.get(0).contentDocument)

Then you can do:

bodyFrame = iframeDoc.find("body");
headFrame = iframeDoc.find("head");

Because an iframe has it's own document root you have to search for the iframe's html from that document root.

EDIT

So a/the issue is that changing the innerHTML of a script tag doesn't run new JS. So I would recommend either using jQuery's .replaceWith() method (http://api.jquery.com/replacewith/#replaceWith-newContent) or wrapping the embedded JS in a div or something and changing that element's HTML

Upvotes: 0

Related Questions