Working with Javascript in Joomla - Part 1

As Douglas Crockford puts it: “Javascript is the world’s most misunderstood language” . I think that in the Joomla universe this statement is 200% accurate. Most of the extension developers out there are good with PHP, but when it comes to javascript one wants to just find that snippet online, copy & paste it and forget about it - code quality here is not that important! And I say doh! It is important!

Joomla extensions are installed on 1000s of websites. But the thing is – users don’t install just 1 extension. They install a lot of them! Modules, plugins, and components – everything is thrown into the mix. And out of one small JS mess we get one big mess! Javascript is mixed with html, global variables are all over the place, there is no trace of modularity, no trace of good design patterns and it is just painful to watch. If you are lucky enough – your component will work and you won’t have to do any support, but as it happens most of the time – your extensions are not going to work because of other peoples copy and pasting!

I say let us put this to an end! Let us start to take care of our JS the same way we try to do our best with PHP. In this blog series I’ll try to give you some ideas on how to write better Javascript. I’ll give you links to good resources and hopefully I’ll convince you that we need better JS in our extensions!

Today I want to talk about namespacing your JS in Joomla. There are a lot of good online resources about namespacing and since I don’t like to reinvent the wheel all the time I’ll just share the links with you:

For beginners:
http://addyosmani.com/blog/essential-js-namespacing/#beginners

Once you’ve read the fundamentals, you can jump to the first part of the same blog post:
http://addyosmani.com/blog/essential-js-namespacing/

My preferred way of namespacing is “nested namespacing”. Starting with hotspots version 3 all our extensions will be slowly refactored and updated to use this pattern. Our JS code will reside in:

compojoom.extensionName

For example:

compojoom.hotspots.modules.modulelName
compojoom.hotspots.helpers.helperName
compojoom.ccomment.modules .moduleName

By accepting this approach – the only global javascript variable that our code will produce will be “compojoom”. No matter how many of our extensions you use – they will all reside in the compojoom namespace. This will ensure that we won’t collide with other extensions and of course that we won't polute the global namespace. In matter of fact - Joomla is already using this pattern. Have a look in media/system/js/core.js . Most of the joomla js functions are namespaced in the Joomla object. In the core.js file you can also see some functions that don't use the Joomla namespace, but most of them are deprecated and they will be removed in the future.

If you’ve read the blog post that I suggested above you are most probably asking yourself – “Hm, nested namespaces – there is so much writing involved for each nested module”. Like here:

var myApp = myApp || {};
// perform a similar existence check when defining nested children
myApp.routers = myApp.routers || {};
myApp.model = myApp.model || {};
myApp.model.special = myApp.model.special || {};

Well, thanks to David Walsh we are not going to do this. As he explains in this blog post with a little bit of code we can create nested classes with ease! Yes, this is going to be a mootools example! ( no secret that we love mootools at compojoom...)

This code:

new Class(‘compojoom.hotspots.module.myModule’, {}); 

will automatically create a js object that is properly namespaced. To illustrate it a little better, using the code from David Walsh I wrote this small jsfiddle:

http://jsfiddle.net/compojoom/t3eHX/1/

If you look at the DOM output in firebug of that page http://fiddle.jshell.net/compojoom/t3eHX/1/show/ - you can see that there is a single compojoom object that contains a demo and then a namespace object.

Hopefully by now you have realised that namespacing is good and poluting the global scrope with your functions is not an option!

If you have any questions or remarks -> use the comment form bellow :)