The Dollar Safe Mode
Written By Valerio Proietti, on Monday, June 22nd 2009, 10:39amSince the dawn of time, MooTools used a method named $ to get an HTML element by it’s id or direct reference. This method name, being the coolest and shortest you can find in JavaScript, is also used by a number of other javascript frameworks and libraries for similar functionality. Now, we do not think including 2 libraries or frameworks is OK. It’s not. Never. It’s an overhead of duplication you do not want to have. However, you might not have the full control of the page in some circumstances, and we recognize that. That’s why we implemented this: Dollar Safe Mode™. It’s nothing special really, but it should help in those situations where including multiple libraries is not your choice (because if it is, quite frankly, you’re doing everything wrong. Pick one, will you? And make sure it’s MooTools :-)).
MooTools 1.2.3 DOM stuff doesn’t depend on the presence of $ anymore. The method that used to be $ is now called document.id (short for identify). The method $ is still assigned when not already present in the page, and aliased to document.id.
But let me show you how it works:
Let’s say you have mootools.js and a fictional JS library called jLib.js. Both use a method called $.
This is what it used to happen:
Scenario 1: Include mootools first:
<script type="text/javascript" src="mootools.js" />
<script type="text/javascript" src="jLib.js" />
jLib would “steal” the $ method from MooTools. MooTools doesn’t work unless jLib has some sort of no-conflict mode of its own that will allow you to prevent it from “stealing” $ from MooTools.
Scenario 2: Include jLib first:
<script type="text/javascript" src="jLib.js" />
<script type="text/javascript" src="mootools.js" />
MooTools would “steal” the $ method from jLib, which may or may not work without it.
What happens now:
Scenario 1: Include MooTools first:
<script type="text/javascript" src="mootools.js" />
<script type="text/javascript" src="jLib.js" />
MooTools checks if a method called $ exists; if not, it defines it. In this scenario, MooTools defines it as it doesn’t find anything named $, being included first.
jLib “steals” the $ method from MooTools.
MooTools doesn’t care. MooTools now doesnt need $ to properly function. You can regain control of $ simply by reassigning it to its alias ($ = document.id).
Scenario 2: Include jLib first:
<script type="text/javascript" src="jLib.js" />
<script type="text/javascript" src="mootools.js" />
MooTools checks if a method called $ exists. It does find it, being included last, therefore it doesn’t define it. You can directly use document.id() or assign your own var to it, or manually assign $ to document.id, if you would like MooTools to have control of it.
As you can see, it’s pretty straightforward. In short, MooTools doesn’t need $ to function anymore, and doesn’t steal it from other frameworks when included after them.
Plugins
The above applies for MooTools-Core and MooTools-More. However, MooTools plugins use the $ method, therefore, while not breaking MooTools by including jLib, you will break the MooTools plugins. If you desperately need plugins to be multiple-framework compatible, and you the other frameworks to have control of $, there are a few things you can do.
The first, most obvious and recommended option is to replace every call to $() with document.id() by hand. It doesn’t take more than 10 seconds with a simple find and replace. This is probably what plugin authors should do, if they wish their plugin to be dollar-safe.
Another option is to encapsulate the plugin using a closure. This might come handy if you are processing a plugin that isn’t yours:
var X = new Class({
initialize: function(element){
this.element = $(element);
}
});
it should become:
(function(){
var $ = document.id;
this.X = new Class({
initialize: function(element){
this.element = $(element);
}
});
})();
As you can see, we’ve simply assigned $ as a local variable, using a closure. Everything in that closure will use document.id as its $ method. Remember to export the global variables though, as vars defined in the closure will stay private. I like to export globals using this., but you can use window. as well.
Please note that MooTools will probably remain incompatible with other frameworks that modify native prototypes, as there will probably be more name clashes. This isn’t a cross-framework compatible MooTools version by any means, nor does it want to be. The whole point is not to “steal” the dollar function from other libraries.
And that’s pretty much it about the Dollar Safe Mode™ in MooTools 1.2.3.
June 22nd, 2009 at 11:34 am
Although I rather share your thoughts on using only one framework/library I have always liked jQuery’s noconflict() because it gives more freedom to users and developers. Congrats on the Dollar Safe Mode (tm).
June 22nd, 2009 at 12:18 pm
Just like jQuery.noconflict(), good to see other frameworks worrying about compatibility. I’d use it like this:
(function($){ this.X = new Class({ initialize: function(element){ this.element = $(element); } }); })(document.id);June 22nd, 2009 at 1:19 pm
Is there a DollarSafe™ mode for the stock market?! Also want to implement it on the subway.
June 22nd, 2009 at 2:42 pm
innovation is often behind semplicity…
June 22nd, 2009 at 3:26 pm
Congrats on the latest release, looking good!
Why not just use “moo” instead of “document.id”? It’s only one more key stroke than “$”. Just a thought
June 22nd, 2009 at 5:16 pm
This great. We’ve had a lot of people wanting to use mootools with the concrete5 content management system, but the edit mode of the CMS is currently bundled with jquery.
June 22nd, 2009 at 6:01 pm
@atwork8 document.id is more verbose IMHO. I mean, what a function called moo does? (almost like $ if it wasn’t so spread)
I often use this kind of functionality like @ricardo said in his comment.
Its nice to see useful post like this.
Mootools FTW!
June 22nd, 2009 at 6:37 pm
@Fábio - Yeah document.id is significantly more verbose than $. Like you say $ doesn’t suggest what the function does at all, which is why I think “moo” is as good a substitute as any. You could argue that document.id isn’t much better, if you have to put in brackets “(short for identify)” then maybe it could have been named more appropriately, and you could as easily do: moo ($ alternative). To be honest though it’s hardly an issue, I’d just do what I do in JQuery and use a closure if required. I was asking more out of curiousity why document.id and not something shorter, that was all.
Anyways, still loving working with MooTools, thanks for sharing it! :o)
June 23rd, 2009 at 8:17 am
@atwork8: It isnt called “moo” or anything like that because in MooTools $ is just another utility function, used more often that the others, sure, but still an utility function.
$isnt the “main” object for our entire framework. It targets elements that are in the document, so document is the logical parent object that should contain this function.In any case, you can assign document.id to whatever var you prefer, like this:
var whatevr = document.id.June 23rd, 2009 at 3:55 pm
What’s up with the ™ ?
June 23rd, 2009 at 5:44 pm
Well, that’s one more item that can be removed from the “Stupid Reasons Not To Use MooTools™”-list! ;)