Executing [removed] elements inserted with [removed]

后端 未结 20 2516
囚心锁ツ
囚心锁ツ 2020-11-22 00:12

I\'ve got a script that inserts some content into an element using innerHTML.

The content could for example be:



        
相关标签:
20条回答
  • 2020-11-22 00:57

    It's easier to use jquery $(parent).html(code) instead of parent.innerHTML = code:

    var oldDocumentWrite = document.write;
    var oldDocumentWriteln = document.writeln;
    try {
        document.write = function(code) {
            $(parent).append(code);
        }
        document.writeln = function(code) {
            document.write(code + "<br/>");
        }
        $(parent).html(html); 
    } finally {
        $(window).load(function() {
            document.write = oldDocumentWrite
            document.writeln = oldDocumentWriteln
        })
    }
    

    This also works with scripts that use document.write and scripts loaded via src attribute. Unfortunately even this doesn't work with Google AdSense scripts.

    0 讨论(0)
  • 2020-11-22 01:01

    You may take a look at this post. The code might look like this:

    var actualDivToBeUpdated = document.getElementById('test');
    var div = document.createElement('div');
    div.innerHTML = '<script type="text/javascript">alert("test");<\/script>';
    var children = div.childNodes;
    actualDivToBeUpdated.innerHTML = '';
    for(var i = 0; i < children.length; i++) {
        actualDivToBeUpdated.appendChild(children[i]);
    }
    
    0 讨论(0)
  • 2020-11-22 01:02

    Try this snippet:

    function stripAndExecuteScript(text) {
        var scripts = '';
        var cleaned = text.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
            scripts += arguments[1] + '\n';
            return '';
        });
    
        if (window.execScript){
            window.execScript(scripts);
        } else {
            var head = document.getElementsByTagName('head')[0];
            var scriptElement = document.createElement('script');
            scriptElement.setAttribute('type', 'text/javascript');
            scriptElement.innerText = scripts;
            head.appendChild(scriptElement);
            head.removeChild(scriptElement);
        }
        return cleaned;
    };
    
    
    var scriptString = '<scrip' + 't + type="text/javascript">alert(\'test\');</scr' + 'ipt><strong>test</strong>';
    document.getElementById('element').innerHTML = stripAndExecuteScript(scriptString);
    
    0 讨论(0)
  • 2020-11-22 01:03

    Extending off of Larry's. I made it recursively search the entire block and children nodes.
    The script now will also call external scripts that are specified with src parameter. Scripts are appended to the head instead of inserted and placed in the order they are found. So specifically order scripts are preserved. And each script is executed synchronously similar to how the browser handles the initial DOM loading. So if you have a script block that calls jQuery from a CDN and than the next script node uses jQuery... No prob! Oh and I tagged the appended scripts with a serialized id based off of what you set in the tag parameter so you can find what was added by this script.

    exec_body_scripts: function(body_el, tag) {
        // Finds and executes scripts in a newly added element's body.
        // Needed since innerHTML does not run scripts.
        //
        // Argument body_el is an element in the dom.
    
        function nodeName(elem, name) {
            return elem.nodeName && elem.nodeName.toUpperCase() ===
                  name.toUpperCase();
        };
    
        function evalScript(elem, id, callback) {
            var data = (elem.text || elem.textContent || elem.innerHTML || "" ),
                head = document.getElementsByTagName("head")[0] ||
                          document.documentElement;
    
            var script = document.createElement("script");
            script.type = "text/javascript";
            if (id != '') {
                script.setAttribute('id', id);
            }
    
            if (elem.src != '') {
                script.src = elem.src;
                head.appendChild(script);
                // Then bind the event to the callback function.
                // There are several events for cross browser compatibility.
                script.onreadystatechange = callback;
                script.onload = callback;
            } else {
                try {
                    // doesn't work on ie...
                    script.appendChild(document.createTextNode(data));      
                } catch(e) {
                    // IE has funky script nodes
                    script.text = data;
                }
                head.appendChild(script);
                callback();
            }
        };
    
        function walk_children(node) {
            var scripts = [],
              script,
              children_nodes = node.childNodes,
              child,
              i;
    
            if (children_nodes === undefined) return;
    
            for (i = 0; i<children_nodes.length; i++) {
                child = children_nodes[i];
                if (nodeName(child, "script" ) &&
                    (!child.type || child.type.toLowerCase() === "text/javascript")) {
                    scripts.push(child);
                } else {
                    var new_scripts = walk_children(child);
                    for(j=0; j<new_scripts.length; j++) {
                        scripts.push(new_scripts[j]);
                    }
                }
            }
    
            return scripts;
        }
    
        var i = 0;
        function execute_script(i) {
            script = scripts[i];
            if (script.parentNode) {script.parentNode.removeChild(script);}
            evalScript(scripts[i], tag+"_"+i, function() {
                if (i < scripts.length-1) {
                    execute_script(++i);
                }                
            });
        }
    
        // main section of function
        if (tag === undefined) tag = 'tmp';
    
        var scripts = walk_children(body_el);
    
        execute_script(i);
    }
    
    0 讨论(0)
  • 2020-11-22 01:04

    Simplified ES6 version of @joshcomley's answer with an example.

    No JQuery, No library, No eval, No DOM change, Just pure Javascript.

    http://plnkr.co/edit/MMegiu?p=preview

    var setInnerHTML = function(elm, html) {
      elm.innerHTML = html;
      Array.from(elm.querySelectorAll("script")).forEach( oldScript => {
        const newScript = document.createElement("script");
        Array.from(oldScript.attributes)
          .forEach( attr => newScript.setAttribute(attr.name, attr.value) );
        newScript.appendChild(document.createTextNode(oldScript.innerHTML));
        oldScript.parentNode.replaceChild(newScript, oldScript);
      });
    }
    

    Usage

    $0.innerHTML = HTML;    // does *NOT* run <script> tags in HTML
    setInnerHTML($0, HTML); // does run <script> tags in HTML
    
    0 讨论(0)
  • 2020-11-22 01:04
    function insertHtml(id, html)  
    {  
       var ele = document.getElementById(id);  
       ele.innerHTML = html;  
       var codes = ele.getElementsByTagName("script");   
       for(var i=0;i<codes.length;i++)  
       {  
           eval(codes[i].text);  
       }  
    }  
    

    It works in Chrome in my project

    0 讨论(0)
提交回复
热议问题