0

I'm trying to embed a web application using jQueryUI I have into a third-party site. My web application uses jQuery & jQueryUI (mainly for autocomplete and a few smaller things). The third-party site also uses both.

My code assumes a very recent version of jQueryUI. The third-party site could contain a much older version.

What are my options? I have seen conflicting reports as to whether jQueryUI can be loaded twice or can only be loaded once. However, this SO question suggests it is possible if jQueryUI is built with 'CONTEXT', but I can't find any reference to what 'CONTEXT' means.

Here in outline is what I'm trying to do:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
        <!-- Some version of jQuery and jQueryUI - may change -->
        <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.18/jquery-ui.min.js"></script>
    </head>
<body>

<script type="text/javascript">
    // some third-party jQuery & jQueryUI stuff here
</script>

<!-- Up to this point, I cannot make any changes to the code, as all of the above is third-party code -->


<!-- Start of MY application -->

    <!-- Load jQuery and jQueryUI -->
    <script src="/jquery-ui-1.10.4.custom/js/jquery-1.10.2.js"></script>
    <script src="/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.js"></script>

    <!-- Application code, which wants to use jquery-1.10.2 and jquery-ui-1.10.4 -->
    <input name="foo" />
    <script language="javascript" type="text/javascript">
        alert('START OF AUTOCOMPLETE jQuery version: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);

        function addAutocomplete (inputElement, options) {

            // Run on document ready
            $(function() {
                alert('WITHIN CODE: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);
                <!-- *** Currently this gives "WITHIN CODE: 1.7.1; jQueryUI version: 1.8.18" -->
                <!-- *** But what I want is WITHIN CODE: 1.10.2; jQueryUI version: 1.10.4" -->
            })
        };
        addAutocomplete('foo');
    </script>

    <!-- End of MY application -->


<!-- From this point, I cannot make changes to the code - is third-party code which could include jQuery/jQueryUI code potentially -->


</body>
</html>

What are my options? I'm tearing my hair out over this!

1) I've tried reassigning $ and jquery, as suggested on this page, but I cannot see why the code at *** shows the old version of jQueryUI:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
        <!-- Some version of jQuery and jQueryUI - may change -->
        <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.18/jquery-ui.min.js"></script>
    </head>
<body>

<script type="text/javascript">
    // some third-party jQuery & jQueryUI stuff here
</script>

<!-- Up to this point, I cannot make any changes to the code, as all of the above is third-party code -->


<!-- Start of MY application -->

    <script type="text/javascript">
        alert('START jQuery version: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);
        var oldJQuery = jQuery;
        var oldDollar = $;
    </script>


    <script src="/jquery-ui-1.10.4.custom/js/jquery-1.10.2.js"></script>
    <script src="/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.js"></script>
    <script type="text/javascript">
        alert('REPLACED jQuery version: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);
    </script>


    <!-- Application code, which wants to use jquery-1.10.2 and jquery-ui-1.10.4 -->
    <input name="foo" />
    <script language="javascript" type="text/javascript">
        alert('START OF AUTOCOMPLETE jQuery version: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);

        function addAutocomplete (inputElement, options) {

            // Run on document ready
            $(function() {
                alert('WITHIN CODE: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);
                <!-- *** Currently this gives "WITHIN CODE: 1.7.1; jQueryUI version: 1.8.18" -->
                <!-- *** But what I want is WITHIN CODE: 1.10.2; jQueryUI version: 1.10.4" -->
            })
        };
        addAutocomplete('foo');
    </script>


    <script language="javascript" type="text/javascript">
        // var rnSDJQ = jQuery;
        window.jQuery = oldJQuery;
        window.$ = oldDollar;
        alert('AFTER jQuery version: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);
    </script>

<!-- End of MY application -->


<!-- From this point, I cannot make changes to the code - is third-party code which could include jQuery/jQueryUI code potentially -->


</body>
</html>

That method seems very similar to this but I think that only applies to jQuery - jQueryUI apparently doesn't have a similar noConflict method.

2) Rewrite my application code to assume only early versions of jQuery and jQueryUI?

3) Make a copy of jQueryUI and do search-and-replace on (jquery) as suggested here - sounds very nasty, and a maintenance nightmare!

4) Something like this? (Though I can't see how to apply it in my situation since I can't call noConflict on the first jQuery presumably?)

5) Some other option?

A further difficulty is that I can't find a way to include jQuery/jQueryUI conditionally - the third-party site might not actually be loading jQuery/jQueryUI so I need to cope with that possibility also.

Community
  • 1
  • 1
fooquency
  • 1,575
  • 3
  • 16
  • 29

2 Answers2

3

So the problem that you're having is that window.$ and window.jQuery still match the old jQuery and jQuery-UI is connecting to one of those. If instead you use noConflict before the initialization of your library then later restore the window.$ and window.jQuery you should be alright. E.g.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
        <!-- Some version of jQuery and jQueryUI - may change -->
        <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.18/jquery-ui.min.js"></script>
    </head>
    <body>

        <script type="text/javascript">
            // some third-party jQuery & jQueryUI stuff here
        </script>

    <!-- Up to this point, I cannot make any changes to the code, as all of the above is third-party code -->


    <!-- Start of MY application -->

        <script type="text/javascript">
            alert('START jQuery version: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);
            var jq171 = $.noConflict(true);
        </script>


        <script src="/jquery-ui-1.10.4.custom/js/jquery-1.10.2.js"></script>
        <script src="/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.js"></script>
        <script type="text/javascript">
             alert('REPLACED jQuery version: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);
        </script>

        <script src="/autocomplete.js"></script>
        <input name="foo" />
        <script language="javascript" type="text/javascript">
            function addAutocomplete (inputElement, options) {

                // Run on document ready
                $(function($) {
                    alert('WITHIN CODE: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);                      
                    <!-- *** Should give WITHIN CODE: 1.10.2; jQueryUI version: 1.10.4" -->
                });
            };

            addAutocomplete('foo');
            <!-- *** If I do console.log ($.ui.version); within the $(function() { ... } block in this file, it should show the new one -->
        </script>


        <script language="javascript" type="text/javascript">
            window.jQuery = jq171;
            window.$ = jq171;
            alert('AFTER jQuery version: ' + $.fn.jquery + '; jQueryUI version: ' + $.ui.version);
        </script>

    <!-- End of MY application -->


    <!-- From this point, I cannot make changes to the code - is third-party code which could include jQuery/jQueryUI code potentially -->


    </body>
</html>

Edit: So I see what your problem is now! If you add in a reference to $ in to the function call, e.g.:

$(function($) { ... });

That should fix it - However, I guess do you have access to that?

Zeripath
  • 46
  • 1
  • 3
  • Thanks, and welcome to StackOverflow! However, I'm still finding that the application code is getting the earlier version, not the later one, so this still isn't right unfortunately. I've updated the code to give a specific application code example. See the two lines with *** above. – fooquency Mar 01 '14 at 21:09
  • Thanks - that testcase seems to give the correct result now. I'm going to try to put this into the code now and see from there. I'm still not clear about the ```$(function($)``` stuff as there are several functions in a file which need to be wrapped - but this is a definite step forward - thank you! – fooquency Mar 01 '14 at 21:51
  • So the $(function ($) { ... }); bit ensures that the $ inside the function is the same jquery as the jquery that called it. If you did jq171(function ($) { ... }) the $ inside that function will be jq171. – Zeripath Mar 01 '14 at 22:44
  • The other thing you should really be doing is working in the module pattern i.e. wrap all of your code up in an immediately invoked function. That way you can simply ensure that if the old jQuery invokes one of your functions it will your jQuery not theirs. – Zeripath Mar 01 '14 at 22:46
  • The main example has worked - thanks. The wrapping is the issue I'm working through now. I'm surrounding the code with ```(function($) {``` ... ```})(jQuery);``` though it currently contains several functions, so am just trying to understand the syntax for this. Am very used to OO classes so this feels more like where the code should be anyway, once I work out the JS/jQuery syntax. – fooquency Mar 01 '14 at 23:13
0

Assuming you will load your jQuery files before to the third party page, here is the approach.

Load your first jQuery file the load your jQuery UI file

<script src="jquery-min.js"></script>
<script src="jquery.ui.js"></script>

Later even if your thirdparty page loads jQuery and jQuery UI check like below

if(window._$ and window._jQuery){
    /*
        _$ is jQuery that you have loaded. As jQuery UI will be bind to 
        running jQuery version you can start using _$ for jQuery UI too 
    */

}else{
    // None has loaded other jQuery versions. You can use $
}

jQuery.noConflict() gives you the latest running instance of jQuery.

redV
  • 684
  • 1
  • 9
  • 26