【问题标题】:Running script tags fetched with jsonp运行使用 jsonp 获取的脚本标签
【发布时间】:2011-10-10 23:54:28
【问题描述】:

编辑:已解决,请参阅下面的答案。

我要解决的问题是一个广告加载脚本,它使用 jsonp 加载广告代码并将其插入到 dom 中。

现在有时广告代码会包含 javascript 标签,从 stackoverflow 上的一些帖子中,我得到了将它们移动到文档头部以使其运行的想法,经过一些实验后,我提出了这个问题:

Appending scripts to head using javascript - weird behavior

我的问题已经解决,但问题仍然存在,我插入到我的测试 div 中的脚本没有运行,当它们移到头部时它们也没有运行。

我这里有一个代码示例:

http://m.iijax.com/p1.html

这里还有一个简单的 jsonp 示例:

http://m.iijax.com/p2.php

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>

【问题讨论】:

    标签: javascript jsonp innerhtml


    【解决方案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>
    

    【讨论】:

    • 我认为您缺少具有“src”的脚本的 src 标签
    【解决方案2】:

    答案似乎有些臃肿。这里是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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-26
      • 1970-01-01
      • 1970-01-01
      • 2013-05-22
      • 2017-04-07
      • 2018-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多