【问题标题】:Problem using dynamically added html-object from javascript使用从 javascript 动态添加的 html-object 的问题
【发布时间】:2011-01-14 02:27:59
【问题描述】:

在我的 html 中动态包含对象标记时遇到问题。 我们有一个外部服务,我们调用它来获取一些 html-fragment,它包括一个 object-tag、一个脚本和一个简单的 html-form。我获取该内容并将其添加到页面中的 div 中,然后尝试执行使用包含对象的脚本。当我使用 Firebug 进行调试时,我可以看到代码已正确插入页面中,但脚本在尝试访问对象时出错。在我看来,该对象未初始化。让我给你看一些代码来说明我的意思。

getFragment 使用 jQuery 进行 ajax 调用以获取内容。

var htmlSnippet = RequestModule.getFragment( dto );
$('#plugin').html( htmlSnippet ).hide();

plugin-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”方法并且脚本有效。但不知何故,当我之后将它动态添加到页面时它不起作用。

过去几天我在 Google 上搜索了很多次,但都没有成功。 有没有人知道如何让它发挥作用?

最好的问候, 亨里克

【问题讨论】:

    标签: javascript jquery html


    【解决方案1】:

    首先,并非所有浏览器都完全支持 Object 标签(Source) 接下来,根据我的经验,jQuery(严重依赖 document.createDocumentFragment)有时无法在动态创建/克隆的 DOM 节点上附加/触发事件,这可以解释为什么您的对象无法初始化。

    也就是说,要尝试解决您的问题,我建议使用本机 document.createElementdocument.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 在之后添加对象时附加和触发事件时存在问题,您可能是对的。现在我已经通过在页面首次加载时包含空的对象标签来解决,然后当我知道它们的值并且它可以工作时动态添加不同的参数。如果我将来有时间,我会测试你提出的解决方案。
    【解决方案2】:

    对于 jQuery 解决方案,我认为这应该可行:

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

    如果您在该页面上有多个表单,则可能希望为提交按钮提供 classid 并将其用作选择器。

    希望这会有所帮助。

    【讨论】:

    • 感谢您帮助我,但此解决方案也不起作用。请看我对另一个答案的评论。
    【解决方案3】:

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

    如果您打开 Firebug/Web Inspector,您会看到 SetParam 方法实际上是未定义的。我不知道它应该做什么,但在这两种情况下都没有定义。如果您尝试将 &lt;param&gt; 标记添加到您的嵌入中,您可以使用 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 这是 Firefox 支持的仅 IE 方法之一,因为它应该是为了兼容性?我真的在任何地方都找不到关于SetParam 的任何文档。
    • 据我了解,SetParam 方法在对象标签上不可用。它实际上是一种可以在底层对象本身上调用的方法。有点像他们在这个页面上做 mySwf.myFlexFunction(..) livedocs.adobe.com/flex/3/html/…
    猜你喜欢
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    相关资源
    最近更新 更多