0

I have a textarea box where the user inputs HTML and it gets output into the body element of an iframe.

This works just fine using most HTML tags, but if you use the <script> tag (in order to add JavaScript), the script element does not get transferred to the iframe.

For example, I should be able type the following in the textarea:

<script>
    function test() {
        alert('test');
    }
</script>
<button onclick="test()">test</button>

The button gets added to the iframe but since the script element apparently doesn't, clicking the button does not fire the alert().

One work-around for this is to declare alert() on the button click, rather than using a pre-scripted function; this work-around is shown below:

<button onclick="alert('test')">test</button>

However this only allows one javascript command (whereas the user may want to use a function with multiple commands).

You can see the webpage here

The JavaScript to fill the iframe contents is:

(function () {
    $('.grid').height($(window).height());
    var frame = $('iframe'),
        contents = frame.contents(),
        body = contents.find('body'),
        styleTag = contents.find('head')
            .append('<style></style>')
            .children('style');
    $('textarea').focus(function () {
        var $this = $(this);
        $this.keyup(function () {
            if ($this.attr('id') === 'html') {
                body.html($this.val());
            } else {
                styleTag.text($this.val());
            }
        });
    });
})();
  • Please clarify what you mean by the last line. ... `But the – Ryan Tse Jun 30 '13 at 18:26
  • It would probably be easier if I posted the link: http://gazza-911.co.uk/iframe.html Short explanation: Body of Iframe = Value in textarea, Iframe body is updated on each key press, it doesn't update when using the script tag – user2536988 Jun 30 '13 at 19:03
  • well... i made the experience that jquery since 1.6 or then sanitizes script tags out when doing html()... actually i tried to use `body[0].innerHTML = $this.val()`, however it makes now sence what jquery does, because for each set innerHTML there will be new closures added. you will have to do it the hard way, specialize scripts like you did with css, and insert it as explained here: http://stackoverflow.com/a/3603496/1352471 and then congratz to your on jsfiddle implementation ;) – metadings Jul 01 '13 at 01:35

1 Answers1

1

The problem is any "user-generated" scripts will be executed in the parent window's global context (which the iframe cannot [normally] access). The console shows the following error when clicking the button because the test() function is not accessible scope-wise for the iframe:

Uncaught ReferenceError: test is not defined

To fix this, scripts need to add functions to the global scope of the iframe's internal window:

<script>
(function () {
    'use strict';
    var iframe = document.getElementById('iframe'), //grab the iframe
        win = iframe.contentWindow; //get the window of the iframe
    win.test = function () { //declare function in scope of iframe's window
        alert('test'); //now "test" will fire because it's defined in a scope accessible to the iframe
    };
}());
</script>
<button onclick="test()">test</button>
pete
  • 24,141
  • 4
  • 37
  • 51