Странный прототип Chrome / конфликт jQuery - PullRequest
24 голосов
/ 07 мая 2009

У нас есть приложение с унаследованным кодом, которое опирается на прототип, но мы обнаружили, что оно слишком «тяжелое» для большинства мест, где мы хотим его использовать, и обнаружили, что 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, который имеет значение true, а это не так, поскольку документ XPath document.evaluate не поддерживается.

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

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

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

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

Ответы [ 2 ]

44 голосов
/ 08 мая 2009

С 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>
10 голосов
/ 16 декабря 2009

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

  1. Прототип загружается, и, поскольку в WebKit отсутствует document.getElementsByClass(), Prototype (коварно) создает его.

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

  3. Во время инициализации JQuery инициализируется движок Sizzle (добавлен в 1.3.2?). Как часть своего самоанализа, он проверяет, а затем проверяет функциональность document.getElementsByClass(). В результате он вызывает реализацию Прототипа getElementsByClass(), которая зависит от того, установлен ли window.$ на Прототип $, а не на jQuery.

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

...