Подтвердить что ты не робот

Третий конфликт прототипа /jQuery Chrome

У нас есть приложение с устаревшим кодом, основанным на прототипе, но мы обнаружили, что он слишком "тяжелый" для большинства мест, которые мы хотим использовать, и обнаружил, что jQuery лучше подходит для того, как мы Работа. Поэтому мы переходим к jQuery для новых функций.

Тем временем у нас есть несколько страниц, которые должны загружать обе библиотеки:

<script language="javascript" type="text/javascript"
        src="prototype-1.5.1.2.js"></script> 
<script language="javascript" type="text/javascript"  
        src="jquery-1.3.2.js"></script> 
<script language="javascript" type="text/javascript">
    $j = jQuery.noConflict();
</script> 

(обратите внимание на более старую версию прототипа, мы обнаружили проблемы с обновлением, которые мы не хотим исправлять, когда мы поэтапно отказываемся от этого)

Это работает в IE6, IE7, IE8-as-7 и FX3, но загружает их в Chrome и все вещи jQuery не работают.

Загрузка javascript-консоли разработчика содержит следующие ошибки:

Uncaught Error: NOT_SUPPORTED_ERR: DOM Exception 9 http://.../prototype-1.5.1.2.js (line 1272)
Uncaught TypeError: Object #<an Object> has no method 'ready' http://.../lib.js (line 161)
Uncaught TypeError: Object #<an Object> has no method 'slideUp' http://.../page.aspx (line 173)
... and so on - all the failures are missing jQuery methods

Таким образом, это похоже на конфликт в прототипе, который вызывает сбой создания объекта jQuery.

Специфическая проблема с прототипом, как представляется, Prototype.BrowserFeatures.XPath является истиной, когда ее не должно быть, поскольку XPath document.evaluate не поддерживается.

Итак, теперь перезагрузите страницу при открытой консоли javascript - все это работает! WTF? Закройте консоль, перезагрузите и снова сработайте.

Сбой возникает только при загрузке страницы без открытой консоли javascript - почему это имеет значение? Это очень похоже на ошибку в Chrome.

Кто-нибудь может объяснить, что происходит? Почему ошибка в прототипе приводит к сбою инициализации jQuery? Почему загрузка страницы с открытой консолью делает ее работу?

Кто-нибудь знает хороший обход? (кроме обновления до prototype-1.6.0.3.js, который исправляет эту проблему, но нарушает загрузку устаревшего кода в другом месте)

4b9b3361

Ответ 1

От Core/jQuery.noConflict:

ПРИМЕЧАНИЕ. Эта функция должна вызываться после включения javascript файла jQuery, но ПЕРЕД, включая любую другую конфликтующую библиотеку, а также до того, как фактически используется другая конфликтующая библиотека, в случае, если jQuery включен последним. noConflict можно вызвать в конце файла jQuery.js, чтобы глобально отключить псевдоним $() jQuery. jQuery.noConflict возвращает ссылку на jQuery, поэтому его можно использовать для переопределения псевдонима $() объекта jQuery.

Возможно, попробуйте изменить его на:

<script language="javascript" type="text/javascript"
  src="jquery-1.3.2.js"></script> 
<script language="javascript" type="text/javascript">
    $j = jQuery.noConflict();
</script>
<script language="javascript" type="text/javascript"
  src="prototype-1.5.1.2.js"></script>

Ответ 2

Я нашел корень этой проблемы:

  • Загрузка прототипа, и поскольку WebKit не хватает document.getElementsByClass(), Prototype (insidously) создает его.

  • Инициализация jQuery начинается, и в самом верху она устанавливает window.$ в jQuery.

  • Во время инициализации JQuery запускается движок Sizzle (добавленный в 1.3.2?). В рамках своей интроспекции он проверяет, а затем проверяет функциональность document.getElementsByClass(). В результате он вызывает прототип impelementation getElementsByClass(), который зависит от window.$, установленного в Prototype $, а не jQuery.

В конечном итоге это нужно будет исправить в jQuery (см. билеты http://bugs.jquery.com/ticket/4365 и 5027). Моим быстрым патчем было удаление назначения window.$ в начале инициализации jQuery.