Ticket #4834 (closed enhancement: fixed)
Don't set window.$ until the outro
|Reported by:||obrie||Owned by:|
$ is the one generic function that's added to the window when loading jQuery that might conflict with other libraries when jQuery is being evaluated. As a result, it's best that $ not be set by jQuery until the outro when the rest of the framework has been evaluated.
This is best shown by example. I have the following test page:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <script src="http://www.prototypejs.org/assets/2007/1/18/prototype.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script> </head> <body></body> </html>
This has Prototype 1.5.0 and jQuery 1.3.2 embedded on the page. When loaded in Safari 3.2.1, it causes the following error:
Error: NOT_SUPPORTED_ERR: DOM Exception 9 http://www.prototypejs.org/assets/2007/1/19/prototype.js (line 1081)
While this is an older version of Prototype, I think it still demonstrates the issue at hand. What happens is the following:
- Prototype loads, defining a global $ function and overriding getElementsByClassName which uses the $ function it has defined.
- jQuery loads, overriding the global $ function immediately.
- While jQuery is being evaluated (specifically selector.js), it calls getElementsByClassName (overridden by Prototype).
- At this point, Prototype's implementation of getElementsByClassName expects to have access to the global $ function it defined. Unfortunately, it's been overridden by jQuery causing the error described above.
Usually you can get away with library conflicts by using jQuery's $.noConflict(true) feature. However, the problem here is that the conflict occurs during the evaluation of jQuery as a result of jQuery adding global functions too early on in the process.
I believe the solution to this admittedly somewhat rare occurrence is to move the declaration of global functions to the bottom of jQuery rather than at the top. This will help solidify jQuery's ability to be compatible with anything else defined on the page and resolve the problem described here.