编辑:已解决,请参阅下面的答案。
我要解决的问题是广告加载脚本,它使用jsonp加载广告代码并将其插入到dom中。
现在有时候广告代码会包含javascript代码,而且在stackoverflow上的一些帖子中,我认为将它们移动到文档的头部以使它们运行,经过一些实验后我提出了这个问题:
Appending scripts to head using javascript - weird behavior
我的问题已经解决,但问题仍然存在,我插入测试div的脚本不会运行,也不会在移动到头部时运行。
我这里有一个代码示例:
这里有一个简单的jsonp示例:
p2中的代码会尝试将消息记录到控制台,提醒消息,然后设置一个变量然后尝试打印出来,所有这些都会失败。
是使用eval函数运行这样的代码的唯一方法还是我做了一些基本的错误?
以下是第一部分的代码:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
if (typeof JSONP === 'undefined') {
/*Lightweight JSONP fetcher - www.nonobtrusive.com*/
var JSONP = (function(){
var counter = 0, head, query, key, window = this;
function load(url) {
var script = document.createElement('script'),
done = false;
script.src = url;
script.async = true;
script.onload = script.onreadystatechange = function() {
if ( !done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") ) {
done = true;
script.onload = script.onreadystatechange = null;
if ( script && script.parentNode ) {
script.parentNode.removeChild( script );
}
}
};
if ( !head ) {
head = document.getElementsByTagName('head')[0];
}
head.appendChild( script );
}
function jsonp(url, params, callback) {
query = "?";
params = params || {};
for ( key in params ) {
if ( params.hasOwnProperty(key) ) {
query += encodeURIComponent(key) + "=" + encodeURIComponent(params[key]) + "&";
}
}
var jsonp = "json" + (++counter);
window[ jsonp ] = function(data){
callback(data);
window[ jsonp ] = null;
try {
delete window[ jsonp ];
} catch (e) {}
};
load(url + query + "callback=" + jsonp);
return jsonp;
}
return {
get:jsonp
};
}());
}
JSONP.get( 'http://m.iijax.com/p2.php', { requestType:'demoRequest'}, function(data){
var adC = document.getElementById("testId");
adC.innerHTML = data.code;
// Move script tags to head
var scripts = adC.getElementsByTagName("script");
for(i=scripts.length - 1;i>-1;i--) {
document.head.appendChild(scripts[i]);
}
// Now check value of var letsSeeIfThisIsDefined, set in the fetched code
console.log(letsSeeIfThisIsDefined);
});
</script>
</head>
<body>
<div id="testId"></div>
</body>
</html>
答案 0 :(得分:4)
答案似乎有些臃肿。这是my version:
function execJSONP(url, cb) {
var script = document.createElement('script');
script.async = true;
var callb = 'exec'+Math.floor((Math.random()*65535)+1);
window[callb] = function(data) {
var scr = document.getElementById(callb);
scr.parentNode.removeChild(scr);
cb(data);
window[callb] = null;
delete window[callb];
}
var sepchar = (url.indexOf('?') > -1)?'&':'?';
script.src = url+sepchar+'callback='+callb;
script.id = callb;
document.getElementsByTagName('head')[0].appendChild(script);
}
答案 1 :(得分:1)
感谢这篇文章:
Executing <script> elements inserted with .innerHTML
我能够稍微修改我的代码,我现在从jsonp提取的脚本标签中挑选数据,将其放入新创建的脚本标签中并将它们附加到头部并且它可以工作。 :)
以下是修订后的代码,包括新函数parseScripts():
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function parseScripts(elementId) {
// Get the div where code has been inserted by innerHTML
var td = document.getElementById(elementId);
// Find any script tags in that code
var scripts = td.getElementsByTagName("script");
for(i=scripts.length - 1;i>-1;i--) {
// For each script found pick out the data
var elem = scripts[i];
var data = (elem.text || elem.textContent || elem.innerHTML || "" );
// Create a new script element and add the data
var script = document.createElement("script");
script.type = "text/javascript";
try {
// doesn't work on ie...
script.appendChild(document.createTextNode(data));
} catch(e) {
// IE has funky script nodes
script.text = data;
}
// Append new script tag to head of document
document.head.appendChild(script);
}
}
if (typeof JSONP === 'undefined') {
/*Lightweight JSONP fetcher - www.nonobtrusive.com*/
var JSONP = (function(){
var counter = 0, head, query, key, window = this;
function load(url) {
var script = document.createElement('script'),
done = false;
script.src = url;
script.async = true;
script.onload = script.onreadystatechange = function() {
if ( !done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") ) {
done = true;
script.onload = script.onreadystatechange = null;
if ( script && script.parentNode ) {
script.parentNode.removeChild( script );
}
}
};
if ( !head ) {
head = document.getElementsByTagName('head')[0];
}
head.appendChild( script );
}
function jsonp(url, params, callback) {
query = "?";
params = params || {};
for ( key in params ) {
if ( params.hasOwnProperty(key) ) {
query += encodeURIComponent(key) + "=" + encodeURIComponent(params[key]) + "&";
}
}
var jsonp = "json" + (++counter);
window[ jsonp ] = function(data){
callback(data);
window[ jsonp ] = null;
try {
delete window[ jsonp ];
} catch (e) {}
};
load(url + query + "callback=" + jsonp);
return jsonp;
}
return {
get:jsonp
};
}());
}
JSONP.get( 'http://m.iijax.com/p2.php', { requestType:'demoRequest'}, function(data){
var adC = document.getElementById("testId");
adC.innerHTML = data.code;
// Try and run the scripts
parseScripts("testId");
});
</script>
</head>
<body>
<div id="testId"></div>
<div style="height: 0px; width: 0px; border: 10px solid transparent; border-left-color: #505050;"></div>
</body>
</html>