Suppose we need to embed a widget in third party page. This widget might use jquery for instance so widget carries a jquery library with itself. Suppose third party page also uses jquery but a different version. How to prevent clash between them when embedding widgets? jquery.noConflict is not an option because it's required to call this method for the first jquery library which is loaded in the page and this means that third party website should call it. The idea is that third party site should not amend or do anything aside putting tag with a src to the widget in order to use it.
Also this is not the problem with jquery in particular - google closure li开发者_开发知识库brary (even compiled) might be taken as an example.
What solutions are exist to isolate different javascript libraries aside from obvious iframe? Maybe loading javascript as string and then eval (by using Function('code to eval'), not the eval('code to eval')) it in anonymous function might do the trick?
Actually, I think jQuery.noConflict is precisely what you want to use. If I understand its implementation correctly, your code should look like this:
(function () {
var my$;
// your copy of the minified jQuery source
my$ = jQuery.noConflict(true);
// your widget code, which should use my$ instead of $
}());
The call to noConflict
will restore the global jQuery
and $
objects to their former values.
Function(...)
makes an eval inside your function, it isn't any better.
Why not use the iframe
they provide a default sandboxing for third party content.
And for friendly ones you can share text data, between them and your page, using parent.postMessage
for modern browser or the window.name
hack for the olders.
I built a library to solve this very problem. I am not sure if it will help you of course, because the code still has to be aware of the problem and use the library in the first place, so it will help only if you are able to change your code to use the library.
The library in question is called Packages JS and can be downloaded and used for free as it is Open Source under a Creative Commons license.
It basically works by packaging code inside functions. From those functions you export those objects you want to expose to other packages. In the consumer packages you import these objects into your local namespace. It doesn't matter if someone else or indeed even you yourself use the same name multiple times because you can resolve the ambiguity.
Here is an example:
(file example/greeting.js)
Package("example.greeting", function() {
// Create a function hello...
function hello() {
return "Hello world!";
};
// ...then export it for use by other packages
Export(hello);
// You need to supply a name for anonymous functions...
Export("goodbye", function() {
return "Goodbye cruel world!";
});
});
(file example/ambiguity.js)
Package("example.ambiguity", function() {
// functions hello and goodbye are also in example.greeting, making it ambiguous which
// one is intended when using the unqualified name.
function hello() {
return "Hello ambiguity!";
};
function goodbye() {
return "Goodbye ambiguity!";
};
// export for use by other packages
Export(hello);
Export(goodbye);
});
(file example/ambiguitytest.js)
Package("example.ambiguitytest", ["example.ambiguity", "example.greeting"], function(hello, log) {
// Which hello did we get? The one from example.ambiguity or from example.greeting?
log().info(hello());
// We will get the first one found, so the one from example.ambiguity in this case.
// Use fully qualified names to resolve any ambiguities.
var goodbye1 = Import("example.greeting.goodbye");
var goodbye2 = Import("example.ambiguity.goodbye");
log().info(goodbye1());
log().info(goodbye2());
});
example/ambiguitytest.js uses two libraries that both export a function goodbye, but it can explicitly import the correct ones and assign them to local aliases to disambiguate between them.
To use jQuery in this way would mean 'packaging' jQuery by wrapping it's code in a call to Package and Exporting the objects that it now exposes to the global scope. It means changing the library a bit which may not be what you want but alas there is no way around that that I can see without resorting to iframes.
I am planning on including 'packaged' versions of popular libraries along in the download and jQuery is definitely on the list, but at the moment I only have a packaged version of Sizzle, jQuery's selector engine.
Instead of looking for methods like no conflict, you can very well call full URL of the Google API on jQuery so that it can work in the application.
<script src="myjquery.min.js"></script>
<script>window.myjQuery = window.jQuery.noConflict();</script>
...
<script src='...'></script> //another widget using an old versioned jquery
<script>
(function($){
//...
//now you can access your own jquery here, without conflict
})(window.myjQuery);
delete window.myjQuery;
</script>
Most important points:
call jQuery.noConflict() method IMMEDIATELY AFTER your own jquery and related plugins tags
store the result jquery to a global variable, with a name that has little chance to conflict or confuse
load your widget using the old versioned jquery;
followed up is your logic codes. using a closure to obtain a private $ for convience. The private $ will not conflict with other jquerys.
- You'd better not forget to delete the global temp var.
精彩评论