13

我们给出了一段 javascript 标签,例如<script src="http://ours.com/some.js"></script>哪些网站所有者在他们的网站上放置了http://example.com,并且在这个 javascript 标签中我们希望动态包含一个第三方 js,例如其中可以包含 document.write , 但当然如果我们尝试通过常规方法包含它,

var script_tag = document.createElement('script');
script_tag.type = 'text/javascript';
script_tag.src="http://third-party.com/some.js";
document.getElementById('target').appendChild(script_tag);

我们收到来自浏览器的警告,

警告:从异步加载的外部脚本调用 document.write() 被忽略。

我们如何解决这个问题?请记住,我们无法真正控制第三方脚本,因此我们无法更改其中的逻辑。我们正在寻找一些可以在所有浏览器上运行的解决方案。

4

7 回答 7

3

在已经加载的文档上加载脚本(而不是让浏览器忽略document.write())的问题是您将删除所有现有的 HTML。请参阅此示例,以便您可以准确了解正在发生的事情,或者有关更多详细信息,请查看document.write() 方法 的文档页面。

虽然我知道这可能不是您期望得到的答案,但我相信您很不走运,因为重写脚本不是一种选择。

似乎是一个类似的问题,有类似的回复。

于 2015-09-07T16:56:57.993 回答
1

您可以通过以下方式拦截对 document.write 的调用,从而以正确的方式支持脚本注入:

document.writeText = document.write;

document.write = function(parameter) {
    if (!parameter) return; 
    var scriptPattern = /<script.*?src=['|"](.*?)['|"]/;
    if (scriptPattern.test(parameter)) {
        var srcAttribute = scriptPattern.exec(parameter)[1];
        var script = document.createElement('script');
        script.src = srcAttribute;
        document.head.appendChild(script); 
    }
    else {
        document.writeText(parameter);
    }   
};

显然,这可以进一步压缩,但为了清楚起见,包含了变量名称。

资源

于 2017-01-18T11:11:10.557 回答
0

Document.write 不会在异步脚本中工作,因为在脚本开始工作时文档已经加载。

但是你可以这样做:

document.body.innerHTML = document.body.innerHTML + '<h1>Some HTML</h1>';

于 2015-09-07T13:00:49.253 回答
0

与其通过附加脚本元素来加载脚本,不如通过 AJAX 调用加载脚本 URL 的内容,然后使用 eval() 在全局范围内运行它?这是一个示例,我确实对其进行了测试以验证它是否有效:

<!DOCTYPE html>
<html>
<head>
<script>

var xmlhttp;

if (window.XMLHttpRequest) {
  xmlhttp = new XMLHttpRequest();
}else{
  xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

xmlhttp.onreadystatechange = function() {
  if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
    window.eval(xmlhttp.responseText); //Indirect call to eval to execute in global scope (http://perfectionkills.com/global-eval-what-are-the-options/)
  }
}

xmlhttp.open("GET", "https://third-party.com/test.js", false); //This is synchronous so that any document.write calls don't overwrite the entire page when they get called after the document is finished rendering. For all intents and purposes, this just loads the script like any other script, synchronously.

xmlhttp.send();

</script>
</head>
<body>

<div><h2>Hello World</h2></div>

</body>
</html>

这是我在 test.js 文件中的内容:

document.write("This is a test...");
alert("...This is a test alert...");
console.log("...And a console message.");

我为脚本同步了 AJAX 请求,这样它就可以像普通的嵌入脚本标签一样被加载。如果您异步运行它,并且脚本在页面完全呈现后使用 document.write,它会清除 DOM 然后写入它......实际上有点烦人。让我知道这是否适合你。:)

于 2015-09-02T09:21:33.900 回答
0

另一个过程是改变document.write()函数的行为。
假设您有主index.php文件:

<html>
<head>
<meta charset="utf-8" />
</head>
<body>
Hello<br>
<div id="target"></div>
<script>
document.write = function(input) {
    document.body.innerHTML += input;
}
var doit = function() {
    var script_tag = document.createElement('script');
    script_tag.type = 'text/javascript';
    script_tag.src="http://127.0.0.1:8080/testPlace/jsfile.js";
    document.getElementById('target').appendChild(script_tag);
}
</script>
</body>
</html>

jsfile.js这样的:

document.write("OK MAN!");

现在,如果您doit()在 js 浏览器控制台中键入以执行该功能(并且脚本执行您编写的操作),那么结果将是:

Hello
OK MAN!

其中的html是这样的:

<html><head>
<meta charset="utf-8">
</head>
<body>
Hello<br>
<div id="target"><script src="http://127.0.0.1:8080/testPlace/jsfile.js" type="text/javascript"></script></div>
<script>
    //That Script which here I removed it to take less space in answer
</script>

OK MAN!</body>
</html>
于 2015-09-07T18:38:34.073 回答
-1

是的,无法从异步加载的脚本中调用 document.write,因为它与文档分离,因此无法写入。

您可以查看此处用于 google maps api 解决此问题的方法。因此,您的一些未命名的第 3 方脚本可能实现了类似的回调模式。

https://developers.google.com/maps/documentation/javascript/examples/map-simple?hl=EN

<!DOCTYPE html>
<html>
  <head>
    <title>Simple Map</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
      #map {
        height: 100%;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: -34.397, lng: 150.644},
    zoom: 8
  });
}

    </script>
    <script src="https://maps.googleapis.com/maps/api/js?callback=initMap"
        async defer></script>
  </body>
</html>
于 2015-08-31T20:16:59.983 回答
-1

什么是第 3 方 javascript 文件?

如果是 Google Maps JavaScript API v3,请确保在脚本 URL 中包含“&callback=your_init_funct”。然后,一旦加载了地图库,它将调用“your_init_funct”,以便您可以开始显示地图。

另一种解决方案是 bezen.domwrite.js,可在此处获得:http: //bezen.org/javascript/index.html

演示:http ://bezen.org/javascript/test/test-domwrite.html

于 2015-08-31T19:53:09.210 回答