JS小部件(使用Jquery)与主机页面上的Prototype冲突

时间:2011-10-10 21:51:54

标签: javascript jquery jquery-ui prototypejs conflict

我向其他网站提供了一个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给我的错误是: Prototype.js中的invalid array length,但是当我扩展它以获取详细信息时,它引用了jquery.min.js,所以这让我相信这两者是冲突的。

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

我正在使用noConflict调用,但也许它不像我放置的那样工作?

这是我的widget脚本的开头,它包含对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() 
    { 

2 个答案:

答案 0 :(得分:3)

问题是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。

答案 1 :(得分:2)

您必须在jQuery.noConflict()之后立即定义function scriptLoadHandler(){。目前,您在加载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以防止双重执行代码。