11
\$\begingroup\$

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);
\$\endgroup\$
  • \$\begingroup\$ Is the last line of your javascript intentional? })(myJQuery, myJQuery); \$\endgroup\$ – megawac Apr 17 '14 at 17:39
  • \$\begingroup\$ @megawac, yes. myJQuery is the name-spaced jQuery. w/o it, the code would not do what it's intended to do, namespace jQuery. \$\endgroup\$ – RavenHursT Apr 17 '14 at 18:04
  • \$\begingroup\$ @RavenHursT I meant calling with redundant myJQuery arguments \$\endgroup\$ – megawac Apr 17 '14 at 18:23
  • \$\begingroup\$ @megawac, ah.. I'm wanting to ensure that both the $ and jQuery 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 $ and jQuery params are passed into the anonymous function wrapper as myJQuery? \$\endgroup\$ – RavenHursT Apr 17 '14 at 19:08
  • \$\begingroup\$ I'm just suggesting that you proabbly meant })(jQuery, myJQuery) \$\endgroup\$ – megawac Apr 17 '14 at 20:16
5
\$\begingroup\$

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 ;)

\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
  • 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 Apr 18 '14 at 15:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.