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

JS widget (using Jquery) conflicting with Prototype on host page

本文关键字:冲突 Prototype 主机 小部 使用 Jquery JS      更新时间:2023-09-26

我正在为其他站点提供一个Javascript小部件,并且我在小部件中使用的Jquery似乎与主机站点使用的Prototype相冲突。

你可以看到下面的冲突:http://www.phillyrealestateadvocate.idxco.com/idx/8572/results.php?lp=100000&惠普= 500000,平方英尺= 0,bd = 2,英航= 0,searchSubmit =,城市% 5 b % 5 d = 131

在页面的右侧,点击绿色的"Ask a question"按钮-它将生成一个弹出窗口,当你打开弹出窗口时,"无效数组长度"错误开始滚动到JS控制台(并且不会停止)。弹出窗口无法关闭,但仍可拖动。弹出窗口内的代码/内容在iframe中,因此它仍然正常工作,但弹出窗口不会关闭。

Firebug给我的错误是:在Prototype.js中的invalid array length,但是当我扩展它的细节时,它引用了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() 
    { 

问题是Prototype覆盖了默认的Array。以不完全兼容的方式Shift方法。jQuery期望默认的行为。

实际上,它不会引起问题,只有jQuery,当你的页面加载,你得到一个类似的错误引起的调用shift在curfon-yui.js脚本加载到该页。

让我们在没有加载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或者你甚至可以尝试猴子补丁数组。

必须在function scriptLoadHandler(){之后立即定义jQuery.noConflict()。目前,你调用noConflict()后,UI插件已经加载,这是太晚了。

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以防止代码重复执行