如何在IE 8上向页面注入javascript?

时间:2009-04-01 01:30:03

标签: javascript internet-explorer-8 mootools

假设我有以下标记:

<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的问题。

10 个答案:

答案 0 :(得分:5)

这个MSDN post专门解决了如何使用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注入的脚本加载标记来提高安全性并减少跨浏览器的不兼容性。我知道这可能是不可能的,但值得考虑。

答案 1 :(得分:4)

这是我们大约一年前在我们的网站上做到这一点,以使其在IE中工作。以下是步骤:

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

    // get the script nodes, add them into an arrary, and remove them from orphan node
    var scriptNodes = orphNode.getElementsByTagName('script');
    var scripts = [];
    while(scriptNodes.length) {
        // push into script array
        var node = scriptNodes[0];
        scripts.push(node.text);

        // then remove it
        node.parentNode.removeChild(node);
    }

    // add html to place holder element (note: we are adding the html before we execute the scripts)
    document.getElementById(id).innerHTML = orphNode.innerHTML;

    // execute stored scripts
    var head = document.getElementsByTagName('head')[0];
    while(scripts.length) {
        // create script node
        var scriptNode = document.createElement('script');
        scriptNode.type = 'text/javascript';
        scriptNode.text = scripts.shift(); // add the code to the script node
        head.appendChild(scriptNode); // add it to the page
        head.removeChild(scriptNode); // then remove it
    }   
}

set_html('ph', 'this is my html.  alert("alert");');

答案 2 :(得分: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);

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

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

我知道我的答案已经很晚了;然而,迟到总比没有好: - )

答案 3 :(得分:1)

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

  

的document.getElementById( “占位符”)。innerHTML的   = jsVar;

答案 4 :(得分:1)

您可能需要评估脚本标记的内容。这需要解析才能在jsVar和eval(whatsBetweenTheScriptTags)中找到脚本。

答案 5 :(得分:1)

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

只需使用string.replace()来交换<script>的所有<textarea class="myScript" style="display:none">代码,同时保留内容。然后将结果粘贴到div的innerHTML

完成此操作后,您可以使用

div.getElementsByTagName("textarea") 

获取所有textareas,遍历它们并查找您的标记类(在这种情况下为"myScript"),以及eval(textarea.value)(new Function(textarea.value))()您关注的那些。

答案 6 :(得分: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标记。

答案 7 :(得分: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
}

答案 8 :(得分:0)

当你说它在其他浏览器中“有用”时,你的意思是你得到alert弹出消息,或者你只是说<script>标签进入DOM树吗?

如果您的目标是前者,请注意注入嵌入式<script>的html的行为与浏览器非常相关。例如,在最新的MooTools中,我可以尝试:

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

获取弹出窗口,而不是IE(7),而不是FF(3)(但是我获取<script>节点成功进入DOM)。要在所有浏览器中将其转到alert,您必须按this answer进行操作。

答案 9 :(得分:0)

我的评论确实很晚,但这也是最准确的评论 - 你没有看到<script>内容运行的原因是因为你没有将defer属性添加到<script>标记。 MSDN文章明确指出,您需要这样做才能运行<script>标记。