I am evaluating jQuery for use in a Firefox extension. There are two main channels for including Javascript in an extension: overlays and modules.
A Firefox code module is executed in a different context from any chrome window, so there's no chance of clobbering global variables on window. In fact, the window object does not even exist, so even trying to load jQuery as a code module is difficult. To cope with this problem, I wrote this:
http://github.com/retiman/fext/blob/master/modules/fext.jsmThen, with some minor hacking of jQuery, eg by writing this at the top of the file:
- var window = {};
- Components.utils.import("resource://myproject/fext.jsm", window);
...I should be able to get jQuery loading. However, I am uncertain as to the long term ramifications of such actions, since I am not really feeding jQuery a really real window. This is also a rather tortured solution, and I am wondering if anybody has ever used jQuery successfully in a code module. I read reports about people using jQuery in extensions successfully all the time, and I am curious.
On the flip side, I could load jQuery from an overlay, but that introduces another set of complications. Firstly, if I simply load jQuery like so from the overlay:
- <script src="jquery.js" />
...then the two objects jQuery and $ are defined for the entire chrome window, possibly clobbering other extensions. While I can certainly use jQuery.noConflict() and function scope to hide the definitions like so:
- <script>
- <![CDATA[
- var jQuery = jQuery.noConflict();
- var $ = jQuery;
- ]]>
- </script>
...this still poses a problem due to the fact that overlays can be loaded asynchronously and dynamically. A race condition still exists due to the fact that another extension's overlay could have defined and used 'jQuery' and/or '$' on the chrome window before I could call noConflict to remove them.
My final, tortured, solution was to hack the jQuery source to never install itself on the chrome window. I added this to the top of jquery.js:
- var $ = null;
Then, at the end, I removed the code that installed itself on the chrome window:
- // window.jQuery = window.$ = jQuery;
- $ = jQuery;
To prevent the $ object from being defined on the chrome window, I loaded jQuery in a function with mozISubScriptLoader, thus hiding $ from the chrome window using function scope:
- new function () {
- window.addEventListener(
- "load",
- function () {
- Components.classes["@mozilla.org/moz/jssubscript-loader;1"].
- getService(Components.interfaces.mozIJSSubScriptLoader).
- loadSubScript("chrome://myproject/content/jquery.js");
- },
- false
- );
- };
This seems to work, but I'm wondering if anybody else has gotten jQuery to load in an extension, safely, without such a long and tortured process?