Can I reset the name of jQuery's global object?
Let me give my question some context. I have a JavaScript widget. The widget includes a copy of jQuery from my site. This widget is placed on a third-party site. The widget parses a JSON feed and injects the contents into the DOM. Pretty simple stuff.
If the third-party page already has jQuery referenced and relies on jQuery plugins, conflicts could arise. Especially, when the third-party site references a different version of jQuery. $.noConflict() is useful, but the existence of plugins make it unreliable. From the $.noConflict() documentation:
If necessary, we can free up the jQuery name as well by passing true as an argument to the method. This is rarely necessary, and if we must do this (for example, if we need to use multiple versions of the jQuery library on the same page), we need to consider that most plug-ins rely on the presence of the jQuery variable and may not operate correctly in this situation.
To get around this issue, my idea is to reset the name of the jQuery global object. At the bottom of the jQuery source, there are these lines:
// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;
Could I refactor the lines to:
// Expose jQuery to the global object
window.myjQuery = jQuery;
I've removed the shorthand $ variable, and I've changed jQuery to myjQuery. Now my code can look like this:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>myjQuery</title>
<script type="text/javascript" src="myjquery-1.4.js" />
<script type="text/javascript">
// .ready() can alias the jQuery object
// I can pass $ and write code as normal
myjQuery(document).ready(function($) {
$('p').css('color', 'red');
});
// Fails
jQuery(document).ready(function($) {
$('p').css('color', 'blue');
})
// Fails
$(document).ready(function() {
$('p').css('color', 'green');
})
</script>
</head>
<body>
<p>myjQuery changed my color to red.</p>
</body>
</html>
Is this a good idea? I don't know the internals of the library enough to say for sure. I understand the library is basically a closure, so I'm guessing this approach is OK. Thoughts?
EDIT: I've accepted Doug's answer because he provided code which is almost identical to an example on the $.n开发者_JAVA技巧oConflict() documentation page. I didn't notice it before. Here is the example:
// Completely move jQuery to a new namespace in another object.
var dom = {};
dom.query = jQuery.noConflict(true);
// Do something with the new jQuery
dom.query("div p").hide();
// Do something with another library's $()
$("content").style.display = 'none';
// Do something with another version of jQuery
jQuery("div > p").hide();
It's not normally a good idea to edit a released file if you don't need to. I read your question, and this solution will work for your needs. Don't edit the jQuery core at all. Do this:
<script type="text/javascript" src="jquery-1.4.js"></script>
<script type="text/javascript">
// Revert $ and jQuery to their original values:
window.myjQuery = jQuery.noConflict(true);
(function($){
// Inside here, $ = myjQuery
$(document).ready(function(){
});
})(window.myjQuery);
</script>
The important thing is for your widget to include jQuery, then immediately call noConflict(true)
and store it in a variable.
If you follow these steps exactly, it will not affect existing jQuery instances or plugins on the page. It will only give you a private version of jQuery in the variable myjQuery
for your own plugin.
Secondly, using a self executing anonymous function, you can create a private scope for your widget where $
equals your included jQuery file.
精彩评论