Injecting Javascript to Iframe

2019-01-20 18:37发布

I am making a live editor for my website. I have the CSS and HTML parts down, only issue is the JS part now. Here is a snippet of the code

var frame = $('#preview_content'),
           contents = frame.contents(),
           body = contents.find('body');
           csstag = contents.find('head').append('<style></style>').children('style');
           java = contents.find('head').append('<script><\/script>').children('script');//Issues here
       $('.area_content_box').focus(function() {
       var $this = $(this);
       var check = $this.attr('id');
        $this.keyup(function() {

        if (check === "html_process"){
        body.html($this.val());
        } else if(check === "css_process") {
        csstag.text($this.val());
        } else if (check === "java_process"){
        java.text( $this.val() );
        }

        });
      });

Problem is it is not injecting script tags in the iframes body nor the head when ever I try this. I've read up on injecting and some issues containing the ending script tag. I need to figure out how to inject script tags, really want them in the head but if it is easier in the body that is fine.

jfriend00 - I will be focusing on making this vanilla, if you think I should honestly.

So any words of advice on how to go about making my editor work correctly with the injecting JS?

1条回答
对你真心纯属浪费
2楼-- · 2019-01-20 19:09

These two lines of code look like they could have problems:

csstag = contents.find('head').append('<style></style>').children('style');
java = contents.find('head').append('<script><\/script>').children('script');//Issues here

It seems like it would be much better to create the style tag and remember that DOM element.

var iframe = document.getElementById("preview_content");
var iframewindow = iframe.contentWindow || iframe.contentDocument.defaultView;
var doc = iframewindow.document;
var csstag = doc.createElement("style");
var scripttag = doc.createElement("script");
var head = doc.getElementsByTagName("head")[0];
head.appendChild.cssTag;
head.appendChild.scriptTag;

$('.area_content_box').focus(function() {
    var $this = $(this);
    var check = this.id;
    $this.keyup(function() {
        if (check === "html_process") {\
            // I would expect this to work
            doc.body.html($this.val());
        } else if(check === "css_process") {
            // I don't know if you can just replace CSS text like this 
            // or if you have to physically remove the previous style tag
            // and then insert a new one
            csstag.text($this.val());
        } else if (check === "java_process"){
            // this is unlikely to work
            // you probably have to create and insert a new script tag each time
            java.text( $this.val() );
        }
    });
});

This should work for the body HTML and it may work for the CSS text into the style tag.

I do not believe it will work for the javascript as you can't change a script by assigning text to the tag the way you are. Once a script has been parsed, it's in the javascript namespace.

There is no public API I'm aware of for removing previously defined and interpreted scripts. You can redefine global symbols with subsequent scripts, but not remove previous scripts or their effects.

If this were my code, I'd remove the previous style tag, create a new one, set the text on it before it was inserted in the DOM and then insert it in the DOM.

If you're not going to do it that way, then you'll have to test to see if this concept of setting .text() on an already inserted (and parsed) style tag works or not in all relevant browsers.

For the script tag, I'm pretty sure you'll have to create a new script tag and reinsert it, but there's no way to get rid of older code that has already been parsed other than redefining global symbols. If you really wanted to start fresh on the code, you'd have to create a new iframe object from scratch.


There are other issues with this too. You're installing a .keyup() event handler every time the .area_content_box gets focus which could easily end up with many of the event handlers installed, all getting called and all trying to do the same work.

查看更多
登录 后发表回答