代码之家  ›  专栏  ›  技术社区  ›  robhudson

如何将依赖jquery的javascript小部件嵌入未知环境中

  •  60
  • robhudson  · 技术社区  · 15 年前

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

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

    2. 如果网页有jquery,我通常可以使用它。但是,如果jquery版本是旧的,我希望加载自己的版本。但是,如果我真的要自己装,我就必须这样做,以免踩到他们的脚。 $ 变量。如果我设置 jQuery.noConflict() 他们的任何剧本都依赖于 $ 我刚刚把他们的页面弄坏了。

    3. 如果网页使用另一个javascript库(例如原型),我需要对原型的 $ 变量也可以。

    由于上述所有原因,不依赖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 回复  |  直到 11 年前
        1
  •  96
  •   gerry3    11 年前

    在查看了一些答案和指针,并找到了一些有用的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传递给它。

        2
  •  5
  •   Pavel Chuchuva grapeot    13 年前

    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
    
        3
  •  2
  •   cailinanne    14 年前

    如果您还想使用一些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
    });
    
        5
  •  1
  •   Sean Hogan    15 年前

    您可以使用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);
     }
    })()
    
        6
  •  0
  •   Cristian Hernández    11 年前

    我知道这是个老话题…但我得到了比你的黑客更快的东西。 在小工具中尝试

    "init": function()
    

    那会解决问题的

        7
  •  -1
  •   metrobalderas    15 年前

    我将下载jquery源并将jquery对象修改为另一个(jquerycustom)。

    然后找到设置 $ 符号作为jquery对象并注释该例程。

    我不知道这有多容易或困难,但我肯定会试试。

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

    编辑: 我刚查了来源。你只要换一个 jQuery 用另一根绳子( jQcustom 例如)。然后,尝试评论这一行:

    _$ = window.$
    

    您可以这样引用定制jquery:

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