Question

We have an application with legacy code that relies on prototype, but we've found it to be too 'heavy' for most of the places we want to use it and and have found jQuery to be a better fit for how we work. So we're migrating to jQuery for new functionality.

In the meantime we have several pages that need to load both libraries:

<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> 

(note older version of prototype, we found issues on upgrading that we don't want to fix when we're phasing it out anyhow)

This works in IE6, IE7, IE8-as-7 and FX3, but load it in Chrome and all the jQuery stuff fails.

Loading up the developer javascript console displays the following errors:

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

So this looks like a conflict in prototype that causes the creation of the jQuery object to fail.

The specific prototype issue appears to be Prototype.BrowserFeatures.XPath being true when it shouldn't be, as XPath document.evaluate isn't supported.

Ok, so now reload the page with the javascript console open - it all works! WTF? Close the console, reload and it fails again.

The failure only occurs when the page load occurs without the javascript console open - why would that make any difference? That looks very much like a bug in Chrome.

Anyone able to explain what's going wrong? Why should an error in prototype cause the jQuery init to fail? Why does loading the page with the console open make it work?

Anyone know a good workaround? (apart from upgrading to prototype-1.6.0.3.js, which fixes this issue but breaks a load of legacy code elsewhere)

Was it helpful?

Solution

From Core/jQuery.noConflict:

NOTE: This function must be called after including the jQuery javascript file, but BEFORE including any other conflicting library, and also before actually that other conflicting library gets used, in case jQuery is included last. noConflict can be called at the end of the jQuery.js file to globally disable the $() jQuery alias. jQuery.noConflict returns a reference to jQuery, so it can be used to override the $() alias of the jQuery object.

Maybe try changing it to:

<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>

OTHER TIPS

I've found the root of this problem to be:

  1. Prototype loads, and because WebKit lacks document.getElementsByClass(), Prototype (insidously) creates it.

  2. jQuery initialization begins, and at the very top, it sets window.$ to jQuery.

  3. During JQuery's initialization, the Sizzle engine (added in 1.3.2?) initializes. As part of its introspection, it checks for, and then tests the functionality of document.getElementsByClass(). As a result, it calls Prototype's impelementation of getElementsByClass(), which depends on window.$ being set to Prototype's $, not jQuery's.

Ultimately, this will need to be fixed in jQuery (see tickets http://bugs.jquery.com/ticket/4365 and 5027). My quick patch was to remove the assignment to window.$ in the top of jQuery's initialization.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top