jQuery in Joomla: I was wrong

For quite some time now, it’s been no secret that I’m a fan of jQuery and prefer it to MooTools for JavaScript development. However, Joomla ships with MooTools as the preferred JavaScript framework. Both jQuery and MooTools like using $ as a shortcut method name, which can cause conflicts. Fortunately, both frameworks have ways of disabling this shortcut so that you can use them side by side.

Unfortunately, if you’re not paying attention to the ordering of the JavaScripts, you can end up loading both before you have a chance of sending one into “no conflicts” mode. For quite some time now, I’ve advised fellow Joomla developers to always load MooTools first. It turns out that this advice is not correct, and can cause you to load up MooTools when you’re not even going to use it.

So I’d like to explain why I came to this conclusion in the first place, the correct way of avoiding the problem, and a call to solve this centrally so that people don’t have six copies of jQuery loading on their websites.

The real issue

The core issue has to do with the way JDocument adds JavaScript to the HTML document. As you call JDocument::addScript(), JDocument makes an internal list of all the JavaScript files it needs to load. Also, calling JHTML::_(‘behavior.mootools’) adds the MooTools framework to this list. You can also pass JavaScript in a string to be added directly in <script> tags through the JDocument::addScriptDeclaration() method. With these methods in mind, you would assume that you could add jQuery via JDocument::addScript() and the JavaScript snippet ‘jQuery.noConflict()’ through JDocument::addScriptDeclaration(), like this:

$document = JFactory::getDocument();
$document->addScript('path/to/jquery.js');
$document->addScriptDeclaration('jQuery.noConflict()');

This sometimes works. However, if (for instance) your module used jQuery and the next one used MooTools, you’d run into a conflict even though you had $document->addScriptDeclaration(‘jQuery.noConflict()’) in your code. The advice passed around by myself and the Joomla community was to do this in your code:

JHTML::_('behavior.mootools');
$document = JFactory::getDocument();
$document->addScript('path/to/jquery.js');
$document->addScriptDeclaration('jQuery.noConflict()');

This ensured that MooTools got loaded first and that the conflict would not happen. This also forced MooTools onto the page regardless of whether or not it was being used. It turns out this approach doesn’t really address the real problem: Joomla loads all of your external scripts first, then loads all of your script declarations. So for instance, the following code snippets result in the same script ordering as the previous sample:

$document = JFactory::getDocument();
$document->addScriptDeclaration('jQuery.noConflict()');
JHTML::_('behavior.mootools');
$document->addScript('path/to/jquery.js');

$document = JFactory::getDocument();
JHTML::_('behavior.mootools');
$document->addScriptDeclaration('jQuery.noConflict()');
$document->addScript('path/to/jquery.js');

The fix

To genuinely solve the problem and not worry about MooTools, you need to first create a JavaScript file with the code jQuery.noConflict();. Then you need to load jQuery, then load the file containing the jQuery.noConflict(); code. Your code in Joomla would look like this:

$document = JFactory::getDocument();
$document->addScript('path/to/jquery.js');
$document->addScript('path/to/jquery.noconflict.js');

In this example, jquery.noconflict.js contains the following code:

jQuery.noConflict();

By doing this, it’s guaranteed that jQuery.noConflict() will get called immediately after jQuery is loaded by the browser. To recap, the ordering of MooTools and jQuery does not matter if you make sure jQuery.noConflict() is called immediately after jQuery is loaded. After you send jQuery into noConflict mode, you still must either use jQuery() instead of $(), or use one of the referencing methods described here in your jQuery-powered code.

But wait, I still have a thousand extensions all loading jQuery!

Ideally, each Joomla site should be loading either zero or one copies of jQuery. Having multiple copies of jQuery sitting around Joomla puts site owners in the position of having to manage conflicts. Also, distributing multiple copies of jQuery discourages the use of Google’s JavaScript library CDN. We don’t want to foist this problem onto site administrators; they just want all of their extensions to work.

Fortunately, there’s an effort underway to standardize and document the use of jQuery in Joomla. If you’re willing to help out, join our Joomla People Group jump into the discussion. We should be able to document a way for extension developers to bundle a jQuery plugin with their extensions, as well as avoid version conflicts. Ultimately, a copy of jQuery should be installed and updated as necessary without the intervention of site administrators.

3 Responses to “jQuery in Joomla: I was wrong”

  • Thanks for providing such an elegant solution. This helped me solve a niggling IE 7 only issue with sites using mootools dropdown menus.

  • I build joomla template and I prefer using jquery rather than mootools. I have built several joomla templates with other noconflict method. But I still get complain about how its not loading and causing problem.

    After reading this article it is clear why it is happening. I will try out the fix you suggested and see if it works.

    Towfiq I.

  • Andre Stahl:

    Hi Joe, I have unfortunately found no other way to contact you. Do not be evil.
    I only have one question about this post:
    http://www.designvsdevelop.com/quick-and-dirty-christmas-list-a-joomla-recipe/#
    At first this is a great work. This script is exactly what I was looking for.
    Did you continue this project? Unfortunately, there is still no good component for Joomla for this purpose.
    Unfortunately, I’m a PHP newbie. Can you tell me briefly explain how I ad a link in MYLIST to delete an entry? Where in the code you have to make a change?

    Best wishes from Essen in Germany.