Executing <script> elements inserted with .innerHTML
我有一个脚本,它使用
例如,内容可以是:
1 2 | <script type="text/javascript">; test |
问题是
有没有人有执行所有
编辑:
通过查看jquery代码,我已经设法了解了jquery是如何做到这一点的,这导致了以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | Demo: <script type="text/javascript"> function insertAndExecute(id, text) { domelement = document.getElementById(id); domelement.innerHTML = text; var scripts = []; ret = domelement.childNodes; for ( var i = 0; ret[i]; i++ ) { if ( scripts && nodeName( ret[i],"script" ) && (!ret[i].type || ret[i].type.toLowerCase() ==="text/javascript") ) { scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); } } for(script in scripts) { evalScript(scripts[script]); } } function nodeName( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); } function evalScript( elem ) { data = ( elem.text || elem.textContent || elem.innerHTML ||"" ); var head = document.getElementsByTagName("head")[0] || document.documentElement, script = document.createElement("script"); script.type ="text/javascript"; script.appendChild( document.createTextNode( data ) ); head.insertBefore( script, head.firstChild ); head.removeChild( script ); if ( elem.parentNode ) { elem.parentNode.removeChild( elem ); } } insertAndExecute("element","<scri"+"pt type='text/javascript'>document.write('This text should appear as well.')</scr"+"ipt>this text should also be inserted."); |
@Phidah…这是一个非常有趣的解决你的问题的方法:http://24ways.org/2005/have-your-dom-and-script-it-too
所以,它看起来像这样:
The op's script doesn't work in the 7.With help from so,here's a script that does:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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]); } }; |
这是一个简短的脚本,更有效的脚本也是用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function insertAndExecute(id, text) { document.getElementById(id).innerHTML = text; var scripts = Array.prototype.slice.call(document.getElementById(id).getElementsByTagName("script")); for (var i = 0; i < scripts.length; i++) { if (scripts[i].src !="") { var tag = document.createElement("script"); tag.src = scripts[i].src; document.getElementsByTagName("head")[0].appendChild(tag); } else { eval(scripts[i].innerHTML); } } } |
注:如果不使用预先防范,可能会造成安全脆弱性,这比在飞行上创建脚本标记要快得多。
你不应使用内含属性,而应错过节点的附录方法:文档树中的节点[HTML DOM]。这条路你可以稍后打电话给你的注射代码。
确保你明白
样品注射工艺:
ZZU1
看
Try this snippet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | function stripAndExecuteScript(text) { var scripts = ''; var cleaned = text.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){ scripts += arguments[1] + ' '; 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>test'; document.getElementById('element').innerHTML = stripAndExecuteScript(scriptString); |
简化ES6 version of@joshcomley's answer with an example.
没有Jquery,没有图书馆,没有Eval,没有Dom Change,只有纯洁的Javascript。
http://plnkr.co/edit/mmegiu?预览
1 2 3 4 5 6 7 8 9 10 | 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); }); } |
使用
1 2 | $0.innerHTML = HTML; // does *NOT* run tags in HTML setInnerHTML($0, HTML); // does run tags in HTML |
1 2 3 4 5 6 7 8 9 10 | 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); } } |
它在我的项目中是铬的
不使用"Eval":
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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); } } |
本发明基本上克隆了脚本标记,然后将封闭脚本标记替换为新产生的一个,从而允许执行。
It's easier to use JQuery
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 }) } |
这也包括使用
你没有为他做任何工作,只有用
做吧
1 | document.body.innerHTML = '<img src="../images/loaded.gif" alt="" onload="alert(\'test\');this.parentNode.removeChild(this);" />'; |
谢谢你给拉里写的剧本,这是我用的
1 2 | $('#' + id)[0].innerHTML = result; $('#' + id +" script").each(function() { this.text = this.text || $(this).text();} ); |
你可以看一下这个邮件。The code might look like this:
1 2 3 4 5 6 7 8 | 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]); } |
Extending off of Larry's.and children nodes.现在的脚本还将被称为外部脚本,该脚本与SRC参数具体化。脚本被称为头插入插入,并被置于次序中。因此,特有的顺序脚本是保存的。每一个脚本都被执行同步类似于浏览器如何处理初始DOM负载。如果你有一个脚本块,从CDN呼叫JQUERY,而不是下一个脚本Node使用JQUERY不要!哦,我用一个串行标记的脚本,根据你在标记参数中设置的内容来标记脚本,所以你可以找到该脚本添加的内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | 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); } |
我需要一些相似的东西,但需要一个脚本作为原始脚本留存或重新创建,因为我的脚本指向了脚本标记在创建/目标元素的DOM中的位置。我还做了递归脚本,以确保它的工作,如果它比一个水平下降。
备注:如果你有一个老浏览器,就使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | window.exec_body_scripts = function(body_el) { // ref: https://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml based on Larry K's answer // 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. const type__Js = 'text/javascript', tagName__Script = 'script', tagName__Script__Upper = tagName__Script.toUpperCase(); var scripts = [], script, i; function evalScript(elem) { var parent = elem.parentNode, data = (elem.text || elem.textContent || elem.innerHTML ||""), script = document.createElement(tagName__Script); script.type = type__Js; try { // doesn't work on ie... script.appendChild(document.createTextNode(data)); } catch (e) { // IE has funky script nodes script.text = data; } // Make sure to re-insert the script at the same position // to make sure scripts that target their position // in the DOM function as expected. var parent = elem.parentNode; parent.insertBefore(script, elem); parent.removeChild(elem); }; // Get all scripts (recursive) if (typeof (document.querySelectorAll) !== typeof (void 0)) { document.querySelectorAll('script').forEach((scr) => { if (!scr.type || scr.type.toLowerCase() === type__Js) scripts.push(scr); }); } else { var children_nodes = body_el.childNodes, child; for (i = 0; children_nodes[i]; i++) { child = children_nodes[i]; if ( child.nodeName && child.nodeName.toUpperCase() === tagName__Script__Upper && ( !child.type || child.type.toLowerCase() === type__Js ) ) { scripts.push(child); } // Recursive call window.exec_body_scripts(child); } } for (i = 0; scripts[i]; i++) { evalScript(scripts[i]); } }; |
尝试这个,它为我在铬上工作,狩猎和firefox:
1 2 3 4 | var script = document.createElement('script'); script.innerHTML = 'console.log("hi")'; document.body.appendChild(script); --> logs"hi" |
One thing to note though,is that the following div-nested script will not run:
1 2 3 4 | var script = document.createElement('div'); script.innerHTML = 'console.log("hi")'; document.body.appendChild(script); --> doesn't log anything |
为了运行一个脚本,它必须被创建为一个节点,然后作为一个孩子出现。你甚至可以在一个预先注入的DIV&中找到一个脚本(我在试图获得服务器代码之前就已经跑进了这个):
1 2 3 4 5 6 7 | var div = document.createElement('div'); div.id = 'test-id'; document.body.appendChild(div); var script = document.createElement('script'); script.innerHTML = 'console.log("hi")'; document.getElementById('test-id').appendChild(script); --> logs"hi" |
Expending the answer of lambder
document.body.innerHTML = ' onload="alert(\'test\');this.parentNode.removeChild(this);" />' ;
你可以使用基于64的图像创建和装载脚本
1 2 | <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAADUlEQVQYV2P4//8/AwAI/AL+iF8G4AAAAABJRU5ErkJggg==" onload="var script = document.createElement('script'); script.src = './yourCustomScript.js'; parentElement.append(script);" /> |
或者如果你有一个EDOCX1
1 2 3 | <iframe src='//your-orginal-page.com' style='width:100%;height:100%' onload="var script = document.createElement('script'); script.src = './your-coustom-script.js'; parentElement.append(script);" frameborder='0'></iframe> |
尝试功能Eval
1 2 3 4 | data.newScript = '<script type="text/javascript">//my script...' var element = document.getElementById('elementToRefresh'); element.innerHTML = data.newScript; eval(element.firstChild.innerHTML); |
这是我正在开发的一个项目的一个实例。谢谢你的邮件
这是我最近一个项目的解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> Sample </head> <body> <h1 id="hello_world">Sample <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); </body> </html> |