0

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

2
  • With the currently posted code we can do nothing. We need the code that handles the execution of the Javascript code in the user iframe! Commented Feb 21, 2015 at 9:44
  • Added more code, hopefully helps. Commented Feb 21, 2015 at 10:05

2 Answers 2

1

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);
Sign up to request clarification or add additional context in comments.

Comments

0

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

3 Comments

Doesn't seem to do any difference
Sorry for confusion. But the code itself does execute, what I am asking is that is there a way to make the code run inside iframe's document root (in the screenshot the code worked, but it changed the background of the body of the whole page, not the iframe (4th block))
Thanks for this though, this was the next problem that came up after fixing this one.

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.