Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible to load jQuery only inside closure?

I don't think this can be done, though I know requirejs can do something similar, and I was wondering if this might be possible outside of require.

I'm writing a piece of SaaS JavaScript code that will most likely need jQuery to run cross browser. Some sites have it, some don't, but I don't want to stick jQuery on the window object if they aren't using it. Though I could individually create alternatives for everything I use jQuery for... I was wondering if there is a way I can load jQuery only for use inside my closure. Is this possible?

like image 442
Shane Avatar asked Dec 25 '22 19:12

Shane


2 Answers

When you load the standard release of jQuery, by default jQuery assigns itself to the global names jQuery and $. If you load your version of jQuery before your closure file within the page, then within your closure do

var $ = jQuery.noConflict(true);

It will undo whatever modifications your version of jQuery did to the global object.

It is worth noting, however, that this produces a race condition. If any events or timeouts fire between the time that your jQuery file loads and your closure calls jQuery.noConflict(true) they will accidentally use the version of jQuery that you loaded.

An alternative is to edit the jQuery file that you are using to include a call to jQuery.noConflict(true) at the bottom of the jQuery file. You can assign the result to an arbitrary name that no one else would ever think to use, like "abcRandomNumberHere". Then you can retrieve your instance of jQuery from that global name within your closure assigning it to a local variable named jQuery and/or $ and delete the global reference at that time.

// Your jQuery file on your server
// ...
// End of file:
someRandomGlobalName = jQuery.noConflict(true);

// The file that contains your closure:
(function() {
    var $, jQuery;
    $ = jQuery = someRandomGlobalName;
    delete window.someRandomGlobalName;

    // Your code that uses jQuery here
} ());

This is a rough approximation of what RequireJS does to keep jQuery out of the global namespace. Recent versions of jQuery have built-in code that detects the existence of a script loader like RequireJS and rather than assigning to global names jQuery passes a reference to itself into RequireJS and leaves the global object untouched. That way RequireJS contains the reference to jQuery internally, but the global.requirejs variable is modified instead.

Creating your own non-conflicting global name for your jQuery version and your closure to "rendezvous" on is analogous to RequireJS' functionality. The name RequireJS uses is the "global name": requirejs.s.contexts._.jQuery (not exactly, but something like this).

like image 146
Mike Edwards Avatar answered Dec 28 '22 07:12

Mike Edwards


Call jQuery.noConflict(true) and it will re-assign $ and jQuery to wherever it was.

Then, you can pass the reference returned by the above expression into your closure.

(function(jQuery) {

})(jQuery.noConflict(true));
like image 33
alex Avatar answered Dec 28 '22 08:12

alex