Dovev Hefetz Dovev Hefetz - 8 days ago 6
jQuery Question

Can I load JQuery and JQueryUI in local variables, without using noConflict?

I have a widget that uses jQuery that is added into other various websites that I do not control and that may or may not load one or more instances of jQuery of any versions. I was until now loading jQuery and jQueryUI and using noConflict to restore the global variables. I also load all resources asynchronously, and have a delay between loading jQuery and jQueryUI for efficiency (I don't need jQueryUI right away). Now I have this problem: first my jQuery loads (and I save out window.jQuery locally), then the native jQuery loads, then jQueryUI loads into their jQuery. I already tried:

var jQueryOriginal = window.jQuery;
var original$ = window.$;
window.jQuery = localJQuery;
window.$ = local$;
promise = loadResource(url + "?r=" + rand).then(function() {
localJQuery = window.jQuery;
local$ = window.$;
window.jQuery = jQueryOriginal;
window.$ = original$;
});


Don't know if the $ was necessary, added that when it didn't work without it, but either way this didn't help at all. It could be because their library is loading after I save the variables out, not sure.

Either way, the best thing for me (and the websites) would be to load jQuery and jQueryUI directly into local or alternate variables, rather than the default window.$ and window.jQuery. Is that possible?

Answer

I just came up with a solution for jquery-ui that I hope can help other people too. Still looking for a solution to loading jQuery itself locally though.

The jquery-ui code references a global jQuery variable. If you wrap the library in this:

function loadJQueryUIInto(jQuery) {
// jquery-ui code
    return jQuery;
}

Then after including the jquery-ui code you can do this:

localJQuery = loadJQueryUIInto(localJQuery);

If you are hosting the jquery-ui library yourself (not advised unless you have a CDN to put it on) you can wrap the function directly. Alternatively, after getting the script code via XHR, simply include the extra code before and after it inside the eval:

var runBefore = 'function aspectivaLoadJQueryUIInto(jQuery) {';
var runAfter = 'return jQuery;}';
eval.apply(window, [ runBefore + script + runAfter ]);

Regarding jquery itself, if you load it in an AMD environment I think you can get a standalone object. Other than that it looks like it doesn't lend itself to loading locally because it is tied up with the window object. Another option is to clone an existing jquery object with this function and then load jquery-ui into it as above after using noConflict.

function clone(jQuery) {
    var copy = function() {
        return jQuery.apply(this, arguments);
    };

    for ( var prop in jQuery) {
        if (prop == 'ui') {
            copy[prop] = clone(jQuery[prop]);
        } else {
            copy[prop] = jQuery[prop];
        }
    }

    return copy;
}