Executing [removed] elements inserted with [removed]

后端 未结 20 2513
囚心锁ツ
囚心锁ツ 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:49

    A solution without using "eval":

    var setInnerHtml = function(elm, html) {
      elm.innerHTML = html;
      var scripts = elm.getElementsByTagName("script");
      // If we don't clone the results then "scripts"
      // will actually update live as we insert the new
      // tags, and we'll get caught in an endless loop
      var scriptsClone = [];
      for (var i = 0; i < scripts.length; i++) {
        scriptsClone.push(scripts[i]);
      }
      for (var i = 0; i < scriptsClone.length; i++) {
        var currentScript = scriptsClone[i];
        var s = document.createElement("script");
        // Copy all the attributes from the original script
        for (var j = 0; j < currentScript.attributes.length; j++) {
          var a = currentScript.attributes[j];
          s.setAttribute(a.name, a.value);
        }
        s.appendChild(document.createTextNode(currentScript.innerHTML));
        currentScript.parentNode.replaceChild(s, currentScript);
      }
    }
    

    This essentially clones the script tag and then replaces the blocked script tag with the newly generated one, thus allowing execution.

    0 讨论(0)
  • 2020-11-22 00:50

    Here is my solution in a recent project.

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Sample</title>
    </head>
    <body>
    <h1 id="hello_world">Sample</h1>
    <script type="text/javascript">
     var div = document.createElement("div");
      var t = document.createElement('template');
      t.innerHTML =  "Check Console tab for javascript output: Hello world!!!<br/><script type='text/javascript' >console.log('Hello world!!!');<\/script>";
      
      for (var i=0; i < t.content.childNodes.length; i++){
        var node = document.importNode(t.content.childNodes[i], true);
        div.appendChild(node);
      }
     document.body.appendChild(div);
    </script>
     
    </body>
    </html>

    0 讨论(0)
  • 2020-11-22 00:52

    The OP's script doesn't work in IE 7. With help from SO, here's a script that does:

    exec_body_scripts: function(body_el) {
      // 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) {
        var data = (elem.text || elem.textContent || elem.innerHTML || "" ),
            head = document.getElementsByTagName("head")[0] ||
                      document.documentElement,
            script = document.createElement("script");
    
        script.type = "text/javascript";
        try {
          // doesn't work on ie...
          script.appendChild(document.createTextNode(data));      
        } catch(e) {
          // IE has funky script nodes
          script.text = data;
        }
    
        head.insertBefore(script, head.firstChild);
        head.removeChild(script);
      };
    
      // main section of function
      var scripts = [],
          script,
          children_nodes = body_el.childNodes,
          child,
          i;
    
      for (i = 0; children_nodes[i]; i++) {
        child = children_nodes[i];
        if (nodeName(child, "script" ) &&
          (!child.type || child.type.toLowerCase() === "text/javascript")) {
              scripts.push(child);
          }
      }
    
      for (i = 0; scripts[i]; i++) {
        script = scripts[i];
        if (script.parentNode) {script.parentNode.removeChild(script);}
        evalScript(scripts[i]);
      }
    };
    
    0 讨论(0)
  • 2020-11-22 00:54

    Just do:

    document.body.innerHTML = document.body.innerHTML + '<img src="../images/loaded.gif" alt="" onload="alert(\'test\');this.parentNode.removeChild(this);" />';
    
    0 讨论(0)
  • 2020-11-22 00:55

    You should not use the innerHTML property but rather the appendChild method of the Node: a node in a document tree [HTML DOM]. This way you are able to later call your injected code.

    Make sure that you understand that node.innerHTML is not the same as node.appendChild. You might want to spend some time on the Javascript Client Reference for more details and the DOM. Hope the following helps...

    Sample injection works:

    <!DOCTYPE HTML>
    <html>
    <head>
        <title>test</title>
        <script language="javascript" type="text/javascript">
            function doOnLoad() {
                addScript('inject',"function foo(){ alert('injected'); }");
            }
        
            function addScript(inject,code) {
                var _in = document.getElementById('inject');
                var scriptNode = document.createElement('script');
                scriptNode.innerHTML = code;
                _in.appendChild(scriptNode);
            }
        </script>
    </head>
    <body onload="doOnLoad();">
        <div id="header">some content</div>
        <div id="inject"></div>
        <input type="button" onclick="foo(); return false;" value="Test Injected" />
    </body>
    </html>

    regards

    0 讨论(0)
  • 2020-11-22 00:56

    Thanks to Larry's script, which worked perfectly well in IE10, this is what I've used:

    $('#' + id)[0].innerHTML = result;
    $('#' + id + " script").each(function() { this.text = this.text || $(this).text();} );
    
    0 讨论(0)
提交回复
热议问题