【问题标题】:JS widget (using Jquery) conflicting with Prototype on host pageJS 小部件(使用 Jquery)与主机页面上的 Prototype 冲突
【发布时间】:2011-10-10 21:51:54
【问题描述】:

我正在向其他网站提供 Javascript 小部件,而我在小部件中使用的 Jquery 似乎与主机站点对 Prototype 的使用相冲突。

您可以在此处查看实际发生的冲突: http://www.phillyrealestateadvocate.idxco.com/idx/8572/results.php?lp=100000&hp=500000&sqFt=0&bd=2&ba=0&searchSubmit=&city%5B%5D=131

在页面的右侧,单击绿色的“提问”按钮 - 它会生成一个弹出窗口,一旦您打开弹出窗口,“无效数组长度”错误就会开始滚动到 JS 控制台(并且不要停止。)然后弹出窗口无法关闭但仍然可以拖动。弹出窗口中的代码/内容位于 iframe 中,因此它仍然可以正常工作,但弹出窗口不会关闭。

Firebug 给我的错误是: invalid array length 在 Prototype.js 中,但是当我展开详细信息时,它引用了 jquery.min.js,所以这让我相信两者是冲突的。

我的小部件代码完全在一个匿名函数中,并使用 Alex Marandon 描述的模型加载 Jquery: http://alexmarandon.com/articles/web_widget_jquery/

我正在使用 noConflict 调用,但它可能没有按照我放置的方式工作?

这是我的小部件脚本的开头,其中包含对 jquery.min.js 和 jqueryui 的引用:

    (function() {

        // Localize jQuery variable
        var jQuery;

        /******** Load jQuery if not present *********/
        if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.6.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.6.2/jquery.min.js");
            script_tag.onload = scriptLoadHandler;
            script_tag.onreadystatechange = function () { // Same thing but for IE
                if (this.readyState == 'complete' || this.readyState == 'loaded') {
                    scriptLoadHandler();
                }
            };
            // Try to find the head, otherwise default to the documentElement
            (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
        } 
        else 
        {
            $.getScript( "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js" , 
                function()
                {
                    // The jQuery version on the window is the one we want to use
                    jQuery = window.jQuery;
                    main();
                }
            );
        }

        /******** Called once jQuery has loaded ******/
        function scriptLoadHandler() 
        {
            $.getScript( "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js" , 
                function()
                {
                    // Restore $ and window.jQuery to their previous values and store the
                    // new jQuery in our local jQuery variable
                    jQuery = window.jQuery.noConflict(true);
                    main(); 
                }
            );
        }

        /******** Our main function ********/
        function main() 
        { 

           // Do a bunch of stuff here

    }

})(); // We call our anonymous function immediately

任何帮助将不胜感激!

编辑:我现在在小部件中直接拥有 Jquery UI,因此我完全消除了 getScript 调用。不幸的是,这并没有解决冲突。这是新代码:

(function() {

    // Localize jQuery variable
    var jQuery, 

    /******** Load jQuery if not present *********/
    if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.6.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.6.2/jquery.min.js");
        script_tag.onload = scriptLoadHandler;
        script_tag.onreadystatechange = function () { // Same thing but for IE
            if (this.readyState == 'complete' || this.readyState == 'loaded') {
                scriptLoadHandler();
            }
        };
        // Try to find the head, otherwise default to the documentElement
        (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
    } 
    else 
    {
        jQuery = window.jQuery;
        main();
    }

    /******** Called once jQuery has loaded ******/
    function scriptLoadHandler() 
    {
        jQuery = window.jQuery.noConflict(true);
        main(); 
    }

    /******** Our main function ********/
    function main() 
    { 

【问题讨论】:

    标签: javascript jquery jquery-ui prototypejs conflict


    【解决方案1】:

    问题在于 Prototype 以一种不完全兼容的方式覆盖了默认的 Array.shift 方法。 jQuery 期望默认行为。

    实际上,它不仅仅对 jQuery 造成问题,当您的页面加载时,您会收到类似的错误,这是由于调用该页面上加载的 curfon-yui.js 脚本中的 shift 引起的。

    让我们在不加载 Prototype 的 Firebug 中尝试一下:

      >>> [].shift()
      undefined
    

    现在在您的页面上:

    >>> [].shift()
    RangeError: invalid array length
    this[i]=this[i+1];this.length--;return...ct).join(': ');}).join(', ')+'}>';}} 
    

    显然你不是唯一一个遇到这个问题的人:http://tommysetiawan.com/post/7887390641/jquery-and-prototype-conflict-array-shift

    不幸的是,jQuery 的 noConflict 对此无济于事。这个问题似乎在 Prototype 的更新版本中得到了解决,因此如果您对主机页面有任何控制权,它可能有助于更新其 Prototype 版本。它已经导致另一个脚本错误的事实可能是说服该页面的所有者修复它的一个很好的论据。否则,您可能需要修改您的小部件,使其不调用 Array.shift,或者您甚至可以尝试以修复它的方式对 Array.shift 进行猴子修补。

    【讨论】:

      【解决方案2】:

      您必须在function scriptLoadHandler(){ 之后立即定义jQuery.noConflict()。目前,您在加载 UI 插件后调用noConflict(),为时已晚。

      var hasLoaded = false;
      function scriptLoadHandler() 
          {
              if(hasLoaded) return;
              hasLoaded = true;
              window.jQuery = jQuery.noConflict(true);
              jQuery.getScript( "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js" , 
                  function(){
                      main(); 
                  }
              );
          }
      

      更新:添加hasLoaded 以防止代码重复执行。

      【讨论】:

      • 所以我刚试过这个,但现在 Firebug 说 jQuery 没有定义(在 noConflict 行)
      • 您的加载程序有缺陷,正在更新答案以解决该问题。
      • 在 noConflict 之后,我无法使用 getScript 让它工作,所以我最终将 jQuery UI 代码粘贴到小部件代码本身中。如果有人能看到我做错了什么,我很想听听!
      猜你喜欢
      • 2011-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-07
      • 1970-01-01
      • 2011-02-15
      • 2012-08-28
      相关资源
      最近更新 更多