Reputation: 11212
I'm making a widget that consists of a snippet of code to drop in your site that will then pull in content via js. Here's an example snippet:
<div data-token="bc1cea6304e8" id="my-widget">
<script src="http://localhost:8080/assets/eg-widget.js" type="text/javascript"></script>
</div>
I'm doing a test to check if the page already has jQuery, and if so, that the version is at least 1.5.
if (typeof jQuery == 'undefined' || isVersion("1.5", ">")) {
var script_tag = document.createElement('script');
script_tag.setAttribute("type", "text/javascript");
script_tag.setAttribute("src",
"http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js");
// Try to find the head, otherwise default to the documentElement
(document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
if (script_tag.readyState) {
script_tag.onreadystatechange = function () { // For old versions of IE
if (this.readyState == 'complete' || this.readyState == 'loaded') {
scriptLoadHandler();
}
};
} else { // Other browsers
script_tag.onload = scriptLoadHandler;
}
} else {
// The jQuery version on the window is the one we want to use
jQueryEg = window.jQuery;
scriptLoadHandler();
}
In either case, we set a variable jQueryEg to the jQuery we decide to use so that we can avoid conflicts.
If jQuery is not already loaded, everything is dandy. But if an older version is loaded, we run into conflicts when trying to load other libraries such as jQuery-ui.
To do this, we set window.jQuery to our newly loaded jQuery so that when we load jquery-ui and bootstrap.js, their references to window.jQuery or $ point to the correct version.
The problem is that sometimes the other parts of the page are calling jQuery at the same time that we've set window.jQuery to our version which causes problems.
Any thoughts on how we can avoid these conflicts?
jQueryEg = window.jQuery.noConflict(true);
window.jQueryEg = jQueryEg;
// jquery-ui reference window.jQuery so we need to set that to our new jquery for a sec
if (jQueryEg.ui == undefined || jQueryEg.ui.datepicker == undefined) {
var otherjQuery = window.jQuery;
window.jQuery = jQueryEg;
var script_tag = document.createElement('script');
script_tag.setAttribute("type", "text/javascript");
script_tag.setAttribute("src",
"//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js");
(document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
script_tag.onload = function () {
window.jQuery = otherjQuery;
main();
};
}
Upvotes: 3
Views: 3108
Reputation: 20885
Once I run into a similar issue. Looking at the jQuery-UI code, I noticed that it's all wrapped in an immediately invoked function expression (or maybe I wrapped it myself? I can't remember):
( function ( jQuery, undefined ){
// Code here...
})( jQuery );
to create private scopes. So my solution was to
jQuery
to jQuery_OLD
jQuery
So the following gives the idea
<script src="jquery-1.4.js"></script>
<script>
var jQuery_1_4 = jQuery.noConflict();
</script>
<script src="jquery-1.8.js"> </script>
<!-- load jquery UI -->
<script src="jquery-ui.js"> </script>
<!-- restore window.jQuery -->
<script>
jQuery = jQuery_1_4;
</script>
Upvotes: 5
Reputation: 5952
Having run into this exact situation before, in the end the determination was what you probably already know, and don't want to hear: There is simply no good way to avoid all edge-cases when loading multiple versions of external libraries like that, due to the reasons you have already specified. A summary of the complications involved are:
Unfortunately, the only answer is the obvious one: Host modified versions of the libraries on your own servers.
Of course, you don't need to serve these versions all the time, so you can still benefit from the use of Google's CDN. Meanwhile, you can still use your own CDN to deliver the modified versions. The main guidelines to follow are:
You'll usually find that the number of hits on your own server are actually quite minimal, comparatively. As always, don't trust me: keep statistics on your own, real-world scenarios!
Upvotes: 1