Using getScript to import a plugin into a page using multiple jQuery versions

I am developing an application on a page using jQuery 1.2.6, but I would like to use jQuery 1.4.2 for my application. I really don't like using multiple versions of jQuery like this, but the copy on page (1.2.6) is something I have no control over. I decided to isolate my code like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<script type="text/javascript" src="jquery-1.2.6.min.js>
<script type="text/javascript" src="pageStuff.js"></script>
</head>
<body>
Welcome to our page.
<div id="app">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script type="text/javascript" src="myStuff.js"></script>
</div>
</body></html>

      

The myStuff.js file has my own code that needs to use jQuery 1.4.2 and it looks like this:

(function($) {  //wrap everything in function to add ability to use $ var with noConflict
    var jQuery = $;
    //my code
})(jQuery.noConflict(true));

      

This is an extremely simplified version, but I hope you understand what I did. Everything worked fine for a while. However, I decided to use the jQuery plugin in a separate file. I tested it and it acted funny. After some experimentation, I found out that the plugin was using the old version of jQuery when I wanted it to use the newer version. Does anyone know how to import and run a js file from context inside a function that wraps code in myStuff.js?

In case it matters to everyone, this is how I know the plugin is using the old version and what I did to try and solve the problem: I created a test.js file consisting of this line:

alert($.fn.jquery);

      

I tried referencing the file in the script tag as external Javascript is usually included, below myStuff.js and it looked like 1.2.6 as I expected. Then I got rid of that script tag and put this line in myStuff.js:

$.getScript("test.js");

      

and it came back as 1.2.6 anyway. This was not a big surprise - according to the jQuery documentation , scripts included this way are executed in the global context. Then I tried to do this:

var testFn = $.proxy($.getScript, this);
testFn("test.js");

      

and it came back as 1.2.6 anyway. After some tinkering, I found out that the "this" keyword refers to the window, which I assume means the global context. I'm looking for something instead of "this" to refer to the context of the closing function, or in some other way to make the code in the file runnable from the closing function. I noticed that if I copy and paste the code, it works great, but it's a big plugin that is used in many places and I would rather not clutter my file with my code. I have no idea. Does anyone else know how to do this?

+2


a source to share


5 answers


When you load jQuery, all it does is create a jQuery object for root and set window.jQuery

and window.$

to point to it. This way you can just load old jQuery, copy window.jQuery

to window.jQuery126

, load new jQuery, copy window.jQuery

to window.jQuery142

, then change window.jQuery

and window.$

whenever you want the plugin to use a different version.

This is an ugly and erratic hack, but it should work as long as



  • all code written for the non-version is encapsulated with (function($){...})($)

    (the corresponding jQuery plugins should do this and you can easily provide it for your own code)
  • scripts used with different versions of jQuery do not communicate with each other (e.g. binding an event handler and the other trying to unbind it).

Another simpler but less repairable solution is to simply change the plugin to look like (function($){...})(jQuery142)

instead(function($){...})(jQuery)

+3


a source


Version

There is a script that specifically tries to fix this issue: Versions . However, it is quite old.

It's just a neat helper for switching versions.

Until I tested this script myself, you can do something like this based on the GitHub repository for the project:

<!-- Old jQuery and it plugins -->
<script type="text/javascript" src="../jquery/jquery-1.2.6.js"></script>
<script type="text/javascript" src="test-plugin-for-old.js"></script>

<!-- Include the Versions helper -->
<script type="text/javascript" src="versions.js"></script>

<!-- Include a new jQuery -->
<script type="text/javascript" src="../jquery/jquery.js"></script>
<script type="text/javascript">
Versions.add('jquery', 'latest', jQuery.noConflict(true));
Versions.add('jquery', 'default', jQuery);
</script>

<!-- Load a plugin into the new jQuery -->
<script type="text/javascript">jQuery = Versions.use('jquery', 'latest');</script>
<!-- Do whatever you need with the new jQuery -->
<script type="text/javascript" src="test-plugin-for-new.js"></script>
<!-- Finish up and use the old jQuery back -->
<script type="text/javascript">jQuery = Versions.use('jquery', 'default');</script>

      

Loading on demand JavaScript (lazy loading)



From this point of view, there are some ways of loading on demand on demand , but I don't think they will work well with loading jQuery since jQuery modifies and requires an object window

.

Alternatively, you can read about the loading script. More on this at fooobar.com/questions/189414 / ... and the article is referenced .

RequireJS

The list RequireJS not mentioned. It's pretty new and you can do things like:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
  <script type="text/javascript" src="pageStuff.js"></script>
</head>
<body>
Welcome to our page.
<div id="app">
    <script type="text/javascript" src="require.js"></script>
    <script type="text/javascript">
      require({context: "1.4.2"}, 
        ["http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"],
        function() {
          console.log($.fn.jquery); // returns 1.4.2
          // myStuff.js
        });
      require({context: "1.2.6"}, 
        ["http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"],
        function() {
          console.log($.fn.jquery); // returns 1.2.6
        });
    </script>
</div>
</body></html>

      

I am always up to date with the latest stuff, haha, so I recommend this. However, due to the nature of jquery loading (it modifies window

, as mentioned above), all links to $

and from jQuery

and after the last one require

in the HTML code block above will link to jQuery 1.2.6.

+2


a source


jQuery

is actually a variable in context window

. So whenever you load the jQuery library, it will create this variable in context window

if you load it outside of any function.

I believe you could do something like this to achieve what you want. While somewhat restrictive, in theory it should work:

<script type="text/javascript">
  // Get new jQuery code
  $.get( "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", function (data, textStatus, XMLHttpRequest){
    if(data){
      // data should contain the file content. eval() it
      eval(data);

      // Use jQuery 1.4.2 from here, only inside this callback function.
    }
  }, "html" );
</script>

      

It's ugly, but a trick has to be done.

0


a source


<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" />
<script type="text/javascript">
    $new = $.noConflict();

    document.write("$new = " + $new.fn.jquery + "<br/>");
    document.write("$ = " + $.fn.jquery + "<br/>");

</script>

      

I just tried this and it seems to work, $ reports will be the old version and you just have to make sure to use $ new when calling jquery for what you want to do with 1.4.2

0


a source


I currently agree with Tgr's solution. Here are the details on how I implemented it:

page.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<script type="text/javascript" src="jquery-1.2.6.min.js>
<script type="text/javascript" src="pageStuff.js"></script>
</head>
<body>
Welcome to our page.
<div id="app">
    Here is our app.
    <script type="text/javascript">
        var oldJQuery = $;
    </script>
    <script type="text/javascript"
        src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script type="text/javascript" src="myStuff.js"></script>
</div>
</body></html>

      

myStuff.js:

var jq142 = jQuery.noConflict(true);
(function($) {
    var jQuery = $;
    $(function() {
        //init app stuff
        includeScript("jCarousel.js", function() {
            //init carousel stuff
        });
    });
})(jq142);

function includeScript(URL, callback) {
    window.$ = window.jQuery = jq142;
    window.$.ajax({
        url: URL,
        dataType: "script",
        error: function() {
            window.$ = window.jQuery = oldJQuery;
        },
        success: function() {
            if (typeof callback != "undefined")
                callback();
            window.$ = window.jQuery = oldJQuery;
        },
        async: false
    });
}

      

I still don't like the idea of ​​putting another variable (jq142) into the global namespace, but I couldn't think of any sane way to solve it. If I come up with something better, I'll post it here.

0


a source







All Articles