calmcalmuncle
calmcalmuncle

Reputation: 143

Try It Yourself Editor JS

I have created a very simple editor that has been working great. However, I just tried to put JavaScript into it and I can't get it to work.

The code for the editor:

<div id="buttoncontainer">
    <input id="button" onclick="update();" type="button" value="Update page">
</div>
<div id="tryitcontainer">
    <textarea id="codebox"></textarea>
    <iframe id="showpage"></iframe>
</div>

The JavaScript for the editor:

<script>
    function update() {
        var codeinput = document.getElementById('codebox').value;
        window.frames[0].document.body.innerHTML = codeinput;
    }
</script>

I just wanted to run some simple JavaScript that changes an image when it is clicked. This code works fine when I run it in a full browser, so I know its the editor thats the problem.

Is there a simple fix for this that I'm missing?

Upvotes: 1

Views: 918

Answers (2)

Ryan Wheale
Ryan Wheale

Reputation: 28450

The button is not finding the update() method. You need that function to be globally available:

http://jsfiddle.net/t5swb7w9/1/

UPDATE: I understand now. Internally jQuery basically evals script tags. There's too much going on to be worth replicating yourself... either use a library to append, or eval the code yourself. Just a warning that eval'ing user input is rarely a good thing and is usually a welcome mat for hackers.

window.myScope = {
    update: function() {
        var div = document.createElement('div'),
            codeinput = document.getElementById('codebox').value,
            scriptcode = "";

        div.innerHTML = codeinput;
        Array.prototype.slice.apply(div.querySelectorAll("script")).forEach(function(script) {
            scriptcode += ";" + script.innerHTML;
            div.removeChild(script);
        });
        window.frames[0].document.body.appendChild(div);
        // hackers love to see user input eval'd like this...
        eval(scriptcode);
    }
};

And then you would update your button like so:

<input id="button" onclick="myScope.update();" type="button" value="Update page">

Or, even better, use addEventListener and forget the onclick part altogether. I'll let you do that research on your own ;)

Upvotes: 3

insertusernamehere
insertusernamehere

Reputation: 23610

JavaScript inserted via innerHTML will not be executed due to security reasons:

HTML5 specifies that a <script> tag inserted via innerHTML should not execute.

from MDN: Element.innerHTML - Security considerations, see also: W3: The applied innerHTML algorithm.

A possible solution using the jQuery method .append() works around that, as it somehow evals the content. But this will still not solve your problem, as the JavaScript code is executed in the current scope. Here's a test scenario:

function update() {
    var codeinput = document.getElementById('codebox').value;
    $(window.frames[0].document.body).append(codeinput);
}

Try it here

Try to insert this script:

<script>
    alert( document.getElementById('tryitcontainer') );
</script>

and this one:

<p id="test">Test</p>
<script>
    window.frames[0].document.getElementById('test').innerHTML = 'updated';
</script>

The first one will return a [object HTMLDivElement] or similar. Here you can see, that you're still in the same scope as the parent frame. The second one will correctly update the content within the iframe. Keep that in mind, when experimenting with those things.

Maybe Executing elements inserted with .innerHTML has some more infos for you.

Upvotes: 0

Related Questions