jquery在动态创建时在iframe中运行

时间:2013-04-17 05:44:00

标签: javascript jquery

我正在尝试首先创建一个iframe,然后向其中注入jQuery库,然后发出警告,说明jQuery已经加载。

正在按预期将jQuery库插入iframe头部,并且jQuery上的警报会加载到正文中。

问题是,它没有显示警告,而是显示jQuery is not defined

有人可以提出任何建议吗?

这是代码

<!doctype html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
        <title>iFrame Test</title>
    </head>
    <body>
        <script>
            var insertScript = function(src){
                var script = document.createElement('script');
                script.type = 'text/javascript';
                script.async = false;
                script.src = src;
                $('iframe').contents().find('head')[0].appendChild(script);
            }

            var insertScriptContent = function(code){
                var script = document.createElement('script');
                script.type = 'text/javascript';
                script.async = false;
                script.innerHTML  = code;
                $('iframe').contents().find('body')[0].appendChild(script);
            }

            $(function(){
                $('iframe').load(function(){
                    var contents = $('iframe').contents();
                    insertScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
                    insertScriptContent('jQuery(function(){ alert("loaded"); });');
                });
            });
        </script>

        <div class="output">
            <iframe></iframe>
        </div>
    </body>
</html>

1 个答案:

答案 0 :(得分:2)

您正在异步加载jQuery(尽管script.async=false),然后在此之后立即加载警报脚本。该脚本运行时尚未加载jQuery,因此您将获得未定义的jQuery引用。

作为快速解决方案,我添加了一个等待setInterval()定义的jQuery。我还做了其他改变:

  • 删除了script.async = false;这两个地方,因为它没有任何好处。
  • 删除了$('iframe').load()包装器。当我测试你的代码时,该包装器中的回调函数永远不会被调用。这并不奇怪,因为此时没有任何内容被加载到iframe中。
  • 更改了使用document.createElement()的两个地方,以使用iframe文档(在我的版本中称为iframedoc)。它可以使用document正常工作,但我更容易在它们将被加载到的文档下创建这些脚本。
  • ...find(something)[0].appendChild();的两个实例更改为更简单的...find(something).append();

这是工作代码:

<!doctype html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript">
</script>

    <title>iFrame Test</title>
</head>

<body>
    <script type="text/javascript">

        $(function() {
            var $contents = $('iframe').contents();
            var iframedoc = $contents[0];

            var insertScript = function(src) {
                var script = iframedoc.createElement('script');
                script.type = 'text/javascript';
                script.src = src;
                $('iframe').contents().find('head').append(script);
            }

            var insertScriptContent = function(code) {
                var script = iframedoc.createElement('script');
                script.type = 'text/javascript';
                script.innerHTML = code;
                $('iframe').contents().find('body').append(script);
            }

            insertScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');

            insertScriptContent(
                'var timer = setInterval( function() {' +
                    'if( typeof jQuery == "undefined" ) return;' +
                    'clearInterval( timer );' +
                    'jQuery(function(){ alert("loaded"); });' +
                '}, 50 )'
            );

        });
    </script>

    <div class="output">
        <iframe></iframe>
    </div>
</body>
</html>

这对于第一次传球来说是好的,但有一种更简单的方法可以做到这一点。我尝试用jQuery代码替换这两个脚本函数,所以这是另一个工作版本:

<!doctype html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript">
</script>

    <title>iFrame Test</title>
</head>

<body>
    <script type="text/javascript">

        $(function() {
            var $contents = $('iframe').contents();

            $contents.find('head').append(
                '<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"><\/script>'
            );

            $contents.find('body').append(
                '<script>' +
                    'jQuery(function(){ alert("loaded"); });' +
                '<\/script>'
            );

        });
    </script>

    <div class="output">
        <iframe></iframe>
    </div>
</body>
</html>

奇怪的是,这个可以正常没有 setInterval()计时器,所以我把那个代码拿出来了。我不确定为什么这会起作用 - 这不是一种令人安慰的感觉 - 但它确实在我测试过的浏览器中是一致的。

最后,这是一个非工作实验。在过去,我使用document.write()定位iframe以达到良好效果。所以我想我会尝试:

<!doctype html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript">
</script>

    <title>iFrame Test</title>
</head>

<body>
    <script type="text/javascript">

        $(function() {
            var $contents = $('iframe').contents();
            var iframedoc = $contents[0];

            iframedoc.write(
                '<!doctype html>',
                '<html>',
                '<head>',
                    '<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js"><\/script>',
                '</head>',
                '<body>',
                    '<script>',
                        'debugger;',
                        'jQuery( function(){ alert("loaded"); } );',
                    '<\/script>',
                '</body>',
                '</html>'
            );
        });
    </script>

    <div class="output">
        <iframe></iframe>
    </div>
</body>
</html>

此版本确实将jQuery和内联脚本加载到iframe中,并在内联脚本中执行jQuery()调用。但它永远不会使用alert()调用回调函数。这实际上与我正在做的事情有关,所以我明天可能会再看一下它,但与此同时我留下了实验代码以防你好奇。我将其更改为在iframe中使用未压缩的jQuery以便于调试,并在其中留下debugger;语句。