2010-06-28 44 views
4

我有一个独特的问题脚本 -加载jQuery的,则执行依赖于它

我设计,创建小工具,用户就可以在自己的网页中嵌入(博客文章的Web应用程序,大多)。我希望他们只需要嵌入一行,所以我只是将该行作为include语句,以便将JavaScript从我的服务器上删除。

问题是,我正在使用jQuery构建小部件代码,我需要加载jQuery插件,因为我显然不知道我的用户是否有它可用。我想“这应该是非常简单的” ....

function includeJavaScript(jsFile) { 
    var script = document.createElement('script'); 
    script.src = jsFile; 
    script.type = 'text/javascript'; 
    document.getElementsByTagName('head')[0].appendChild(script); 
} 

includeJavaScript('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'); 
jQuery(); 

所以,我追加了jQuery文件的头部,然后事后,试图运行一个jQuery功能。麻烦的是,这是行不通的!每次运行它,我都会遇到错误,说明未定义变量jQuery。我已经尝试了几件事情。我尝试将jQuery函数放入onLoad触发器中,以便在调用我的脚本之前加载整个页面(包括,大概是jQuery文件)。我试着把jQuery函数放在一个单独的文件中,并在加载jQuery lib文件后加载它。但我得到我想的东西简单的想法 - 我是新来的jQuery,所以如果我失去了一些东西很明显,我很抱歉......

编辑

OK,我试图通过所提供的建议digitalFresh,如下所示(使用Safari 5,如果有帮助),但我仍然得到相同的错误?

function test() { 
    jQuery() 
} 

var script = document.createElement("script"); 
script.type = "text/javascript"; 
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'; 
script.onload = test(); //execute 
document.body.appendChild(script); 

编辑

OK,我终于得到它的工作,从布伦丹唐突的建议,通过将呼叫本身在 'onload事件' 的处理程序,就像这样:

function addLoadEvent(func) { 
     var oldonload = window.onload; 
     if (typeof window.onload != 'function') { 
     window.onload = func; 
     } else { 
     window.onload = function() { 
      if (oldonload) { 
      oldonload(); 
      } 
      func(); 
     } 
    } 
} 
addLoadEvent(function() { 
    var script = document.createElement("script"); 
    script.type = "text/javascript"; 
    script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'; 
    document.body.appendChild(script); 
    jQuery(); 
}); 

在这一点上,正如你所看到的,我甚至不需要把它放在“负载”上 - 它只是起作用。虽然我不得不承认,但我仍然不明白它为什么起作用,这使我困扰......

+2

加载事件的人? – 2010-06-28 00:30:09

回答

1

你应该先检查,以确保他们不已经使用jquery所以像:

if (jQuery) { 
    // jQuery is loaded 
} else { 
    // jQuery is not loaded 
} 

其次,你应该确保你在no conflict mode使用jQuery和不使用$操作符,因为它可能由另一个脚本库声称。

然后嵌入,声明此功能:

function load_script (url) 
{ 
    var xmlhttp; 
    try { 
    // Mozilla/Safari/IE7 
    xmlhttp = new XMLHttpRequest(); 
    } catch (e) { 
     //Other IE 
     xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); 
    } 
    xmlhttp.open('GET', url, false); x.send(''); 
    eval(xmlhttp.responseText); 
    var s = xmlhttp.responseText.split(/\n/); 
    var r = /^function\s*([a-z_]+)/i; 

     for (var i = 0; i < s.length; i++) 
     { 
      var m = r.exec(s[i]); 
      if (m != null) 
       window[m[1]] = eval(m[1]); 
     } 
    } 

然后调用它:

load_script('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'); 

希望这有助于。

+0

感谢关于如何保持jQuery安全的指针。至于你的解决方案,虽然,我很困惑 - ActiveXObject,我认为是特定于IE/Windows/JScript?它肯定不适用于我的Safari浏览器测试... – jasonpgignac 2010-06-28 01:16:38

+0

用新的XmlHttpRequest()替换它。我不知道这是不是最好的解决方案 – 2010-06-28 01:32:29

+0

好吧 - 试过了,但是我很害怕,然后我得到了同样的错误... * GRRRRR * – jasonpgignac 2010-06-28 01:40:40

2

当您调用jQuery函数时,脚本未加载或执行。这就是为什么你会得到jQuery没有定义的错误。

我在Loading Scripts Dynamically上回答了这个问题。该脚本对于除IE以外的所有浏览器都很简单。只需添加一个onload事件监听器

+0

我试过你的解决方案,但仍然失败。我还错过了什么吗?这几乎是我以前所想的(尽管我将它附加到整个页面的加载事件中,这也不起作用)。我不明白,我必须丢失一些东西...... – jasonpgignac 2010-06-28 01:25:58

+0

不是整个页面的加载事件 - 你想要在脚本完成时加载事件。当您将脚本标记添加到DOM然后立即调用jQuery时,DOM尚未完成添加脚本标记。你需要添加一个加载事件到'appendChild()' – 2010-06-28 04:53:47

1

使用LABjs。嵌入<script>标签的工作原理是因为浏览器加载并执行其中的任何脚本或引用它时引用它,但这也意味着浏览器将阻塞,直到完成脚本。

+1

这不就是鸡/鸡蛋问题吗?那么我将不得不动态地包含LABjs,并且在加载之前不会使用LABjs会有同样的问题? – jasonpgignac 2010-06-28 01:28:18

+0

Ach的确如此。但是,您可以使用'$ LAB.script(path.to.jQuery.js).wait(function(){moreProcessing()});'而不是手动插入涉及浏览器特性的脚本标记。您甚至可以压缩'LABjs'并将其隐藏在页面的其余部分。 – 2010-06-28 02:32:19

7

您最终使用的解决方案工程但启动缓慢不是100%失败证明。如果有人重写window.onload,你的代码将不会运行。当页面上的所有内容都被加载(包括图像)时,window.onload也会发生,这不完全是你想要的。你不希望你的脚本等那么久。

幸运<脚本>元素都有自己的onload(就绪)事件,可以用来与他们夫妇的其他脚本。

function include(file, callback) { 
    var head  = document.getElementsByTagName('head')[0]; 
    var script = document.createElement('script'); 
    script.type = 'text/javascript'; 
    script.src = file; 
    script.onload = script.onreadystatechange = function() { 
    // execute dependent code 
    if (callback) callback(); 
    // prevent memory leak in IE 
    head.removeChild(script); 
    script.onload = null; 
    }; 
    head.appendChild(script); 
} 

include('http://ajax.googleapis.com/.../jquery.min.js', myFunction); 

在这种情况下,当jquery可用时,函数将被精确调用。你的代码是无法证明的并且很快开始。

1

如果您使用jQuery,则可以使用getScript()Facebook has a good example on how to employ this。这是我在下面发布的原始解决方案更易于管理的解决方案。

或者:

大厦关闭galambalazs的回答的,你可以换他include()功能的事件,如jQuery的$(document).ready(),而不必依赖于额外的JS插件创建一个依赖行递延脚本。我还添加了一个callbackOnError,如果您从Google CDN中提取,这很方便。

/* galambalazs's include() */ 
function include(file, callback, callbackOnError) { 
    var head  = document.getElementsByTagName('head')[0]; 
    var script = document.createElement('script'); 
    script.type = 'text/javascript'; 
    script.src = file; 
    script.onload = script.onreadystatechange = function() { 
     // execute dependent code 
     if (callback) callback(); 
     // prevent memory leak in IE 
     head.removeChild(script); 
     script.onload = null; 
     script.onerror = null; 
    }; 
    script.onerror = function() { 
     if(callbackOnError) callbackOnError(); 
     // prevent memory leak in IE 
     head.removeChild(script); 
     script.onload = null; 
     script.onerror = null; 
    }; 
    head.appendChild(script); 
} 

/* If you need a deferred inline script, this will work */ 
function init() { 
    // Insert Code 
} 

/* Example with callback */ 
$(document).ready(function() { 
    include('something.js', init); 
}); 

/* Maybe I want something on window.load() */ 
$(window).load(function() { 
    // Without a callback 
    include('whatever.js'); 
}); 

/* Or use an event to load and initialize script when it's needed */ 
$(".nearAButton").hover(include('button.js',function() {initButtonJS()})); 

function initButtonJS() { 
    $(".nearAButton").off("mouseenter mouseleave"); 
} 

/* Attempt to load Google Code, on fail load local */ 
include(
    '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js', 
    function() { 
     // Inline Callback 
    }, 
    function() { 
     include('/local/jquery-ui-1.10.3.custom.min.js', function() { 
      // Inline Callback 
     }); 
    } 
);