如何将依赖于jQuery的Javascript小部件embedded到未知的环境中

我正在开发一个依赖于jQuery的JavaScript小部件。 该小部件可能会或可能不会被加载到已经加载了jQuery的页面上。 在这种情况下出现了很多问题…

  1. 如果网页没有jQuery,我必须加载我自己的jQuery。 但是,这样做似乎有一个微妙的时间问题。 例如,如果我的小部件在jQuery完成加载和执行之前加载并执行,我得到一个jQuery is not defined错误。

  2. 如果网页有jQuery,我通常可以使用它。 如果jQuery的版本是旧的,但是,我想加载我自己的。 如果我加载自己的,但是,我需要这样做,不要跺脚他们的$variables。 如果我设置了jQuery.noConflict()并且它们的任何脚本依赖于$ ,那么我只是打破了他们的页面。

  3. 如果网页使用另一个JavaScript库(例如原型),我还需要对原型的$variables敏感。

由于以上所有,不依赖于jQuery似乎更容易。 但是,在我走下这条道路之前,我将首先征求build议。

我的代码的基本框架,包括计时错误和有时$ bug,如下所示:

 <script type="text/javascript" charset="utf-8"> // <![CDATA if (typeof jQuery === 'undefined') { var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.src = '{{ URL }}/jquery.js'; head.appendChild(script); } // ]]> </script> <script type="text/javascript" src="{{ URL }}/widget.js"></script> 

我的小部件具有以下结构:

 (function($) { var mywidget = { init: function() { ... } }; $(document).ready(function() { mywidget.init(); }); })(jQuery); 

如果有任何指针或资源实现一个小工具,可以在所有提到的环境中工作,他们将不胜感激。

在回顾一些答案和指针,并find一些有用的jQuery黑客之后,我最终得到了如下内容:

 (function(window, document, version, callback) { var j, d; var loaded = false; if (!(j = window.jQuery) || version > j.fn.jquery || callback(j, loaded)) { var script = document.createElement("script"); script.type = "text/javascript"; script.src = "/media/jquery.js"; script.onload = script.onreadystatechange = function() { if (!loaded && (!(d = this.readyState) || d == "loaded" || d == "complete")) { callback((j = window.jQuery).noConflict(1), loaded = true); j(script).remove(); } }; (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script); } })(window, document, "1.3", function($, jquery_loaded) { // Widget code here }); 

这将加载jQuery,如果它尚未加载,并封装在callback,所以它不会与页面上的预先存在的jQuery冲突。 它还会检查最低版本是否可用,否则会加载已知版本(在本例中为v1.3)。 它发送一个布尔值的callback(我的部件)是否加载jQuery是否有任何触发器需要作出。 只有在jQuery被加载后,它才会调用我的小部件,并将jQuery传递给它。

请参阅Alex Marandon 如何构build一个Web小部件(使用jQuery) 。

 (function() { // Localize jQuery variable var jQuery; /******** Load jQuery if not present *********/ if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.4.2') { var script_tag = document.createElement('script'); script_tag.setAttribute("type","text/javascript"); script_tag.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"); if (script_tag.readyState) { script_tag.onreadystatechange = function () { // For old versions of IE if (this.readyState == 'complete' || this.readyState == 'loaded') { scriptLoadHandler(); } }; } else { // Other browsers script_tag.onload = scriptLoadHandler; } // Try to find the head, otherwise default to the documentElement (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag); } else { // The jQuery version on the window is the one we want to use jQuery = window.jQuery; main(); } /******** Called once jQuery has loaded ******/ function scriptLoadHandler() { // Restore $ and window.jQuery to their previous values and store the // new jQuery in our local jQuery variable jQuery = window.jQuery.noConflict(true); // Call our main function main(); } /******** Our main function ********/ function main() { jQuery(document).ready(function($) { // We can use jQuery 1.4.2 here }); } })(); // We call our anonymous function immediately 

如果你还想使用一些jQuery插件呢? 使用缩小版本的插件制作单个文件是否安全,还要加载这些文件,如下所示? (从S3中加载,在这个特定的例子中)

 (function(window, document, version, callback) { var j, d; var loaded = false; if (!(j = window.jQuery) || version > j.fn.jquery || callback(j, loaded)) { var script = document.createElement("script"); script.type = "text/javascript"; script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"; script.onload = script.onreadystatechange = function() { if (!loaded && (!(d = this.readyState) || d == "loaded" || d == "complete")) { window.jQuery.getScript('http://mydomain.s3.amazonaws.com/assets/jquery-plugins.js', function() { callback((j = window.jQuery).noConflict(1), loaded = true); j(script).remove(); }); } }; document.documentElement.childNodes[0].appendChild(script) } })(window, document, "1.5.2", function($, jquery_loaded) { // widget code goes here }); 

看我可以在同一页面上使用多个版本的jQuery吗?

你可以使用document.write()来select添加jQuery脚本到页面吗? 这应该强制jQuery同步加载。 尝试这个:

 <script type="text/javascript" charset="utf-8"> // <![CDATA if (typeof jQuery === 'undefined') { document.write('<script src="{{ URL }}/jquery.js"><' + '/script>'); } // ]]> </script> <script type="text/javascript" src="{{ URL }}/widget.js"></script> 

如果你想在你的小部件脚本中做jQuery检查,那么我相信下面的工作是跨浏览器的:

 (function() { function your_call($) { // your widget code goes here } if (typeof jQuery !== 'undefined') your_call(jQuery); else { var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.src = '{{ URL }}/jquery.js'; var onload = function() { if (!script.readyState || script.readyState === "complete") your_call(jQuery); } if ("onreadystatechange" in script) script.onreadystatechange = onload; else script.onload = onload; head.appendChild(script); } })() 

我知道这是一个古老的话题,但是我的东西更快一点。 尝试在你的小部件

 "init": function() 

这将解决麻烦

我会下载jQuery源代码并将jQuery对象修改为另一个(jQueryCustom)。

然后find将$符号设置为jQuery对象的实例并注释该例程。

我不知道这会是多么容易或困难,但我一定会试一试。

(另外,检查你的第二个选项,因为它不坏,小部件将执行的网站,可能有一个比你需要的jQuery版本更旧)。

编辑:我只是检查了来源。 你只需要用另一个stringreplacejQuery (例如jQcustom )。 然后,尝试评论这一行:

 _$ = window.$ 

你可以像这样引用自定义的jQuery:

 jQcustom("#id").attr(...)