8

I'm writing a little JavaScript tool for myself that I plan on making available to other people and it uses jQuery. My dream for this little utility is for people to be able to include a single .js file from a remote source and, when that file is loaded, have it check to see if jQuery has already been included and, if it has, make sure it's a recent enough version so as to be compatible with what my code needs to do. Some pseudocode which may explain my issue more clearly (this code would appear at the top of the single .js file I mentioned earlier):

if jQuery is loaded {
    if version is less than (say) 1.3 {
        // load latest version of jQuery 
    }
} else {
    // load latest version of jQuery
}

// and do the jQuery.noConflict() 
// dance to avoid trampling any other libraries, etc. that the 
// user may be utilizing.

// The rest of my code lives here, happy in the knowledge that it's running in
// isolation from the rest of the JS that the page knows about.

My question, distilled into three friendly parts:

  1. Is it possible to load two separate versions of jQuery without them crapping all over each other?
  2. Can I stop the execution of my JS code while jQuery is loaded, then proceed?
  3. Is it possible to use noConflict() as I'm describing it? Or should I just call everything using jQuery() and not bother with it?

The overarching idea here is that any old user could grab a small snippet of HTML and drop it into their site/blog/whatever and have it Just Work™. And since many modern publishing platforms now ship with jQuery, I can't just quietly assume that it's not running and include it.

Thanks for your time, and please let me know if any part of this isn't clear or if I can provide additional context/detail to make your providing a response easier.

brettkelly
  • 25,565
  • 8
  • 51
  • 67

6 Answers6

15
function doMyStuff(jQueryJustForThisFn) {
    // do jQuery stuff!
    jQueryJustForThisFn('div').addClass('wow');
}

function check() {
    return window.jQuery && jQuery.fn && /^1\.[3-9]/.test(jQuery.fn.jquery);
}

if ( check() ) {

    doMyStuff( jQuery );

} else {

    var script = document.createElement('script'),

        timer = setInterval(function(){
            if ( check() ) {
                clearInterval(timer);
                document.body.removeChild(script);
                doMyStuff( jQuery.noConflict(true) );
            }
        }, 30);

    script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js';

    document.body.insertBefore( script, document.body.firstChild );

}
James
  • 103,518
  • 28
  • 156
  • 172
  • Question: where does `doMyStuff` get called in the `else` case? – Pat R Ellery Jun 06 '13 at 19:45
  • Since jQuery can now be found in the wild as 1.10.2 and 2.0.3, this regex would not work very well anymore. To future proof it, I'd suggest this instead: `/(^1\.([3-9]|\d{2,}))|((^[2-9])|^\d{2,})/` – Philipp Tsipman Oct 06 '13 at 05:12
1
(function(){

    var myBkl = {
             jq: null,
             loadScript: function(src) {
                    if(window.jQuery && window.jQuery.fn.jquery == '1.3.2'){
                            return;
                    }
                    var s = document.createElement('script');
                    s.setAttribute('src', src);
                    s.setAttribute('type', 'text/javascript');
                    document.getElementsByTagName('head')[0].appendChild(s); 
            },
            whenLoaded: function(callback){
                    if (typeof(window.jQuery) !== 'undefined' && window.jQuery.fn.jquery == '1.3.2') { 
                            myBkl.jq = window.jQuery.noConflict(true);
                            callback(myBkl.jq); 
                    } 
                    else {
                            setTimeout((function() {myBkl.whenLoaded(callback); }),      
100);
                    } 
            },
            init: function($){
                    console.log($.fn.jquery);
                    console.log(window.jQuery.fn.jquery);
            }
    };
    myBkl.loadScript('http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js');
    myBkl.whenLoaded(myBkl.init);
})();
wallyk
  • 53,902
  • 14
  • 79
  • 135
routerguy
  • 11
  • 1
1

This question has been answered here

jQueryCode = function(){
    // your jQuery code
}

if(window.jQuery)  jQueryCode();
else{   
    var script = document.createElement('script');   
    script.type = 'text/javascript';
    script.src = "//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js";
    document.head.appendChild(script);

    script.onload = jQueryCode;
}
Community
  • 1
  • 1
0

I don't know much about the noConflict, so i can only mostly answer 2.

This is usually called lazy loading. See my answer on a similar question to do this

Community
  • 1
  • 1
seanmonstar
  • 10,888
  • 2
  • 19
  • 25
0

I haven't tried to see how it behaves with a lower-version already loaded, but you may want to check out google.load

http://code.google.com/apis/ajaxlibs/documentation/#googleDotLoad

James Manning
  • 13,141
  • 2
  • 37
  • 63
0

For absolute safety, you may want to consider namespacing the version of jQuery you are using. It's a bit ugly, but a regex against the codebase to define your own global attach point will ensure you break nothing. If the code will be widely deployed across a variety of sites, this will be your best option and most ensure future compatibility.

Don Albrecht
  • 1,034
  • 1
  • 7
  • 10