加载外部JavaScript源代码时,document.write不起作用

10
我正在尝试动态地将一个外部JavaScript文件加载到HTML元素中,以预览广告标签。这个脚本被成功加载和执行,但是脚本中包含"document.write"命令,它不能正常执行,但没有任何错误提示。
<html>
    <head>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
        <script type="text/javascript">
        $(function() {
            source = 'http://ib.adnxs.com/ttj?id=555281';

            // DOM Insert Approach
            // -----------------------------------
            var script = document.createElement('script');
                script.setAttribute('type', 'text/javascript');
                script.setAttribute('src', source);

            document.body.appendChild(script);
        });
        </script>
    </head>

<body>
</body>
</html>

如果我将源代码移动到同一域中进行测试,就可以使其正常工作

  1. 如果脚本使用document.createElement和appendChild而不是像上面的代码一样使用document.write进行修改。

由于脚本是由第三方生成和托管的,因此我无法修改脚本。

有人知道为什么document.write无法正常工作吗?是否有办法解决这个问题?

感谢帮助!


为什么不直接将脚本标签放在您想要广告出现的元素内部?很可能,这就是广告脚本的设计方式。 - David Hellsing
因为我将通过ajax调用接收脚本源的URL。这不能从后端脚本呈现。 - jadent
那么...你希望广告脚本如何知道在哪里放置广告? - David Hellsing
广告脚本正在执行的位置进行 document.write 操作。因此,尝试将其放置在页面内的 div 中,以使其代码能够写入到 div 标签中。当然,这就是问题的本质,因为我找不到代码来完成这个操作。 - jadent
4个回答

9
另一种解决方案是创建一个iframe,然后在ajax调用准备就绪时将脚本加载到该iframe中:
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
var doc = iframe.contentWindow.document;

// do this whenever you want (f.ex after ajax is made):
doc.open();
doc.write('<script src="http://ib.adnxs.com/ttj?id=555281">\x3C/script>');
doc.close();

那么,最后一个脚本中的document.write不会影响您的网站,只会影响iframe。您需要为iframe设置样式以适应广告。

这可能是唯一的答案。由于我们不知道大小,所以必须在加载后从iframes内抓取内容的宽度和高度。虽然有些巧妙,但可能有效。 - jadent

1
如果外部脚本标签同时包含 document.write,异步加载它可能会潜在地带来危险。因此,我建议您要么也在自己的端口使用 document.write,要么不使用这个标签。
document.write('\x3Cscript src="http://ib.adnxs.com/ttj?id=555281">\x3C/script>');

或者只是一个脚本标签(duh):

<script src="http://ib.adnxs.com/ttj?id=555281"></script>

在我看来,在“\x3Cscript”中,只有闭合标签需要最初的“\x3c”。 - Royi Namir
@RoyiNamir 可能是真的,我只是从一些旧片段中复制/粘贴过来... :) - David Hellsing
不能仅使用脚本标签,因为URL是通过从Web服务的Ajax调用动态加载的。在这种情况下应该使用document.write。 - jadent

0

在编程中,当DOM准备就绪时,您不希望在$(function()上使用document.write

移除document .ready包装器。

您的代码移到</body>之前。(或者移到容器位置-您想要小部件出现的位置。)

所以:

<html>
    <head>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
    </head>

<body>

//bla bla...

<script type="text/javascript">

  (function (){

           var source = 'http://ib.adnxs.com/ttj?id=555281';

            // DOM Insert Approach
            // -----------------------------------
            var script = document.createElement('script');
                script.setAttribute('type', 'text/javascript');
                script.setAttribute('src', source);
                document.body.appendChild(script);
   })();

</script>
</body>
</html>

重要提示:

enter image description here


@David 是的,我改了那个词。 :-) - 我的意思是一样的。(如果他想让用户看到他的网站 - 他不能这样做/不应该这样做。) - Royi Namir
是的,正确的。但是,如果带有 document.write 的脚本是异步加载的,它可能也会清理DOM,因为请求需要一些时间来执行。请参见此演示:http://jsbin.com/OhUDIJE/2/edit - David Hellsing
@David 是的,我同意。实际上,使用defer相比async更有可能发生这种情况——因为defer确保在DOM准备就绪时执行...一个“太晚”的事件。 - Royi Namir
尝试了上述代码,但仍无法执行document.write。在FF和Chrome中尝试过。您在执行此操作时是否看到广告显示? - jadent

0

我曾经遇到过同样的问题,并想出了一个解决方案。我认为我的方案可能会更加复杂,因为我的布局是在客户端生成的,在dom-ready之后,这意味着我无法以这种方式渲染脚本包含文件。这对我来说增加了一个额外的步骤,但如果您的布局是在服务器端生成的,则可能不需要额外的步骤。

  1. 生成您的URL。在您的情况下,它来自ajax请求,在我的情况下,它来自用户交互
  2. 使用此URL重新加载页面(也许将URL POST到具有新创建表单的服务器)

如果您能够在服务器上正确地渲染脚本包含文件,则可以这样做并完成。否则:

  1. 在服务器端创建一个隐藏的具有特定ID的div。这将在dom-ready之前加载脚本并正确触发document.write。
  2. 抓取包含脚本的div的内容,现在您已经将html存储在变量中,可以将其放置在页面的任何位置!

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