I've been reading up on global namespace pollution when developing an extension for Firefox, and I want to avoid it as much as possible in my extension. There are several solutions, but generally, the solutions seem to center around only declaring one global variable for your extension, and putting everything in that. Thus you only add one extra variable to the global namespace, which isn't too bad.
As a brief aside, I have had a solution proposed to me that avoids putting any extra variables into the global namespace; wrap everything in a function. The problem here is that there's nothing to refer to in your XUL overlays. You have to declare elements in your overlays, and then in JS add a ton of addEventListener
s to replace what would've been something like an oncommand="..."
in XUL. I don't want to do this; I definitely want my XUL to include events in the XUL itself because I think it looks cleaner, so this isn't a solution for me. I therefore need at least 1 global variable for XUL oncommand="..."
attributes to refer to.
So the consensus seems to be to have one (and only one) variable for your extension, and put all your code inside that. Here's the problem: generally, people recommend that that variable be named a nice long, unique name so as to have almost zero chance of colliding with other variables. So if my extension's ID is [email protected]
, I could name my variable myextensionAtMycompanyDotCom
, or com.mycompany.myextension
. This is good for avoiding collisions in the global namespace, but there's one problem; that variable name is long and unwieldy. My XUL is going to be littered with references to event handlers along the lines of oncommand="myextensionAtMycompanyDotCom.doSomeEvent"
. There's no way to avoid having to refer to the global namespace in my XUL overlays, because an overlay just gets added to the browser window's DOM; it doesn't have a namespace of its own, so we can't somehow limit our extension's variable scope only to our own overlays. So, as I see it, there are four solutions:
This results in rather unwieldy, verbose XUL code like:
<statusbarpanel id="myStatusBar" onmousedown="myextensionAtMycompanyDotCom.onMyStatusBarClick();">
We come up with a much nicer short variable name for our extension, let's say myExt
, and add some random characters on to make it almost certainly unique, such as myExtAX8T9
. Then in the XUL, we have:
<statusbarpanel id="myStatusBar" onmousedown="myExtAX8T9.onMyStatusBarClick();">
Clearly, this results in rather ugly and even confusing code as the random characters look odd, and make it look like some kind of temporary variable.
You could just wrap up everything in functions. This, of course, means that there is nothing to refer to in your XUL, and so every event must be attached to the XUL elements using addEventListener
in your JavaScript code. I don't like this solution because, as mentioned above, I think it's cleaner to have the events referenced in the XUL code rather than having to search a ton of JS code to find which events are attached to which XUL elements.
I could just call my extension's variable myExt
, and then I get nice XUL code like:
<statusbarpanel id="myStatusBar" onmousedown="myExt.onMyStatusBarClick();">
Of course, this short name is much more likely to clash with something else in the global namespace and so isn't ideal.
So, have I missed something? Is there any alternative to the 4 solutions I proposed above? If not, what would be the best of the 4 (given that #3 is basically unacceptable to me), and why?
We use the JavaScript module pattern described in this blog post: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth. You can export the symbols that you want to use in your XUL handlers as described.
In addition, we use a reversed host name as the module name prefix to ensure that we control the namespace:
/* Set up the global namespace. */
if (typeof(com) == "undefined") var com = {};
if (!com.salsitasoft) com.salsitasoft = {};
/* Main namespace. */
com.salsitasoft.myExtensionGlobalStuffGoesHere = (function (my) {
return my;
})(com.salsitasoft.myExtensionGlobalStuffGoesHere || {});
Update: I changed this to pass com.salsitasoft.myExtensionGlobalStuffGoesHere into the closure if it already exists so that the namespace can be spread across multiple files.
Your functions have to "live" somewhere either way, so you cannot avoid to claim some kind of namespace. I also agree to your point that defining the event in the XUL is better than attaching them. So, I propose a hybrid between 3+4:
Place all the code of your plugin and all variables inside this namespace. Use the anonymous function wrapper pattern like (have a look at some jQuery plugins as code examples):
window.catchyseo = (function(){var private = x; [...] })();
In your namespace, expose some event handlers which you can reference in your XUL.
This approach gives you the best of two worlds: you can define your events in XUL and you have a closed namespace without any global namespace pollution - except your one namespace variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With