JS уиджет (с помощта на Jquery) е в конфликт с прототипа на хост страницата

Предоставям приспособление за 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 конзолата (и не t stop.) Тогава изскачащият прозорец не може да се затвори, но все още може да се плъзга. Кодът/съдържанието в изскачащия прозорец е във вградена рамка, така че все още работи нормално, но изскачащият прозорец просто не се затваря.

Грешката, която Firebug ми дава, е: invalid array length в Prototype.js, но когато разширя това за подробности, има препратки към jquery.min.js, така че това ме накара да повярвам, че двете са в конфликт.

Моят код на джаджа е изцяло в анонимна функция и зарежда 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() 
    { 

person Wemmick    schedule 10.10.2011    source източник


Отговори (2)


Проблемът е, че Prototype заменя метода Array.shift по подразбиране по начин, който не е напълно съвместим. jQuery очаква поведението по подразбиране.

Всъщност това не създава проблем само на jQuery, когато страницата ви се зареди, получавате подобна грешка, причинена от извикване на shift в скрипта curfon-yui.js, зареден на тази страница.

Нека да го пробваме във 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

NoConflict на jQuery няма да помогне с това за съжаление. Проблемът изглежда е разрешен в по-нови версии на Prototype, така че ако имате някакъв контрол върху хост страницата, може да помогне да актуализирате нейната версия на Prototype. Фактът, че вече причинява грешки с друг скрипт, може да бъде добър аргумент да убедите собственика на тази страница да я поправи. В противен случай може да се наложи да модифицирате джаджата си, така че да не извиква Array.shift или дори можете да опитате да направите маймунска корекция на Array.shift по начин, който го коригира.

person Alex Marandon    schedule 12.10.2011

Трябва да дефинирате jQuery.noConflict() веднага след function scriptLoadHandler(){. В момента вие се обаждате на 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 за предотвратяване на двойно изпълнение на кода.

person Rob W    schedule 10.10.2011
comment
Току-що опитах това, но сега Firebug казва, че jQuery не е дефиниран (на реда noConflict) - person Wemmick; 11.10.2011
comment
Вашият товарач е дефектен, актуализирате отговора, за да поправите това. - person Rob W; 11.10.2011
comment
Не можах да накарам това да работи с помощта на getScript след noConflict, така че в крайна сметка поставих кода на jQuery UI в самия код на джаджа. Ако някой може да види какво правя грешно, ще се радвам да го чуя! - person Wemmick; 11.10.2011