6

假设我有以下标记:

<div id="placeHolder"></div>

我有一个 JavaScript 变量jsVar,其中包含一些标记和一些 JavaScript。

通过使用 Mootools 1.1,我可以将 JavaScript 内容注入到占位符中,如下所示:

$('placeHolder').setHTML(jsVar);

这适用于 Firefox、Opera 甚至 Safari,生成的标记如下所示:

<div id="placeHolder">
    <strong>I was injected</strong>
    <script type="text/javascript">
        alert("I was injected too!");
    </script>
</div>

但是,在 IE 8 上,我得到以下信息:

<div id="placeHolder">
    <strong>I was injected</strong>
</div>

有什么方法可以在 IE 8 上注入 JavaScript,还是安全模型完全禁止我这样做?

我尝试了 Luca Matteis 的使用建议

document.getElementById("placeHolder").innerHTML = jsVar;

而不是 MooTools 代码,我得到了相同的结果。这不是 MooTools 问题。

4

10 回答 10

5

这篇MSDN 帖子专门讨论了如何使用 innerHTML 将 javascript 插入页面。你是对的:IE 确实认为这是一个安全问题,所以需要你跳过某些环节才能注入脚本......大概黑客可以像我们一样阅读这个 MSDN 帖子,所以我很茫然为什么 MS 认为这个额外的间接层是“安全的”,但我离题了。

来自 MSDN 文章:

<HTML>
<SCRIPT>
function insertScript(){
    var sHTML="<input type=button onclick=" + "go2()" + " value='Click Me'><BR>";
    var sScript="<SCRIPT DEFER>";
    sScript = sScript + "function go2(){ alert('Hello from inserted script.') }";
    sScript = sScript + "</SCRIPT" + ">";
    ScriptDiv.innerHTML = sHTML + sScript;
}    
</SCRIPT>
<BODY onload="insertScript();">
    <DIV ID="ScriptDiv"></DIV>
</BODY>
</HTML>

如果可能的话,您可能希望考虑使用document.write注入的脚本加载标签来提高安全性并减少跨浏览器的不兼容性。我知道这可能是不可能的,但值得考虑。

于 2009-04-01T02:09:39.303 回答
4

大约一年前,我们就是这样在我们的网站上做的,让它在 IE 中运行。以下是步骤:

  • 将 HTML 添加到孤立的 DOM 元素
  • 在孤立节点中搜索脚本标签 (orphan.getElementsByTagName)
  • 从那些脚本节点获取代码(保存以备后用),然后将它们从孤儿中删除
  • 添加孤立的 html 剩余部分并将其添加到占位符 (placeholder.innerHTML = orphan.innerHTML)
  • 创建一个脚本元素并将存储的代码添加到其中 (scriptElem.text = 'alert("my code");')
  • 然后将脚本元素添加到DOM(最好是头部),然后将其删除
函数 set_html( id, html ) {
    // 创建孤立元素设置 HTML
    var orphNode = document.createElement('div');
    orphNode.innerHTML = html;

    // 获取脚本节点,将它们添加到一个数组中,并从孤立节点中删除它们
    var scriptNodes = orphNode.getElementsByTagName('script');
    var 脚本 = [];
    而(scriptNodes.length){
        // 压入脚本数组
        var 节点 = scriptNodes[0];
        scripts.push(node.text);

        // 然后删除它
        node.parentNode.removeChild(node);
    }

    // 添加 html 到占位符元素(注意:我们在执行脚本之前添加 html)
    document.getElementById(id).innerHTML = orphNode.innerHTML;

    // 执行存储的脚本
    var head = document.getElementsByTagName('head')[0];
    而(脚本。长度){
        // 创建脚本节点
        var scriptNode = document.createElement('script');
        scriptNode.type = '文本/javascript';
        scriptNode.text = scripts.shift(); // 将代码添加到脚本节点
        head.appendChild(scriptNode); // 添加到页面
        head.removeChild(scriptNode); // 然后删除它
    }   
}

set_html('ph', '这是我的 html.alert("alert");');
于 2009-04-01T07:39:00.200 回答
2

我在 IE8(和 IE7)中遇到了同样的问题 我可以动态注入脚本(使用 src)的唯一方法是使用计时器:

source = "bla.js";

setTimeout(function () {
            // run main code
            var s = document.createElement('script');
            s.setAttribute('src', source);
            document.getElementsByTagName('body')[0].appendChild(s);
        }, 50);

如果您有要注入的内联代码,您可以删除计时器并为脚本元素使用“文本”方法:

s.text = "alert('hello world');";

我知道我的答案来得太晚了;然而,迟到总比没有好:-)

于 2011-04-25T19:24:14.360 回答
1

我从来没有尝试过,它只是浮​​现在我的脑海......你可以试试以下:

var script = document.createElement('script');
script.type = 'text/javascript';

script.innerHTML = '//javascript code here'; // not sure if it works
// OR
script.innerText = '//javascript code here'; // not sure if it works
// OR
script.src = 'my_javascript_file.js';

document.getElementById('placeholder').appendChild(script);

您可以使用相同的技术 (DOM) 插入 HTML 标记。

于 2009-04-01T05:44:00.287 回答
1

对不起,也许我在这里遗漏了一些东西——但这是一个 mootools 1.11 的问题,你为什么不使用 assets.js?

// you can  also add a json argument with events, etc.
new Asset.javascript("path-to-script.js", { 
    onload: function() { 
        callFuncFromScript(); 
    }, 
    id: "myscript"
});

这难道不是我们使用框架不必重新发明轮子的原因之一吗……

就“其他”内容而言,您是如何获得的?如果通过 Request 类,它可以通过使用选项很好地做你想做的事:

{
    update: $("targetId"),
    evalScripts: true,
    evalResponse: false
}
于 2009-06-24T08:34:40.293 回答
1

我不确定 MooTools,但是您尝试过 innerHTML 吗?

document.getElementById("placeHolder").innerHTML = jsVar;

于 2009-04-01T01:40:29.810 回答
1

您可能需要评估 script 标签的内容。这将需要解析以在您的 jsVar 和 eval(whatsBetweenTheScriptTags) 中查找脚本。

于 2009-04-01T01:54:17.063 回答
1

由于 IE 默认拒绝插入内容,您必须自己执行它,但您至少可以欺骗 IE 为您进行解析。

只需使用将所有标签string.replace()交换为,保留内容。然后将结果粘贴到一个 div 中。<script><textarea class="myScript" style="display:none">innerHTML

完成后,您可以使用

div.getElementsByTagName("textarea") 

要获取所有文本区域,请遍历它们并查找您的标记类("myScript"在本例中),以及您关心的任何一个eval(textarea.value)或那些。(new Function(textarea.value))()

于 2009-04-01T05:03:36.763 回答
0

当你说它在其他浏览器中“工作”时,你的意思是你得到了alert弹出消息,还是你只是意味着<script>标签使它进入 DOM 树?

如果您的目标是前者,请意识到注入嵌入的 html 的行为<script>非常依赖于浏览器。例如在最新的 MooTools 我可以尝试:

$(element).set('html', '<strong>Foo</strong><script>alert(3)</script>')

而且我没有得到弹出窗口,没有在 IE(7) 中,也没有在 FF(3) 中(但是我确实成功地将<script>节点放入 DOM)。要alert在所有浏览器中使用它,您必须按照此答案进行操作。

于 2009-04-02T04:16:36.200 回答
0

我的评论真的很晚,但它也是这里最准确的评论 - 你没有看到<script>内容正在运行的原因是因为你没有将defer属性添加到<script>标签中。MSDN 文章特别指出您需要这样做才能使<script>标签运行。

于 2011-10-14T15:21:58.380 回答