1

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?

insertusernamehere
  • 23,204
  • 9
  • 87
  • 126
calmcalmuncle
  • 143
  • 1
  • 2
  • 16
  • What's the problem? Is the image not changing? – Cristik May 07 '15 at 21:07
  • @Cristik Yes, exactly that. When I run the exact same code for the changing image on a page in chrome it works perfectly. Just not in the iframe. – calmcalmuncle May 07 '15 at 21:09
  • Where does your javascript code you posted run? In the parent document or in the iframe? – Cristik May 07 '15 at 21:11
  • @Cristik The code posted runs in the parent document. That code works fine for displaying HTML and CSS but i haven't managed to get any JavaScript that i input to the textarea to work in the iframe. – calmcalmuncle May 07 '15 at 21:13

2 Answers2

3

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

Ryan Wheale
  • 26,022
  • 8
  • 76
  • 96
  • Thanks for the response, its not that the editor doesnt work, on update it displays html and css well. Its just that the javascript i write has no effect. Will this fix that or had i not made the problem clear? – calmcalmuncle May 07 '15 at 21:16
  • I gave a fiddle, and it indeed fixes it. – Ryan Wheale May 07 '15 at 21:17
  • Im trying to run this js in the iframe: I still cant get a result? – calmcalmuncle May 07 '15 at 21:20
  • You need to update your question. Don't obscure the problem. Tell us what your real problem is and create a fiddle so we can test. If you don't I will close your question as too vague. We can't solve issues unless you give us enough info to solve. Just saying "my code isn't working" isn't enough. – Ryan Wheale May 07 '15 at 21:27
  • The OPs problem is actually that JavaScript inserted into the editor (which basically works) won't be executed once pasted into the ` – insertusernamehere May 07 '15 at 21:42
0

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.

Community
  • 1
  • 1
insertusernamehere
  • 23,204
  • 9
  • 87
  • 126