I have a project that I've been trying to get just right for the past three months and it's still not quite there yet.
I'm injecting some jQuery and jQueryUI code into pages that I have no control over and I need to be able to "sandbox" my code away from anything that may or may not be there at DOM-ready, or at anytime there after...
I think I've got it, but I know there's most likely some edge cases and race conditions that I'm missing. Please fork this and tell me what I've missed. I'm tired of spinning my wheels on this issue.
Markup:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css" />
<script type="text/javascript" src="//www.litmos.com/wp-includes/js/jquery/jquery.js?ver=1.11.0"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
</head>
<body>
<h1>Loading multiple versions of jQuery!</h1>
<script type="text/javascript">
;(function($){
var $h2 = $('<h2>').append('Original jQuery: ' + $.fn.jquery + ' | Original ui: ' + $.ui.version);
document.write($h2[0].outerHTML);
})(jQuery);
</script>
<div>Some other html</div>
<!--// Code that is being "injected into the page" //-->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
;(function($){
window.myJQuery = jQuery.noConflict(true);
})(jQuery);
</script>
<script src="jquery-ui.js"></script>
<script src="script.js"></script>
<!--// End injection code //-->
<script type="text/javascript">
;(function($){
var $h2 = $('<h2>').append('Original jQuery: ' + $.fn.jquery + ' | Original ui: ' + $.ui.version + ' | After namespacing');
document.write($h2[0].outerHTML);
window.setTimeout(function(){
$('h2').not('.namespaced')
.addClass('not-namespaced')
.hide()
.draggable()
.toggle( "highlight" );
}, 2000);
})(jQuery);
</script>
</body>
</html>
JavaScript:
;(function(,ドル jQuery){
var $h2 = $('<h2 class="namespaced">').append('Namespaced $: ' + $.fn.jquery + ' | $.ui: ' + $.ui.version);
document.write($h2[0].outerHTML);
var $jh2 = $('<h2 class="namespaced">').append('Namespaced jQuery: ' + jQuery.fn.jquery + ' | jQuery.ui: ' + jQuery.ui.version);
document.write($jh2[0].outerHTML);
//Verify that jQueryUi works on OUR version of jQuery:
$(document).ready(function(){
console.log($('h2.namespaced').draggable());
});
})(myJQuery, myJQuery);
2 Answers 2
I've worked for a media company where ads had to run with their own version of JavaScript libraries, in the end we preferred to let ads run in their own iframe. Especially since some ads required access to document.write
which creates havoc to your content ;)
It is a bit scary that your solution has to modify jquery-ui.js, I would be very (very) hesitant to do that. I also dont understand why you employ })(myJQuery, myJQuery);
there, since you know you only need 1 of the parameters to initialize jQuery UI.
The worst part is that I played around a bit with a fork and I could not get to a superior solution easily, so if this works for you, then perhaps you should stop researching and just go forth ;)
As far as experience goes, what my team does is to actually agree on a single version of a library and stick to it for the entire production release. That way, each developer will not encounter bugs due to differences. We then talk about upgrades in a meeting to agree on the next version to support, then test the switch for any bugs that old code might generate.
I think this isn't a code issue. This is a management issue, and you should talk this over with your team.
Also, if my semantic versioning isn't that rusty, changes on the third number in a version are bugfixes. jQuery 1.10.x
versions should have no big changes and you should have no reason to actually use multiple versions. You can a single 1.10.x
instead, preferably the latest.
As for sandboxing your code, an IIFE should suffice.
-
5\$\begingroup\$ This is a widget that is being injected into pages outside if my organization. I can't manage other organizations' libraries. \$\endgroup\$RavenHursT– RavenHursT2014年04月18日 15:57:13 +00:00Commented Apr 18, 2014 at 15:57
Explore related questions
See similar questions with these tags.
})(myJQuery, myJQuery);
\$\endgroup\$myJQuery
arguments \$\endgroup\$$
andjQuery
objects are being "sandboxed" just in case any plugins used in the future reference one or the other. As for "redundant", is there a better way to ensure that both the$
andjQuery
params are passed into the anonymous function wrapper asmyJQuery
? \$\endgroup\$})(jQuery, myJQuery)
\$\endgroup\$