【问题标题】:Dynamically inserting javascript into HTML that uses document.write将 javascript 动态插入到使用 document.write 的 HTML 中
【发布时间】:2010-09-08 09:52:07
【问题描述】:

我目前正在加载一个灯箱样式的弹出窗口,它从 XHR 调用加载它的 HTML。然后使用element.innerHTML = content 在“模态”弹出窗口中显示此内容,这就像一个魅力。

在本网站的另一部分,我使用 Flickr 'badge' (http://www.elliotswan.com/2006/08/06/custom-flickr-badge-api-documentation/) 来动态加载 flickr 图像。这包括一个加载 flickr javascript 的脚本标记,然后执行一些 document.write 状态。

当包含在 HTML 中时,它们都可以完美地工作。仅当在灯箱inside 加载 flickr 徽章代码时,根本不会呈现任何内容。使用innerHTML 编写document.write 语句似乎走得太远了,但我在这种行为的javascript实现(FF2&3,IE6&7)中找不到任何线索。

谁能澄清这是否应该或不应该工作?谢谢。

【问题讨论】:

    标签: javascript html ajax


    【解决方案1】:

    使用document.writeln(content); 而不是document.write(content)

    但是,更好的方法是使用innerHTML 的串联,如下所示:

    element.innerHTML += content;
    

    element.innerHTML = content; 方法将用新内容替换旧内容,这将覆盖元素的 innerHTML!

    而在element.innerHTML += content 中使用+= 运算符会将您的文本附加到旧内容之后。 (类似于document.write 所做的。)

    【讨论】:

      【解决方案2】:

      一般来说,使用innerHTML 时不会执行脚本标签。在您的情况下,这很好,因为 document.write 调用会清除页面中已有的所有内容。但是,这会让您没有任何 HTML document.write 应该添加的内容。

      jQuery 的 HTML 操作方法将为您执行 HTML 中的脚本,诀窍是捕获对 document.write 的调用并将 HTML 放在适当的位置。如果它足够简单,那么这样的事情就可以了:

      var content = '';
      document.write = function(s) {
          content += s;
      };
      // execute the script
      $('#foo').html(markupWithScriptInIt);
      $('#foo .whereverTheDocumentWriteContentGoes').html(content);
      

      但它变得复杂。如果脚本在另一个域上,它将异步加载,因此您必须等到它完成才能获取内容。此外,如果它只是将 HTML 写入片段的中间而没有您可以轻松选择的包装元素怎么办? writeCapture.js(完全披露:我写的)处理所有这些问题。我建议只使用它,但至少您可以查看代码以了解它如何处理所有内容。

      编辑:这是一个page,展示了您想要的效果。

      【讨论】:

      • 有趣...我还开发了 document.write 的替代品以允许动态加载脚本:bezen.domwrite (bezen.org/javascript)
      • 谢谢!我们前段时间解决了这个问题,但这看起来可行!
      • 这是一个非常聪明的解决方案。保存供参考!
      【解决方案3】:

      document.write 与它们一样被弃用。不过,感谢 JavaScript 的奇妙之处,您可以将自己的函数分配给 document 对象的 write 方法,该方法在您选择的元素上使用 innerHTML 以附加提供的内容。

      【讨论】:

      • 是的,但是 flickr 在他们的 API 中使用 document.write,我确实需要脚本所在位置的内容。我无法更改 API,更改写入的元素不会解决问题。
      【解决方案4】:

      理论上,是的,我可以通过这种方式挑选出一个脚本标签。问题是我们可能有几十种情况发生这种情况,所以我试图找到这种行为的一些原因或文档。

      此外,script 标签在加载后似乎不再是 DOM 的一部分。在我们的环境中,我的 container div 仍然为空,因此我无法获取 script 标记。不过它应该可以工作,因为在我上面的示例中,脚本没有被执行,但仍然是 DOM 的一部分。

      【讨论】:

        【解决方案5】:

        所以您使用 DOM 方法创建 script 元素并将其附加到现有元素,然后这会导致附加的 script 元素的内容执行?听起来不错。

        您说脚本标记是较大 HTML 页面的一部分,因此不能单独列出。你不能给脚本标签一个ID并定位它吗?我可能在这里遗漏了一些明显的东西。

        【讨论】:

          【解决方案6】:

          我创建了一个简单的测试页面来说明问题:

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
              "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
          <html>
              <head>
                  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
                  <title>Document Write Testcase</title>
              </head>
              <body>
                  <div id="container">
                  </div>
                  <div id="container2">
                  </div>
          
                  <script>
                      // This doesn't work!
                      var container = document.getElementById('container');
                      container.innerHTML = "<script type='text/javascript'>alert('foo');document.write('bar');<\/script>";
          
                      // This does!
                      var container2 = document.getElementById('container2');
                      var script = document.createElement("script");
                      script.type = 'text/javascript';
                      script.innerHTML = "alert('bar');document.write('foo');";
                      container.appendChild(script);
                  </script>
              </body>
          </html>
          

          此页面会提醒“bar”并打印“foo”,而我希望它也会提醒“foo”并打印“bar”。但是,不幸的是,由于script 标记是较大 HTML 页面的一部分,我不能像上面的示例那样单独选择该标记并附加它。好吧,我可以,但这需要扫描innerHTML 内容中的script 标签,并在字符串中用占位符替换它们,然后使用DOM 插入它们。听起来不是微不足道的。

          【讨论】:

            【解决方案7】:

            我可以先得到一些澄清以确保我解决了问题吗?

            document.write 调用会将内容添加到标记中它们发生的位置。例如,如果您在函数中包含document.write 调用,但在其他地方调用该函数,则document.write 输出将发生在标记中的点处,该函数是定义而不是调用的位置.

            因此,要使其在所有 Flickr document.write 语句中起作用,需要成为 element.innerHTML = content 中的 content 的一部分。确定是这样吗?

            您可以通过在设置为innerHTML 的内容中添加一个简单的document.write 调用来快速测试这是否应该工作,并查看它的作用:

            <script>
              var content = "<p>1st para</p><script>document.write('<p>2nd para</p>');</script>"
              element.innerHTML = content;
            </script>
            

            如果这样行得通,document.write 在内容集中作为元素的innerHTML 工作的概念可能行得通。

            我的直觉是它行不通,但测试这个概念应该很简单。

            【讨论】:

            • "document.write 输出将发生在标记中定义函数的位置而不是调用它的位置。" - 不正确,我有一个测试页面可以证明这一点:jsbin.com/inuka
            猜你喜欢
            • 2014-08-28
            • 1970-01-01
            • 1970-01-01
            • 2012-11-19
            • 2013-05-31
            • 1970-01-01
            • 1970-01-01
            • 2017-10-24
            • 2017-06-26
            相关资源
            最近更新 更多