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

时间:2010-01-31 03:22:32

标签: javascript jquery widget

我正在开发一个依赖于jQuery的javascript小部件。小部件可能会也可能不会加载到已加载jQuery的页面上。在这种情况下出现了许多问题...

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

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

  3. 如果网页使用其他javascript库(例如原型),我也需要对原型的$变量敏感。

  4. 由于上述所有原因,似乎更容易不依赖于jQuery。但是在我走这条路之前,我将首先寻求建议。

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

    <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);
    

    如果有任何指针或资源可用于实现可在所有上述环境中使用的小部件,那么我们将非常感激。

7 个答案:

答案 0 :(得分:96)

在回顾了一些答案和指针,并找到了一些有用的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(如果它尚未加载)并将其封装在回调中,因此它不会与页面上预先存在的jQuery冲突。它还会检查最低版本是否可用,或者加载已知版本 - 在本例中为v1.3。它向回调(我的小部件)发送一个布尔值,判断是否加载了jQuery,以防需要进行任何触发。只有在加载jQuery之后才会调用我的小部件,将jQuery传递给它。

答案 1 :(得分:5)

请参阅Alex Marandon的How to build a web widget (using 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

答案 2 :(得分:2)

如果你还想使用一些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
});

答案 3 :(得分:1)

答案 4 :(得分:1)

您可以使用document.write()来有选择地将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);
 }
})()

答案 5 :(得分:0)

我知道这是一个古老的话题......但是我得到的东西比你的黑客更快。 试试你的小部件

"init": function()

将解决问题

答案 6 :(得分:-1)

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

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

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

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

编辑:我刚检查过来源。您只需将jQuery替换为另一个字符串(例如jQcustom)。然后,尝试评论这一行:

_$ = window.$

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

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