Запуск тегов сценариев с помощью jsonp - PullRequest
0 голосов
/ 22 июля 2011

Редактировать: Решено, см. Ответ ниже.

Проблема, которую я пытаюсь решить, это скрипт загрузки рекламы, который загружает рекламный код с помощью jsonp и вставляет его в dom.

Теперь иногда рекламный код будет включать теги javascript, и из некоторых постов здесь, посвященных stackoverflow, мне пришла в голову мысль, что для их запуска нужно переместить их в начало документа, что после некоторых экспериментов побудило меня задать этот вопрос:

Добавление сценариев к заголовку с использованием javascript - странное поведение

Мой вопрос там был решен, но проблема остается, сценарии, которые я вставляю в мой тестовый блок, не запускаются и не запускаются, когдаПереместился в голову.

У меня есть пример кода здесь:

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>

Ответы [ 2 ]

4 голосов
/ 05 ноября 2012

Ответ кажется немного раздутым.Вот моя версия :

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 голос
/ 26 июля 2011

Благодаря этому сообщению:

Выполнение элементов, вставленных с .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>
...