Use the media Folder, Allow Overridable Media

So after an interesting discussion about overriding CSS and JS in Joomla! over the weekend, I might have accidentally stumbled on this nifty little Hidden Joomla Secret.  Best part is it works in the currently supported versions of Joomla!, 2.5 and 3.0 (testing on earlier versions is encouraged though).

So What's The Secret!?

The secret is to follow a simple best practice; use Joomla's /media folder for your extension media.  If you follow how the /media/system folder is set up to implement your extension's media and call your media using JHtml::script() or JHtml::stylesheet() (some will argue to use JHtml::_('script'), but that's another discussion for another day), then the API will automatically check for the file in the your template first, then the media folder.  No more reason to hack your own methods to override media, so long as we all get on the same page and use this piece of the API.

So, How's It Work?

Using my Tweet Display Back module as an example, to override the CSS, I call the stylesheet like this: JHtml::stylesheet('mod_tweetdisplayback/construct-css3.css', false, true, false);. The important parameter is the true in the middle there; it tells the API to search for a file in the media folder or elsewhere. If searching elsewhere, it just tries to add the file you've specified, but if you're using the media folder, then the magic happens. Using the filename in the first parameter, my CSS file is at /media/mod_tweetdisplayback/css/construct-css3.css. As I said before, before looking here, the API will look in your template. For a stylesheet, the API looks in /templates/my_template/css/mod_tweetdisplayback/construct-css3.css for this specific file. For JavaScript files, JHtml::script('com_finder/indexer.js', false, true); will check in /templates/my_template/js/com_finder/indexer.js before using the file at /media/com_finder/js/indexer.js. Too easy, isn't it?

How Do I Know If An Extension Supports This?

Well, you can either read the code or do some practical testing.  If you see media files being loaded from the media folder in your page's <head> element, there's a decent chance the extension already supports this.  For example, to convert that mod_tweetdisplayback/construct-css3.css example from before, if the <link> element path is /media/mod_tweetdisplayback/css/construct-css3.css, you drop the leading media portion of the path and the media type (css) in the middle to get /mod_tweetdisplayback/construct-css3.css, then you create your override at /templates/my_template/css/my_override_path.  If an extension doesn't support this, then pester the developer to see if they'll change their code, otherwise you'll have to stick to tried and true methods of overriding their media as you were doing before.  Expect the next releases of all my extensions to support this, now that I know how the API works ;-).