使用JavaScript动态添加HTML对象时出现问题

3
我在动态包含一个object标签的html中遇到了问题。 我们调用外部服务来获取一些html片段,其中包括一个object标签、一个脚本和一个简单的html表单。我将该内容添加到页面的一个div中,然后尝试执行使用所包含对象的脚本。当我使用Firebug调试时,我可以看到代码已经正确地插入到页面中,但是当脚本尝试访问该对象时,它出现了错误。对我来说看起来像对象没有初始化。让我给你展示一些代码来说明我的意思。
getFragment使用jQuery发起ajax调用以获取内容。
var htmlSnippet = RequestModule.getFragment( dto );
$('#plugin').html( htmlSnippet ).hide();

插件div中包含的内容如下所示。
<div id="plugin" style="display: none; ">
    Browser:
    Chrome
    <object name="signer" id="signer" type="application/x-personal-signer2"></object>

<form method="POST" name="signerData" action="#success">
    <input name="nonce" value="ASyhs..." type="hidden">
    <input name="signature" value="" type="hidden">
    <input name="encodedTbs" value="U2l..." type="hidden">
    <input name="provider" value="nexus-personal_4X" type="hidden">

    <input type="submit" onclick="doSign()" value="Sign">
</form>
</div>

试图使用“签名者”对象的JavaScript代码如下:

function doSign(){
    var signer2 = document.getElementById("signer");

   retVal = signer2.SetParam('TextToBeSigned', 'some value...');

   ... and then some more
}

当我调用signer2.SetParam方法时,出现错误提示。
Object #<an HTMLObjectElement> has no method 'SetParam'

但是当我使用加载页面内容时原始页面时,脚本可以正常工作,因此我知道该对象上存在“SetParam”方法并且脚本可以正常工作。但是在我之后动态添加到页面时,它似乎不起作用。
我已经谷歌了很多天,但没有找到解决方法。有人知道如何让这个工作吗?
最好的问候, 亨利克
3个回答

0
首先,Object标签并不是所有浏览器都完全支持(来源) 其次,根据我的经验,jQuery(它严重依赖于document.createDocumentFragment)有时无法在动态创建/克隆的DOM节点上附加/触发事件,这可能解释了为什么您的对象无法初始化。
话虽如此,为了尝试解决您的问题,我建议使用本地的document.createElement和document.appendChild方法,而不是jQuery.html。您可以尝试document.innerHTML,但如果失败,您始终可以使用我之前提到的方法。
我的建议是要么修改您的服务以替换:
<script type="text/javascript">
function addElement(parentid, tag, attributes) {
    var el = document.createElement(tag);
    // Add attributes
    if (typeof attributes != 'undefined') {
        for (var a in attributes) {
          el.setAttribute(a, attributes[a]);
        }
    }

    // Append element to parent
    document.getElementById(parentid).appendChild(el);
}
addElement('plugin', 'object', {name:"signer",id:"signer",type:"application/x-personal-signer2"});
</script>

或者如果您无法更改服务返回的内容,请在将内容包含到页面后运行此操作:

<script type="text/javascript">
    /*
     * Goes through al the object tags in the element with the containerid id
     * and tries to re-create them using the DOM builtin methods
     */
    function reattachObjectTags(containerid) {
        jQuery('#'+containerid+' object').each(function(){
            var attrs = {}, el = this;
            // We're insterested in preserving all the attributes
            var saved_attrs = {}, attr;
            for(var i=0; i < el.attributes.length; i++) {
                attr = el.attributes.item(i);
                if(attr.specified) {
                    saved_attrs[attr.nodeName]=attr.nodeValue;
                }
            }
            this.parentNode.removeChild(this);

            var new_element = document.createElement('object');
            for (var a in saved_attrs) {
                new_element.setAttribute(a,saved_attrs[a]);
            }
            document.getElementById(containerid).appendChild(new_element);
        });
    }

    // Do your stuff
    var htmlSnippet = RequestModule.getFragment( dto ); 
    $('#plugin').html( htmlSnippet ).hide();
    // reattach all the object elements in #plugin
    reattachObjectTags('plugin');
</script>
  • 这是未经测试的 - 我凭记忆打出了这段代码,因为我没有启动IE来测试它的手段。

嗨,感谢您的回复! 当您说jQuery在对象后添加时存在问题时,您可能是正确的。目前,我通过在页面首次加载时包含空的对象标签,然后在稍后动态添加不同的参数时解决了这个问题,并且它可以正常工作。如果将来有时间,我会测试您提出的解决方案。 - Henrik Reinhold

0

我在这里设置了一个测试脚本:https://dl.dropbox.com/u/74874/test_scripts/object.html

如果你打开Firebug/Web Inspector,你会发现SetParam方法实际上并没有被定义。我不知道它应该做什么,但无论如何,在任何情况下都没有被定义。如果你想要添加<param>标签到你的嵌入式内容中,你可以使用DOM API来完成。测试脚本中有一些代码可以实现这个功能,但我还是把它粘贴在这里:

var obj_signer = document.getElementById('signer');

var obj_p = document.createElement('param');
    obj_p.id = "myp2"; 
    obj_p.name = "TextToBeSigned";
    obj_p.value = "some value ...";
    obj_p.setAttribute('valueType', 'ref');
obj_signer.appendChild(e);

或者使用jQuery更快:

$("#signer").append("<param id='myp2' name='TextToBeSigned' value='some value ...' valueType='ref'></param>");

谢谢你的帮助,但这并没有解决我的问题。我实际上正在尝试调用对象链接到的应用程序上的SetParam方法。它应该是可用的,并且如果我在页面加载时加载对象而不是动态添加它到页面后,它就可以工作。在脚本的后面,我尝试通过执行signer2.PerformAction('Sign')来调用另一个方法,但也不起作用。 - Henrik Reinhold
@Henrik 这是那种只有IE支持的方法,Firefox是否支持只是为了兼容性而已吗?我真的找不到任何关于SetParam的文档。 - aditya
据我所了解,SetParam方法在object标记中不可用。实际上,它是可以在底层对象本身上调用的方法,有点像在这个页面上当他们执行mySwf.myFlexFunction(..)时所做的方式。http://livedocs.adobe.com/flex/3/html/help.html?content=passingarguments_5.html - Henrik Reinhold

0

对于一个jQuery解决方案,我认为这应该可以工作:

$("input:submit").click(function(){
    $("#signer").append('<param name="TextToBeSigned" value="some value ...">');

    ... and then some more
});

如果您在页面上有多个表单,可能需要为提交按钮添加一个classid并将其用作选择器。

希望这可以帮到您。


谢谢你的帮助,但这个解决方案也不起作用。请看一下我在另一个答案上的评论。 - Henrik Reinhold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接